mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 19:58:18 +00:00
Merge pull request #3608 from rtfeldman/more-list-builtins
More `List` builtins
This commit is contained in:
commit
11ba64c249
6 changed files with 469 additions and 57 deletions
|
@ -81,7 +81,7 @@ withCapacity = \n -> @Dict (List.withCapacity n)
|
|||
|
||||
get : Dict k v, k -> Result v [KeyNotFound]*
|
||||
get = \@Dict list, needle ->
|
||||
when List.find list (\Pair key _ -> key == needle) is
|
||||
when List.findFirst list (\Pair key _ -> key == needle) is
|
||||
Ok (Pair _ v) ->
|
||||
Ok v
|
||||
|
||||
|
@ -94,7 +94,7 @@ walk = \@Dict list, initialState, transform ->
|
|||
|
||||
insert : Dict k v, k, v -> Dict k v
|
||||
insert = \@Dict list, k, v ->
|
||||
when List.findIndex list (\Pair key _ -> key == k) is
|
||||
when List.findFirstIndex list (\Pair key _ -> key == k) is
|
||||
Err NotFound ->
|
||||
insertFresh (@Dict list) k v
|
||||
|
||||
|
@ -109,7 +109,7 @@ len = \@Dict list ->
|
|||
|
||||
remove : Dict k v, k -> Dict k v
|
||||
remove = \@Dict list, key ->
|
||||
when List.findIndex list (\Pair k _ -> k == key) is
|
||||
when List.findFirstIndex list (\Pair k _ -> k == key) is
|
||||
Err NotFound ->
|
||||
@Dict list
|
||||
|
||||
|
|
|
@ -44,11 +44,17 @@ interface List
|
|||
any,
|
||||
takeFirst,
|
||||
takeLast,
|
||||
find,
|
||||
findIndex,
|
||||
findFirst,
|
||||
findLast,
|
||||
findFirstIndex,
|
||||
findLastIndex,
|
||||
sublist,
|
||||
intersperse,
|
||||
split,
|
||||
splitFirst,
|
||||
splitLast,
|
||||
startsWith,
|
||||
endsWith,
|
||||
all,
|
||||
dropIf,
|
||||
sortAsc,
|
||||
|
@ -770,30 +776,41 @@ maxHelp = \list, initial ->
|
|||
## You may know a similar function named `concatMap` in other languages.
|
||||
joinMap : List a, (a -> List b) -> List b
|
||||
joinMap = \list, mapper ->
|
||||
List.walk list [] (\state, elem -> List.concat state (mapper elem))
|
||||
List.walk list [] \state, elem -> List.concat state (mapper elem)
|
||||
|
||||
## Returns the first element of the list satisfying a predicate function.
|
||||
## If no satisfying element is found, an `Err NotFound` is returned.
|
||||
find : List elem, (elem -> Bool) -> Result elem [NotFound]*
|
||||
find = \array, pred ->
|
||||
findFirst : List elem, (elem -> Bool) -> Result elem [NotFound]*
|
||||
findFirst = \list, pred ->
|
||||
callback = \_, elem ->
|
||||
if pred elem then
|
||||
Break elem
|
||||
else
|
||||
Continue {}
|
||||
|
||||
when List.iterate array {} callback is
|
||||
Continue {} ->
|
||||
Err NotFound
|
||||
when List.iterate list {} callback is
|
||||
Continue {} -> Err NotFound
|
||||
Break found -> Ok found
|
||||
|
||||
Break found ->
|
||||
Ok found
|
||||
## Returns the last element of the list satisfying a predicate function.
|
||||
## If no satisfying element is found, an `Err NotFound` is returned.
|
||||
findLast : List elem, (elem -> Bool) -> Result elem [NotFound]*
|
||||
findLast = \list, pred ->
|
||||
callback = \_, elem ->
|
||||
if pred elem then
|
||||
Break elem
|
||||
else
|
||||
Continue {}
|
||||
|
||||
when List.iterateBackwards list {} callback is
|
||||
Continue {} -> Err NotFound
|
||||
Break found -> Ok found
|
||||
|
||||
## Returns the index at which the first element in the list
|
||||
## satisfying a predicate function can be found.
|
||||
## If no satisfying element is found, an `Err NotFound` is returned.
|
||||
findIndex : List elem, (elem -> Bool) -> Result Nat [NotFound]*
|
||||
findIndex = \list, matcher ->
|
||||
findFirstIndex : List elem, (elem -> Bool) -> Result Nat [NotFound]*
|
||||
findFirstIndex = \list, matcher ->
|
||||
foundIndex = List.iterate list 0 \index, elem ->
|
||||
if matcher elem then
|
||||
Break index
|
||||
|
@ -804,6 +821,21 @@ findIndex = \list, matcher ->
|
|||
Break index -> Ok index
|
||||
Continue _ -> Err NotFound
|
||||
|
||||
## Returns the last index at which the first element in the list
|
||||
## satisfying a predicate function can be found.
|
||||
## If no satisfying element is found, an `Err NotFound` is returned.
|
||||
findLastIndex : List elem, (elem -> Bool) -> Result Nat [NotFound]*
|
||||
findLastIndex = \list, matches ->
|
||||
foundIndex = List.iterateBackwards list (List.len list) \prevIndex, elem ->
|
||||
if matches elem then
|
||||
Break (prevIndex - 1)
|
||||
else
|
||||
Continue (prevIndex - 1)
|
||||
|
||||
when foundIndex is
|
||||
Break index -> Ok index
|
||||
Continue _ -> Err NotFound
|
||||
|
||||
## Returns a subsection of the given list, beginning at the `start` index and
|
||||
## including a total of `len` elements.
|
||||
##
|
||||
|
@ -843,6 +875,33 @@ intersperse = \list, sep ->
|
|||
|
||||
List.dropLast newList
|
||||
|
||||
## Returns `True` if the first list starts with the second list.
|
||||
##
|
||||
## If the second list is empty, this always returns `True`; every list
|
||||
## is considered to "start with" an empty list.
|
||||
##
|
||||
## If the first list is empty, this only returns `True` if the second list is empty.
|
||||
startsWith : List elem, List elem -> Bool
|
||||
startsWith = \list, prefix ->
|
||||
# TODO once we have seamless slices, verify that this wouldn't
|
||||
# have better performance with a function like List.compareSublists
|
||||
prefix == List.sublist list { start: 0, len: List.len prefix }
|
||||
|
||||
## Returns `True` if the first list ends with the second list.
|
||||
##
|
||||
## If the second list is empty, this always returns `True`; every list
|
||||
## is considered to "end with" an empty list.
|
||||
##
|
||||
## If the first list is empty, this only returns `True` if the second list is empty.
|
||||
endsWith : List elem, List elem -> Bool
|
||||
endsWith = \list, suffix ->
|
||||
# TODO once we have seamless slices, verify that this wouldn't
|
||||
# have better performance with a function like List.compareSublists
|
||||
length = List.len suffix
|
||||
start = Num.subSaturated (List.len list) length
|
||||
|
||||
suffix == List.sublist list { start, len: length }
|
||||
|
||||
## Splits the list into two lists, around the given index.
|
||||
##
|
||||
## The returned lists are labeled `before` and `others`. The `before` list will
|
||||
|
@ -859,6 +918,36 @@ split = \elements, userSplitIndex ->
|
|||
|
||||
{ before, others }
|
||||
|
||||
## Returns the elements before the first occurrence of a delimiter, as well as the
|
||||
## remaining elements after that occurrence. If the delimiter is not found, returns `Err`.
|
||||
##
|
||||
## List.splitFirst [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo], after: [Bar, Baz] }
|
||||
splitFirst : List elem, elem -> Result { before : List elem, after : List elem } [NotFound]*
|
||||
splitFirst = \list, delimiter ->
|
||||
when List.findFirstIndex list (\elem -> elem == delimiter) is
|
||||
Ok index ->
|
||||
before = List.sublist list { start: 0, len: index }
|
||||
after = List.sublist list { start: index + 1, len: List.len list - index - 1 }
|
||||
|
||||
Ok { before, after }
|
||||
|
||||
Err NotFound -> Err NotFound
|
||||
|
||||
## Returns the elements before the last occurrence of a delimiter, as well as the
|
||||
## remaining elements after that occurrence. If the delimiter is not found, returns `Err`.
|
||||
##
|
||||
## List.splitLast [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo, Bar], after: [Baz] }
|
||||
splitLast : List elem, elem -> Result { before : List elem, after : List elem } [NotFound]*
|
||||
splitLast = \list, delimiter ->
|
||||
when List.findLastIndex list (\elem -> elem == delimiter) is
|
||||
Ok index ->
|
||||
before = List.sublist list { start: 0, len: index }
|
||||
after = List.sublist list { start: index + 1, len: List.len list - index - 1 }
|
||||
|
||||
Ok { before, after }
|
||||
|
||||
Err NotFound -> Err NotFound
|
||||
|
||||
## Like [List.map], except the transformation function returns a [Result].
|
||||
## If that function ever returns `Err`, [mapTry] immediately returns that `Err`.
|
||||
## If it returns `Ok` for every element, [mapTry] returns `Ok` with the transformed list.
|
||||
|
@ -895,11 +984,26 @@ iterHelp : List elem, s, (s, elem -> [Continue s, Break b]), Nat, Nat -> [Contin
|
|||
iterHelp = \list, state, f, index, length ->
|
||||
if index < length then
|
||||
when f state (List.getUnsafe list index) is
|
||||
Continue nextState ->
|
||||
iterHelp list nextState f (index + 1) length
|
||||
Continue nextState -> iterHelp list nextState f (index + 1) length
|
||||
Break b -> Break b
|
||||
else
|
||||
Continue state
|
||||
|
||||
Break b ->
|
||||
Break b
|
||||
## Primitive for iterating over a List from back to front, being able to decide at every
|
||||
## element whether to continue
|
||||
iterateBackwards : List elem, s, (s, elem -> [Continue s, Break b]) -> [Continue s, Break b]
|
||||
iterateBackwards = \list, init, func ->
|
||||
iterBackwardsHelp list init func (List.len list)
|
||||
|
||||
## internal helper
|
||||
iterBackwardsHelp : List elem, s, (s, elem -> [Continue s, Break b]), Nat -> [Continue s, Break b]
|
||||
iterBackwardsHelp = \list, state, f, prevIndex ->
|
||||
if prevIndex > 0 then
|
||||
index = prevIndex - 1
|
||||
|
||||
when f state (List.getUnsafe list index) is
|
||||
Continue nextState -> iterBackwardsHelp list nextState f index
|
||||
Break b -> Break b
|
||||
else
|
||||
Continue state
|
||||
|
||||
|
|
|
@ -1265,32 +1265,37 @@ define_builtins! {
|
|||
41 LIST_ANY: "any"
|
||||
42 LIST_TAKE_FIRST: "takeFirst"
|
||||
43 LIST_TAKE_LAST: "takeLast"
|
||||
44 LIST_FIND: "find"
|
||||
45 LIST_FIND_RESULT: "#find_result" // symbol used in the definition of List.find
|
||||
46 LIST_SUBLIST: "sublist"
|
||||
47 LIST_INTERSPERSE: "intersperse"
|
||||
48 LIST_INTERSPERSE_CLOS: "#intersperseClos"
|
||||
49 LIST_SPLIT: "split"
|
||||
50 LIST_SPLIT_CLOS: "#splitClos"
|
||||
51 LIST_ALL: "all"
|
||||
52 LIST_DROP_IF: "dropIf"
|
||||
53 LIST_DROP_IF_PREDICATE: "#dropIfPred"
|
||||
54 LIST_SORT_ASC: "sortAsc"
|
||||
55 LIST_SORT_DESC: "sortDesc"
|
||||
56 LIST_SORT_DESC_COMPARE: "#sortDescCompare"
|
||||
57 LIST_REPLACE: "replace"
|
||||
58 LIST_IS_UNIQUE: "#isUnique"
|
||||
59 LIST_FIND_INDEX: "findIndex"
|
||||
60 LIST_GET_UNSAFE: "getUnsafe"
|
||||
61 LIST_REPLACE_UNSAFE: "replaceUnsafe"
|
||||
62 LIST_WITH_CAPACITY: "withCapacity"
|
||||
63 LIST_ITERATE: "iterate"
|
||||
64 LIST_UNREACHABLE: "unreachable"
|
||||
65 LIST_RESERVE: "reserve"
|
||||
66 LIST_APPEND_UNSAFE: "appendUnsafe"
|
||||
67 LIST_SUBLIST_LOWLEVEL: "sublistLowlevel"
|
||||
68 LIST_CAPACITY: "capacity"
|
||||
69 LIST_MAP_TRY: "mapTry"
|
||||
44 LIST_FIND_FIRST: "findFirst"
|
||||
45 LIST_FIND_LAST: "findLast"
|
||||
46 LIST_FIND_FIRST_INDEX: "findFirstIndex"
|
||||
47 LIST_FIND_LAST_INDEX: "findLastIndex"
|
||||
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: "split"
|
||||
53 LIST_SPLIT_FIRST: "splitFirst"
|
||||
54 LIST_SPLIT_LAST: "splitLast"
|
||||
55 LIST_SPLIT_CLOS: "#splitClos"
|
||||
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"
|
||||
64 LIST_REPLACE: "replace"
|
||||
65 LIST_IS_UNIQUE: "#isUnique"
|
||||
66 LIST_GET_UNSAFE: "getUnsafe"
|
||||
67 LIST_REPLACE_UNSAFE: "replaceUnsafe"
|
||||
68 LIST_WITH_CAPACITY: "withCapacity"
|
||||
69 LIST_UNREACHABLE: "unreachable"
|
||||
70 LIST_RESERVE: "reserve"
|
||||
71 LIST_APPEND_UNSAFE: "appendUnsafe"
|
||||
72 LIST_SUBLIST_LOWLEVEL: "sublistLowlevel"
|
||||
73 LIST_CAPACITY: "capacity"
|
||||
74 LIST_MAP_TRY: "mapTry"
|
||||
}
|
||||
7 RESULT: "Result" => {
|
||||
0 RESULT_RESULT: "Result" // the Result.Result type alias
|
||||
|
|
|
@ -360,6 +360,72 @@ fn list_split() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn list_split_first() {
|
||||
assert_evals_to!(
|
||||
r#"
|
||||
List.splitFirst [2, 3, 0, 4, 0, 6, 0, 8, 9] 0
|
||||
|> Result.map .before
|
||||
"#,
|
||||
RocResult::ok(RocList::<i64>::from_slice(&[2, 3])),
|
||||
RocResult<RocList<i64>, ()>
|
||||
);
|
||||
assert_evals_to!(
|
||||
r#"
|
||||
List.splitFirst [2, 3, 0, 4, 0, 6, 0, 8, 9] 0
|
||||
|> Result.map .after
|
||||
"#,
|
||||
RocResult::ok(RocList::<i64>::from_slice(&[4, 0, 6, 0, 8, 9])),
|
||||
RocResult<RocList<i64>, ()>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
"List.splitFirst [1, 2, 3] 0",
|
||||
RocResult::err(()),
|
||||
RocResult<(RocList<i64>, RocList<i64>), ()>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
"List.splitFirst [] 1",
|
||||
RocResult::err(()),
|
||||
RocResult<(RocList<i64>, RocList<i64>), ()>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn list_split_last() {
|
||||
assert_evals_to!(
|
||||
r#"
|
||||
List.splitLast [2, 3, 0, 4, 0, 6, 0, 8, 9] 0
|
||||
|> Result.map .before
|
||||
"#,
|
||||
RocResult::ok(RocList::<i64>::from_slice(&[2, 3, 0, 4, 0, 6])),
|
||||
RocResult<RocList<i64>, ()>
|
||||
);
|
||||
assert_evals_to!(
|
||||
r#"
|
||||
List.splitLast [2, 3, 0, 4, 0, 6, 0, 8, 9] 0
|
||||
|> Result.map .after
|
||||
"#,
|
||||
RocResult::ok(RocList::<i64>::from_slice(&[8, 9])),
|
||||
RocResult<RocList<i64>, ()>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
"List.splitLast [1, 2, 3] 0",
|
||||
RocResult::err(()),
|
||||
RocResult<(RocList<i64>, RocList<i64>), ()>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
"List.splitLast [] 1",
|
||||
RocResult::err(()),
|
||||
RocResult<(RocList<i64>, RocList<i64>), ()>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn list_drop() {
|
||||
|
@ -2846,7 +2912,7 @@ fn list_find() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.find ["a", "bc", "def"] (\s -> Str.countGraphemes s > 1) is
|
||||
when List.findFirst ["a", "bc", "def", "g"] (\s -> Str.countGraphemes s > 1) is
|
||||
Ok v -> v
|
||||
Err _ -> "not found"
|
||||
"#
|
||||
|
@ -2854,6 +2920,18 @@ fn list_find() {
|
|||
RocStr::from("bc"),
|
||||
RocStr
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.findLast ["a", "bc", "def", "g"] (\s -> Str.countGraphemes s > 1) is
|
||||
Ok v -> v
|
||||
Err _ -> "not found"
|
||||
"#
|
||||
),
|
||||
RocStr::from("def"),
|
||||
RocStr
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2862,7 +2940,19 @@ fn list_find_not_found() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.find ["a", "bc", "def"] (\s -> Str.countGraphemes s > 5) is
|
||||
when List.findFirst ["a", "bc", "def", "g"] (\s -> Str.countGraphemes s > 5) is
|
||||
Ok v -> v
|
||||
Err _ -> "not found"
|
||||
"#
|
||||
),
|
||||
RocStr::from("not found"),
|
||||
RocStr
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.findLast ["a", "bc", "def", "g"] (\s -> Str.countGraphemes s > 5) is
|
||||
Ok v -> v
|
||||
Err _ -> "not found"
|
||||
"#
|
||||
|
@ -2878,7 +2968,19 @@ fn list_find_empty_typed_list() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.find [] (\s -> Str.countGraphemes s > 5) is
|
||||
when List.findFirst [] (\s -> Str.countGraphemes s > 5) is
|
||||
Ok v -> v
|
||||
Err _ -> "not found"
|
||||
"#
|
||||
),
|
||||
RocStr::from("not found"),
|
||||
RocStr
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.findLast [] (\s -> Str.countGraphemes s > 5) is
|
||||
Ok v -> v
|
||||
Err _ -> "not found"
|
||||
"#
|
||||
|
@ -2890,16 +2992,25 @@ fn list_find_empty_typed_list() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[ignore = "Fails because monomorphization can't be done if we don't have a concrete element type!"]
|
||||
fn list_find_empty_layout() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.find [] (\_ -> True)
|
||||
List.findFirst [] \_ -> True
|
||||
"#
|
||||
),
|
||||
0,
|
||||
i64
|
||||
RocResult::err(()),
|
||||
RocResult<(), ()>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.findLast [] \_ -> True
|
||||
"#
|
||||
),
|
||||
RocResult::err(()),
|
||||
RocResult<(), ()>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2909,7 +3020,7 @@ fn list_find_index() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.findIndex ["a", "bc", "def"] (\s -> Str.countGraphemes s > 1) is
|
||||
when List.findFirstIndex ["a", "bc", "def", "g"] (\s -> Str.countGraphemes s > 1) is
|
||||
Ok v -> v
|
||||
Err _ -> 999
|
||||
"#
|
||||
|
@ -2917,6 +3028,18 @@ fn list_find_index() {
|
|||
1,
|
||||
usize
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.findLastIndex ["a", "bc", "def", "g"] (\s -> Str.countGraphemes s > 1) is
|
||||
Ok v -> v
|
||||
Err _ -> 999
|
||||
"#
|
||||
),
|
||||
2,
|
||||
usize
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2925,7 +3048,19 @@ fn list_find_index_not_found() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.findIndex ["a", "bc", "def"] (\s -> Str.countGraphemes s > 5) is
|
||||
when List.findFirstIndex ["a", "bc", "def", "g"] (\s -> Str.countGraphemes s > 5) is
|
||||
Ok v -> v
|
||||
Err _ -> 999
|
||||
"#
|
||||
),
|
||||
999,
|
||||
usize
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.findLastIndex ["a", "bc", "def"] (\s -> Str.countGraphemes s > 5) is
|
||||
Ok v -> v
|
||||
Err _ -> 999
|
||||
"#
|
||||
|
@ -2941,7 +3076,7 @@ fn list_find_index_empty_typed_list() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.findIndex [] (\s -> Str.countGraphemes s > 5) is
|
||||
when List.findFirstIndex [] (\s -> Str.countGraphemes s > 5) is
|
||||
Ok v -> v
|
||||
Err _ -> 999
|
||||
"#
|
||||
|
@ -2949,6 +3084,174 @@ fn list_find_index_empty_typed_list() {
|
|||
999,
|
||||
usize
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
when List.findLastIndex [] (\s -> Str.countGraphemes s > 5) is
|
||||
Ok v -> v
|
||||
Err _ -> 999
|
||||
"#
|
||||
),
|
||||
999,
|
||||
usize
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn list_ends_with_empty() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.endsWith [] []
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.endsWith ["a"] []
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.endsWith [] ["a"]
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn list_ends_with_nonempty() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.endsWith ["a", "bc", "def"] ["def"]
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.endsWith ["a", "bc", "def"] ["bc", "def"]
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.endsWith ["a", "bc", "def"] ["a"]
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.endsWith ["a", "bc", "def"] [""]
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn list_starts_with_empty() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.startsWith [] []
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.startsWith ["a"] []
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.startsWith [] ["a"]
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn list_starts_with_nonempty() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.startsWith ["a", "bc", "def"] ["a"]
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.startsWith ["a", "bc", "def"] ["a", "bc"]
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.startsWith ["a", "bc", "def"] ["def"]
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
List.startsWith ["a", "bc", "def"] [""]
|
||||
"#
|
||||
),
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1613,7 +1613,7 @@ fn format_category<'b>(
|
|||
alloc.text(" which was of type:"),
|
||||
),
|
||||
Character => (
|
||||
alloc.concat([this_is, alloc.text(" a character")]),
|
||||
alloc.concat([this_is, alloc.text(" a Unicode scalar value")]),
|
||||
alloc.text(" of type:"),
|
||||
),
|
||||
Lambda => (
|
||||
|
|
|
@ -436,8 +436,8 @@ mod test_reporting {
|
|||
|
||||
List.isEmpty
|
||||
List.set
|
||||
List.iterate
|
||||
List.get
|
||||
List.keepIf
|
||||
"###
|
||||
);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue