-
Notifications
You must be signed in to change notification settings - Fork 98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nat documentation and fromText()
utility
#517
Changes from 2 commits
3ab4995
f918e2f
107f031
69d940a
d90b2cc
d35387e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -1,72 +1,299 @@ | ||||||||
/// Natural numbers | ||||||||
/// Utility functions for working with natural numbers. | ||||||||
/// | ||||||||
/// Most operations on natural numbers (e.g. addition) are available as built-in operators (e.g. `1 + 1`). | ||||||||
/// This module provides equivalent functions and `Text` conversion. | ||||||||
/// | ||||||||
/// Import from the base library to use this module. | ||||||||
/// ```motoko name=import | ||||||||
/// import Nat "mo:base/Nat"; | ||||||||
/// ``` | ||||||||
|
||||||||
import Int "Int"; | ||||||||
import Order "Order"; | ||||||||
import Prim "mo:⛔"; | ||||||||
import Char "Char"; | ||||||||
|
||||||||
module { | ||||||||
|
||||||||
/// Infinite precision natural numbers. | ||||||||
public type Nat = Prim.Types.Nat; | ||||||||
|
||||||||
/// Conversion. | ||||||||
public let toText : Nat -> Text = Int.toText; | ||||||||
/// Converts a natural number to its textual representation. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Detail (unsure whether worth mentioning): Without underscore formatting for thousand digit separators. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will add |
||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// Nat.toText 1234 // => "1234" | ||||||||
/// ``` | ||||||||
public func toText(n : Nat) : Text = Int.toText n; | ||||||||
|
||||||||
/// Creates a natural number from its textual representation. Returns `null` | ||||||||
/// if the input is not a valid natural number. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// Nat.fromText "1234" // => ?1234 | ||||||||
/// ``` | ||||||||
public func fromText(text : Text) : ?Nat { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just noticed that we do not have this function in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #520 Yeah that sounds good! |
||||||||
if (text == "") { | ||||||||
return null | ||||||||
}; | ||||||||
var n = 0; | ||||||||
for (c in text.chars()) { | ||||||||
if (Char.isDigit(c)) { | ||||||||
let charAsNat = Prim.nat32ToNat(Prim.charToNat32(c) -% Prim.charToNat32('0')); | ||||||||
n := n * 10 + charAsNat | ||||||||
} else { | ||||||||
return null | ||||||||
} | ||||||||
}; | ||||||||
?n | ||||||||
}; | ||||||||
|
||||||||
/// Returns the minimum of `x` and `y`. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// Nat.min(1, 2) // => 1 | ||||||||
/// ``` | ||||||||
public func min(x : Nat, y : Nat) : Nat { | ||||||||
if (x < y) { x } else { y } | ||||||||
}; | ||||||||
|
||||||||
/// Returns the maximum of `x` and `y`. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// Nat.max(1, 2) // => 2 | ||||||||
/// ``` | ||||||||
public func max(x : Nat, y : Nat) : Nat { | ||||||||
if (x < y) { y } else { x } | ||||||||
}; | ||||||||
|
||||||||
/// Returns `x == y`. | ||||||||
/// Equality function for Nat types. | ||||||||
/// This is equivalent to `x == y`. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// ignore Nat.equal(1, 1); // => true | ||||||||
/// 1 == 1 // => true | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `==` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `==` | ||||||||
/// as a function value at the moment. | ||||||||
/// | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great comment. Maybe we should also improve |
||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// import Buffer "mo:base/Buffer"; | ||||||||
/// | ||||||||
/// let buffer1 = Buffer.Buffer<Nat>(3); | ||||||||
/// let buffer2 = Buffer.Buffer<Nat>(3); | ||||||||
/// Buffer.equal(buffer1, buffer2, Nat.equal) // => true | ||||||||
/// ``` | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And nice example demonstrating where it makes really sense to use the equal function. |
||||||||
public func equal(x : Nat, y : Nat) : Bool { x == y }; | ||||||||
|
||||||||
/// Returns `x != y`. | ||||||||
/// Inequality function for Nat types. | ||||||||
/// This is equivalent to `x != y`. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// ignore Nat.notEqual(1, 2); // => true | ||||||||
/// 1 != 2 // => true | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `!=` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `!=` | ||||||||
/// as a function value at the moment. | ||||||||
public func notEqual(x : Nat, y : Nat) : Bool { x != y }; | ||||||||
|
||||||||
/// Returns `x < y`. | ||||||||
/// "Less than" function for Nat types. | ||||||||
/// This is equivalent to `x < y`. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// ignore Nat.less(1, 2); // => true | ||||||||
/// 1 < 2 // => true | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `<` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `<` | ||||||||
/// as a function value at the moment. | ||||||||
public func less(x : Nat, y : Nat) : Bool { x < y }; | ||||||||
|
||||||||
/// Returns `x <= y`. | ||||||||
/// "Less than or equal" function for Nat types. | ||||||||
/// This is equivalent to `x <= y`. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// ignore Nat.lessOrEqual(1, 2); // => true | ||||||||
/// 1 <= 2 // => true | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `<=` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `<=` | ||||||||
/// as a function value at the moment. | ||||||||
public func lessOrEqual(x : Nat, y : Nat) : Bool { x <= y }; | ||||||||
|
||||||||
/// Returns `x > y`. | ||||||||
/// "Greater than" function for Nat types. | ||||||||
/// This is equivalent to `x > y`. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// ignore Nat.greater(2, 1); // => true | ||||||||
/// 2 > 1 // => true | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `>` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `>` | ||||||||
/// as a function value at the moment. | ||||||||
public func greater(x : Nat, y : Nat) : Bool { x > y }; | ||||||||
|
||||||||
/// Returns `x >= y`. | ||||||||
/// "Greater than or equal" function for Nat types. | ||||||||
/// This is equivalent to `x >= y`. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// ignore Nat.greaterOrEqual(2, 1); // => true | ||||||||
/// 2 >= 1 // => true | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `>=` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `>=` | ||||||||
/// as a function value at the moment. | ||||||||
public func greaterOrEqual(x : Nat, y : Nat) : Bool { x >= y }; | ||||||||
|
||||||||
/// Returns the order of `x` and `y`. | ||||||||
/// General purpose comparison function for `Nat`. Returns the `Order` ( | ||||||||
/// either `#less`, `#equal`, or `#greater`) of comparing `x` with `y`. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// Nat.compare(2, 3) // => #less | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `>=` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `>=` | ||||||||
/// as a function value at the moment. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// import Array "mo:base/Array"; | ||||||||
/// Array.sort([2, 3, 1], Nat.compare) // => [1, 2, 3] | ||||||||
/// ``` | ||||||||
public func compare(x : Nat, y : Nat) : { #less; #equal; #greater } { | ||||||||
if (x < y) { #less } else if (x == y) { #equal } else { #greater } | ||||||||
}; | ||||||||
|
||||||||
/// Returns the sum of `x` and `y`, `x + y`. | ||||||||
/// | ||||||||
/// Example: | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it could help to mention (again): No overflow since |
||||||||
/// ```motoko include=import | ||||||||
/// ignore Nat.add(1, 2); // => 3 | ||||||||
/// 1 + 2 // => 3 | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `+` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `+` | ||||||||
/// as a function value at the moment. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// import Array "mo:base/Array"; | ||||||||
/// Array.foldLeft([2, 3, 1], 0, Nat.add) // => 6 | ||||||||
/// ``` | ||||||||
public func add(x : Nat, y : Nat) : Nat { x + y }; | ||||||||
|
||||||||
/// Returns the difference of `x` and `y`, `x - y`. | ||||||||
/// Traps on underflow. | ||||||||
/// Traps on underflow below `0`. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// ignore Nat.sub(2, 1); // => 1 | ||||||||
/// // Add a type annotation to avoid a warning about the subtraction | ||||||||
/// 2 - 1 : Nat // => 1 | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `-` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `-` | ||||||||
/// as a function value at the moment. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// import Array "mo:base/Array"; | ||||||||
/// Array.foldLeft([2, 3, 1], 10, Nat.sub) // => 4 | ||||||||
/// ``` | ||||||||
public func sub(x : Nat, y : Nat) : Nat { x - y }; | ||||||||
|
||||||||
/// Returns the product of `x` and `y`, `x * y`. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// ignore Nat.mul(2, 3); // => 6 | ||||||||
/// 2 * 3 // => 6 | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `*` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `*` | ||||||||
/// as a function value at the moment. | ||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// import Array "mo:base/Array"; | ||||||||
/// Array.foldLeft([2, 3, 1], 1, Nat.mul) // => 6 | ||||||||
/// ``` | ||||||||
public func mul(x : Nat, y : Nat) : Nat { x * y }; | ||||||||
|
||||||||
/// Returns the division of `x` by `y`, `x / y`. | ||||||||
/// Traps when `y` is zero. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// ignore Nat.div(6, 2); // => 3 | ||||||||
/// 6 / 2 // => 3 | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `/` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `/` | ||||||||
/// as a function value at the moment. | ||||||||
public func div(x : Nat, y : Nat) : Nat { x / y }; | ||||||||
|
||||||||
/// Returns the remainder of `x` divided by `y`, `x % y`. | ||||||||
/// Traps when `y` is zero. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to |
||||||||
/// | ||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// ignore Nat.rem(6, 4); // => 2 | ||||||||
/// 6 % 4 // => 2 | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `%` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `%` | ||||||||
/// as a function value at the moment. | ||||||||
public func rem(x : Nat, y : Nat) : Nat { x % y }; | ||||||||
|
||||||||
/// Returns `x` to the power of `y`, `x ** y`. | ||||||||
/// | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh! Didn't know that |
||||||||
/// Example: | ||||||||
/// ```motoko include=import | ||||||||
/// ignore Nat.pow(2, 3); // => 8 | ||||||||
/// 2 ** 3 // => 8 | ||||||||
/// ``` | ||||||||
/// | ||||||||
/// Note: The reason why this function is defined in this library (in addition | ||||||||
/// to the existing `**` operator) is so that you can use it as a function | ||||||||
/// value to pass to a higher order function. It is not possible to use `**` | ||||||||
/// as a function value at the moment. | ||||||||
public func pow(x : Nat, y : Nat) : Nat { x ** y }; | ||||||||
|
||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update: (Just saw that it is mentioned below). But maybe it is useful to mention it also in the header that the numbers have infinite precision, in symmetry with the documentation
Int.mo
.