Move builtins to snake_case with auto-case conversion

This commit is contained in:
Sam Mohr 2025-01-04 03:27:16 -08:00
parent 3d4dd5b583
commit 2aac2e01f8
No known key found for this signature in database
GPG key ID: EA41D161A3C1BC99
16 changed files with 3348 additions and 3277 deletions

View file

@ -1,9 +1,9 @@
module [Bool, Eq, true, false, and, or, not, isEq, isNotEq]
module [Bool, Eq, true, false, and, or, not, is_eq, is_not_eq]
## Defines a type that can be compared for total equality.
##
## Total equality means that all values of the type can be compared to each
## other, and two values `a`, `b` are identical if and only if `isEq a b` is
## other, and two values `a`, `b` are identical if and only if `isEq(a, b)` is
## `Bool.true`.
##
## Not all types support total equality. For example, [`F32`](../Num#F32) and [`F64`](../Num#F64) can
@ -14,9 +14,9 @@ Eq implements
## Returns `Bool.true` if the input values are equal. This is
## equivalent to the logic
## [XNOR](https://en.wikipedia.org/wiki/Logical_equality) gate. The infix
## operator `==` can be used as shorthand for `Bool.isEq`.
## operator `==` can be used as shorthand for `Bool.is_eq`.
##
## **Note** that when `isEq` is determined by the Roc compiler, values are
## **Note** that when `is_eq` is determined by the Roc compiler, values are
## compared using structural equality. The rules for this are as follows:
##
## 1. Tags are equal if their name and also contents are equal.
@ -24,25 +24,25 @@ Eq implements
## 3. The collections [Str], [List], [Dict], and [Set] are equal iff they
## are the same length and their elements are equal.
## 4. [Num] values are equal if their numbers are equal. However, if both
## inputs are *NaN* then `isEq` returns `Bool.false`. Refer to `Num.isNaN`
## inputs are *NaN* then `is_eq` returns `Bool.false`. Refer to `Num.is_nan`
## for more detail.
## 5. Functions cannot be compared for structural equality, therefore Roc
## cannot derive `isEq` for types that contain functions.
isEq : a, a -> Bool where a implements Eq
## cannot derive `is_eq` for types that contain functions.
is_eq : a, a -> Bool where a implements Eq
## Represents the boolean true and false using an opaque type.
## `Bool` implements the `Eq` ability.
Bool := [True, False] implements [Eq { isEq: boolIsEq }]
Bool := [True, False] implements [Eq { is_eq: bool_is_eq }]
boolIsEq = \@Bool b1, @Bool b2 -> structuralEq b1 b2
bool_is_eq = \@Bool b1, @Bool b2 -> structural_eq b1 b2
## The boolean true value.
true : Bool
true = @Bool True
true = @Bool (True)
## The boolean false value.
false : Bool
false = @Bool False
false = @Bool (False)
## Returns `Bool.true` when both inputs are `Bool.true`. This is equivalent to
## the logic [AND](https://en.wikipedia.org/wiki/Logical_conjunction)
@ -50,7 +50,7 @@ false = @Bool False
## `Bool.and`.
##
## ```roc
## expect (Bool.and Bool.true Bool.true) == Bool.true
## expect Bool.and(Bool.true, Bool.true) == Bool.true
## expect (Bool.true && Bool.true) == Bool.true
## expect (Bool.false && Bool.true) == Bool.false
## expect (Bool.true && Bool.false) == Bool.false
@ -63,10 +63,10 @@ false = @Bool False
## other function. However, in some languages `&&` and `||` are special-cased.
## In these languages the compiler will skip evaluating the expression after the
## first operator under certain circumstances. For example an expression like
## `enablePets && likesDogs user` would compile to.
## `enable_pets && likes_dogs(user)` would compile to.
## ```roc
## if enablePets then
## likesDogs user
## if enable_pets then
## likes_dogs(user)
## else
## Bool.false
## ```
@ -79,7 +79,7 @@ and : Bool, Bool -> Bool
## the logic [OR](https://en.wikipedia.org/wiki/Logical_disjunction) gate.
## The infix operator `||` can also be used as shorthand for `Bool.or`.
## ```roc
## expect (Bool.or Bool.false Bool.true) == Bool.true
## expect Bool.or(Bool.false, Bool.true) == Bool.true
## expect (Bool.true || Bool.true) == Bool.true
## expect (Bool.false || Bool.true) == Bool.true
## expect (Bool.true || Bool.false) == Bool.true
@ -97,30 +97,30 @@ or : Bool, Bool -> Bool
## equivalent to the logic [NOT](https://en.wikipedia.org/wiki/Negation)
## gate. The operator `!` can also be used as shorthand for `Bool.not`.
## ```roc
## expect (Bool.not Bool.false) == Bool.true
## expect (!Bool.false) == Bool.true
## expect Bool.not(Bool.false) == Bool.true
## expect !Bool.false == Bool.true
## ```
not : Bool -> Bool
## This will call the function `Bool.isEq` on the inputs, and then `Bool.not`
## This will call the function `Bool.is_eq` on the inputs, and then `Bool.not`
## on the result. The is equivalent to the logic
## [XOR](https://en.wikipedia.org/wiki/Exclusive_or) gate. The infix operator
## `!=` can also be used as shorthand for `Bool.isNotEq`.
## `!=` can also be used as shorthand for `Bool.is_not_eq`.
##
## **Note** that `isNotEq` does not accept arguments whose types contain
## **Note** that `is_not_eq` does not accept arguments whose types contain
## functions.
## ```roc
## expect (Bool.isNotEq Bool.false Bool.true) == Bool.true
## expect Bool.is_not_eq(Bool.false, Bool.true) == Bool.true
## expect (Bool.false != Bool.false) == Bool.false
## expect "Apples" != "Oranges"
## ```
isNotEq : a, a -> Bool where a implements Eq
isNotEq = \a, b -> structuralNotEq a b
is_not_eq : a, a -> Bool where a implements Eq
is_not_eq = \a, b -> structural_not_eq(a, b)
# INTERNAL COMPILER USE ONLY: used to lower calls to `isEq` to structural
# INTERNAL COMPILER USE ONLY: used to lower calls to `is_eq` to structural
# equality via the `Eq` low-level for derived types.
structuralEq : a, a -> Bool
structural_eq : a, a -> Bool
# INTERNAL COMPILER USE ONLY: used to lower calls to `isNotEq` to structural
# INTERNAL COMPILER USE ONLY: used to lower calls to `is_not_eq` to structural
# inequality via the `NotEq` low-level for derived types.
structuralNotEq : a, a -> Bool
structural_not_eq : a, a -> Bool

View file

@ -9,13 +9,13 @@ module [box, unbox]
## optimization for advanced use cases with large values. A platform may require
## that some values are boxed.
## ```roc
## expect Box.unbox (Box.box "Stack Faster") == "Stack Faster"
## expect Box.unbox(Box.box("Stack Faster")) == "Stack Faster"
## ```
box : a -> Box a
## Returns a boxed value.
## ```roc
## expect Box.unbox (Box.box "Stack Faster") == "Stack Faster"
## expect Box.unbox(Box.box("Stack Faster") == "Stack Faster"
## ```
unbox : Box a -> a

View file

@ -24,10 +24,10 @@ module [
record,
tuple,
custom,
decodeWith,
fromBytesPartial,
fromBytes,
mapResult,
decode_with,
from_bytes_partial,
from_bytes,
map_result,
]
import List
@ -55,13 +55,13 @@ DecodeError : [TooShort]
## Return type of a [Decoder].
##
## This can be useful when creating a [custom](#custom) decoder or when
## using [fromBytesPartial](#fromBytesPartial). For example writing unit tests,
## using [from_bytes_partial](#from_bytes_partial). For example writing unit tests,
## such as;
## ```roc
## expect
## input = "\"hello\", " |> Str.toUtf8
## actual = Decode.fromBytesPartial input Json.json
## expected = Ok "hello"
## actual = Decode.from_bytes_partial(input, Json.json)
## expected = Ok("hello")
##
## actual.result == expected
## ```
@ -95,51 +95,51 @@ DecoderFormatting implements
string : Decoder Str fmt where fmt implements DecoderFormatting
list : Decoder elem fmt -> Decoder (List elem) fmt where fmt implements DecoderFormatting
## `record state stepField finalizer` decodes a record field-by-field.
## `record(state, step_field, finalizer)` decodes a record field-by-field.
##
## `stepField` returns a decoder for the given field in the record, or
## `step_field` returns a decoder for the given field in the record, or
## `Skip` if the field is not a part of the decoded record.
##
## `finalizer` should produce the record value from the decoded `state`.
record : state, (state, Str -> [Keep (Decoder state fmt), Skip]), (state, fmt -> Result val DecodeError) -> Decoder val fmt where fmt implements DecoderFormatting
## `tuple state stepElem finalizer` decodes a tuple element-by-element.
## `tuple(state, step_elem, finalizer)` decodes a tuple element-by-element.
##
## `stepElem` returns a decoder for the nth index in the tuple, or
## `step_elem` returns a decoder for the nth index in the tuple, or
## `TooLong` if the index is larger than the expected size of the tuple. The
## index passed to `stepElem` is 0-indexed.
## index passed to `step_elem` is 0-indexed.
##
## `finalizer` should produce the tuple value from the decoded `state`.
tuple : state, (state, U64 -> [Next (Decoder state fmt), TooLong]), (state -> Result val DecodeError) -> Decoder val fmt where fmt implements DecoderFormatting
## Build a custom [Decoder] function. For example the implementation of
## `decodeBool` could be defined as follows;
## `decode_bool` could be defined as follows;
##
## ```roc
## decodeBool = Decode.custom \bytes, @Json {} ->
## decode_bool = Decode.custom \bytes, @Json({}) ->
## when bytes is
## ['f', 'a', 'l', 's', 'e', ..] -> { result: Ok Bool.false, rest: List.dropFirst bytes 5 }
## ['t', 'r', 'u', 'e', ..] -> { result: Ok Bool.true, rest: List.dropFirst bytes 4 }
## _ -> { result: Err TooShort, rest: bytes }
## ['f', 'a', 'l', 's', 'e', ..] -> { result: Ok(Bool.false), rest: List.drop_first(bytes, 5) }
## ['t', 'r', 'u', 'e', ..] -> { result: Ok Bool.true, rest: List.drop_first(bytes, 4) }
## _ -> { result: Err(TooShort), rest: bytes }
## ```
custom : (List U8, fmt -> DecodeResult val) -> Decoder val fmt where fmt implements DecoderFormatting
custom = \decode -> @Decoder decode
custom = \decode -> @Decoder(decode)
## Decode a `List U8` utf-8 bytes using a specific [Decoder] function
decodeWith : List U8, Decoder val fmt, fmt -> DecodeResult val where fmt implements DecoderFormatting
decodeWith = \bytes, @Decoder decode, fmt -> decode bytes fmt
decode_with : List U8, Decoder val fmt, fmt -> DecodeResult val where fmt implements DecoderFormatting
decode_with = \bytes, @Decoder(decode), fmt -> decode(bytes, fmt)
## Decode a `List U8` utf-8 bytes and return a [DecodeResult](#DecodeResult)
## ```roc
## expect
## input = "\"hello\", " |> Str.toUtf8
## actual = Decode.fromBytesPartial input Json.json
## expected = Ok "hello"
## actual = Decode.from_bytes_partial(input Json.json)
## expected = Ok("hello")
##
## actual.result == expected
## ```
fromBytesPartial : List U8, fmt -> DecodeResult val where val implements Decoding, fmt implements DecoderFormatting
fromBytesPartial = \bytes, fmt -> decodeWith bytes decoder fmt
from_bytes_partial : List U8, fmt -> DecodeResult val where val implements Decoding, fmt implements DecoderFormatting
from_bytes_partial = \bytes, fmt -> decode_with(bytes, decoder, fmt)
## Decode a `List U8` utf-8 bytes and return a [Result] with no leftover bytes
## expected. If successful returns `Ok val`, however, if there are bytes
@ -147,22 +147,22 @@ fromBytesPartial = \bytes, fmt -> decodeWith bytes decoder fmt
## ```roc
## expect
## input = "\"hello\", " |> Str.toUtf8
## actual = Decode.fromBytes input Json.json
## expected = Ok "hello"
## actual = Decode.from_bytes(input, Json.json)
## expected = Ok("hello")
##
## actual == expected
## ```
fromBytes : List U8, fmt -> Result val [Leftover (List U8)]DecodeError where val implements Decoding, fmt implements DecoderFormatting
fromBytes = \bytes, fmt ->
when fromBytesPartial bytes fmt is
from_bytes : List U8, fmt -> Result val [Leftover (List U8)]DecodeError where val implements Decoding, fmt implements DecoderFormatting
from_bytes = \bytes, fmt ->
when from_bytes_partial(bytes, fmt) is
{ result, rest } ->
if List.isEmpty rest then
if List.is_empty(rest) then
when result is
Ok val -> Ok val
Err TooShort -> Err TooShort
Ok val -> Ok (val)
Err TooShort -> Err (TooShort)
else
Err (Leftover rest)
Err (Leftover (rest))
## Transform the `val` of a [DecodeResult]
mapResult : DecodeResult a, (a -> b) -> DecodeResult b
mapResult = \{ result, rest }, mapper -> { result: Result.map result mapper, rest }
map_result : DecodeResult a, (a -> b) -> DecodeResult b
map_result = \{ result, rest }, mapper -> { result: Result.map(result, mapper), rest }

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
module [
Encoder,
Encoding,
toEncoder,
to_encoder,
EncoderFormatting,
u8,
u16,
@ -23,9 +23,9 @@ module [
tag,
tuple,
custom,
appendWith,
append_with,
append,
toBytes,
to_bytes,
]
import Num exposing [
@ -48,7 +48,7 @@ import Bool exposing [Bool]
Encoder fmt := List U8, fmt -> List U8 where fmt implements EncoderFormatting
Encoding implements
toEncoder : val -> Encoder fmt where val implements Encoding, fmt implements EncoderFormatting
to_encoder : val -> Encoder fmt where val implements Encoding, fmt implements EncoderFormatting
EncoderFormatting implements
u8 : U8 -> Encoder fmt where fmt implements EncoderFormatting
@ -76,41 +76,41 @@ EncoderFormatting implements
## ```roc
## expect
## # Appends the byte 42
## customEncoder = Encode.custom (\bytes, _fmt -> List.append bytes 42)
## custom_encoder = Encode.custom(\bytes, _fmt -> List.append(bytes, 42))
##
## actual = Encode.appendWith [] customEncoder Core.json
## actual = Encode.append_with([], custom_encoder, Core.json)
## expected = [42] # Expected result is a list with a single byte, 42
##
## actual == expected
## ```
custom : (List U8, fmt -> List U8) -> Encoder fmt where fmt implements EncoderFormatting
custom = \encoder -> @Encoder encoder
custom = \encoder -> @Encoder(encoder)
appendWith : List U8, Encoder fmt, fmt -> List U8 where fmt implements EncoderFormatting
appendWith = \lst, @Encoder doEncoding, fmt -> doEncoding lst fmt
append_with : List U8, Encoder fmt, fmt -> List U8 where fmt implements EncoderFormatting
append_with = \lst, @Encoder(do_encoding), fmt -> do_encoding(lst, fmt)
## Appends the encoded representation of a value to an existing list of bytes.
##
## ```roc
## expect
## actual = Encode.append [] { foo: 43 } Core.json
## expected = Str.toUtf8 """{"foo":43}"""
## actual = Encode.append([], { foo: 43 }, Core.json)
## expected = Str.to_utf8("""{"foo":43}""")
##
## actual == expected
## ```
append : List U8, val, fmt -> List U8 where val implements Encoding, fmt implements EncoderFormatting
append = \lst, val, fmt -> appendWith lst (toEncoder val) fmt
append = \lst, val, fmt -> append_with(lst, to_encoder(val), fmt)
## Encodes a value to a list of bytes (`List U8`) according to the specified format.
##
## ```roc
## expect
## fooRec = { foo: 42 }
## foo_rec = { foo: 42 }
##
## actual = Encode.toBytes fooRec Core.json
## expected = Str.toUtf8 """{"foo":42}"""
## actual = Encode.to_bytes(foo_rec, Core.json)
## expected = Str.to_utf8("""{"foo":42}""")
##
## actual == expected
## ```
toBytes : val, fmt -> List U8 where val implements Encoding, fmt implements EncoderFormatting
toBytes = \val, fmt -> appendWith [] (toEncoder val) fmt
to_bytes : val, fmt -> List U8 where val implements Encoding, fmt implements EncoderFormatting
to_bytes = \val, fmt -> append_with([], to_encoder(val), fmt)

View file

@ -2,23 +2,23 @@ module [
Hash,
Hasher,
hash,
addBytes,
addU8,
addU16,
addU32,
addU64,
addU128,
hashBool,
hashI8,
hashI16,
hashI32,
hashI64,
hashI128,
hashDec,
add_bytes,
add_u8,
add_u16,
add_u32,
add_u64,
add_u128,
hash_bool,
hash_i8,
hash_i16,
hash_i32,
hash_i64,
hash_i128,
hash_dec,
complete,
hashStrBytes,
hashList,
hashUnordered,
hash_str_bytes,
hash_list,
hash_unordered,
]
import Bool exposing [Bool]
@ -52,86 +52,88 @@ Hash implements
## cryptographically-secure hashing.
Hasher implements
## Adds a list of bytes to the hasher.
addBytes : a, List U8 -> a where a implements Hasher
add_bytes : a, List U8 -> a where a implements Hasher
## Adds a single U8 to the hasher.
addU8 : a, U8 -> a where a implements Hasher
add_u8 : a, U8 -> a where a implements Hasher
## Adds a single U16 to the hasher.
addU16 : a, U16 -> a where a implements Hasher
add_u16 : a, U16 -> a where a implements Hasher
## Adds a single U32 to the hasher.
addU32 : a, U32 -> a where a implements Hasher
add_u32 : a, U32 -> a where a implements Hasher
## Adds a single U64 to the hasher.
addU64 : a, U64 -> a where a implements Hasher
add_u64 : a, U64 -> a where a implements Hasher
## Adds a single U128 to the hasher.
addU128 : a, U128 -> a where a implements Hasher
add_u128 : a, U128 -> a where a implements Hasher
## Completes the hasher, extracting a hash value from its
## accumulated hash state.
complete : a -> U64 where a implements Hasher
## Adds a string into a [Hasher] by hashing its UTF-8 bytes.
hashStrBytes = \hasher, s ->
addBytes hasher (Str.toUtf8 s)
hash_str_bytes = \hasher, s ->
add_bytes(hasher, Str.to_utf8(s))
## Adds a list of [Hash]able elements to a [Hasher] by hashing each element.
hashList = \hasher, lst ->
List.walk lst hasher \accumHasher, elem ->
hash accumHasher elem
hash_list = \hasher, lst ->
List.walk(lst, hasher, (\accum_hasher, elem ->
hash(accum_hasher, elem)
))
## Adds a single [Bool] to a hasher.
hashBool : a, Bool -> a where a implements Hasher
hashBool = \hasher, b ->
asU8 = if b then 1 else 0
addU8 hasher asU8
hash_bool : a, Bool -> a where a implements Hasher
hash_bool = \hasher, b ->
as_u8 = if b then 1 else 0
add_u8(hasher, as_u8)
## Adds a single I8 to a hasher.
hashI8 : a, I8 -> a where a implements Hasher
hashI8 = \hasher, n -> addU8 hasher (Num.toU8 n)
hash_i8 : a, I8 -> a where a implements Hasher
hash_i8 = \hasher, n -> add_u8(hasher, Num.to_u8(n))
## Adds a single I16 to a hasher.
hashI16 : a, I16 -> a where a implements Hasher
hashI16 = \hasher, n -> addU16 hasher (Num.toU16 n)
hash_i16 : a, I16 -> a where a implements Hasher
hash_i16 = \hasher, n -> add_u16(hasher, Num.to_u16(n))
## Adds a single I32 to a hasher.
hashI32 : a, I32 -> a where a implements Hasher
hashI32 = \hasher, n -> addU32 hasher (Num.toU32 n)
hash_i32 : a, I32 -> a where a implements Hasher
hash_i32 = \hasher, n -> add_u32(hasher, Num.to_u32(n))
## Adds a single I64 to a hasher.
hashI64 : a, I64 -> a where a implements Hasher
hashI64 = \hasher, n -> addU64 hasher (Num.toU64 n)
hash_i64 : a, I64 -> a where a implements Hasher
hash_i64 = \hasher, n -> add_u64(hasher, Num.to_u64(n))
## Adds a single I128 to a hasher.
hashI128 : a, I128 -> a where a implements Hasher
hashI128 = \hasher, n -> addU128 hasher (Num.toU128 n)
hash_i128 : a, I128 -> a where a implements Hasher
hash_i128 = \hasher, n -> add_u128(hasher, Num.to_u128(n))
## Adds a single [Dec] to a hasher.
hashDec : a, Dec -> a where a implements Hasher
hashDec = \hasher, n -> hashI128 hasher (Num.withoutDecimalPoint n)
hash_dec : a, Dec -> a where a implements Hasher
hash_dec = \hasher, n -> hash_i128(hasher, Num.without_decimal_point(n))
## Adds a container of [Hash]able elements to a [Hasher] by hashing each element.
## The container is iterated using the walk method passed in.
## The order of the elements does not affect the final hash.
hashUnordered = \hasher, container, walk ->
walk
container
0
hash_unordered = \hasher, container, walk ->
walk(
container,
0,
(\accum, elem ->
x =
# Note, we intentionally copy the hasher in every iteration.
# Having the same base state is required for unordered hashing.
hasher
|> hash elem
|> hash(elem)
|> complete
nextAccum = Num.addWrap accum x
next_accum = Num.add_wrap(accum, x)
if nextAccum < accum then
if next_accum < accum then
# we don't want to lose a bit of entropy on overflow, so add it back in.
Num.addWrap nextAccum 1
Num.add_wrap(next_accum, 1)
else
nextAccum
next_accum
)
|> \accum -> addU64 hasher accum
)
|> \accum -> add_u64(hasher, accum)

View file

@ -31,8 +31,8 @@ module [
dec,
custom,
apply,
toInspector,
toStr,
to_inspector,
to_str,
]
import Bool exposing [Bool]
@ -81,24 +81,24 @@ InspectFormatter implements
Inspector f := f -> f where f implements InspectFormatter
custom : (f -> f) -> Inspector f where f implements InspectFormatter
custom = \fn -> @Inspector fn
custom = \fn -> @Inspector(fn)
apply : Inspector f, f -> f where f implements InspectFormatter
apply = \@Inspector fn, fmt -> fn fmt
apply = \@Inspector fn, fmt -> fn(fmt)
Inspect implements
toInspector : val -> Inspector f where val implements Inspect, f implements InspectFormatter
to_inspector : val -> Inspector f where val implements Inspect, f implements InspectFormatter
inspect : val -> f where val implements Inspect, f implements InspectFormatter
inspect = \val ->
(@Inspector valFn) = toInspector val
valFn (init {})
@Inspector(val_fn) = to_inspector(val)
val_fn(init({}))
toStr : val -> Str where val implements Inspect
toStr = \val ->
to_str : val -> Str where val implements Inspect
to_str = \val ->
val
|> inspect
|> toDbgStr
|> to_dbg_str
# The current default formatter for inspect.
# This just returns a simple string for debugging.
@ -106,239 +106,232 @@ toStr = \val ->
DbgFormatter := { data : Str }
implements [
InspectFormatter {
init: dbgInit,
list: dbgList,
set: dbgSet,
dict: dbgDict,
tag: dbgTag,
tuple: dbgTuple,
record: dbgRecord,
bool: dbgBool,
str: dbgStr,
opaque: dbgOpaque,
function: dbgFunction,
u8: dbgU8,
i8: dbgI8,
u16: dbgU16,
i16: dbgI16,
u32: dbgU32,
i32: dbgI32,
u64: dbgU64,
i64: dbgI64,
u128: dbgU128,
i128: dbgI128,
f32: dbgF32,
f64: dbgF64,
dec: dbgDec,
init: dbg_init,
list: dbg_list,
set: dbg_set,
dict: dbg_dict,
tag: dbg_tag,
tuple: dbg_tuple,
record: dbg_record,
bool: dbg_bool,
str: dbg_str,
opaque: dbg_opaque,
function: dbg_function,
u8: dbg_u8,
i8: dbg_i8,
u16: dbg_u16,
i16: dbg_i16,
u32: dbg_u32,
i32: dbg_i32,
u64: dbg_u64,
i64: dbg_i64,
u128: dbg_u128,
i128: dbg_i128,
f32: dbg_f32,
f64: dbg_f64,
dec: dbg_dec,
},
]
dbgInit : {} -> DbgFormatter
dbgInit = \{} -> @DbgFormatter { data: "" }
dbg_init : {} -> DbgFormatter
dbg_init = \{} -> @DbgFormatter({ data: "" })
dbgList : list, ElemWalker (DbgFormatter, Bool) list elem, (elem -> Inspector DbgFormatter) -> Inspector DbgFormatter
dbgList = \content, walkFn, toDbgInspector ->
custom \f0 ->
dbgWrite f0 "["
dbg_list : list, ElemWalker (DbgFormatter, Bool) list elem, (elem -> Inspector DbgFormatter) -> Inspector DbgFormatter
dbg_list = \content, walk_fn, to_dbg_inspector ->
custom(\f0 ->
dbg_write(f0, "[")
|> \f1 ->
walkFn content (f1, Bool.false) \(f2, prependSep), elem ->
walk_fn(content, (f1, Bool.false), (\(f2, prepend_sep), elem ->
f3 =
if prependSep then
dbgWrite f2 ", "
if prepend_sep then
dbg_write(f2, ", ")
else
f2
elem
|> toDbgInspector
|> apply f3
|> to_dbg_inspector
|> apply(f3)
|> \f4 -> (f4, Bool.true)
))
|> .0
|> dbgWrite "]"
|> dbg_write("]")
)
dbgSet : set, ElemWalker (DbgFormatter, Bool) set elem, (elem -> Inspector DbgFormatter) -> Inspector DbgFormatter
dbgSet = \content, walkFn, toDbgInspector ->
custom \f0 ->
dbgWrite f0 "{"
dbg_set : set, ElemWalker (DbgFormatter, Bool) set elem, (elem -> Inspector DbgFormatter) -> Inspector DbgFormatter
dbg_set = \content, walk_fn, to_dbg_inspector ->
custom(\f0 ->
dbg_write(f0, "{")
|> \f1 ->
walkFn content (f1, Bool.false) \(f2, prependSep), elem ->
walk_fn(content, (f1, Bool.false), (\(f2, prepend_sep), elem ->
f3 =
if prependSep then
dbgWrite f2 ", "
if prepend_sep then
dbg_write(f2, ", ")
else
f2
elem
|> toDbgInspector
|> apply f3
|> to_dbg_inspector
|> apply(f3)
|> \f4 -> (f4, Bool.true)
))
|> .0
|> dbgWrite "}"
|> dbg_write("}")
)
dbgDict : dict, KeyValWalker (DbgFormatter, Bool) dict key value, (key -> Inspector DbgFormatter), (value -> Inspector DbgFormatter) -> Inspector DbgFormatter
dbgDict = \d, walkFn, keyToInspector, valueToInspector ->
custom \f0 ->
dbgWrite f0 "{"
dbg_dict : dict, KeyValWalker (DbgFormatter, Bool) dict key value, (key -> Inspector DbgFormatter), (value -> Inspector DbgFormatter) -> Inspector DbgFormatter
dbg_dict = \d, walk_fn, key_to_inspector, value_to_inspector ->
custom(\f0 ->
dbg_write(f0, "{")
|> \f1 ->
walkFn d (f1, Bool.false) \(f2, prependSep), key, value ->
walk_fn(d, (f1, Bool.false), (\(f2, prepend_sep), key, value ->
f3 =
if prependSep then
dbgWrite f2 ", "
if prepend_sep then
dbg_write(f2, ", ")
else
f2
apply (keyToInspector key) f3
|> dbgWrite ": "
|> \x -> apply (valueToInspector value) x
apply(key_to_inspector(key), f3)
|> dbg_write(": ")
|> \x -> apply(value_to_inspector(value), x)
|> \f4 -> (f4, Bool.true)
))
|> .0
|> dbgWrite "}"
|> dbg_write("}")
)
dbgTag : Str, List (Inspector DbgFormatter) -> Inspector DbgFormatter
dbgTag = \name, fields ->
if List.isEmpty fields then
custom \f0 ->
dbgWrite f0 name
dbg_tag : Str, List (Inspector DbgFormatter) -> Inspector DbgFormatter
dbg_tag = \name, fields ->
if List.is_empty(fields) then
custom(\f0 -> dbg_write(f0, name))
else
custom \f0 ->
dbgWrite f0 "("
|> dbgWrite name
custom(\f0 ->
dbg_write(f0, "(")
|> dbg_write(name)
|> \f1 ->
List.walk fields f1 \f2, inspector ->
dbgWrite f2 " "
|> \x -> apply inspector x
|> dbgWrite ")"
List.walk(fields, f1, (\f2, inspector ->
dbg_write(f2, " ")
|> \x -> apply(inspector, x)
))
|> dbg_write(")")
)
dbgTuple : List (Inspector DbgFormatter) -> Inspector DbgFormatter
dbgTuple = \fields ->
custom \f0 ->
dbgWrite f0 "("
dbg_tuple : List (Inspector DbgFormatter) -> Inspector DbgFormatter
dbg_tuple = \fields ->
custom(\f0 ->
dbg_write(f0, "(")
|> \f1 ->
List.walk fields (f1, Bool.false) \(f2, prependSep), inspector ->
(List.walk, fields, (f1, Bool.false), (\(f2, prepend_sep), inspector ->
f3 =
if prependSep then
dbgWrite f2 ", "
if prepend_sep then
dbg_write(f2, ", ")
else
f2
apply inspector f3
apply(inspector, f3)
|> \f4 -> (f4, Bool.true)
))
|> .0
|> dbgWrite ")"
|> dbg_write(")")
)
dbgRecord : List { key : Str, value : Inspector DbgFormatter } -> Inspector DbgFormatter
dbgRecord = \fields ->
custom \f0 ->
dbgWrite f0 "{"
dbg_record : List { key : Str, value : Inspector DbgFormatter } -> Inspector DbgFormatter
dbg_record = \fields ->
custom(\f0 ->
dbg_write(f0, "{")
|> \f1 ->
List.walk fields (f1, Bool.false) \(f2, prependSep), { key, value } ->
List.walk(fields, (f1, Bool.false), (\(f2, prepend_sep), { key, value } ->
f3 =
if prependSep then
dbgWrite f2 ", "
if prepend_sep then
dbg_write(f2, ", ")
else
f2
dbgWrite f3 key
|> dbgWrite ": "
|> \x -> apply value x
dbg_write(f3, key)
|> dbg_write(": ")
|> \x -> apply(value, x)
|> \f4 -> (f4, Bool.true)
))
|> .0
|> dbgWrite "}"
|> dbg_write("}")
)
dbgBool : Bool -> Inspector DbgFormatter
dbgBool = \b ->
if b then
custom \f0 ->
dbgWrite f0 "Bool.true"
else
custom \f0 ->
dbgWrite f0 "Bool.false"
dbg_bool : Bool -> Inspector DbgFormatter
dbg_bool = \b ->
text = if b then "Bool.true" else "Bool.false"
custom(\f0 -> dbg_write(f0, text))
dbgStr : Str -> Inspector DbgFormatter
dbgStr = \s ->
custom \f0 ->
dbg_str : Str -> Inspector DbgFormatter
dbg_str = \s ->
custom(\f0 ->
f0
|> dbgWrite "\""
|> dbgWrite s # TODO: Should we be escaping strings for dbg/logging?
|> dbgWrite "\""
|> dbg_write("\"")
|> dbg_write(s) # TODO: Should we be escaping strings for dbg/logging?
|> dbg_write("\"")
)
dbgOpaque : * -> Inspector DbgFormatter
dbgOpaque = \_ ->
custom \f0 ->
dbgWrite f0 "<opaque>"
dbg_opaque : * -> Inspector DbgFormatter
dbg_opaque = \_ ->
custom(\f0 -> dbg_write(f0, "<opaque>"))
dbgFunction : * -> Inspector DbgFormatter
dbgFunction = \_ ->
custom \f0 ->
dbgWrite f0 "<function>"
dbg_function : * -> Inspector DbgFormatter
dbg_function = \_ ->
custom(\f0 -> dbg_write(f0, "<function>"))
dbgU8 : U8 -> Inspector DbgFormatter
dbgU8 = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_u8 : U8 -> Inspector DbgFormatter
dbg_u8 = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgI8 : I8 -> Inspector DbgFormatter
dbgI8 = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_i8 : I8 -> Inspector DbgFormatter
dbg_i8 = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgU16 : U16 -> Inspector DbgFormatter
dbgU16 = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_u16 : U16 -> Inspector DbgFormatter
dbg_u16 = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgI16 : I16 -> Inspector DbgFormatter
dbgI16 = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_i16 : I16 -> Inspector DbgFormatter
dbg_i16 = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgU32 : U32 -> Inspector DbgFormatter
dbgU32 = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_u32 : U32 -> Inspector DbgFormatter
dbg_u32 = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgI32 : I32 -> Inspector DbgFormatter
dbgI32 = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_i32 : I32 -> Inspector DbgFormatter
dbg_i32 = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgU64 : U64 -> Inspector DbgFormatter
dbgU64 = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_u64 : U64 -> Inspector DbgFormatter
dbg_u64 = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgI64 : I64 -> Inspector DbgFormatter
dbgI64 = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_i64 : I64 -> Inspector DbgFormatter
dbg_i64 = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgU128 : U128 -> Inspector DbgFormatter
dbgU128 = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_u128 : U128 -> Inspector DbgFormatter
dbg_u128 = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgI128 : I128 -> Inspector DbgFormatter
dbgI128 = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_i128 : I128 -> Inspector DbgFormatter
dbg_i128 = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgF32 : F32 -> Inspector DbgFormatter
dbgF32 = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_f32 : F32 -> Inspector DbgFormatter
dbg_f32 = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgF64 : F64 -> Inspector DbgFormatter
dbgF64 = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_f64 : F64 -> Inspector DbgFormatter
dbg_f64 = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgDec : Dec -> Inspector DbgFormatter
dbgDec = \num ->
custom \f0 ->
dbgWrite f0 (num |> Num.toStr)
dbg_dec : Dec -> Inspector DbgFormatter
dbg_dec = \num ->
custom(\f0 -> dbg_write(f0, Num.to_str(num)))
dbgWrite : DbgFormatter, Str -> DbgFormatter
dbgWrite = \@DbgFormatter { data }, added ->
@DbgFormatter { data: Str.concat data added }
dbg_write : DbgFormatter, Str -> DbgFormatter
dbg_write = \@DbgFormatter({ data }), added ->
@DbgFormatter({ data: Str.concat(data, added) })
toDbgStr : DbgFormatter -> Str
toDbgStr = \@DbgFormatter { data } -> data
to_dbg_str : DbgFormatter -> Str
to_dbg_str = \@DbgFormatter({ data }) -> data

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,15 +1,15 @@
module [
Result,
isOk,
isErr,
is_ok,
is_err,
map,
mapErr,
mapBoth,
map_err,
map_both,
map2,
try,
onErr,
onErr!,
withDefault,
on_err,
on_err!,
with_default,
]
import Bool exposing [Bool]
@ -20,42 +20,42 @@ Result ok err : [Ok ok, Err err]
## Returns `Bool.true` if the result indicates a success, else returns `Bool.false`
## ```roc
## Result.isOk (Ok 5)
## Result.is_ok(Ok(5))
## ```
isOk : Result ok err -> Bool
isOk = \result ->
is_ok : Result ok err -> Bool
is_ok = \result ->
when result is
Ok _ -> Bool.true
Err _ -> Bool.false
Ok(_) -> Bool.true
Err(_) -> Bool.false
## Returns `Bool.true` if the result indicates a failure, else returns `Bool.false`
## ```roc
## Result.isErr (Err "uh oh")
## Result.is_err(Err("uh oh"))
## ```
isErr : Result ok err -> Bool
isErr = \result ->
is_err : Result ok err -> Bool
is_err = \result ->
when result is
Ok _ -> Bool.false
Err _ -> Bool.true
Ok(_) -> Bool.false
Err(_) -> Bool.true
## If the result is `Ok`, returns the value it holds. Otherwise, returns
## the given default value.
## ```roc
## Result.withDefault (Ok 7) 42
## Result.withDefault (Err "uh oh") 42
## Result.with_default(Ok(7), 42)
## Result.with_default(Err("uh oh"), 42)
## ```
withDefault : Result ok err, ok -> ok
withDefault = \result, default ->
with_default : Result ok err, ok -> ok
with_default = \result, default ->
when result is
Ok value -> value
Err _ -> default
Ok(value) -> value
Err(_) -> default
## If the result is `Ok`, transforms the value it holds by running a conversion
## function on it. Then returns a new `Ok` holding the transformed value. If the
## result is `Err`, this has no effect. Use [mapErr] to transform an `Err`.
## result is `Err`, this has no effect. Use [map_err] to transform an `Err`.
## ```roc
## Result.map (Ok 12) Num.neg
## Result.map (Err "yipes!") Num.neg
## Result.map(Ok(12), Num.neg)
## Result.map(Err("yipes!"), Num.neg)
## ```
##
## Functions like `map` are common in Roc; see for example [List.map],
@ -63,73 +63,75 @@ withDefault = \result, default ->
map : Result a err, (a -> b) -> Result b err
map = \result, transform ->
when result is
Ok v -> Ok (transform v)
Err e -> Err e
Ok(v) -> Ok(transform(v))
Err(e) -> Err(e)
## If the result is `Err`, transforms the value it holds by running a conversion
## function on it. Then returns a new `Err` holding the transformed value. If
## the result is `Ok`, this has no effect. Use [map] to transform an `Ok`.
## ```roc
## Result.mapErr (Err "yipes!") Str.isEmpty
## Result.mapErr (Ok 12) Str.isEmpty
## Result.map_err(Err("yipes!"), Str.is_empty)
## Result.map_err(Ok(12), Str.is_empty)
## ```
mapErr : Result ok a, (a -> b) -> Result ok b
mapErr = \result, transform ->
map_err : Result ok a, (a -> b) -> Result ok b
map_err = \result, transform ->
when result is
Ok v -> Ok v
Err e -> Err (transform e)
Ok(v) -> Ok(v)
Err(e) -> Err(transform(e))
## Maps both the `Ok` and `Err` values of a `Result` to new values.
mapBoth : Result ok1 err1, (ok1 -> ok2), (err1 -> err2) -> Result ok2 err2
mapBoth = \result, okTransform, errTransform ->
map_both : Result ok1 err1, (ok1 -> ok2), (err1 -> err2) -> Result ok2 err2
map_both = \result, ok_transform, err_transform ->
when result is
Ok val -> Ok (okTransform val)
Err err -> Err (errTransform err)
Ok(val) -> Ok(ok_transform(val))
Err(err) -> Err(err_transform(err))
## Maps the `Ok` values of two `Result`s to a new value using a given transformation,
## or returns the first `Err` value encountered.
map2 : Result a err, Result b err, (a, b -> c) -> Result c err
map2 = \firstResult, secondResult, transform ->
when (firstResult, secondResult) is
(Ok first, Ok second) -> Ok (transform first second)
(Err err, _) -> Err err
(_, Err err) -> Err err
map2 = \first_result, second_result, transform ->
when (first_result, second_result) is
(Ok(first), Ok(second)) -> Ok(transform(first, second))
(Err(err), _) -> Err(err)
(_, Err(err)) -> Err(err)
## If the result is `Ok`, transforms the entire result by running a conversion
## function on the value the `Ok` holds. Then returns that new result. If the
## result is `Err`, this has no effect. Use `onErr` to transform an `Err`.
## result is `Err`, this has no effect. Use `on_err` to transform an `Err`.
## ```roc
## Result.try (Ok -1) \num -> if num < 0 then Err "negative!" else Ok -num
## Result.try (Err "yipes!") \num -> if num < 0 then Err "negative!" else Ok -num
## Result.try(Ok(-1), (\num -> if num < 0 then Err("negative!") else Ok(-num)))
## Result.try(Err("yipes!"), (\num -> if num < 0 then Err("negative!") else Ok(-num)))
## ```
try : Result a err, (a -> Result b err) -> Result b err
try = \result, transform ->
when result is
Ok v -> transform v
Err e -> Err e
Ok(v) -> transform(v)
Err(e) -> Err(e)
## If the result is `Err`, transforms the entire result by running a conversion
## function on the value the `Err` holds. Then returns that new result. If the
## result is `Ok`, this has no effect. Use `try` to transform an `Ok`.
## ```roc
## Result.onErr (Ok 10) \errorNum -> Str.toU64 errorNum
## Result.onErr (Err "42") \errorNum -> Str.toU64 errorNum
## Result.on_err(Ok(10), (\error_num -> Str.to_u64(error_num)))
## Result.on_err(Err("42"), (\error_num -> Str.to_u64(error_num)))
## ```
onErr : Result a err, (err -> Result a otherErr) -> Result a otherErr
onErr = \result, transform ->
on_err : Result a err, (err -> Result a other_err) -> Result a other_err
on_err = \result, transform ->
when result is
Ok v -> Ok v
Err e -> transform e
Ok(v) -> Ok(v)
Err(e) -> transform(e)
## Like [onErr], but it allows the transformation function to produce effects.
## Like [on_err], but it allows the transformation function to produce effects.
##
## ```roc
## Result.onErr (Err "missing user") \msg ->
## try Stdout.line! "ERROR: $(msg)"
## Err msg
## Result.on_err(Err("missing user"), (\msg ->
## Stdout.line!("ERROR: $(msg)")?
##
## Err(msg)
## ))
## ```
onErr! : Result a err, (err => Result a otherErr) => Result a otherErr
onErr! = \result, transform! ->
on_err! : Result a err, (err => Result a other_err) => Result a other_err
on_err! = \result, transform! ->
when result is
Ok v -> Ok v
Err e -> transform! e
Ok(v) -> Ok(v)
Err(e) -> transform!(e)

View file

@ -1,27 +1,27 @@
module [
Set,
empty,
withCapacity,
with_capacity,
reserve,
releaseExcessCapacity,
release_excess_capacity,
single,
walk,
walkUntil,
keepIf,
dropIf,
walk_until,
keep_if,
drop_if,
insert,
len,
isEmpty,
is_empty,
capacity,
remove,
contains,
toList,
fromList,
to_list,
from_list,
union,
intersection,
difference,
map,
joinMap,
join_map,
]
import List
@ -36,154 +36,154 @@ import Inspect exposing [Inspect, Inspector, InspectFormatter]
Set k := Dict.Dict k {} where k implements Hash & Eq
implements [
Eq {
isEq,
is_eq,
},
Hash {
hash: hashSet,
hash: hash_set,
},
Inspect {
toInspector: toInspectorSet,
to_inspector: to_inspector_set,
},
]
isEq : Set k, Set k -> Bool
isEq = \xs, ys ->
if len xs != len ys then
is_eq : Set k, Set k -> Bool
is_eq = \xs, ys ->
if len(xs) != len(ys) then
Bool.false
else
walkUntil xs Bool.true \_, elem ->
if contains ys elem then
Continue Bool.true
walk_until(xs, Bool.true, \_, elem ->
if contains(ys, elem) then
Continue(Bool.true)
else
Break Bool.false
Break(Bool.false))
hashSet : hasher, Set k -> hasher where hasher implements Hasher
hashSet = \hasher, @Set inner -> Hash.hash hasher inner
hash_set : hasher, Set k -> hasher where hasher implements Hasher
hash_set = \hasher, @Set(inner) -> Hash.hash(hasher, inner)
toInspectorSet : Set k -> Inspector f where k implements Inspect & Hash & Eq, f implements InspectFormatter
toInspectorSet = \set ->
Inspect.custom \fmt ->
Inspect.apply (Inspect.set set walk Inspect.toInspector) fmt
to_inspector_set : Set k -> Inspector f where k implements Inspect & Hash & Eq, f implements InspectFormatter
to_inspector_set = \set ->
Inspect.custom(\fmt ->
Inspect.apply(Inspect.set(set, walk, Inspect.to_inspector), fmt))
## Creates a new empty `Set`.
## ```roc
## emptySet = Set.empty {}
## countValues = Set.len emptySet
## empty_set = Set.empty({})
## count_values = Set.len(empty_set)
##
## expect countValues == 0
## expect count_values == 0
## ```
empty : {} -> Set *
empty = \{} -> @Set (Dict.empty {})
empty = \{} -> @Set(Dict.empty({}))
## Return a set with space allocated for a number of entries. This
## may provide a performance optimization if you know how many entries will be
## inserted.
withCapacity : U64 -> Set *
withCapacity = \cap ->
@Set (Dict.withCapacity cap)
with_capacity : U64 -> Set *
with_capacity = \cap ->
@Set(Dict.with_capacity(cap))
## Enlarge the set for at least capacity additional elements
reserve : Set k, U64 -> Set k
reserve = \@Set dict, requested ->
@Set (Dict.reserve dict requested)
reserve = \@Set(dict), requested ->
@Set(Dict.reserve(dict, requested))
## Shrink the memory footprint of a set such that capacity is as small as possible.
## This function will require regenerating the metadata if the size changes.
## There will still be some overhead due to dictionary metadata always being a power of 2.
releaseExcessCapacity : Set k -> Set k
releaseExcessCapacity = \@Set dict ->
@Set (Dict.releaseExcessCapacity dict)
release_excess_capacity : Set k -> Set k
release_excess_capacity = \@Set(dict) ->
@Set(Dict.release_excess_capacity(dict))
## Creates a new `Set` with a single value.
## ```roc
## singleItemSet = Set.single "Apple"
## countValues = Set.len singleItemSet
## single_item_set = Set.single("Apple")
## count_values = Set.len(single_item_set)
##
## expect countValues == 1
## expect count_values == 1
## ```
single : k -> Set k
single = \key ->
Dict.single key {} |> @Set
Dict.single(key, {}) |> @Set
## Insert a value into a `Set`.
## ```roc
## fewItemSet =
## Set.empty {}
## |> Set.insert "Apple"
## |> Set.insert "Pear"
## |> Set.insert "Banana"
## few_item_set =
## Set.empty({})
## |> Set.insert("Apple")
## |> Set.insert("Pear")
## |> Set.insert("Banana")
##
## countValues = Set.len fewItemSet
## count_values = Set.len(few_item_set)
##
## expect countValues == 3
## expect count_values == 3
## ```
insert : Set k, k -> Set k
insert = \@Set dict, key ->
Dict.insert dict key {} |> @Set
insert = \@Set(dict), key ->
Dict.insert(dict, key, {}) |> @Set
# Inserting a duplicate key has no effect.
expect
actual =
empty {}
|> insert "foo"
|> insert "bar"
|> insert "foo"
|> insert "baz"
empty({})
|> insert("foo")
|> insert("bar")
|> insert("foo")
|> insert("baz")
expected =
empty {}
|> insert "foo"
|> insert "bar"
|> insert "baz"
empty({})
|> insert("foo")
|> insert("bar")
|> insert("baz")
expected == actual
## Counts the number of values in a given `Set`.
## ```roc
## fewItemSet =
## Set.empty {}
## |> Set.insert "Apple"
## |> Set.insert "Pear"
## |> Set.insert "Banana"
## few_item_set =
## Set.empty({})
## |> Set.insert("Apple")
## |> Set.insert("Pear")
## |> Set.insert("Banana")
##
## countValues = Set.len fewItemSet
## count_values = Set.len(few_item_set)
##
## expect countValues == 3
## expect count_values == 3
## ```
len : Set * -> U64
len = \@Set dict ->
Dict.len dict
len = \@Set(dict) ->
Dict.len(dict)
## Returns the max number of elements the set can hold before requiring a rehash.
## ```roc
## foodSet =
## Set.empty {}
## |> Set.insert "apple"
## food_set =
## Set.empty({})
## |> Set.insert("apple")
##
## capacityOfSet = Set.capacity foodSet
## capacity_of_set = Set.capacity(food_set)
## ```
capacity : Set * -> U64
capacity = \@Set dict ->
Dict.capacity dict
capacity = \@Set(dict) ->
Dict.capacity(dict)
## Check if the set is empty.
## ```roc
## Set.isEmpty (Set.empty {} |> Set.insert 42)
## Set.is_empty(Set.empty({}) |> Set.insert(42))
##
## Set.isEmpty (Set.empty {})
## Set.is_empty(Set.empty({}))
## ```
isEmpty : Set * -> Bool
isEmpty = \@Set dict ->
Dict.isEmpty dict
is_empty : Set * -> Bool
is_empty = \@Set(dict) ->
Dict.is_empty(dict)
# Inserting a duplicate key has no effect on length.
expect
actual =
empty {}
|> insert "foo"
|> insert "bar"
|> insert "foo"
|> insert "baz"
empty({})
|> insert("foo")
|> insert("bar")
|> insert("foo")
|> insert("baz")
|> len
actual == 3
@ -191,20 +191,20 @@ expect
## Removes the value from the given `Set`.
## ```roc
## numbers =
## Set.empty {}
## |> Set.insert 10
## |> Set.insert 20
## |> Set.remove 10
## Set.empty({})
## |> Set.insert(10)
## |> Set.insert(20)
## |> Set.remove(10)
##
## has10 = Set.contains numbers 10
## has20 = Set.contains numbers 20
## has10 = Set.contains(numbers, 10)
## has20 = Set.contains(numbers, 20)
##
## expect has10 == Bool.false
## expect has20 == Bool.true
## ```
remove : Set k, k -> Set k
remove = \@Set dict, key ->
Dict.remove dict key |> @Set
remove = \@Set(dict), key ->
Dict.remove(dict, key) |> @Set
## Test if a value is in the `Set`.
## ```roc
@ -212,47 +212,47 @@ remove = \@Set dict, key ->
##
## fruit : Set Fruit
## fruit =
## Set.single Apple
## |> Set.insert Pear
## Set.single(Apple)
## |> Set.insert(Pear)
##
## hasApple = Set.contains fruit Apple
## hasBanana = Set.contains fruit Banana
## has_apple = Set.contains(fruit, Apple)
## has_banana = Set.contains(fruit, Banana)
##
## expect hasApple == Bool.true
## expect hasBanana == Bool.false
## expect has_apple == Bool.true
## expect has_banana == Bool.false
## ```
contains : Set k, k -> Bool
contains = \@Set dict, key ->
Dict.contains dict key
contains = \@Set(dict), key ->
Dict.contains(dict, key)
## Retrieve the values in a `Set` as a `List`.
## ```roc
## numbers : Set U64
## numbers = Set.fromList [1,2,3,4,5]
## numbers = Set.from_list([1,2,3,4,5])
##
## values = [1,2,3,4,5]
##
## expect Set.toList numbers == values
## expect Set.to_list(numbers) == values
## ```
toList : Set k -> List k
toList = \@Set dict ->
Dict.keys dict
to_list : Set k -> List k
to_list = \@Set(dict) ->
Dict.keys(dict)
## Create a `Set` from a `List` of values.
## ```roc
## values =
## Set.empty {}
## |> Set.insert Banana
## |> Set.insert Apple
## |> Set.insert Pear
## Set.empty({})
## |> Set.insert(Banana)
## |> Set.insert(Apple)
## |> Set.insert(Pear)
##
## expect Set.fromList [Pear, Apple, Banana] == values
## expect Set.from_list([Pear, Apple, Banana]) == values
## ```
fromList : List k -> Set k
fromList = \list ->
from_list : List k -> Set k
from_list = \list ->
list
|> List.map \k -> (k, {})
|> Dict.fromList
|> List.map(\k -> (k, {}))
|> Dict.from_list
|> @Set
## Combine two `Set` collection by keeping the
@ -260,234 +260,234 @@ fromList = \list ->
## of all the values pairs. This means that all of the values in both `Set`s
## will be combined.
## ```roc
## set1 = Set.single Left
## set2 = Set.single Right
## set1 = Set.single(Left)
## set2 = Set.single(Right)
##
## expect Set.union set1 set2 == Set.fromList [Left, Right]
## expect Set.union(set1, set2) == Set.from_list([Left, Right])
## ```
union : Set k, Set k -> Set k
union = \@Set dict1, @Set dict2 ->
Dict.insertAll dict1 dict2 |> @Set
union = \@Set(dict1), @Set(dict2) ->
Dict.insert_all(dict1, dict2) |> @Set
## Combine two `Set`s by keeping the [intersection](https://en.wikipedia.org/wiki/Intersection_(set_theory))
## of all the values pairs. This means that we keep only those values that are
## in both `Set`s.
## ```roc
## set1 = Set.fromList [Left, Other]
## set2 = Set.fromList [Left, Right]
## set1 = Set.from_list([Left, Other])
## set2 = Set.from_list([Left, Right])
##
## expect Set.intersection set1 set2 == Set.single Left
## expect Set.intersection(set1, set2) == Set.single(Left)
## ```
intersection : Set k, Set k -> Set k
intersection = \@Set dict1, @Set dict2 ->
Dict.keepShared dict1 dict2 |> @Set
intersection = \@Set(dict1), @Set(dict2) ->
Dict.keep_shared(dict1, dict2) |> @Set
## Remove the values in the first `Set` that are also in the second `Set`
## using the [set difference](https://en.wikipedia.org/wiki/Complement_(set_theory)#Relative_complement)
## of the values. This means that we will be left with only those values that
## are in the first and not in the second.
## ```roc
## first = Set.fromList [Left, Right, Up, Down]
## second = Set.fromList [Left, Right]
## first = Set.from_list([Left, Right, Up, Down])
## second = Set.from_list([Left, Right])
##
## expect Set.difference first second == Set.fromList [Up, Down]
## expect Set.difference(first, second) == Set.from_list([Up, Down])
## ```
difference : Set k, Set k -> Set k
difference = \@Set dict1, @Set dict2 ->
Dict.removeAll dict1 dict2 |> @Set
difference = \@Set(dict1), @Set(dict2) ->
Dict.remove_all(dict1, dict2) |> @Set
## Iterate through the values of a given `Set` and build a value.
## ```roc
## values = Set.fromList ["March", "April", "May"]
## values = Set.from_list(["March", "April", "May"])
##
## startsWithLetterM = \month ->
## when Str.toUtf8 month is
## starts_with_letter_m = \month ->
## when Str.to_utf8(month) is
## ['M', ..] -> Bool.true
## _ -> Bool.false
##
## reduce = \state, k ->
## if startsWithLetterM k then
## if starts_with_letter_m(k) then
## state + 1
## else
## state
##
## result = Set.walk values 0 reduce
## result = Set.walk(values, 0, reduce)
##
## expect result == 2
## ```
walk : Set k, state, (state, k -> state) -> state
walk = \@Set dict, state, step ->
Dict.walk dict state (\s, k, _ -> step s k)
walk = \@Set(dict), state, step ->
Dict.walk(dict, state, \s, k, _ -> step(s, k))
## Convert each value in the set to something new, by calling a conversion
## function on each of them which receives the old value. Then return a
## new set containing the converted values.
map : Set a, (a -> b) -> Set b
map = \set, transform ->
init = withCapacity (capacity set)
init = with_capacity(capacity(set))
walk set init \answer, k ->
insert answer (transform k)
walk(set, init, \answer, k ->
insert(answer, transform(k)))
## Like [Set.map], except the transformation function wraps the return value
## in a set. At the end, all the sets get joined together
## (using [Set.union]) into one set.
##
## You may know a similar function named `concatMap` in other languages.
joinMap : Set a, (a -> Set b) -> Set b
joinMap = \set, transform ->
init = withCapacity (capacity set) # Might be a pessimization
## You may know a similar function named `concat_map` in other languages.
join_map : Set a, (a -> Set b) -> Set b
join_map = \set, transform ->
init = with_capacity(capacity(set)) # Might be a pessimization
walk set init \answer, k ->
union answer (transform k)
walk(set, init, \answer, k ->
union(answer, transform(k)))
## Iterate through the values of a given `Set` and build a value, can stop
## iterating part way through the collection.
## ```roc
## numbers = Set.fromList [1,2,3,4,5,6,42,7,8,9,10]
## numbers = Set.from_list([1,2,3,4,5,6,42,7,8,9,10])
##
## find42 = \state, k ->
## if k == 42 then
## Break FoundTheAnswer
## Break(FoundTheAnswer)
## else
## Continue state
## Continue(state)
##
## result = Set.walkUntil numbers NotFound find42
## result = Set.walk_until(numbers, NotFound, find42)
##
## expect result == FoundTheAnswer
## ```
walkUntil : Set k, state, (state, k -> [Continue state, Break state]) -> state
walkUntil = \@Set dict, state, step ->
Dict.walkUntil dict state (\s, k, _ -> step s k)
walk_until : Set k, state, (state, k -> [Continue state, Break state]) -> state
walk_until = \@Set(dict), state, step ->
Dict.walk_until(dict, state, \s, k, _ -> step(s, k))
## Run the given function on each element in the `Set`, and return
## a `Set` with just the elements for which the function returned `Bool.true`.
## ```roc
## expect Set.fromList [1,2,3,4,5]
## |> Set.keepIf \k -> k >= 3
## |> Bool.isEq (Set.fromList [3,4,5])
## expect Set.from_list([1,2,3,4,5])
## |> Set.keep_if(\k -> k >= 3)
## |> Bool.is_eq(Set.from_list([3,4,5]))
## ```
keepIf : Set k, (k -> Bool) -> Set k
keepIf = \@Set dict, predicate ->
@Set (Dict.keepIf dict (\(k, _v) -> predicate k))
keep_if : Set k, (k -> Bool) -> Set k
keep_if = \@Set(dict), predicate ->
@Set(Dict.keep_if(dict, \(k, _v) -> predicate(k)))
## Run the given function on each element in the `Set`, and return
## a `Set` with just the elements for which the function returned `Bool.false`.
## ```roc
## expect Set.fromList [1,2,3,4,5]
## |> Set.dropIf \k -> k >= 3
## |> Bool.isEq (Set.fromList [1,2])
## expect Set.from_list [1,2,3,4,5]
## |> Set.drop_if(\k -> k >= 3)
## |> Bool.is_eq(Set.from_list([1,2]))
## ```
dropIf : Set k, (k -> Bool) -> Set k
dropIf = \@Set dict, predicate ->
@Set (Dict.dropIf dict (\(k, _v) -> predicate k))
drop_if : Set k, (k -> Bool) -> Set k
drop_if = \@Set(dict), predicate ->
@Set(Dict.drop_if(dict, \(k, _v) -> predicate(k)))
expect
first =
single "Keep Me"
|> insert "And Me"
|> insert "Remove Me"
single("Keep Me")
|> insert("And Me")
|> insert("Remove Me")
second =
single "Remove Me"
|> insert "I do nothing..."
single("Remove Me")
|> insert("I do nothing...")
expected =
single "Keep Me"
|> insert "And Me"
single("Keep Me")
|> insert("And Me")
difference first second == expected
difference(first, second) == expected
expect
first =
single "Keep Me"
|> insert "And Me"
|> insert "Remove Me"
single("Keep Me")
|> insert("And Me")
|> insert("Remove Me")
second =
single "Remove Me"
|> insert "I do nothing..."
single("Remove Me")
|> insert("I do nothing...")
expected =
single "Keep Me"
|> insert "And Me"
single("Keep Me")
|> insert("And Me")
difference first second == expected
difference(first, second) == expected
expect
first =
single 1
|> insert 2
single(1)
|> insert(2)
second =
single 1
|> insert 3
|> insert 4
single(1)
|> insert(3)
|> insert(4)
expected =
single 1
|> insert 2
|> insert 3
|> insert 4
single(1)
|> insert(2)
|> insert(3)
|> insert(4)
union first second == expected
union(first, second) == expected
expect
base =
single "Remove Me"
|> insert "Keep Me"
|> insert "And Me"
single("Remove Me")
|> insert("Keep Me")
|> insert("And Me")
expected =
single "Keep Me"
|> insert "And Me"
single("Keep Me")
|> insert("And Me")
remove base "Remove Me" == expected
remove(base, "Remove Me") == expected
expect
x =
single 0
|> insert 1
|> insert 2
|> insert 3
|> insert 4
|> insert 5
|> insert 6
|> insert 7
|> insert 8
|> insert 9
single(0)
|> insert(1)
|> insert(2)
|> insert(3)
|> insert(4)
|> insert(5)
|> insert(6)
|> insert(7)
|> insert(8)
|> insert(9)
x == fromList (toList x)
x == from_list(to_list(x))
expect
orderOne : Set U64
orderOne =
single 1
|> insert 2
order_one : Set U64
order_one =
single(1)
|> insert(2)
orderTwo : Set U64
orderTwo =
single 2
|> insert 1
order_two : Set U64
order_two =
single(2)
|> insert(1)
wrapperOne : Set (Set U64)
wrapperOne =
single orderOne
|> insert orderTwo
wrapper_one : Set (Set U64)
wrapper_one =
single(order_one)
|> insert(order_two)
wrapperTwo : Set (Set U64)
wrapperTwo =
single orderTwo
|> insert orderOne
wrapper_two : Set (Set U64)
wrapper_two =
single(order_two)
|> insert(order_one)
wrapperOne == wrapperTwo
wrapper_one == wrapper_two
expect
Set.fromList [1, 2, 3, 4, 5]
|> Set.keepIf \k -> k >= 3
|> Bool.isEq (Set.fromList [3, 4, 5])
Set.from_list([1, 2, 3, 4, 5])
|> Set.keep_if(\k -> k >= 3)
|> Bool.is_eq(Set.from_list([3, 4, 5]))
expect
Set.fromList [1, 2, 3, 4, 5]
|> Set.dropIf \k -> k >= 3
|> Bool.isEq (Set.fromList [1, 2])
Set.from_list([1, 2, 3, 4, 5])
|> Set.drop_if(\k -> k >= 3)
|> Bool.is_eq(Set.from_list([1, 2]))

File diff suppressed because it is too large Load diff

View file

@ -4,16 +4,16 @@ module [
err,
await,
map,
mapErr,
onErr,
map_err,
on_err,
attempt,
forever,
loop,
fromResult,
from_result,
batch,
combine,
sequence,
forEach,
for_each,
result,
]
@ -26,61 +26,62 @@ Task ok err := {} -> Result ok err
## Run a task repeatedly, until it fails with `err`. Note that this task does not return a success value.
forever : Task a err -> Task * err
forever = \@Task task ->
forever = \@Task(task) ->
looper = \{} ->
when task {} is
Err e -> Err e
Ok _ -> looper {}
when task({}) is
Err(e) -> Err(e)
Ok(_) -> looper({})
@Task \{} -> looper {}
@Task(\{} -> looper({}))
## Run a task repeatedly, until it fails with `err` or completes with `done`.
##
## ```
## sum =
## Task.loop! 0 \total ->
## numResult =
## Task.loop!(0, \total ->
## num_result =
## Stdin.line
## |> Task.result!
## |> Result.try Str.toU64
## |> Result.try(Str.toU64)
##
## when numResult is
## Ok num -> Task.ok (Step (total + num))
## Err (StdinErr EndOfFile) -> Task.ok (Done total)
## Err InvalidNumStr -> Task.err NonNumberGiven
## when num_result is
## Ok num -> Task.ok(Step(total + num))
## Err(StdinErr(EndOfFile)) -> Task.ok(Done(total))
## Err(InvalidNumStr) -> Task.err(NonNumberGiven)
## )
## ```
loop : state, (state -> Task [Step state, Done done] err) -> Task done err
loop = \state, step ->
looper = \current ->
(@Task next) = step current
when next {} is
Err e -> Err e
Ok (Done newResult) -> Ok newResult
Ok (Step newState) -> looper (newState)
@Task(next) = step(current)
when next({}) is
Err(e) -> Err(e)
Ok(Done(new_result)) -> Ok(new_result)
Ok(Step(new_state)) -> looper(new_state)
@Task \{} -> looper state
@Task(\{} -> looper(state))
## Create a task that always succeeds with the value provided.
##
## ```
## # Always succeeds with "Louis"
## getName : Task.Task Str *
## getName = Task.ok "Louis"
## get_name : Task.Task Str *
## get_name = Task.ok("Louis")
## ```
##
ok : a -> Task a *
ok = \a -> @Task \{} -> Ok a
ok = \a -> @Task(\{} -> Ok(a))
## Create a task that always fails with the error provided.
##
## ```
## # Always fails with the tag `CustomError Str`
## customError : Str -> Task.Task {} [CustomError Str]
## customError = \err -> Task.err (CustomError err)
## customError = \err -> Task.err(CustomError(err))
## ```
##
err : a -> Task * a
err = \a -> @Task \{} -> Err a
err = \a -> @Task(\{} -> Err(a))
## Transform a given Task with a function that handles the success or error case
## and returns another task based on that. This is useful for chaining tasks
@ -88,105 +89,107 @@ err = \a -> @Task \{} -> Err a
##
## Consider the following task:
##
## `canFail : Task {} [Failure, AnotherFail, YetAnotherFail]`
## `can_fail : Task {} [Failure, AnotherFail, YetAnotherFail]`
##
## We can use [attempt] to handle the failure cases using the following:
##
## ```
## Task.attempt canFail \result ->
## Task.attempt(can_fail, \result ->
## when result is
## Ok Success -> Stdout.line "Success!"
## Err Failure -> Stdout.line "Oops, failed!"
## Err AnotherFail -> Stdout.line "Ooooops, another failure!"
## Err YetAnotherFail -> Stdout.line "Really big oooooops, yet again!"
## Ok(Success) -> Stdout.line("Success!")
## Err(Failure) -> Stdout.line("Oops, failed!")
## Err(AnotherFail) -> Stdout.line("Ooooops, another failure!")
## Err(YetAnotherFail) -> Stdout.line("Really big oooooops, yet again!")
## )
## ```
##
## Here we know that the `canFail` task may fail, and so we use
## Here we know that the `can_fail` task may fail, and so we use
## `Task.attempt` to convert the task to a `Result` and then use pattern
## matching to handle the success and possible failure cases.
attempt : Task a b, (Result a b -> Task c d) -> Task c d
attempt = \@Task task, transform ->
@Task \{} ->
(@Task transformed) = transform (task {})
attempt = \@Task(task), transform ->
@Task(\{} ->
@Task(transformed) = transform(task({}))
transformed {}
transformed({}))
## Take the success value from a given [Task] and use that to generate a new [Task].
##
## We can [await] Task results with callbacks:
##
## ```
## Task.await (Stdin.line "What's your name?") \name ->
## Stdout.line "Your name is: $(name)"
## Task.await(Stdin.line("What's your name?")), \name ->
## Stdout.line("Your name is: $(name)")
## )
## ```
##
## Or we can more succinctly use the `!` bang operator, which desugars to [await]:
##
## ```
## name = Stdin.line! "What's your name?"
## Stdout.line "Your name is: $(name)"
## name = Stdin.line!("What's your name?")
## Stdout.line("Your name is: $(name)")
## ```
await : Task a b, (a -> Task c b) -> Task c b
await = \@Task task, transform ->
@Task \{} ->
when task {} is
Ok a ->
(@Task transformed) = transform a
transformed {}
await = \@Task(task), transform ->
@Task(\{} ->
when task({}) is
Ok(a) ->
@Task(transformed) = transform(a)
transformed({})
Err b ->
Err b
Err(b) ->
Err(b))
## Take the error value from a given [Task] and use that to generate a new [Task].
##
## ```
## # Prints "Something went wrong!" to standard error if `canFail` fails.
## canFail
## |> Task.onErr \_ -> Stderr.line "Something went wrong!"
## # Prints "Something went wrong!" to standard error if `can_fail` fails.
## can_fail
## |> Task.on_err(\_ -> Stderr.line("Something went wrong!"))
## ```
onErr : Task a b, (b -> Task a c) -> Task a c
onErr = \@Task task, transform ->
@Task \{} ->
when task {} is
Ok a ->
Ok a
on_err : Task a b, (b -> Task a c) -> Task a c
on_err = \@Task(task), transform ->
@Task(\{} ->
when task({}) is
Ok(a) ->
Ok(a)
Err b ->
(@Task transformed) = transform b
transformed {}
Err(b) ->
@Task(transformed) = transform(b)
transformed({}))
## Transform the success value of a given [Task] with a given function.
##
## ```
## # Succeeds with a value of "Bonjour Louis!"
## Task.ok "Louis"
## |> Task.map (\name -> "Bonjour $(name)!")
## Task.ok("Louis")
## |> Task.map(\name -> "Bonjour $(name)!")
## ```
map : Task a c, (a -> b) -> Task b c
map = \@Task task, transform ->
@Task \{} ->
when task {} is
Ok a -> Ok (transform a)
Err b -> Err b
map = \@Task(task), transform ->
@Task(\{} ->
when task({}) is
Ok(a) -> Ok(transform(a))
Err(b) -> Err(b))
## Transform the error value of a given [Task] with a given function.
##
## ```
## # Ignore the fail value, and map it to the tag `CustomError`
## canFail
## |> Task.mapErr \_ -> CustomError
## can_fail
## |> Task.map_err(\_ -> CustomError)
## ```
mapErr : Task c a, (a -> b) -> Task c b
mapErr = \@Task task, transform ->
@Task \{} ->
when task {} is
Ok a -> Ok a
Err b -> Err (transform b)
map_err : Task c a, (a -> b) -> Task c b
map_err = \@Task(task), transform ->
@Task(\{} ->
when task({}) is
Ok(a) -> Ok(a)
Err(b) -> Err(transform(b)))
## Use a Result among other Tasks by converting it into a [Task].
fromResult : Result a b -> Task a b
fromResult = \res ->
@Task \{} -> res
from_result : Result a b -> Task a b
from_result = \res ->
@Task(\{} -> res)
## Apply a task to another task applicatively.
##
@ -194,8 +197,8 @@ fromResult = \res ->
batch : Task a c -> (Task (a -> b) c -> Task b c)
batch = \current ->
\next ->
await next \f ->
map current f
await(next, \f ->
map(current, f))
## Combine the values of two tasks with a custom combining function.
##
@ -204,54 +207,54 @@ batch = \current ->
## ```
## { a, b, c } =
## { Task.combine <-
## a: Task.ok 123,
## b: File.read "file.txt",
## c: Http.get "http://api.com/",
## a: Task.ok(123),
## b: File.read("file.txt"),
## c: Http.get("http://api.com/"),
## }!
## ```
combine : Task a err, Task b err, (a, b -> c) -> Task c err
combine = \@Task leftTask, @Task rightTask, combiner ->
@Task \{} ->
left = try leftTask {}
right = try rightTask {}
combine = \@Task(left_task), @Task(right_task), combiner ->
@Task(\{} ->
left = try(left_task, {})
right = try(right_task, {})
Ok (combiner left right)
Ok(combiner(left, right)))
## Apply each task in a list sequentially, and return a list of the resulting values.
## Each task will be awaited before beginning the next task.
##
## ```
## fetchAuthorTasks : List (Task Author [DbError])
## fetch_author_tasks : List (Task Author [DbError])
##
## getAuthors : Task (List Author) [DbError]
## getAuthors = Task.sequence fetchAuthorTasks
## get_authors : Task (List Author) [DbError]
## get_authors = Task.sequence(fetch_author_tasks)
## ```
##
sequence : List (Task ok err) -> Task (List ok) err
sequence = \taskList ->
Task.loop (taskList, List.withCapacity (List.len taskList)) \(tasks, values) ->
sequence = \task_list ->
Task.loop((task_list, List.with_capacity(List.len(task_list))), \(tasks, values) ->
when tasks is
[task, .. as rest] ->
Task.map task \value ->
Step (rest, List.append values value)
Task.map(task, \value ->
Step((rest, List.append(values, value))))
[] ->
Task.ok (Done values)
Task.ok(Done(values)))
## Apply a task repeatedly for each item in a list
##
## ```
## authors : List Author
## saveAuthor : Author -> Task {} [DbError]
## save_author : Author -> Task {} [DbError]
##
## saveAuthors : Task (List Author) [DbError]
## saveAuthors = Task.forEach authors saveAuthor
## save_authors : Task (List Author) [DbError]
## save_authors = Task.for_each(authors, save_author)
## ```
##
forEach : List a, (a -> Task {} b) -> Task {} b
forEach = \items, fn ->
List.walk items (ok {}) \state, item ->
state |> await \_ -> fn item
for_each : List a, (a -> Task {} b) -> Task {} b
for_each = \items, fn ->
List.walk(items, ok({}), \state, item ->
state |> await(\_ -> fn(item)))
## Transform a task that can either succeed with `ok`, or fail with `err`, into
## a task that succeeds with `Result ok err`.
@ -260,16 +263,16 @@ forEach = \items, fn ->
##
## ```
## # Path.roc
## checkFile : Str -> Task [Good, Bad] [IOError]
## check_file : Str -> Task [Good, Bad] [IOError]
##
## # main.roc
## when checkFile "/usr/local/bin/roc" |> Task.result! is
## Ok Good -> "..."
## Ok Bad -> "..."
## Err IOError -> "..."
## when check_file("/usr/local/bin/roc") |> Task.result! is
## Ok(Good) -> "..."
## Ok(Bad) -> "..."
## Err(IOError) -> "..."
## ```
##
result : Task ok err -> Task (Result ok err) *
result = \@Task task ->
@Task \{} ->
Ok (task {})
result = \@Task(task) ->
@Task(\{} ->
Ok(task({})))

View file

@ -1,4 +1,5 @@
use std::{fmt::Debug, mem::ManuallyDrop};
use std::borrow::Cow;
/// Collection of small (length < u16::MAX) strings, stored compactly.
#[derive(Clone, Default, PartialEq, Eq)]
@ -113,6 +114,7 @@ impl SmallStringInterner {
/// Insert without deduplicating
pub fn insert(&mut self, string: &str) -> usize {
let string = Self::snakify_ident(string);
let bytes = string.as_bytes();
assert!(bytes.len() < (1 << 15));
@ -175,6 +177,7 @@ impl SmallStringInterner {
pub fn find_indices<'a>(&'a self, string: &'a str) -> impl Iterator<Item = usize> + 'a {
use std::slice::from_raw_parts;
let string = Self::snakify_ident(string);
let target_length = string.len();
let lengths: &[i16] =
@ -226,6 +229,7 @@ impl SmallStringInterner {
}
pub fn update(&mut self, index: usize, new_string: &str) {
let new_string = Self::snakify_ident(new_string);
let length = new_string.len();
let offset = self.buffer.len();
@ -240,7 +244,8 @@ impl SmallStringInterner {
pub fn find_and_update(&mut self, old_string: &str, new_string: &str) -> Option<usize> {
match self.find_index(old_string) {
Some(index) => {
self.update(index, new_string);
let new_string = Self::snakify_ident(new_string);
self.update(index, &new_string);
Some(index)
}
@ -255,6 +260,52 @@ impl SmallStringInterner {
pub fn is_empty(&self) -> bool {
self.lengths.is_empty()
}
fn snakify_ident(s: &str) -> Cow<'_, str> {
if s.chars()
.next()
.is_some_and(|first_char| first_char.is_ascii_uppercase())
|| (s.contains('_') && !s.ends_with('_'))
{
return s.into();
}
let chars: Vec<char> = s.chars().collect();
let mut index = 0;
let len = chars.len();
let mut out = String::new();
while index < len {
let prev = if index == 0 {
None
} else {
Some(chars[index - 1])
};
let c = chars[index];
let next = chars.get(index + 1);
let boundary = match (prev, c, next) {
// LUU, LUN, and LUL (simplified to LU_)
(Some(p), curr, _) if !p.is_ascii_uppercase() && curr.is_ascii_uppercase() => true,
// UUL
(Some(p), curr, Some(n))
if p.is_ascii_uppercase()
&& curr.is_ascii_uppercase()
&& n.is_ascii_lowercase() =>
{
true
}
_ => false,
};
// those are boundary transitions - should push _ and curr
if boundary {
out.push('_');
}
out.push(c.to_ascii_lowercase());
index += 1;
}
out.into()
}
}
#[allow(dead_code)]

View file

@ -29,6 +29,8 @@ const MODULES: &[(ModuleId, &str)] = &[
];
fn main() {
panic!("Fail now to avoid infinite loading.");
for (module_id, filename) in MODULES {
write_subs_for_module(*module_id, filename);
}

View file

@ -1195,45 +1195,45 @@ define_builtins! {
12 NUM_F64: "F64" exposed_type=true // the Num.F64 type alias
13 NUM_F32: "F32" exposed_type=true // the Num.F32 type alias
14 NUM_FLOATINGPOINT: "FloatingPoint" exposed_type=true // Float : Num FloatingPoint
15 NUM_MAX_F32: "maxF32"
16 NUM_MIN_F32: "minF32"
15 NUM_MAX_F32: "max_f32"
16 NUM_MIN_F32: "min_f32"
17 NUM_ABS: "abs"
18 NUM_NEG: "neg"
19 NUM_ADD: "add"
20 NUM_SUB: "sub"
21 NUM_MUL: "mul"
22 NUM_LT: "isLt"
23 NUM_LTE: "isLte"
24 NUM_GT: "isGt"
25 NUM_GTE: "isGte"
26 NUM_TO_FRAC: "toFrac"
22 NUM_LT: "is_lt"
23 NUM_LTE: "is_lte"
24 NUM_GT: "is_gt"
25 NUM_GTE: "is_gte"
26 NUM_TO_FRAC: "to_frac"
27 NUM_SIN: "sin"
28 NUM_COS: "cos"
29 NUM_TAN: "tan"
30 NUM_IS_ZERO: "isZero"
31 NUM_IS_EVEN: "isEven"
32 NUM_IS_ODD: "isOdd"
33 NUM_IS_POSITIVE: "isPositive"
34 NUM_IS_NEGATIVE: "isNegative"
30 NUM_IS_ZERO: "is_zero"
31 NUM_IS_EVEN: "is_even"
32 NUM_IS_ODD: "is_odd"
33 NUM_IS_POSITIVE: "is_positive"
34 NUM_IS_NEGATIVE: "is_negative"
35 NUM_REM: "rem"
36 NUM_REM_CHECKED: "remChecked"
36 NUM_REM_CHECKED: "rem_checked"
37 NUM_DIV_FRAC: "div"
38 NUM_DIV_FRAC_CHECKED: "divChecked"
39 NUM_DIV_TRUNC: "divTrunc"
40 NUM_DIV_TRUNC_CHECKED: "divTruncChecked"
38 NUM_DIV_FRAC_CHECKED: "div_checked"
39 NUM_DIV_TRUNC: "div_trunc"
40 NUM_DIV_TRUNC_CHECKED: "div_trunc_checked"
41 NUM_SQRT: "sqrt"
42 NUM_SQRT_CHECKED: "sqrtChecked"
42 NUM_SQRT_CHECKED: "sqrt_checked"
43 NUM_LOG: "log"
44 NUM_LOG_CHECKED: "logChecked"
44 NUM_LOG_CHECKED: "log_checked"
45 NUM_ROUND: "round"
46 NUM_COMPARE: "compare"
47 NUM_POW: "pow"
48 NUM_CEILING: "ceiling"
49 NUM_POW_INT: "powInt"
49 NUM_POW_INT: "pow_int"
50 NUM_FLOOR: "floor"
51 NUM_ADD_WRAP: "addWrap"
52 NUM_ADD_CHECKED: "addChecked"
53 NUM_ADD_SATURATED: "addSaturated"
51 NUM_ADD_WRAP: "add_wrap"
52 NUM_ADD_CHECKED: "add_checked"
53 NUM_ADD_SATURATED: "add_saturated"
54 NUM_ATAN: "atan"
55 NUM_ACOS: "acos"
56 NUM_ASIN: "asin"
@ -1249,107 +1249,107 @@ define_builtins! {
66 NUM_UNSIGNED8: "Unsigned8" exposed_type=true
67 NUM_BINARY64: "Binary64" exposed_type=true
68 NUM_BINARY32: "Binary32" exposed_type=true
69 NUM_BITWISE_AND: "bitwiseAnd"
70 NUM_BITWISE_XOR: "bitwiseXor"
71 NUM_BITWISE_OR: "bitwiseOr"
72 NUM_SHIFT_LEFT: "shiftLeftBy"
73 NUM_SHIFT_RIGHT: "shiftRightBy"
74 NUM_SHIFT_RIGHT_ZERO_FILL: "shiftRightZfBy"
75 NUM_SUB_WRAP: "subWrap"
76 NUM_SUB_CHECKED: "subChecked"
77 NUM_SUB_SATURATED: "subSaturated"
78 NUM_MUL_WRAP: "mulWrap"
79 NUM_MUL_CHECKED: "mulChecked"
80 NUM_MUL_SATURATED: "mulSaturated"
69 NUM_BITWISE_AND: "bitwise_and"
70 NUM_BITWISE_XOR: "bitwise_xor"
71 NUM_BITWISE_OR: "bitwise_or"
72 NUM_SHIFT_LEFT: "shift_left_by"
73 NUM_SHIFT_RIGHT: "shift_right_by"
74 NUM_SHIFT_RIGHT_ZERO_FILL: "shift_right_zf_by"
75 NUM_SUB_WRAP: "sub_wrap"
76 NUM_SUB_CHECKED: "sub_checked"
77 NUM_SUB_SATURATED: "sub_saturated"
78 NUM_MUL_WRAP: "mul_wrap"
79 NUM_MUL_CHECKED: "mul_checked"
80 NUM_MUL_SATURATED: "mul_saturated"
81 NUM_INT: "Int" exposed_type=true
82 NUM_FRAC: "Frac" exposed_type=true
83 NUM_E: "e"
84 NUM_PI: "pi"
85 NUM_TAU: "tau"
86 NUM_IS_MULTIPLE_OF: "isMultipleOf"
86 NUM_IS_MULTIPLE_OF: "is_multiple_of"
87 NUM_DECIMAL: "Decimal" exposed_type=true
88 NUM_DEC: "Dec" exposed_type=true // the Num.Dectype alias
89 NUM_COUNT_ONE_BITS: "countOneBits"
90 NUM_ABS_DIFF: "absDiff"
91 NUM_IS_NAN: "isNaN"
92 NUM_IS_INFINITE: "isInfinite"
93 NUM_IS_FINITE: "isFinite"
94 NUM_COUNT_LEADING_ZERO_BITS: "countLeadingZeroBits"
95 NUM_COUNT_TRAILING_ZERO_BITS: "countTrailingZeroBits"
96 NUM_TO_STR: "toStr"
97 NUM_MIN_I8: "minI8"
98 NUM_MAX_I8: "maxI8"
99 NUM_MIN_U8: "minU8"
100 NUM_MAX_U8: "maxU8"
101 NUM_MIN_I16: "minI16"
102 NUM_MAX_I16: "maxI16"
103 NUM_MIN_U16: "minU16"
104 NUM_MAX_U16: "maxU16"
105 NUM_MIN_I32: "minI32"
106 NUM_MAX_I32: "maxI32"
107 NUM_MIN_U32: "minU32"
108 NUM_MAX_U32: "maxU32"
109 NUM_MIN_I64: "minI64"
110 NUM_MAX_I64: "maxI64"
111 NUM_MIN_U64: "minU64"
112 NUM_MAX_U64: "maxU64"
113 NUM_MIN_I128: "minI128"
114 NUM_MAX_I128: "maxI128"
115 NUM_MIN_U128: "minU128"
116 NUM_MAX_U128: "maxU128"
117 NUM_TO_I8: "toI8"
118 NUM_TO_I8_CHECKED: "toI8Checked"
119 NUM_TO_I16: "toI16"
120 NUM_TO_I16_CHECKED: "toI16Checked"
121 NUM_TO_I32: "toI32"
122 NUM_TO_I32_CHECKED: "toI32Checked"
123 NUM_TO_I64: "toI64"
124 NUM_TO_I64_CHECKED: "toI64Checked"
125 NUM_TO_I128: "toI128"
126 NUM_TO_I128_CHECKED: "toI128Checked"
127 NUM_TO_U8: "toU8"
128 NUM_TO_U8_CHECKED: "toU8Checked"
129 NUM_TO_U16: "toU16"
130 NUM_TO_U16_CHECKED: "toU16Checked"
131 NUM_TO_U32: "toU32"
132 NUM_TO_U32_CHECKED: "toU32Checked"
133 NUM_TO_U64: "toU64"
134 NUM_TO_U64_CHECKED: "toU64Checked"
135 NUM_TO_U128: "toU128"
136 NUM_TO_U128_CHECKED: "toU128Checked"
137 NUM_DIV_CEIL: "divCeil"
138 NUM_DIV_CEIL_CHECKED: "divCeilChecked"
139 NUM_TO_F32: "toF32"
140 NUM_TO_F32_CHECKED: "toF32Checked"
141 NUM_TO_F64: "toF64"
142 NUM_TO_F64_CHECKED: "toF64Checked"
143 NUM_MAX_F64: "maxF64"
144 NUM_MIN_F64: "minF64"
145 NUM_ADD_CHECKED_LOWLEVEL: "addCheckedLowlevel"
146 NUM_SUB_CHECKED_LOWLEVEL: "subCheckedLowlevel"
147 NUM_MUL_CHECKED_LOWLEVEL: "mulCheckedLowlevel"
89 NUM_COUNT_ONE_BITS: "count_one_bits"
90 NUM_ABS_DIFF: "abs_diff"
91 NUM_IS_NAN: "is_nan"
92 NUM_IS_INFINITE: "is_infinite"
93 NUM_IS_FINITE: "is_finite"
94 NUM_COUNT_LEADING_ZERO_BITS: "count_leading_zero_bits"
95 NUM_COUNT_TRAILING_ZERO_BITS: "count_trailing_zero_bits"
96 NUM_TO_STR: "to_str"
97 NUM_MIN_I8: "min_i8"
98 NUM_MAX_I8: "max_i8"
99 NUM_MIN_U8: "min_u8"
100 NUM_MAX_U8: "max_u8"
101 NUM_MIN_I16: "min_i16"
102 NUM_MAX_I16: "max_i16"
103 NUM_MIN_U16: "min_u16"
104 NUM_MAX_U16: "max_u16"
105 NUM_MIN_I32: "min_i32"
106 NUM_MAX_I32: "max_i32"
107 NUM_MIN_U32: "min_u32"
108 NUM_MAX_U32: "max_u32"
109 NUM_MIN_I64: "min_i64"
110 NUM_MAX_I64: "max_i64"
111 NUM_MIN_U64: "min_u64"
112 NUM_MAX_U64: "max_u64"
113 NUM_MIN_I128: "min_i128"
114 NUM_MAX_I128: "max_i128"
115 NUM_MIN_U128: "min_u128"
116 NUM_MAX_U128: "max_u128"
117 NUM_TO_I8: "to_i8"
118 NUM_TO_I8_CHECKED: "to_i8_checked"
119 NUM_TO_I16: "to_i16"
120 NUM_TO_I16_CHECKED: "to_i16_checked"
121 NUM_TO_I32: "to_i32"
122 NUM_TO_I32_CHECKED: "to_i32_checked"
123 NUM_TO_I64: "to_i64"
124 NUM_TO_I64_CHECKED: "to_i64_checked"
125 NUM_TO_I128: "to_i128"
126 NUM_TO_I128_CHECKED: "to_i128_checked"
127 NUM_TO_U8: "to_u8"
128 NUM_TO_U8_CHECKED: "to_u8_checked"
129 NUM_TO_U16: "to_u16"
130 NUM_TO_U16_CHECKED: "to_u16_checked"
131 NUM_TO_U32: "to_u32"
132 NUM_TO_U32_CHECKED: "to_u32_checked"
133 NUM_TO_U64: "to_u64"
134 NUM_TO_U64_CHECKED: "to_u64_checked"
135 NUM_TO_U128: "to_u128"
136 NUM_TO_U128_CHECKED: "to_u128_checked"
137 NUM_DIV_CEIL: "div_ceil"
138 NUM_DIV_CEIL_CHECKED: "div_ceil_checked"
139 NUM_TO_F32: "to_f32"
140 NUM_TO_F32_CHECKED: "to_f32_checked"
141 NUM_TO_F64: "to_f64"
142 NUM_TO_F64_CHECKED: "to_f64_checked"
143 NUM_MAX_F64: "max_f64"
144 NUM_MIN_F64: "min_f64"
145 NUM_ADD_CHECKED_LOWLEVEL: "add_checked_lowlevel"
146 NUM_SUB_CHECKED_LOWLEVEL: "sub_checked_lowlevel"
147 NUM_MUL_CHECKED_LOWLEVEL: "mul_checked_lowlevel"
148 NUM_MIN: "min"
149 NUM_MAX: "max"
150 NUM_BITWISE_NOT: "bitwiseNot"
151 NUM_INT_CAST: "intCast"
152 NUM_IS_APPROX_EQ: "isApproxEq"
153 NUM_BYTES_TO_U16_LOWLEVEL: "bytesToU16Lowlevel"
154 NUM_BYTES_TO_U32_LOWLEVEL: "bytesToU32Lowlevel"
155 NUM_BYTES_TO_U64_LOWLEVEL: "bytesToU64Lowlevel"
156 NUM_BYTES_TO_U128_LOWLEVEL: "bytesToU128Lowlevel"
157 NUM_DIV_TRUNC_UNCHECKED: "divTruncUnchecked" // traps on division by zero
158 NUM_REM_UNCHECKED: "remUnchecked" // traps on division by zero
159 NUM_WITHOUT_DECIMAL_POINT: "withoutDecimalPoint"
160 NUM_WITH_DECIMAL_POINT: "withDecimalPoint"
161 NUM_F32_TO_PARTS: "f32ToParts"
162 NUM_F64_TO_PARTS: "f64ToParts"
163 NUM_F32_FROM_PARTS: "f32FromParts"
164 NUM_F64_FROM_PARTS: "f64FromParts"
165 NUM_NAN_F32: "nanF32"
166 NUM_NAN_F64: "nanF64"
167 NUM_INFINITY_F32: "infinityF32"
168 NUM_INFINITY_F64: "infinityF64"
169 NUM_FROM_BOOL: "fromBool"
150 NUM_BITWISE_NOT: "bitwise_not"
151 NUM_INT_CAST: "int_cast"
152 NUM_IS_APPROX_EQ: "is_approx_eq"
153 NUM_BYTES_TO_U16_LOWLEVEL: "bytes_to_u16_owlevel"
154 NUM_BYTES_TO_U32_LOWLEVEL: "bytes_to_u32_lowlevel"
155 NUM_BYTES_TO_U64_LOWLEVEL: "bytes_to_u64_lowlevel"
156 NUM_BYTES_TO_U128_LOWLEVEL: "bytes_to_u128_lowlevel"
157 NUM_DIV_TRUNC_UNCHECKED: "div_trunc_unchecked" // traps on division by zero
158 NUM_REM_UNCHECKED: "rem_unchecked" // traps on division by zero
159 NUM_WITHOUT_DECIMAL_POINT: "without_decimal_point"
160 NUM_WITH_DECIMAL_POINT: "with_decimal_point"
161 NUM_F32_TO_PARTS: "f32_to_parts"
162 NUM_F64_TO_PARTS: "f64_to_parts"
163 NUM_F32_FROM_PARTS: "f32_from_parts"
164 NUM_F64_FROM_PARTS: "f64_from_parts"
165 NUM_NAN_F32: "nan_f32"
166 NUM_NAN_F64: "nan_f64"
167 NUM_INFINITY_F32: "infinity_f32"
168 NUM_INFINITY_F64: "infinity_f64"
169 NUM_FROM_BOOL: "from_bool"
}
4 BOOL: "Bool" => {
0 BOOL_BOOL: "Bool" exposed_type=true // the Bool.Bool type alias
@ -1359,75 +1359,75 @@ define_builtins! {
4 BOOL_OR: "or"
5 BOOL_NOT: "not"
6 BOOL_XOR: "xor"
7 BOOL_NEQ: "isNotEq"
7 BOOL_NEQ: "is_not_eq"
8 BOOL_EQ: "Eq" exposed_type=true
9 BOOL_IS_EQ: "isEq"
10 BOOL_IS_EQ_IMPL: "boolIsEq"
unexposed 11 BOOL_STRUCTURAL_EQ: "structuralEq"
unexposed 12 BOOL_STRUCTURAL_NOT_EQ: "structuralNotEq"
9 BOOL_IS_EQ: "is_eq"
10 BOOL_IS_EQ_IMPL: "bool_is_eq"
unexposed 11 BOOL_STRUCTURAL_EQ: "structural_eq"
unexposed 12 BOOL_STRUCTURAL_NOT_EQ: "structural_not_eq"
}
5 STR: "Str" => {
0 STR_STR: "Str" exposed_apply_type=true // the Str.Str type alias
1 STR_IS_EMPTY: "isEmpty"
1 STR_IS_EMPTY: "is_empty"
2 STR_APPEND: "#append" // unused
3 STR_CONCAT: "concat"
4 STR_JOIN_WITH: "joinWith"
5 STR_SPLIT_ON: "splitOn"
6 STR_WITH_PREFIX: "withPrefix"
7 STR_STARTS_WITH: "startsWith"
8 STR_ENDS_WITH: "endsWith"
9 STR_FROM_UTF8: "fromUtf8"
4 STR_JOIN_WITH: "join_with"
5 STR_SPLIT_ON: "split_on"
6 STR_WITH_PREFIX: "with_prefix"
7 STR_STARTS_WITH: "starts_with"
8 STR_ENDS_WITH: "ends_with"
9 STR_FROM_UTF8: "from_utf8"
10 STR_UT8_PROBLEM: "Utf8Problem" // the Utf8Problem type alias
11 STR_UT8_BYTE_PROBLEM: "Utf8ByteProblem" // the Utf8ByteProblem type alias
12 STR_TO_UTF8: "toUtf8"
13 STR_WALK_UTF8: "walkUtf8"
12 STR_TO_UTF8: "to_utf8"
13 STR_WALK_UTF8: "walk_utf8"
14 STR_ALIAS_ANALYSIS_STATIC: "#aliasAnalysisStatic" // string with the static lifetime
15 STR_FROM_UTF8_RANGE: "fromUtf8Range"
15 STR_FROM_UTF8_RANGE: "from_utf8_range"
16 STR_REPEAT: "repeat"
17 STR_TRIM: "trim"
18 STR_TRIM_START: "trimStart"
19 STR_TRIM_END: "trimEnd"
20 STR_WITH_CAPACITY: "withCapacity"
21 STR_TO_F64: "toF64"
22 STR_TO_F32: "toF32"
23 STR_TO_DEC: "toDec"
24 STR_TO_U128: "toU128"
25 STR_TO_I128: "toI128"
26 STR_TO_U64: "toU64"
27 STR_TO_I64: "toI64"
28 STR_TO_U32: "toU32"
29 STR_TO_I32: "toI32"
30 STR_TO_U16: "toU16"
31 STR_TO_I16: "toI16"
32 STR_TO_U8: "toU8"
33 STR_TO_I8: "toI8"
18 STR_TRIM_START: "trim_start"
19 STR_TRIM_END: "trim_end"
20 STR_WITH_CAPACITY: "with_capacity"
21 STR_TO_F64: "to_f64"
22 STR_TO_F32: "to_f32"
23 STR_TO_DEC: "to_dec"
24 STR_TO_U128: "to_u128"
25 STR_TO_I128: "to_i128"
26 STR_TO_U64: "to_u64"
27 STR_TO_I64: "to_i64"
28 STR_TO_U32: "to_u32"
29 STR_TO_I32: "to_i32"
30 STR_TO_U16: "to_u16"
31 STR_TO_I16: "to_i16"
32 STR_TO_U8: "to_u8"
33 STR_TO_I8: "to_i8"
34 STR_CONTAINS: "contains"
35 STR_GET_UNSAFE: "getUnsafe"
36 STR_COUNT_UTF8_BYTES: "countUtf8Bytes"
37 STR_SUBSTRING_UNSAFE: "substringUnsafe"
38 STR_SPLIT_FIRST: "splitFirst"
39 STR_SPLIT_LAST: "splitLast"
40 STR_WALK_UTF8_WITH_INDEX: "walkUtf8WithIndex"
35 STR_GET_UNSAFE: "get_unsafe"
36 STR_COUNT_UTF8_BYTES: "count_utf8_bytes"
37 STR_SUBSTRING_UNSAFE: "substring_unsafe"
38 STR_SPLIT_FIRST: "split_first"
39 STR_SPLIT_LAST: "split_last"
40 STR_WALK_UTF8_WITH_INDEX: "walk_utf8_with_index"
41 STR_RESERVE: "reserve"
42 STR_TO_NUM: "strToNum"
43 STR_FROM_UTF8_LOWLEVEL: "fromUtf8Lowlevel"
42 STR_TO_NUM: "str_to_num"
43 STR_FROM_UTF8_LOWLEVEL: "from_utf8_lowlevel"
44 STR_CAPACITY: "capacity"
45 STR_REPLACE_EACH: "replaceEach"
46 STR_REPLACE_FIRST: "replaceFirst"
47 STR_REPLACE_LAST: "replaceLast"
48 STR_RELEASE_EXCESS_CAPACITY: "releaseExcessCapacity"
49 STR_DROP_PREFIX: "dropPrefix"
50 STR_DROP_SUFFIX: "dropSuffix"
45 STR_REPLACE_EACH: "replace_each"
46 STR_REPLACE_FIRST: "replace_first"
47 STR_REPLACE_LAST: "replace_last"
48 STR_RELEASE_EXCESS_CAPACITY: "release_excess_capacity"
49 STR_DROP_PREFIX: "drop_prefix"
50 STR_DROP_SUFFIX: "drop_suffix"
}
6 LIST: "List" => {
0 LIST_LIST: "List" exposed_apply_type=true // the List.List type alias
1 LIST_IS_EMPTY: "isEmpty"
1 LIST_IS_EMPTY: "is_empty"
2 LIST_GET: "get"
3 LIST_SET: "set"
4 LIST_APPEND: "append"
5 LIST_MAP: "map"
6 LIST_LEN_U64: "len"
7 LIST_WALK_BACKWARDS: "walkBackwards"
7 LIST_WALK_BACKWARDS: "walk_backwards"
8 LIST_CONCAT: "concat"
9 LIST_FIRST: "first"
10 LIST_SINGLE: "single"
@ -1435,99 +1435,99 @@ define_builtins! {
12 LIST_REVERSE: "reverse"
13 LIST_PREPEND: "prepend"
14 LIST_JOIN: "join"
15 LIST_KEEP_IF: "keepIf"
15 LIST_KEEP_IF: "keep_if"
16 LIST_CONTAINS: "contains"
17 LIST_SUM: "sum"
18 LIST_WALK: "walk"
19 LIST_LAST: "last"
20 LIST_KEEP_OKS: "keepOks"
21 LIST_KEEP_ERRS: "keepErrs"
22 LIST_MAP_WITH_INDEX: "mapWithIndex"
20 LIST_KEEP_OKS: "keep_oks"
21 LIST_KEEP_ERRS: "keep_errs"
22 LIST_MAP_WITH_INDEX: "map_with_index"
23 LIST_MAP2: "map2"
24 LIST_MAP3: "map3"
25 LIST_PRODUCT: "product"
26 LIST_WALK_UNTIL: "walkUntil"
26 LIST_WALK_UNTIL: "walk_until"
27 LIST_RANGE: "range"
28 LIST_SORT_WITH: "sortWith"
29 LIST_CHUNKS_OF: "chunksOf"
28 LIST_SORT_WITH: "sort_with"
29 LIST_CHUNKS_OF: "chunks_of"
30 LIST_SWAP: "swap"
31 LIST_DROP_AT: "dropAt"
32 LIST_DROP_LAST: "dropLast"
31 LIST_DROP_AT: "drop_at"
32 LIST_DROP_LAST: "drop_last"
33 LIST_MIN: "min"
34 LIST_MIN_LT: "#minlt"
34 LIST_MIN_LT: "#min_lt"
35 LIST_MAX: "max"
36 LIST_MAX_GT: "#maxGt"
36 LIST_MAX_GT: "#max_gt"
37 LIST_MAP4: "map4"
38 LIST_DROP_FIRST: "dropFirst"
39 LIST_JOIN_MAP: "joinMap"
40 LIST_JOIN_MAP_CONCAT: "#joinMapConcat"
38 LIST_DROP_FIRST: "drop_first"
39 LIST_JOIN_MAP: "join_map"
40 LIST_JOIN_MAP_CONCAT: "#join_map_concat"
41 LIST_ANY: "any"
42 LIST_TAKE_FIRST: "takeFirst"
43 LIST_TAKE_LAST: "takeLast"
44 LIST_FIND_FIRST: "findFirst"
45 LIST_FIND_LAST: "findLast"
46 LIST_FIND_FIRST_INDEX: "findFirstIndex"
47 LIST_FIND_LAST_INDEX: "findLastIndex"
42 LIST_TAKE_FIRST: "take_first"
43 LIST_TAKE_LAST: "take_last"
44 LIST_FIND_FIRST: "find_first"
45 LIST_FIND_LAST: "find_last"
46 LIST_FIND_FIRST_INDEX: "find_first_index"
47 LIST_FIND_LAST_INDEX: "find_last_index"
48 LIST_FIND_RESULT: "#find_result" // symbol used in the definition of List.findFirst
49 LIST_SUBLIST: "sublist"
50 LIST_INTERSPERSE: "intersperse"
51 LIST_INTERSPERSE_CLOS: "#intersperseClos"
52 LIST_SPLIT_AT: "splitAt"
53 LIST_SPLIT_FIRST: "splitFirst"
54 LIST_SPLIT_LAST: "splitLast"
55 LIST_SPLIT_CLOS: "#splitClos"
51 LIST_INTERSPERSE_CLOS: "#intersperse_clos"
52 LIST_SPLIT_AT: "split_at"
53 LIST_SPLIT_FIRST: "split_first"
54 LIST_SPLIT_LAST: "split_last"
55 LIST_SPLIT_CLOS: "#split_clos"
56 LIST_ALL: "all"
57 LIST_DROP_IF: "dropIf"
58 LIST_DROP_IF_PREDICATE: "#dropIfPred"
59 LIST_SORT_ASC: "sortAsc"
60 LIST_SORT_DESC: "sortDesc"
61 LIST_SORT_DESC_COMPARE: "#sortDescCompare"
62 LIST_STARTS_WITH: "startsWith"
63 LIST_ENDS_WITH: "endsWith"
57 LIST_DROP_IF: "drop_if"
58 LIST_DROP_IF_PREDICATE: "#drop_if_pred"
59 LIST_SORT_ASC: "sort_asc"
60 LIST_SORT_DESC: "sort_desc"
61 LIST_SORT_DESC_COMPARE: "#sort_desc_compare"
62 LIST_STARTS_WITH: "starts_with"
63 LIST_ENDS_WITH: "ends_with"
64 LIST_REPLACE: "replace"
65 LIST_IS_UNIQUE: "#isUnique"
66 LIST_GET_UNSAFE: "getUnsafe"
67 LIST_REPLACE_UNSAFE: "replaceUnsafe"
68 LIST_WITH_CAPACITY: "withCapacity"
65 LIST_IS_UNIQUE: "#is_unique"
66 LIST_GET_UNSAFE: "get_unsafe"
67 LIST_REPLACE_UNSAFE: "replace_unsafe"
68 LIST_WITH_CAPACITY: "with_capacity"
69 LIST_UNREACHABLE: "unreachable"
70 LIST_RESERVE: "reserve"
71 LIST_APPEND_UNSAFE: "appendUnsafe"
72 LIST_SUBLIST_LOWLEVEL: "sublistLowlevel"
71 LIST_APPEND_UNSAFE: "append_unsafe"
72 LIST_SUBLIST_LOWLEVEL: "sublist_lowlevel"
73 LIST_CAPACITY: "capacity"
74 LIST_MAP_TRY: "mapTry"
75 LIST_WALK_TRY: "walkTry"
76 LIST_WALK_BACKWARDS_UNTIL: "walkBackwardsUntil"
77 LIST_COUNT_IF: "countIf"
78 LIST_WALK_FROM: "walkFrom"
79 LIST_WALK_FROM_UNTIL: "walkFromUntil"
80 LIST_ITER_HELP: "iterHelp"
81 LIST_RELEASE_EXCESS_CAPACITY: "releaseExcessCapacity"
74 LIST_MAP_TRY: "map_try"
75 LIST_WALK_TRY: "walk_try"
76 LIST_WALK_BACKWARDS_UNTIL: "walk_backwards_until"
77 LIST_COUNT_IF: "count_if"
78 LIST_WALK_FROM: "walk_from"
79 LIST_WALK_FROM_UNTIL: "walk_from_until"
80 LIST_ITER_HELP: "iter_help"
81 LIST_RELEASE_EXCESS_CAPACITY: "release_excess_capacity"
82 LIST_UPDATE: "update"
83 LIST_WALK_WITH_INDEX: "walkWithIndex"
84 LIST_APPEND_IF_OK: "appendIfOk"
85 LIST_PREPEND_IF_OK: "prependIfOk"
86 LIST_WALK_WITH_INDEX_UNTIL: "walkWithIndexUntil"
83 LIST_WALK_WITH_INDEX: "walk_with_index"
84 LIST_APPEND_IF_OK: "append_if_ok"
85 LIST_PREPEND_IF_OK: "prepend_if_ok"
86 LIST_WALK_WITH_INDEX_UNTIL: "walk_with_index_until"
87 LIST_CLONE: "clone"
88 LIST_LEN_USIZE: "lenUsize"
89 LIST_CONCAT_UTF8: "concatUtf8"
90 LIST_FOR_EACH_FX: "forEach!"
91 LIST_FOR_EACH_TRY_FX: "forEachTry!"
88 LIST_LEN_USIZE: "len_usize"
89 LIST_CONCAT_UTF8: "concat_utf8"
90 LIST_FOR_EACH_FX: "for_each!"
91 LIST_FOR_EACH_TRY_FX: "for_each_try!"
92 LIST_WALK_FX: "walk!"
93 LIST_SPLIT_ON: "splitOn"
94 LIST_SPLIT_ON_LIST: "splitOnList"
93 LIST_SPLIT_ON: "split_on"
94 LIST_SPLIT_ON_LIST: "split_on_list"
}
7 RESULT: "Result" => {
0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias
1 RESULT_IS_ERR: "isErr"
2 RESULT_ON_ERR: "onErr"
1 RESULT_IS_ERR: "is_err"
2 RESULT_ON_ERR: "on_err"
3 RESULT_MAP: "map"
4 RESULT_MAP_ERR: "mapErr"
5 RESULT_WITH_DEFAULT: "withDefault"
4 RESULT_MAP_ERR: "map_err"
5 RESULT_WITH_DEFAULT: "with_default"
6 RESULT_TRY: "try"
7 RESULT_IS_OK: "isOk"
8 RESULT_MAP_BOTH: "mapBoth"
7 RESULT_IS_OK: "is_ok"
8 RESULT_MAP_BOTH: "map_both"
9 RESULT_MAP_TWO: "map2"
10 RESULT_ON_ERR_FX: "onErr!"
10 RESULT_ON_ERR_FX: "on_err!"
}
8 DICT: "Dict" => {
0 DICT_DICT: "Dict" exposed_type=true // the Dict.Dict type alias
@ -1542,29 +1542,29 @@ define_builtins! {
9 DICT_REMOVE: "remove"
10 DICT_WALK: "walk"
11 DICT_WALK_UNTIL: "walkUntil"
12 DICT_FROM_LIST: "fromList"
13 DICT_TO_LIST: "toList"
11 DICT_WALK_UNTIL: "walk_until"
12 DICT_FROM_LIST: "from_list"
13 DICT_TO_LIST: "to_list"
14 DICT_KEYS: "keys"
15 DICT_VALUES: "values"
16 DICT_INSERT_ALL: "insertAll" // union
17 DICT_KEEP_SHARED: "keepShared" // intersection
18 DICT_REMOVE_ALL: "removeAll" // difference
16 DICT_INSERT_ALL: "insert_all" // union
17 DICT_KEEP_SHARED: "keep_shared" // intersection
18 DICT_REMOVE_ALL: "remove_all" // difference
19 DICT_WITH_CAPACITY: "withCapacity"
19 DICT_WITH_CAPACITY: "with_capacity"
20 DICT_CAPACITY: "capacity"
21 DICT_UPDATE: "update"
22 DICT_LIST_GET_UNSAFE: "listGetUnsafe"
23 DICT_PSEUDO_SEED: "pseudoSeed"
24 DICT_IS_EMPTY: "isEmpty"
22 DICT_LIST_GET_UNSAFE: "list_get_unsafe"
23 DICT_PSEUDO_SEED: "pseudo_seed"
24 DICT_IS_EMPTY: "is_empty"
25 DICT_MAP: "map"
26 DICT_JOINMAP: "joinMap"
27 DICT_KEEP_IF: "keepIf"
28 DICT_DROP_IF: "dropIf"
26 DICT_JOINMAP: "join_map"
27 DICT_KEEP_IF: "keep_if"
28 DICT_DROP_IF: "drop_if"
29 DICT_RESERVE: "reserve"
30 DICT_RELEASE_EXCESS_CAPACITY: "releaseExcessCapacity"
30 DICT_RELEASE_EXCESS_CAPACITY: "release_excess_capacity"
}
9 SET: "Set" => {
0 SET_SET: "Set" exposed_type=true // the Set.Set type alias
@ -1576,22 +1576,22 @@ define_builtins! {
6 SET_UNION: "union"
7 SET_DIFFERENCE: "difference"
8 SET_INTERSECTION: "intersection"
9 SET_TO_LIST: "toList"
10 SET_FROM_LIST: "fromList"
9 SET_TO_LIST: "to_list"
10 SET_FROM_LIST: "from_list"
11 SET_WALK: "walk"
12 SET_WALK_UNTIL: "walkUntil"
12 SET_WALK_UNTIL: "walk_until"
13 SET_WALK_USER_FUNCTION: "#walk_user_function"
14 SET_CONTAINS: "contains"
15 SET_TO_DICT: "toDict"
15 SET_TO_DICT: "to_dict"
16 SET_CAPACITY: "capacity"
17 SET_IS_EMPTY: "isEmpty"
17 SET_IS_EMPTY: "is_empty"
18 SET_MAP: "map"
19 SET_JOIN_MAP: "joinMap"
20 SET_KEEP_IF: "keepIf"
21 SET_DROP_IF: "dropIf"
22 SET_WITH_CAPACITY: "withCapacity"
19 SET_JOIN_MAP: "join_map"
20 SET_KEEP_IF: "keep_if"
21 SET_DROP_IF: "drop_if"
22 SET_WITH_CAPACITY: "with_capacity"
23 SET_RESERVE: "reserve"
24 SET_RELEASE_EXCESS_CAPACITY: "releaseExcessCapacity"
24 SET_RELEASE_EXCESS_CAPACITY: "release_excess_capacity"
}
10 BOX: "Box" => {
0 BOX_BOX_TYPE: "Box" exposed_apply_type=true // the Box.Box opaque type
@ -1601,7 +1601,7 @@ define_builtins! {
11 ENCODE: "Encode" => {
0 ENCODE_ENCODER: "Encoder" exposed_type=true
1 ENCODE_ENCODING: "Encoding" exposed_type=true
2 ENCODE_TO_ENCODER: "toEncoder"
2 ENCODE_TO_ENCODER: "to_encoder"
3 ENCODE_ENCODERFORMATTING: "EncoderFormatting" exposed_type=true
4 ENCODE_U8: "u8"
5 ENCODE_U16: "u16"
@ -1623,9 +1623,9 @@ define_builtins! {
21 ENCODE_TUPLE: "tuple"
22 ENCODE_TAG: "tag"
23 ENCODE_CUSTOM: "custom"
24 ENCODE_APPEND_WITH: "appendWith"
24 ENCODE_APPEND_WITH: "append_with"
25 ENCODE_APPEND: "append"
26 ENCODE_TO_BYTES: "toBytes"
26 ENCODE_TO_BYTES: "to_bytes"
}
12 DECODE: "Decode" => {
0 DECODE_DECODE_ERROR: "DecodeError" exposed_type=true
@ -1653,33 +1653,33 @@ define_builtins! {
22 DECODE_RECORD: "record"
23 DECODE_TUPLE: "tuple"
24 DECODE_CUSTOM: "custom"
25 DECODE_DECODE_WITH: "decodeWith"
26 DECODE_FROM_BYTES_PARTIAL: "fromBytesPartial"
27 DECODE_FROM_BYTES: "fromBytes"
28 DECODE_MAP_RESULT: "mapResult"
25 DECODE_DECODE_WITH: "decode_with"
26 DECODE_FROM_BYTES_PARTIAL: "from_bytes_partial"
27 DECODE_FROM_BYTES: "from_bytes"
28 DECODE_MAP_RESULT: "map_result"
}
13 HASH: "Hash" => {
0 HASH_HASH_ABILITY: "Hash" exposed_type=true
1 HASH_HASH: "hash"
2 HASH_HASHER: "Hasher" exposed_type=true
3 HASH_ADD_BYTES: "addBytes"
4 HASH_ADD_U8: "addU8"
5 HASH_ADD_U16: "addU16"
6 HASH_ADD_U32: "addU32"
7 HASH_ADD_U64: "addU64"
8 HASH_ADD_U128: "addU128"
9 HASH_HASH_BOOL: "hashBool"
10 HASH_HASH_I8: "hashI8"
11 HASH_HASH_I16: "hashI16"
12 HASH_HASH_I32: "hashI32"
13 HASH_HASH_I64: "hashI64"
14 HASH_HASH_I128: "hashI128"
15 HASH_HASH_UNORDERED: "hashUnordered"
16 I128_OF_DEC: "i128OfDec"
17 HASH_HASH_DEC: "hashDec"
3 HASH_ADD_BYTES: "add_bytes"
4 HASH_ADD_U8: "add_u8"
5 HASH_ADD_U16: "add_u16"
6 HASH_ADD_U32: "add_u32"
7 HASH_ADD_U64: "add_u64"
8 HASH_ADD_U128: "add_u128"
9 HASH_HASH_BOOL: "hash_bool"
10 HASH_HASH_I8: "hash_i8"
11 HASH_HASH_I16: "hash_i16"
12 HASH_HASH_I32: "hash_i32"
13 HASH_HASH_I64: "hash_i64"
14 HASH_HASH_I128: "hash_i128"
15 HASH_HASH_UNORDERED: "hash_unordered"
16 I128_OF_DEC: "i128_of_dec"
17 HASH_HASH_DEC: "hash_dec"
18 HASH_COMPLETE: "complete"
19 HASH_HASH_STR_BYTES: "hashStrBytes"
20 HASH_HASH_LIST: "hashList"
19 HASH_HASH_STR_BYTES: "hash_str_bytes"
20 HASH_HASH_LIST: "hash_list"
}
14 INSPECT: "Inspect" => {
0 INSPECT_INSPECT_ABILITY: "Inspect" exposed_type=true
@ -1714,8 +1714,8 @@ define_builtins! {
29 INSPECT_DEC: "dec"
30 INSPECT_CUSTOM: "custom"
31 INSPECT_APPLY: "apply"
32 INSPECT_TO_INSPECTOR: "toInspector"
33 INSPECT_TO_STR: "toStr"
32 INSPECT_TO_INSPECTOR: "to_inspector"
33 INSPECT_TO_STR: "to_str"
}
15 TASK: "Task" => {
0 TASK_TASK: "Task" exposed_type=true // the Task.Task opaque type
@ -1725,14 +1725,14 @@ define_builtins! {
4 TASK_ERR: "err"
5 TASK_ATTEMPT: "attempt"
6 TASK_AWAIT: "await"
7 TASK_ON_ERR: "onErr"
7 TASK_ON_ERR: "on_err"
8 TASK_MAP: "map"
9 TASK_MAP_ERR: "mapErr"
10 TASK_FROM_RESULT: "fromResult"
9 TASK_MAP_ERR: "map_err"
10 TASK_FROM_RESULT: "from_result"
11 TASK_BATCH: "batch"
12 TASK_COMBINE: "combine"
13 TASK_SEQUENCE: "sequence"
14 TASK_FOR_EACH: "forEach"
14 TASK_FOR_EACH: "for_each"
15 TASK_RESULT: "result"
}