mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 17:03:32 +03:00
Add missing methods to the standard library (#1284)
This commit is contained in:
parent
670cffb380
commit
a0f87b3611
@ -107,7 +107,7 @@ Any.to_json =
|
||||
cons = Meta.Constructor m.constructor
|
||||
fs = m.fields
|
||||
fnames = cons.fields
|
||||
json_fs = 0.upto fnames.length . fold Map.empty m-> i->
|
||||
json_fs = 0.up_to fnames.length . fold Map.empty m-> i->
|
||||
m.insert (fnames.at i) (fs.at i . to_json)
|
||||
with_tp = json_fs . insert "type" (String cons.name)
|
||||
Object with_tp
|
||||
|
@ -1,5 +1,4 @@
|
||||
from Builtins import all
|
||||
|
||||
from Builtins export Nil, Cons
|
||||
|
||||
## PRIVATE
|
||||
@ -18,8 +17,10 @@ map_helper list cons f = case list of
|
||||
## The basic cons-list type.
|
||||
|
||||
A cons-list allows to store an arbitrary number of elements.
|
||||
|
||||
Prepending to the list can be achieved by using the `Cons` constructor,
|
||||
while an empty list is represented by `Nil`.
|
||||
|
||||
> Example
|
||||
A list containing the elements `1`, `2`, and `3`, in this order is:
|
||||
Cons 1 (Cons 2 (Cons 3 Nil))
|
||||
@ -27,6 +28,107 @@ type List
|
||||
Nil
|
||||
Cons
|
||||
|
||||
## Computes the number of elements in the list.
|
||||
length : Number
|
||||
length = this.fold 0 (acc -> _ -> acc + 1)
|
||||
|
||||
## Combines all the elements of the list, by iteratively applying the
|
||||
passed function with next elements of the list.
|
||||
|
||||
In general, the result of
|
||||
(Cons l0 <| Cons l1 <| ... <| Cons ln) . fold init f
|
||||
is the same as
|
||||
f (...(f (f init l0) l1)...) ln
|
||||
|
||||
> Example
|
||||
In the following example, we'll compute the sum of all elements of a
|
||||
list:
|
||||
(Cons 0 <| Cons 1 <| Cons 2 <| Nil) . fold 0 (+)
|
||||
fold : Any -> (Any -> Any -> Any) -> Any
|
||||
fold init f =
|
||||
go acc list = case list of
|
||||
Nil -> acc
|
||||
Cons h t -> @Tail_Call go (f acc h) t
|
||||
res = go init this
|
||||
res
|
||||
|
||||
## Checks whether any element of the list matches the given predicate.
|
||||
|
||||
A predicate is a function that takes a list element and returns
|
||||
a Boolean value.
|
||||
|
||||
> Example
|
||||
In the following example, we'll check if any element of the list is
|
||||
larger than `5`:
|
||||
(Cons 0 <| Cons 1 <| Cons 2 <| Nil) . exists (> 5)
|
||||
exists : (Any -> Boolean) -> Boolean
|
||||
exists predicate =
|
||||
go list = case list of
|
||||
Nil -> False
|
||||
Cons h t -> if predicate h then True else
|
||||
@Tail_Call go t
|
||||
res = go this
|
||||
res
|
||||
|
||||
## Checks whether any element of the list matches the given predicate.
|
||||
|
||||
A predicate is a function that takes a list element and returns
|
||||
a Boolean value.
|
||||
|
||||
> Example
|
||||
In the following example, we'll check if any element of the list is
|
||||
larger than `5`:
|
||||
(Cons 0 <| Cons 1 <| Cons 2 <| Nil) . any (> 5)
|
||||
any : (Any -> Boolean) -> Boolean
|
||||
any predicate = this.exists predicate
|
||||
|
||||
## Checks whether a predicate holds for all elements in this list.
|
||||
|
||||
> Example
|
||||
Check if all elements in the list are less than zero.
|
||||
(Cons 1 (Cons 2 Nil)).all (< 0)
|
||||
all : (Any -> Boolean) -> Boolean
|
||||
all predicate = this.fold True (l -> r -> l && predicate r)
|
||||
|
||||
## Checks whether this list contains a given value as an element.
|
||||
|
||||
> Example
|
||||
Checking if the list contains the number 72.
|
||||
(Cons 1 (Cons 72 Nil)).contains 72
|
||||
contains : Any -> Boolean
|
||||
contains elem = this.exists ix-> ix == elem
|
||||
|
||||
## Checks if this list is empty.
|
||||
|
||||
> Example
|
||||
Checking for emptiness.
|
||||
Nil.is_empty == true
|
||||
Cons 1 Nil . is_empty == false
|
||||
is_empty : Boolean
|
||||
is_empty = this.length == 0
|
||||
|
||||
## Checks if the list is not empty.
|
||||
|
||||
> Example
|
||||
Checking for emptiness.
|
||||
Nil.not_empty == false
|
||||
Cons 1 Nil . not_empty == true
|
||||
not_empty : Boolean
|
||||
not_empty = not this.is_empty
|
||||
|
||||
## Selects all elements of this list which satisfy a predicate.
|
||||
|
||||
> Example
|
||||
Selecting all elements that are greater than 3.
|
||||
(Cons 1 Nil).filter (> 3)
|
||||
filter : (Any -> Boolean) -> List
|
||||
filter predicate =
|
||||
case this of
|
||||
Cons a b ->
|
||||
rest = b.filter predicate
|
||||
if predicate a then Cons a rest else rest
|
||||
Nil -> Nil
|
||||
|
||||
## Applies a function to each element of the list, returning the list of
|
||||
results.
|
||||
|
||||
@ -59,52 +161,94 @@ type List
|
||||
Cons h t ->
|
||||
f h
|
||||
@Tail_Call go t
|
||||
res = go this
|
||||
res
|
||||
|
||||
## Combines all the elements of the list, by iteratively applying the
|
||||
passed function with next elements of the list.
|
||||
|
||||
In general, the result of
|
||||
(Cons l0 <| Cons l1 <| ... <| Cons ln) . fold init f
|
||||
is the same as
|
||||
f (...(f (f init l0) l1)...) ln
|
||||
|
||||
> Example
|
||||
In the following example, we'll compute the sum of all elements of a
|
||||
list:
|
||||
(Cons 0 <| Cons 1 <| Cons 2 <| Nil) . fold 0 (+)
|
||||
fold : Any -> (Any -> Any -> Any) -> Any
|
||||
fold init f =
|
||||
go acc list = case list of
|
||||
Nil -> acc
|
||||
Cons h t -> @Tail_Call go (f acc h) t
|
||||
res = go init this
|
||||
res
|
||||
go this
|
||||
Nothing
|
||||
|
||||
## Reverses the list, returning a list with the same elements, but in the
|
||||
opposite order.
|
||||
|
||||
> Example
|
||||
Reversing a small list.
|
||||
(Cons 1 (Cons 2 Nil)).reverse == (Cons 2 (Cons 1 Nil))
|
||||
reverse : List
|
||||
reverse = this.fold Nil (l -> el -> Cons el l)
|
||||
|
||||
## Computes the number of elements in the list.
|
||||
length : Number
|
||||
length = this.fold 0 (acc -> _ -> acc + 1)
|
||||
|
||||
## Checks whether any element of the list matches the given predicate.
|
||||
|
||||
A predicate is a function that takes a list element and returns
|
||||
a Boolean value.
|
||||
## Creates a new list with the first `count` elements on the left of `this`
|
||||
removed.
|
||||
|
||||
> Example
|
||||
In the following example, we'll check if any element of the list is
|
||||
larger than `1`:
|
||||
(Cons 0 <| Cons 1 <| Cons 2 <| Nil) . any (> 5)
|
||||
any : (Any -> Boolean) -> Boolean
|
||||
any predicate =
|
||||
go list = case list of
|
||||
Nil -> False
|
||||
Cons h t -> if predicate h then True else
|
||||
@Tail_Call go t
|
||||
res = go this
|
||||
res
|
||||
Removing the first element from a list.
|
||||
(Cons 1 (Cons 2 (Nil))).drop 1
|
||||
drop : Integer -> List
|
||||
drop count = if count <= 0 then this else case this of
|
||||
Cons _ b -> b.drop count-1
|
||||
Nil -> Nil
|
||||
|
||||
## Creates a new list consisting of the first `count` elements on the left
|
||||
of this.
|
||||
|
||||
> Example
|
||||
Obtaining the first 2 elements of a list.
|
||||
(Cons 1 (Cons 2 (Cons 3 Nil))).take 2
|
||||
take : Integer -> List
|
||||
take count = if count <= 0 then Nil else case this of
|
||||
Cons a b -> Cons a (b.take count-1)
|
||||
Nil -> Nil
|
||||
|
||||
## Get the first element from the list.
|
||||
|
||||
> Example
|
||||
This returns 1.
|
||||
(Cons 1 (Cons 2 Nil)).head
|
||||
head : Any | Nothing
|
||||
head = case this of
|
||||
Cons a _ -> a
|
||||
Nil -> Nothing
|
||||
|
||||
## Get all elements from the list except the first.
|
||||
|
||||
> Example
|
||||
This returns (Cons 2 Nil).
|
||||
(Cons 1 (Cons 2 Nil)).tail
|
||||
tail : List | Nothing
|
||||
tail = case this of
|
||||
Cons _ b -> b
|
||||
Nil -> Nothing
|
||||
|
||||
## Get all elements from the list except the last.
|
||||
|
||||
> Example
|
||||
Removing the last element of the list to give (Cons 1 Nil).
|
||||
(Cons 1 (Cons 2 Nil)).init
|
||||
init : List | Nothing
|
||||
init =
|
||||
init' x y = case y of
|
||||
Nil -> Nil
|
||||
Cons a b -> Cons x (init' a b)
|
||||
case this of
|
||||
Cons a b -> init' a b
|
||||
Nil -> Nothing
|
||||
|
||||
## Get the last element of the list.
|
||||
|
||||
> Example
|
||||
Getting the final element, in this case 2.
|
||||
(Cons 1 (Cons 2 Nil)).last
|
||||
last : Any | Nothing
|
||||
last = this.fold Nothing (_ -> r -> r)
|
||||
|
||||
## Get the first element from the list.
|
||||
|
||||
> Example
|
||||
This returns 1.
|
||||
(Cons 1 (Cons 2 Nil)).first
|
||||
first : Any | Nothing
|
||||
first = this.head
|
||||
|
||||
## Get all elements from the list except the first.
|
||||
|
||||
> Example
|
||||
This returns (Cons 2 Nil).
|
||||
(Cons 1 (Cons 2 Nil)).rest
|
||||
rest : List | Nothing
|
||||
rest = this.tail
|
||||
|
@ -67,16 +67,15 @@ Number.sqrt = Math.sqrt [this.to_decimal]
|
||||
Number.log : Number -> Decimal
|
||||
Number.log base = this.ln / base.ln
|
||||
|
||||
# TODO this should expose a more-user friendly API in the future.
|
||||
## Converts a decimal value to a string, using the Java string formatting
|
||||
syntax.
|
||||
|
||||
TODO this should expose a more-user friendly API in the future.
|
||||
Decimal.format : Text -> Text
|
||||
Decimal.format fmt = String.format [fmt, this]
|
||||
|
||||
## Creates a new right-exclusive range of integers from `this` to `n`.
|
||||
Integer.upto : Integer -> Range
|
||||
Integer.upto n = Range this n
|
||||
Integer.up_to : Integer -> Range
|
||||
Integer.up_to n = Range this n
|
||||
|
||||
## Checks equality of numbers, using an `epsilon` value.
|
||||
|
||||
|
5
distribution/std-lib/Base/src/Data/Pair.enso
Normal file
5
distribution/std-lib/Base/src/Data/Pair.enso
Normal file
@ -0,0 +1,5 @@
|
||||
from Base import all
|
||||
|
||||
## A pair of elements.
|
||||
type Pair
|
||||
type Pair first second
|
109
distribution/std-lib/Base/src/Data/Range.enso
Normal file
109
distribution/std-lib/Base/src/Data/Range.enso
Normal file
@ -0,0 +1,109 @@
|
||||
from Base import all
|
||||
|
||||
## Represents a right-exclusive range of integer values.
|
||||
type Range
|
||||
type Range start end
|
||||
|
||||
## Get the number of elements in the range.
|
||||
|
||||
> Example
|
||||
The following range has 100 elements.
|
||||
0.up_to 100
|
||||
length : Number
|
||||
length = this.end - this.start
|
||||
|
||||
## Checks if this range is empty.
|
||||
|
||||
> Example
|
||||
0.up_to 0 . is_empty == True
|
||||
0.up_to 100 . is_empty == False
|
||||
is_empty : Boolean
|
||||
is_empty = this.end <= this.start
|
||||
|
||||
## Checks if this range is not empty.
|
||||
|
||||
> Example
|
||||
0.up_to 0 . not_empty == False
|
||||
0.up_to 100 . not_empty == True
|
||||
not_empty : Boolean
|
||||
not_empty = not this.is_empty
|
||||
|
||||
## Applies a function for each element in the range.
|
||||
|
||||
> Example
|
||||
To print all the numbers from 1 to 100 use:
|
||||
1.up_to 101 . each IO.println
|
||||
each : (Number -> Any) -> Nothing
|
||||
each function =
|
||||
it start end = if start == end then Nothing else
|
||||
function start
|
||||
@Tail_Call it start+1 end
|
||||
it this.start this.end
|
||||
Nothing
|
||||
|
||||
## Combines all the elements of the range, by iteratively applying the
|
||||
passed function with next elements of the range.
|
||||
|
||||
In general, the result of
|
||||
Range start end . fold init f
|
||||
is the same as
|
||||
f (...(f (f init start) start+1)...) end-1
|
||||
|
||||
> Example
|
||||
In the following example, we'll compute the sum of all elements of a
|
||||
range:
|
||||
Range 0 100 . fold 0 (+)
|
||||
fold : Any -> (Number -> Any) -> Any
|
||||
fold initial function =
|
||||
it acc start end = if start == end then acc else
|
||||
new_acc = function acc start
|
||||
@Tail_Call it new_acc start+1 end
|
||||
res = it initial this.start this.end
|
||||
res
|
||||
|
||||
## Checks whether `predicate` is satisfied for all numbers in this range.
|
||||
|
||||
A predicate is a function that takes an element in the range and returns
|
||||
a boolean.
|
||||
|
||||
> Example
|
||||
Checking that all numbers in the range are greater than 5.
|
||||
10.up_to 100 . all (> 5)
|
||||
all : (Number -> Boolean) -> Boolean
|
||||
all predicate =
|
||||
it start end = if start==end then True else
|
||||
r = predicate start
|
||||
if r then (@Tail_Call it start+1 end) else False
|
||||
res = it this.start this.end
|
||||
res
|
||||
|
||||
## Checks whether `predicate` is satisfied for any number in this range.
|
||||
|
||||
A predicate is a function that takes an element in the range and returns
|
||||
a boolean.
|
||||
|
||||
> Example
|
||||
Checking that at least one number in the range is greater than 10.
|
||||
1.up_to 100 . exists (> 10)
|
||||
exists : (Number -> Boolean) -> Boolean
|
||||
exists predicate = this.fold False (l -> r -> l || predicate r)
|
||||
|
||||
## Checks whether `predicate` is satisfied for any number in this range.
|
||||
|
||||
A predicate is a function that takes an element in the range and returns
|
||||
a boolean.
|
||||
|
||||
> Example
|
||||
Checking that at least one number in the range is greater than 10.
|
||||
1.up_to 100 . any (> 10)
|
||||
any : (Number -> Boolean) -> Boolean
|
||||
any predicate = this.exists predicate
|
||||
|
||||
## Converts the range to a vector containing the numbers in the range.
|
||||
|
||||
> Example
|
||||
Getting a vector of the numbers 1 to 5.
|
||||
1.up_to 6 . to_vector == [1, 2, 3, 4, 5]
|
||||
to_vector : Vector
|
||||
to_vector = Vector.new (this.end - 1) (i -> i + this.start)
|
||||
|
@ -6,6 +6,16 @@ from Builtins export Text
|
||||
polyglot java import com.ibm.icu.text.BreakIterator
|
||||
polyglot java import org.enso.base.Text_Utils
|
||||
|
||||
## Computes the number of characters in the text.
|
||||
|
||||
A character is defined as an Extended Grapheme Cluster, see
|
||||
[Unicode Standard Annex #29](https://unicode.org/reports/tr29/).
|
||||
|
||||
This is the smallest unit that still has semantic meaning in most
|
||||
text-processing applications.
|
||||
Text.length : Integer
|
||||
Text.length = this.characters.length
|
||||
|
||||
## Applies `function` to each character in `this`.
|
||||
|
||||
A character is defined as an Extended Grapheme Cluster, see
|
||||
@ -47,11 +57,11 @@ Text.characters =
|
||||
> Example
|
||||
In the following example, we'll split the text into a vector of
|
||||
comma-separated items:
|
||||
"ham,eggs,cheese,tomatoes".split_at ","
|
||||
"ham,eggs,cheese,tomatoes".split ","
|
||||
The code above returns:
|
||||
["ham", "eggs", "cheese", "tomatoes"]
|
||||
Text.split_at : Text -> Vector
|
||||
Text.split_at separator =
|
||||
Text.split : Text -> Vector
|
||||
Text.split (separator = " ") =
|
||||
Vector.from_polyglot_array (Text_Utils.split_at [this, separator])
|
||||
|
||||
## Checks whether `this` is equal to `that`.
|
||||
@ -148,4 +158,4 @@ Text.to_json = Json.String this
|
||||
concatenated copies of `this`.
|
||||
Text.repeat : Integer -> Text
|
||||
Text.repeat count =
|
||||
0.upto count . fold "" acc-> _-> acc + this
|
||||
0.up_to count . fold "" acc-> _-> acc + this
|
||||
|
@ -17,6 +17,38 @@ from Base import all
|
||||
type Vector
|
||||
type Vector to_array
|
||||
|
||||
## Creates a new vector of the given length, initializing elements using
|
||||
the provided constructor function.
|
||||
|
||||
The constructor function is called with the consecutive indices
|
||||
(0-based) of the vector elements.
|
||||
|
||||
> Example
|
||||
To create a vector containing the numbers 1 through 50:
|
||||
Vector.new 50 (ix -> ix + 1)
|
||||
|
||||
> Example
|
||||
To create a copy of the given vector (`my_vec`):
|
||||
Vector.new my_vec.length (ix -> my_vec.at ix)
|
||||
new : Number -> (Number -> Any) -> Vector
|
||||
new length constructor =
|
||||
arr = Array.new length
|
||||
0.up_to length . each ix-> arr.set_at ix (constructor ix)
|
||||
Vector arr
|
||||
|
||||
## Creates a new vector of the given length, filling the elements with
|
||||
the provided constant.
|
||||
|
||||
> Example
|
||||
A vector containing 50 elements, each being the number `42`, can be
|
||||
created by:
|
||||
Vector.fill length=50 item=42
|
||||
fill : Number -> Any -> Vector
|
||||
fill length item =
|
||||
arr = Array.new length
|
||||
0.up_to length . each ix-> arr.set_at ix item
|
||||
Vector arr
|
||||
|
||||
## Gets an element from the vector at a specified index (0-based).
|
||||
|
||||
> Example
|
||||
@ -56,6 +88,10 @@ type Vector
|
||||
from_polyglot_array arr = Vector.new arr.length arr.at
|
||||
|
||||
## Returns the number of elements stored in this vector.
|
||||
|
||||
> Example
|
||||
Checking the length of a vector.
|
||||
[1, 2, 3, 4].length == 4
|
||||
length : Number
|
||||
length = this.to_array.length
|
||||
|
||||
@ -75,56 +111,79 @@ type Vector
|
||||
fold initial function =
|
||||
arr = this.to_array
|
||||
f = acc -> ix -> function acc (arr.at ix)
|
||||
0.upto this.length . fold initial f
|
||||
0.up_to this.length . fold initial f
|
||||
|
||||
## Checks whether a predicate holds for at least one element of this vector.
|
||||
exists : (Any -> Any) -> Boolean
|
||||
exists p =
|
||||
check found ix = if found then found else p ix
|
||||
|
||||
A predicate is a function that takes an element from the vector and
|
||||
returns a boolean value.
|
||||
|
||||
> Example
|
||||
Checking if any element of the list is larger than 3.
|
||||
[1,2,3,4,5].exists (> 3)
|
||||
exists : (Any -> Boolean) -> Boolean
|
||||
exists predicate =
|
||||
check found ix = if found then found else predicate ix
|
||||
this.fold False check
|
||||
|
||||
## Checks whether a predicate holds for at least one element of this vector.
|
||||
|
||||
A predicate is a function that takes an element from the vector and
|
||||
returns a boolean value.
|
||||
|
||||
> Example
|
||||
Checking if any element of the list is larger than 3.
|
||||
[1,2,3,4,5].any (> 3)
|
||||
any : (Any -> Boolean) -> Boolean
|
||||
any predicate = this.exists predicate
|
||||
|
||||
## Checks whether a predicate holds for all elements in this vector.
|
||||
|
||||
> Example
|
||||
Check if all elements in the vector are less than zero.
|
||||
[-1, 1, 5, 8].all (< 0)
|
||||
all : (Any -> Boolean) -> Boolean
|
||||
all predicate = this.fold True (l -> r -> l && predicate r)
|
||||
|
||||
## Checks whether this vector contains a given value as an element.
|
||||
|
||||
> Example
|
||||
Checking if the vector contains the number 72.
|
||||
[1, 383, 72, 301].contains 72
|
||||
contains : Any -> Boolean
|
||||
contains elem = this.exists ix-> ix == elem
|
||||
|
||||
## Checks if this vector is empty.
|
||||
|
||||
> Example
|
||||
Checking for emptiness.
|
||||
[].is_empty == True
|
||||
[1].is_empty == False
|
||||
is_empty : Boolean
|
||||
is_empty = this.length == 0
|
||||
|
||||
## Checks if this vector is not empty.
|
||||
|
||||
> Example
|
||||
Checking for non-emptiness.
|
||||
[].not_empty == False
|
||||
[1].not_empty == True
|
||||
not_empty : Boolean
|
||||
not_empty = not this.is_empty
|
||||
|
||||
## Selects all elements of this vector which satisfy a predicate.
|
||||
|
||||
A predicate is a function that takes an element from the vector and
|
||||
returns a boolean value.
|
||||
|
||||
> Example
|
||||
Selecting all elements that are greater than 3.
|
||||
[1, 2, 3, 4, 5].filter (> 3)
|
||||
filter : (Any -> Boolean) -> Vector
|
||||
filter p =
|
||||
check acc ix = if p ix then acc + [ix] else acc
|
||||
filter predicate =
|
||||
check acc ix = if predicate ix then acc + [ix] else acc
|
||||
this.fold [] check
|
||||
|
||||
## Creates a new vector of the given length, initializing elements using
|
||||
the provided constructor function.
|
||||
|
||||
The constructor function is called with the consecutive indices
|
||||
(0-based) of the vector elements.
|
||||
|
||||
> Example
|
||||
To create a vector containing the numbers 1 through 50:
|
||||
Vector.new 50 (ix -> ix + 1)
|
||||
|
||||
> Example
|
||||
To create a copy of the given vector (`my_vec`):
|
||||
Vector.new my_vec.length (ix -> my_vec.at ix)
|
||||
new : Number -> (Number -> Any) -> Vector
|
||||
new length constructor =
|
||||
arr = Array.new length
|
||||
0.upto length . each ix-> arr.set_at ix (constructor ix)
|
||||
Vector arr
|
||||
|
||||
## Creates a new vector of the given length, filling the elements with
|
||||
the provided constant.
|
||||
|
||||
> Example
|
||||
A vector containing 50 elements, each being the number `42`, can be
|
||||
created by:
|
||||
Vector.fill length=50 item=42
|
||||
fill : Number -> Any -> Vector
|
||||
fill length item =
|
||||
arr = Array.new length
|
||||
0.upto length . each ix-> arr.set_at ix item
|
||||
Vector arr
|
||||
|
||||
## Applies a function to each element of the vector, returning the vector of
|
||||
results.
|
||||
|
||||
@ -137,37 +196,68 @@ type Vector
|
||||
map function =
|
||||
arr = this.to_array
|
||||
new_arr = Array.new arr.length
|
||||
0.upto arr.length . each ix-> new_arr.set_at ix (function (arr.at ix))
|
||||
0.up_to arr.length . each ix-> new_arr.set_at ix (function (arr.at ix))
|
||||
Vector new_arr
|
||||
|
||||
## Applies a function to each element of the vector.
|
||||
|
||||
Unlike `map`, this method does not return the individual results,
|
||||
therefore it is only useful for side-effecting computations.
|
||||
|
||||
> Example
|
||||
In the following example, we're printing each element of the vector
|
||||
to the standard output:
|
||||
[1, 2, 3, 4, 5] . each IO.println
|
||||
each : (Any -> Any) -> Nothing
|
||||
each f =
|
||||
this.map f
|
||||
Nothing
|
||||
|
||||
## Reverses the vector, returning a vector with the same elements, but in
|
||||
the opposite order.
|
||||
reverse : Vector
|
||||
reverse = Vector.new this.length (i -> this.at (this.length - (1 + i)))
|
||||
|
||||
## Generates a human-readable text representation of the vector.
|
||||
|
||||
> Example
|
||||
Converting a vector of numbers to text.
|
||||
[1, 2, 3].to_text == "[1, 2, 3]"
|
||||
to_text : Text
|
||||
to_text =
|
||||
arr = this.to_array
|
||||
if arr.length == 0 then "[]" else
|
||||
if arr.length == 1 then "[" + (arr.at 0 . to_text) + "]" else
|
||||
folder = str -> ix -> str + ", " + (arr.at ix).to_text
|
||||
tail_elems = 1.upto arr.length . fold "" folder
|
||||
tail_elems = 1.up_to arr.length . fold "" folder
|
||||
"[" + (arr.at 0 . to_text) + tail_elems + "]"
|
||||
|
||||
## Checks whether this vector is equal to `that`. Two vectors are considered
|
||||
equal, when they have the same length and their items are pairwise equal.
|
||||
|
||||
> Example
|
||||
Comparing two vectors for equality (this case is false).
|
||||
[1, 2, 3] == [2, 3, 4
|
||||
== : Vector -> Boolean
|
||||
== that =
|
||||
arr1 = this.to_array
|
||||
arr2 = that.to_array
|
||||
eq_at i = arr1.at i == arr2.at i
|
||||
if arr1.length == arr2.length then 0.upto arr1.length . every eq_at else False
|
||||
if arr1.length == arr2.length then 0.up_to arr1.length . all eq_at else False
|
||||
|
||||
## Concatenates two vectors, resulting in a new vector, containing all the
|
||||
elements of `this`, followed by all the elements of `that`.
|
||||
|
||||
> Example
|
||||
Concatenating two single-element vectors.
|
||||
[1] + [2] == [1, 2]
|
||||
+ : Vector -> Vector
|
||||
+ that =
|
||||
this_len = this.length
|
||||
arr = Array.new (this_len + that.length)
|
||||
0.upto this_len . each i->
|
||||
0.up_to this_len . each i->
|
||||
arr.set_at i (this.at i)
|
||||
this.length.upto arr.length . each i->
|
||||
this.length.up_to arr.length . each i->
|
||||
arr.set_at i (that.at i-this_len)
|
||||
Vector arr
|
||||
|
||||
@ -181,28 +271,44 @@ type Vector
|
||||
join separator =
|
||||
if this.length == 0 then "" else
|
||||
if this.length == 1 then this.at 0 else
|
||||
this.at 0 + (1.upto this.length . fold "" acc-> i-> acc + separator + this.at i)
|
||||
this.at 0 + (1.up_to this.length . fold "" acc-> i-> acc + separator + this.at i)
|
||||
|
||||
## Creates a new vector with the first `count` elements on the left of
|
||||
`this` removed.
|
||||
|
||||
> Example
|
||||
The following code returns [2, 3, 4, 5]
|
||||
[1, 2, 3, 4, 5].drop 1
|
||||
drop : Integer -> Vector
|
||||
drop count = if count >= this.length then Vector.new 0 (x -> x) else
|
||||
Vector.new (this.length - count) (i -> this.at i+count)
|
||||
|
||||
## Creates a new vector with the last `count` elements on the right of
|
||||
`this` removed.
|
||||
|
||||
> Example
|
||||
The following code returns [1, 2, 3]
|
||||
[1, 2, 3, 4, 5].drop_right 2
|
||||
drop_right : Integer -> Vector
|
||||
drop_right count = if count >= this.length then Vector.new 0 (x -> x) else
|
||||
this.take (this.length - count)
|
||||
|
||||
## Creates a new vector, consisting of the first `count` elements on the
|
||||
left of `this`.
|
||||
|
||||
> Example
|
||||
The following code returns [1, 2]
|
||||
[1, 2, 3, 4, 5].take 2
|
||||
take : Integer -> Vector
|
||||
take count = if count >= this.length then this else
|
||||
Vector.new count this.at
|
||||
|
||||
## Creates a new vector, consisting of the last `count` elements on the
|
||||
right of `this`.
|
||||
|
||||
> Example
|
||||
The following code returns [3, 4, 5]
|
||||
[1, 2, 3, 4, 5].take_right 3
|
||||
take_right : Integer -> Vector
|
||||
take_right count = if count >= this.length then this else
|
||||
this.drop (this.length - count)
|
||||
@ -226,6 +332,71 @@ type Vector
|
||||
to_json : Json.Array
|
||||
to_json = Json.Array (this.map to_json)
|
||||
|
||||
## Get the first element from the vector.
|
||||
|
||||
> Example
|
||||
The following code returns 1.
|
||||
[1, 2, 3, 4].head
|
||||
> Example
|
||||
Empty vectors return `Nothing`.
|
||||
[].head == Nothing
|
||||
head : Any | Nothing
|
||||
head = if this.length >= 1 then this.at 0 else Nothing
|
||||
|
||||
## Get all elements in the vector except the first.
|
||||
|
||||
> Example
|
||||
The following code returns [2, 3, 4].
|
||||
[1, 2, 3, 4].tail
|
||||
> Example
|
||||
Empty vectors return `Nothing`.
|
||||
[].tail == Nothing
|
||||
tail : Vector | Nothing
|
||||
tail = if this.length >= 1 then this.drop 1 else Nothing
|
||||
|
||||
## Get the all elements in the vector except the last.
|
||||
|
||||
> Example
|
||||
The following code returns [1, 2, 3].
|
||||
[1, 2, 3, 4].init
|
||||
> Example
|
||||
Empty vectors return `Nothing`.
|
||||
[].init == Nothing
|
||||
init : Vector | Nothing
|
||||
init = if this.length >= 1 then this.drop_right 1 else Nothing
|
||||
|
||||
## Get the last element of the vector.
|
||||
|
||||
> Example
|
||||
The following code returns 4.
|
||||
[1, 2, 3, 4].last
|
||||
> Example
|
||||
Empty vectors return `Nothing`.
|
||||
[].last == Nothing
|
||||
last : Vector | Nothing
|
||||
last = if this.length >= 1 then (this.take_right 1).at 0 else Nothing
|
||||
|
||||
## Get the first element from the vector.
|
||||
|
||||
> Example
|
||||
The following code returns 1.
|
||||
[1, 2, 3, 4].head
|
||||
> Example
|
||||
Empty vectors return `Nothing`.
|
||||
[].head == Nothing
|
||||
first : Vector | Nothing
|
||||
first = this.head
|
||||
|
||||
## Get all elements in the vector except the first.
|
||||
|
||||
> Example
|
||||
The following code returns [2, 3, 4].
|
||||
[1, 2, 3, 4].tail
|
||||
> Example
|
||||
Empty vectors return `Nothing`.
|
||||
[].tail == Nothing
|
||||
rest : Vector | Nothing
|
||||
rest = this.tail
|
||||
|
||||
## A builder type for Enso vectors.
|
||||
|
||||
@ -268,7 +439,7 @@ type Builder
|
||||
False ->
|
||||
old_array = this.to_array
|
||||
new_array = Array.new old_array.length*2
|
||||
0.upto this.length . each i->
|
||||
0.up_to this.length . each i->
|
||||
new_array.set_at i (old_array.at i)
|
||||
Nothing
|
||||
Unsafe.set_atom_field this 0 new_array
|
||||
@ -280,7 +451,7 @@ type Builder
|
||||
to_vector =
|
||||
old_array = this.to_array
|
||||
new_array = Array.new this.length
|
||||
0.upto this.length . each i->
|
||||
0.up_to this.length . each i->
|
||||
new_array.set_at i (old_array.at i)
|
||||
Nothing
|
||||
Vector new_array
|
||||
|
@ -1,86 +1,41 @@
|
||||
import Base.Data.Number.Extensions
|
||||
import Base.Data.Text.Extensions
|
||||
import Base.Data.List
|
||||
import Base.Data.Vector
|
||||
import Base.System.File
|
||||
import Base.Meta.Enso_Project
|
||||
import Base.Meta
|
||||
import Base.Error.Extensions
|
||||
import Base.Polyglot.Java
|
||||
import Base.Data.Map
|
||||
import Base.Data.Json
|
||||
import Base.Data.List
|
||||
import Base.Data.Map
|
||||
import Base.Data.Number.Extensions
|
||||
import Base.Data.Pair
|
||||
import Base.Data.Range
|
||||
import Base.Data.Text.Extensions
|
||||
import Base.Data.Vector
|
||||
import Base.Error.Extensions
|
||||
import Base.Math
|
||||
import Base.Meta
|
||||
import Base.Meta.Enso_Project
|
||||
import Base.Polyglot.Java
|
||||
import Base.System.File
|
||||
|
||||
from Builtins import Nothing, Number, Integer, Any, True, False, Cons, Boolean
|
||||
|
||||
export Base.Meta
|
||||
from Builtins export all hiding Meta
|
||||
|
||||
export Base.Data.Map
|
||||
export Base.Data.Json
|
||||
from Base.Data.Number.Extensions export all hiding Math, String
|
||||
from Base.Data.Text.Extensions export Text
|
||||
from Base.Meta.Enso_Project export all
|
||||
from Base.Data.List export Nil, Cons
|
||||
from Base.Data.Vector export Vector
|
||||
from Base.Error.Extensions export all
|
||||
from Base.Polyglot.Java export all
|
||||
export Base.Data.Map
|
||||
export Base.Math
|
||||
export Base.Meta
|
||||
export Base.System.File
|
||||
|
||||
## Represents a right-exclusive range of integer values.
|
||||
type Range
|
||||
type Range start end
|
||||
|
||||
## Applies a function to each element in the range.
|
||||
|
||||
> Example
|
||||
To print all the numbers from 1 to 100 use:
|
||||
1.upto 101 . each IO.println
|
||||
each function =
|
||||
it start end = if start == end then Nothing else
|
||||
function start
|
||||
@Tail_Call it start+1 end
|
||||
it this.start this.end
|
||||
Nothing
|
||||
|
||||
## Combines all the elements of the range, by iteratively applying the
|
||||
passed function with next elements of the range.
|
||||
|
||||
In general, the result of
|
||||
Range start end . fold init f
|
||||
is the same as
|
||||
f (...(f (f init start) start+1)...) end-1
|
||||
|
||||
> Example
|
||||
In the following example, we'll compute the sum of all elements of a
|
||||
range:
|
||||
Range 0 100 . fold 0 (+)
|
||||
fold initial function =
|
||||
it acc start end = if start == end then acc else
|
||||
new_acc = function acc start
|
||||
@Tail_Call it new_acc start+1 end
|
||||
res = it initial this.start this.end
|
||||
res
|
||||
|
||||
## Checks whether `predicate` is satisfied for every number in this range.
|
||||
every predicate =
|
||||
it start end = if start==end then True else
|
||||
r = predicate start
|
||||
if r then (@Tail_Call it start+1 end) else False
|
||||
res = it this.start this.end
|
||||
res
|
||||
|
||||
type Math
|
||||
|
||||
## The mathematical constant pi, equal to the ratio of a circle circumference
|
||||
to its diameter.
|
||||
Math.pi : Decimal
|
||||
Math.pi = 3.141592653589793
|
||||
|
||||
## A pair of elements.
|
||||
type Pair
|
||||
|
||||
type Pair first second
|
||||
from Base.Data.List export Nil, Cons
|
||||
from Base.Data.Number.Extensions export all hiding Math, String
|
||||
from Base.Data.Pair export Pair
|
||||
from Base.Data.Range export Range
|
||||
from Base.Data.Text.Extensions export Text
|
||||
from Base.Data.Vector export Vector
|
||||
from Base.Error.Extensions export all
|
||||
from Base.Meta.Enso_Project export all
|
||||
from Base.Polyglot.Java export all
|
||||
from Builtins export all hiding Meta
|
||||
|
||||
## Generic equality of arbitrary values.
|
||||
|
||||
Two values are considered to be equal in Enso when they have the same
|
||||
structure, and each of the values of their fields are recursively equal.
|
||||
Any.== : Any -> Boolean
|
||||
Any.== that = if Meta.is_same_object this that then True else
|
||||
this_meta = Meta.meta this
|
||||
@ -92,7 +47,7 @@ Any.== that = if Meta.is_same_object this that then True else
|
||||
if not (Meta.is_same_object c_1 c_2) then False else
|
||||
f_1 = this_meta.fields
|
||||
f_2 = that_meta.fields
|
||||
0.upto f_1.length . every i-> (f_1.at i) == (f_2.at i)
|
||||
0.up_to f_1.length . all i-> (f_1.at i) == (f_2.at i)
|
||||
Cons (Meta.Error _) (Meta.Error _) -> this_meta.payload == that_meta.payload
|
||||
Cons (Meta.Polyglot o_1) (Meta.Polyglot o_2) ->
|
||||
langs_match = this_meta.language == Meta.Java && that_meta.language == Meta.Java
|
||||
|
19
distribution/std-lib/Base/src/Math.enso
Normal file
19
distribution/std-lib/Base/src/Math.enso
Normal file
@ -0,0 +1,19 @@
|
||||
from Base import all
|
||||
|
||||
## The mathematical constant pi, equal to the ratio of a circle circumference
|
||||
to its diameter.
|
||||
|
||||
> Example
|
||||
Calculating the area of a circle.
|
||||
circle_area r = 2 * Math.pi * r^2
|
||||
pi : Decimal
|
||||
pi = 3.1415926535897932385
|
||||
|
||||
## The mathematical constant e, the base of the natural logarithm.
|
||||
|
||||
> Example
|
||||
Calculating the natural logarithm of 3.
|
||||
3.log Math.e
|
||||
e : Decimal
|
||||
e = 2.718281828459045235360
|
||||
|
@ -84,7 +84,7 @@ pad txt len =
|
||||
## PRIVATE
|
||||
print_table header rows =
|
||||
content_lengths = Vector.new header.length i->
|
||||
max_row = 0.upto rows.length . fold 0 a-> j-> max a (rows.at j . at i . characters . length)
|
||||
max_row = 0.up_to rows.length . fold 0 a-> j-> max a (rows.at j . at i . characters . length)
|
||||
max max_row (header.at i . characters . length)
|
||||
header_line = zip header content_lengths here.pad . join ' | '
|
||||
divider = content_lengths . map (l -> "-".repeat l+2) . join '+'
|
||||
|
@ -4,7 +4,7 @@ import Test.Bench
|
||||
|
||||
polyglot java import java.util.Random
|
||||
|
||||
gen_list len = 0.upto len . fold Nil (l -> i -> Cons i+1 l)
|
||||
gen_list len = 0.up_to len . fold Nil (l -> i -> Cons i+1 l)
|
||||
|
||||
sum_list_meta list =
|
||||
nil_cons = Meta.meta Nil . constructor
|
||||
@ -20,7 +20,7 @@ sum_recur n = if n == 0 then 0 else 1 + here.sum_recur n-1
|
||||
|
||||
build_map size =
|
||||
rand = Random.new [].to_array
|
||||
0.upto size . fold Map.empty (m -> i -> m.insert (rand.nextInt [10000]) i)
|
||||
0.up_to size . fold Map.empty (m -> i -> m.insert (rand.nextInt [10000]) i)
|
||||
|
||||
main =
|
||||
mil = 1000000
|
||||
|
@ -5,13 +5,13 @@ import Test.Bench
|
||||
polyglot java import java.lang.StringBuilder
|
||||
|
||||
build_long n =
|
||||
res = 1.upto n . fold "" acc-> n-> acc + n.to_text
|
||||
res = 1.up_to n . fold "" acc-> n-> acc + n.to_text
|
||||
Prim_Text_Helper.optimize res
|
||||
res
|
||||
|
||||
build_long_bldr n =
|
||||
bldr = new StringBuilder [].to_array
|
||||
1.upto n . each n-> bldr.append [n]
|
||||
1.up_to n . each n-> bldr.append [n]
|
||||
res = bldr.toString []
|
||||
res
|
||||
|
||||
|
@ -1,16 +1,48 @@
|
||||
import Test
|
||||
|
||||
from Base import all
|
||||
|
||||
spec = describe "List" <|
|
||||
l = Base.Cons 1 <| Base.Cons 2 <| Base.Cons 3 <| Base.Nil
|
||||
l = Cons 1 <| Cons 2 <| Cons 3 <| Nil
|
||||
empty = Nil
|
||||
it "should have properly defined length" <|
|
||||
l.length.should_equal 3
|
||||
it "should have well defined length when empty" <|
|
||||
Nil.length.should_equal 0
|
||||
it "should allow folding the list with an arbitrary operation with .fold" <|
|
||||
sum = l.fold 0 (+)
|
||||
prod = l.fold 1 (*)
|
||||
sum.should_equal 6
|
||||
prod.should_equal 6
|
||||
it "should allow checking if an element satisfies a predicate with .exists" <|
|
||||
any_even = l.exists (x -> x % 2 == 0)
|
||||
any_eq_five = l.exists (== 5)
|
||||
any_even.should_be_true
|
||||
any_eq_five.should_be_false
|
||||
it "should allow checking if an element satisfies a predicate with .any" <|
|
||||
any_even = l.any (x -> x % 2 == 0)
|
||||
any_eq_five = l.any (== 5)
|
||||
any_even.should_be_true
|
||||
any_eq_five.should_be_false
|
||||
it "should allow checking if all elements satisfy a predicate with `.all`" <|
|
||||
all_even = l.all(x -> x % 2 == 0)
|
||||
all_less_than_four = l.all (< 4)
|
||||
all_even . should_be_false
|
||||
all_less_than_four . should_be_true
|
||||
it "should allow checking if an element is in the list with `.contains`" <|
|
||||
l.contains 4 . should_be_false
|
||||
l.contains 3 . should_be_true
|
||||
empty.contains 10 . should_be_false
|
||||
it "should allow checking if the list is empty with `.is_empty`" <|
|
||||
l.is_empty . should_be_false
|
||||
empty.is_empty . should_be_true
|
||||
it "should allow checking if the list is not empty `.not_empty`" <|
|
||||
l.not_empty . should_be_true
|
||||
empty.not_empty . should_be_false
|
||||
it "should allow filtering of the list using `.filter`" <|
|
||||
l.filter (> 2) . should_equal (Cons 3 Nil)
|
||||
it "should allow mapping a function over its elements with .map" <|
|
||||
l.map +1 . head . should_equal 2
|
||||
it "should allow reversing with .reverse" <|
|
||||
l.reverse.head.should_equal 3
|
||||
it "should allow executing an action for each element with .each" <|
|
||||
sum = State.run Number 0 <|
|
||||
l.each el->
|
||||
@ -18,13 +50,30 @@ spec = describe "List" <|
|
||||
State.put Number s+el
|
||||
State.get Number
|
||||
sum.should_equal 6
|
||||
it "should allow folding the list with an arbitrary operation with .fold" <|
|
||||
sum = l.fold 0 (+)
|
||||
prod = l.fold 1 (*)
|
||||
sum.should_equal 6
|
||||
prod.should_equal 6
|
||||
it "should allow checking if an element satisfies a predicate with .any" <|
|
||||
any_even = l.any (x -> x % 2 == 0)
|
||||
any_eq_five = l.any (== 5)
|
||||
any_even.should_be_true
|
||||
any_eq_five.should_be_false
|
||||
it "should allow reversing with .reverse" <|
|
||||
l.reverse.head.should_equal 3
|
||||
it "should allow dropping elements from the left with `.drop`" <|
|
||||
l.drop 1 . should_equal (Cons 2 (Cons 3 Nil))
|
||||
empty.drop 1 . should_equal Nil
|
||||
it "should allow taking elements from the left with `.take`" <|
|
||||
l.take 2 . should_equal (Cons 1 (Cons 2 Nil))
|
||||
empty.take 2 . should_equal Nil
|
||||
it "should allow getting the head of the list with `.head`" <|
|
||||
l.head . should_equal 1
|
||||
empty.head . should_equal Nothing
|
||||
it "should allow getting the tail of the list with `.tail`" <|
|
||||
l.tail . should_equal (Cons 2 (Cons 3 Nil))
|
||||
empty.tail . should_equal Nothing
|
||||
it "should allow getting the init of the list with `.init`" <|
|
||||
l.init . should_equal (Cons 1 (Cons 2 Nil))
|
||||
empty.init . should_equal Nothing
|
||||
it "should allow getting the last element of the list with `.last`" <|
|
||||
l.last . should_equal 3
|
||||
empty.last . should_equal Nothing
|
||||
it "should allow getting the head of the list with `.first`" <|
|
||||
l.first . should_equal 1
|
||||
empty.first . should_equal Nothing
|
||||
it "should allow getting the tail of the list with `.rest`" <|
|
||||
l.rest . should_equal (Cons 2 (Cons 3 Nil))
|
||||
empty.rest . should_equal Nothing
|
||||
|
||||
|
@ -12,20 +12,20 @@ spec =
|
||||
hundred_factorial = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
|
||||
describe "Integers" <|
|
||||
it "should be of unbound size when multiplied" <|
|
||||
1.upto 101 . fold 1 (*) . should_equal hundred_factorial
|
||||
1.up_to 101 . fold 1 (*) . should_equal hundred_factorial
|
||||
it "should be of unbound size when added" <|
|
||||
(almost_max_long + almost_max_long + almost_max_long).should_equal almost_max_long_times_three
|
||||
it "should be of unbound size when subtracted" <|
|
||||
(0 - almost_max_long - almost_max_long - almost_max_long).should_equal almost_max_long_times_three.negate
|
||||
it "should be of unbound size when dividing" <|
|
||||
expected = 3372816184472482867110284450043137767873196479305249187406461598235841786750685581361224832688174410089430537516012695688121622150430744676
|
||||
((1.upto 101 . fold 1 (*)).div 3*almost_max_long).should_equal expected
|
||||
((1.up_to 101 . fold 1 (*)).div 3*almost_max_long).should_equal expected
|
||||
it "should be of unbound size when taking remainder" <|
|
||||
expected = 3191479909175673432
|
||||
((1.upto 101 . fold 1 (*)) % 3*almost_max_long).should_equal expected
|
||||
((1.up_to 101 . fold 1 (*)) % 3*almost_max_long).should_equal expected
|
||||
it "should allow defining extension methods through the Integer type for any number size" <|
|
||||
876543.is_even.should_be_false
|
||||
(1.upto 101 . fold 1 (*)).is_even.should_be_true
|
||||
(1.up_to 101 . fold 1 (*)).is_even.should_be_true
|
||||
it "should handle the negation edge cases" <|
|
||||
x = 9223372036854775808
|
||||
y = -x
|
||||
|
38
test/Tests/src/Data/Range_Spec.enso
Normal file
38
test/Tests/src/Data/Range_Spec.enso
Normal file
@ -0,0 +1,38 @@
|
||||
from Base import all
|
||||
import Test
|
||||
|
||||
spec = describe "Range" <|
|
||||
it "should be created with a start and an end" <|
|
||||
range = 1.up_to 100
|
||||
range.start . should_equal 1
|
||||
range.end . should_equal 100
|
||||
it "should have a length" <|
|
||||
range = 0.up_to 100
|
||||
range.length . should_equal 100
|
||||
it "should allow checking for emptiness" <|
|
||||
0.up_to 0 . is_empty . should_be_true
|
||||
0.up_to -100 . is_empty . should_be_true
|
||||
0.up_to 1 . is_empty . should_be_false
|
||||
0.up_to 5 . is_empty . should_be_false
|
||||
it "should allow checking for non emptiness" <|
|
||||
0.up_to 0 . not_empty . should_be_false
|
||||
0.up_to -100 . not_empty . should_be_false
|
||||
0.up_to 1 . not_empty . should_be_true
|
||||
0.up_to 5 . not_empty . should_be_true
|
||||
it "should allow iteration" <|
|
||||
vec_mut = Vector.new_builder
|
||||
1.up_to 6 . each (i -> vec_mut.append i)
|
||||
vec_mut.to_vector . should_equal [1, 2, 3, 4, 5]
|
||||
it "should be able to be folded" <|
|
||||
1.up_to 6 . fold 0 (+) . should_equal 15
|
||||
it "should check all" <|
|
||||
1.up_to 10 . all (> 0) . should_be_true
|
||||
1.up_to 10 . all (< 0) . should_be_false
|
||||
it "should check exists" <|
|
||||
1.up_to 10 . exists (> 5) . should_be_true
|
||||
1.up_to 10 . exists (> 10) . should_be_false
|
||||
it "should check any" <|
|
||||
1.up_to 10 . any (> 5) . should_be_true
|
||||
1.up_to 10 . any (> 10) . should_be_false
|
||||
it "should allow conversion to vector" <|
|
||||
1.up_to 6 . to_vector . should_equal [1, 2, 3, 4, 5]
|
@ -14,6 +14,9 @@ spec = describe "Text" <|
|
||||
facepalm_codes = [129318, 127996, 8205, 9794, 65039]
|
||||
accent_1 = '\u00E9'
|
||||
accent_2 = '\u0065\u{301}'
|
||||
it "should allow naive length computation over grapheme clusters" <|
|
||||
kshi.length . should_equal 1
|
||||
facepalm.length . should_equal 1
|
||||
it "should compare strings using utf normalization" <|
|
||||
"abc"=="def" . should_be_false
|
||||
accent_1 . should_equal accent_2
|
||||
@ -21,7 +24,7 @@ spec = describe "Text" <|
|
||||
str = kshi + facepalm + accent_1 + accent_2
|
||||
str.characters . should_equal [kshi, facepalm, accent_1, accent_2]
|
||||
it "should split the text on arbitrary sequence" <|
|
||||
"foo, bar, baz" . split_at ", " . should_equal ["foo", "bar", "baz"]
|
||||
"foo, bar, baz" . split ", " . should_equal ["foo", "bar", "baz"]
|
||||
it "should dump utf-8 bytes to a vector" <|
|
||||
kshi.utf_8.should_equal kshi_utf_8
|
||||
it "should convert an array of bytes to text" <|
|
||||
|
@ -1,24 +1,63 @@
|
||||
from Base import all
|
||||
|
||||
import Test
|
||||
|
||||
spec = describe "Vectors" <|
|
||||
it "should allow vector creation with a programmatic constructor" <|
|
||||
Vector.new 100 (ix -> ix + 1) . fold 0 (+) . should_equal 5050
|
||||
it "should allow accessing elements" <|
|
||||
[1,2,3].at 2 . should_equal 3
|
||||
it "should have a well-defined length" <|
|
||||
[1,2,3].length . should_equal 3
|
||||
it "should allow folding an operator over its elements" <|
|
||||
[1,2,3].fold 0 (+) . should_equal 6
|
||||
it "should allow vector creation with a programmatic constructor" <|
|
||||
Vector.new 100 (ix -> ix + 1) . fold 0 (+) . should_equal 5050
|
||||
it "should have a well-defined text conversion" <|
|
||||
[].to_text.should_equal "[]"
|
||||
[1,2,3].to_text.should_equal "[1, 2, 3]"
|
||||
[Nothing].to_text.should_equal "[Nothing]"
|
||||
it "should check exists" <|
|
||||
vec = [1, 2, 3, 4, 5]
|
||||
vec.exists (ix -> ix > 3) . should_be_true
|
||||
vec.exists (ix -> ix < 0) . should_be_false
|
||||
it "should check any" <|
|
||||
vec = [1, 2, 3, 4, 5]
|
||||
vec.any (ix -> ix > 3) . should_be_true
|
||||
vec.any (ix -> ix < 0) . should_be_false
|
||||
it "should check all" <|
|
||||
vec = [1, 2, 3, 4, 5]
|
||||
vec.all (ix -> ix > 0) . should_be_true
|
||||
vec.all (ix -> ix < 5) . should_be_false
|
||||
it "should check contains" <|
|
||||
vec = [1, 2, 3, 4, 5]
|
||||
vec.contains 1 . should_be_true
|
||||
vec.contains 0 . should_be_false
|
||||
it "should check for emptiness" <|
|
||||
non_empty = [1]
|
||||
empty = []
|
||||
non_empty.is_empty . should_be_false
|
||||
empty.is_empty . should_be_true
|
||||
it "should check for non-emptiness" <|
|
||||
non_empty = [1]
|
||||
empty = []
|
||||
non_empty.not_empty . should_be_true
|
||||
empty.not_empty . should_be_false
|
||||
it "should filter elements" <|
|
||||
vec = [1, 2, 3, 4, 5]
|
||||
vec.filter (ix -> ix > 3) . should_equal [4, 5]
|
||||
vec.filter (ix -> ix == 1) . should_equal [1]
|
||||
vec.filter (ix -> ix < 0) . should_equal []
|
||||
it "should allow mapping an operation, returning a new vector" <|
|
||||
vec = [1, 2, 3, 4]
|
||||
mapped = vec.map x-> x * x
|
||||
vec.to_text.should_equal "[1, 2, 3, 4]"
|
||||
mapped.to_text.should_equal "[1, 4, 9, 16]"
|
||||
it "should allow applying a function to each element" <|
|
||||
vec = [1, 2, 3, 4]
|
||||
vec_mut = Vector.new_builder
|
||||
vec.each vec_mut.append
|
||||
vec_mut.to_vector . should_equal vec
|
||||
it "should allow reversing" <|
|
||||
[1, 2, 3].reverse . should_equal [3, 2, 1]
|
||||
it "should have a well-defined text conversion" <|
|
||||
[].to_text.should_equal "[]"
|
||||
[1,2,3].to_text.should_equal "[1, 2, 3]"
|
||||
[Nothing].to_text.should_equal "[Nothing]"
|
||||
it "should define equality" <|
|
||||
[1,2,3]==[1,2] . should_be_false
|
||||
[1,2,3]==[1,2,3] . should_be_true
|
||||
@ -34,16 +73,46 @@ spec = describe "Vectors" <|
|
||||
vec.drop_right 2 . should_equal first_four
|
||||
vec.take 4 . should_equal first_four
|
||||
vec.take_right 4 . should_equal last_four
|
||||
it "should check exists" <|
|
||||
vec = [1, 2, 3, 4, 5]
|
||||
vec.exists (ix -> ix > 3) . should_be_true
|
||||
vec.exists (ix -> ix < 0) . should_be_false
|
||||
it "should check contains" <|
|
||||
vec = [1, 2, 3, 4, 5]
|
||||
vec.contains 1 . should_be_true
|
||||
vec.contains 0 . should_be_false
|
||||
it "should filter elements" <|
|
||||
vec = [1, 2, 3, 4, 5]
|
||||
vec.filter (ix -> ix > 3) . should_equal [4, 5]
|
||||
vec.filter (ix -> ix == 1) . should_equal [1]
|
||||
vec.filter (ix -> ix < 0) . should_equal []
|
||||
it "should allow getting the head element" <|
|
||||
non_empty_vec = [1, 2, 3, 4, 5]
|
||||
singleton_vec = [1]
|
||||
empty_vec = []
|
||||
non_empty_vec.head . should_equal 1
|
||||
singleton_vec.head . should_equal 1
|
||||
empty_vec.head . should_equal Nothing
|
||||
it "should allow getting the tail of the vector" <|
|
||||
non_empty_vec = [1, 2, 3, 4, 5]
|
||||
singleton_vec = [1]
|
||||
empty_vec = []
|
||||
non_empty_vec.tail . should_equal [2, 3, 4, 5]
|
||||
singleton_vec.tail . should_equal []
|
||||
empty_vec.tail . should_equal Nothing
|
||||
it "should allow getting the init of the vector" <|
|
||||
non_empty_vec = [1, 2, 3, 4, 5]
|
||||
singleton_vec = [1]
|
||||
empty_vec = []
|
||||
non_empty_vec.init . should_equal [1, 2, 3, 4]
|
||||
singleton_vec.init . should_equal []
|
||||
empty_vec.init . should_equal Nothing
|
||||
it "should allow getting the last element of the vector" <|
|
||||
non_empty_vec = [1, 2, 3, 4, 5]
|
||||
singleton_vec = [1]
|
||||
empty_vec = []
|
||||
non_empty_vec.last . should_equal 5
|
||||
singleton_vec.last . should_equal 1
|
||||
empty_vec.last . should_equal Nothing
|
||||
it "should allow getting the first element" <|
|
||||
non_empty_vec = [1, 2, 3, 4, 5]
|
||||
singleton_vec = [1]
|
||||
empty_vec = []
|
||||
non_empty_vec.first . should_equal 1
|
||||
singleton_vec.first . should_equal 1
|
||||
empty_vec.first . should_equal Nothing
|
||||
it "should allow getting the rest of the vector" <|
|
||||
non_empty_vec = [1, 2, 3, 4, 5]
|
||||
singleton_vec = [1]
|
||||
empty_vec = []
|
||||
non_empty_vec.rest . should_equal [2, 3, 4, 5]
|
||||
singleton_vec.rest . should_equal []
|
||||
empty_vec.rest . should_equal Nothing
|
||||
|
||||
|
@ -1,43 +1,45 @@
|
||||
import Test
|
||||
|
||||
import Tests.Semantic.Import_Loop.Spec as Import_Loop_Spec
|
||||
import Tests.Semantic.Deep_Export.Spec as Deep_Export_Spec
|
||||
import Tests.Semantic.Java_Interop_Spec
|
||||
import Tests.Semantic.Error_Spec
|
||||
import Tests.Semantic.Names_Spec
|
||||
import Tests.Semantic.Import_Loop.Spec as Import_Loop_Spec
|
||||
import Tests.Semantic.Java_Interop_Spec
|
||||
import Tests.Semantic.Meta_Spec
|
||||
import Tests.Semantic.Names_Spec
|
||||
|
||||
import Tests.Data.Json_Spec
|
||||
import Tests.Data.List_Spec
|
||||
import Tests.Data.Map_Spec
|
||||
import Tests.Data.Numbers_Spec
|
||||
import Tests.Data.Range_Spec
|
||||
import Tests.Data.Text_Spec
|
||||
import Tests.Data.Time.Spec as Time_Spec
|
||||
import Tests.Data.Vector_Spec
|
||||
import Tests.Network.Http_Spec
|
||||
import Tests.Network.Uri_Spec
|
||||
import Tests.Network.Http.Header_Spec
|
||||
import Tests.Network.Http.Request_Spec
|
||||
import Tests.Network.Http_Spec
|
||||
import Tests.Network.Uri_Spec
|
||||
import Tests.System.File_Spec
|
||||
import Tests.System.Process_Spec
|
||||
|
||||
main = Test.Suite.runMain <|
|
||||
List_Spec.spec
|
||||
Numbers_Spec.spec
|
||||
Import_Loop_Spec.spec
|
||||
Names_Spec.spec
|
||||
Error_Spec.spec
|
||||
Deep_Export_Spec.spec
|
||||
Process_Spec.spec
|
||||
Error_Spec.spec
|
||||
File_Spec.spec
|
||||
Header_Spec.spec
|
||||
Http_Spec.spec
|
||||
Import_Loop_Spec.spec
|
||||
Java_Interop_Spec.spec
|
||||
Vector_Spec.spec
|
||||
Json_Spec.spec
|
||||
List_Spec.spec
|
||||
Map_Spec.spec
|
||||
Meta_Spec.spec
|
||||
Names_Spec.spec
|
||||
Numbers_Spec.spec
|
||||
Process_Spec.spec
|
||||
Range_Spec.spec
|
||||
Request_Spec.spec
|
||||
Text_Spec.spec
|
||||
Time_Spec.spec
|
||||
File_Spec.spec
|
||||
Meta_Spec.spec
|
||||
Map_Spec.spec
|
||||
Json_Spec.spec
|
||||
Uri_Spec.spec
|
||||
Header_Spec.spec
|
||||
Request_Spec.spec
|
||||
Http_Spec.spec
|
||||
Vector_Spec.spec
|
||||
|
Loading…
Reference in New Issue
Block a user