Closed nsensfel closed 3 years ago
map
needs a in-place instruction version and a computation version for when in != out
. Same parameters for both.
foldl
, foldr
indexed_map
, merge
, sub_list
, and range
are just computations.
filter
needs an instruction version, which removes the element from the list, and a computation version, which returns a copy of the collection without these elements.
partition
should be a computation returning a cons
of two collections.
pop_left
, pop_right
, push_right
, and push_left
are strictly instructions.
shuffle
can have both an instruction and a computation version.
Let's take this to the extreme, now that registers are cheap: add_element_at
, add_element
, add_elements_of
, remove_all
, remove_element_at
, remove_element
, and reverse
should have computation equivalents.
The strategy would be: implement the instruction version, which is distinguished by a !
suffix. The computation version is simply the instruction version, but working on a copy of the list that was preemptively stored in a register, making the Wyrd implementation easy.
The pop
and push
instructions can have a computation equivalent, which returns a cons
.
The !
notation doesn't look nice. It's not currently set on every instruction either, requiring an effort from the programmer to know whether it is required or not. A better looking alternative needs to be found.
Since there is no sharing of variable between contexts other than global variables, local
variables and parameters that are used inside lambda functions have to be passed as parameters. Because of this, lambda functions used as arguments to map
, fold
, merge
, etc... must be allowed to have extra parameters, which have to be passed as arguments to the calling instruction/computation.
At first glance, it would look like this list of extra arguments could be automatically generated. The issue is: this wouldn't work with stored lambda functions, as the corresponding type would need to include the extra arguments, which makes hiding them for the user a terrible idea.
By https://github.com/nsensfel/tonkadur/commit/91158337a10c006971b66818cabb2e1bed3d494a, the only things that still need to be implemented are the variants of instructions and computations which allow default value (all the merge
ones, basically).
All were added as of https://github.com/nsensfel/tonkadur/commit/0269c0a2943e443179ae6261b265aa06998451f7.
(cons <TYPE> <TYPE>)
(car <CONS>)
and(cdr <CONS>)
(map (lambda <O = TYPE> (<I = TYPE>)) <in = I COLLECTION REFERENCE> <out = COLLECTION REFERENCE>)
(beware thein == out
special case).(indexed_map (lambda <O = TYPE> (<INT> <I = TYPE>)) <in = I COLLECTION REFERENCE> <out = COLLECTION REFERENCE>)
(beware thein == out
special case).(foldl (lambda <O = TYPE> (<I = TYPE> <P = TYPE>)) <P COMPUTATION> <I COLLECTION REFERENCE> <O PTR>)
(foldr (lambda <O = TYPE> (<I = TYPE> <P = TYPE>)) <P COMPUTATION> <I COLLECTION REFERENCE> <O PTR>)
(merge (lambda <O = TYPE> (<I0 = TYPE> <I1 = TYPE>)) <I0 COLLECTION REFERENCE> <I1 COLLECTION REFERENCE> <O COLLECTION REFERENCE>)
, which drops any extra elements.(merge (lambda <O = TYPE> (<I0 = TYPE> <I1 = TYPE>)) <I0 COMPUTATION> <I0 COLLECTION REFERENCE> <I1 COMPUTATION> <I1 COLLECTION REFERENCE> <O COLLECTION REFERENCE>)
, which uses default values for extra elements.(sub_list <INT> <INT> <I = COLLECTION REFERENCE> <O = COLLECTION REFERENCE>)
(filter (lambda <BOOL> (<I0 = TYPE>)) <I0 COLLECTION REFERENCE>)
(partition (lambda <BOOL> (<I0 = TYPE>)) <I0 COLLECTION REFERENCE> <I0 COLLECTION REFERENCE>)
(pop_left <I LIST REFERENCE> <I PTR>)
(pop_right <I LIST REFERENCE> <I PTR>)
(push_right <I> <I LIST REFERENCE>)
(push_left <I> <I LIST REFERENCE>)
(sort (lambda <INT> (<I0 = TYPE> <I0>)) <I0 COLLECTION REFERENCE>)
(range <INT> <INT> <INT> <INT COLLECTION REFERENCE>)
(shuffle <LIST REFERENCE>)