use ./condition fn -i [&reverse=false i c]{ if (and (== $c 0) (or (== $i 0) ($i -1))) { put 0 return } if (< $i 0) { i = (+ $c $i) } if (or (and (>= $i 0) (< $i $c)) (and (== $i -1) $reverse) (and (== $i $c) (not $reverse))) { put $i } else { fail 'Index out of range' } } fn -indexes [&from=$false &step=1 l]{ if (== $step 0) { fail 'Step must be ≠ 0' } local:c local:r = (count $l) (< $step 0) if (not $from) { if $r { range &step=$step[1:] $c | each [i]{ - $c $i 1 } } else { range &step=$step $c } } else { from = (-i &reverse=$r $from $c) if $r { c = (+ $from 1) range &step=$step[1:] $c | each [i]{ - $c $i 1 } } else { range &step=$step $from $c } } } fn -loop [&from=$false &step=1 &end=$false cb l]{ if (not $end) { -indexes &from=$from &step=$step $l | each [i]{ put [$i $l[$i]] } | each [e]{ $cb $@e } } else { -indexes &from=$from &step=$step $l | each [i]{ put [$i $l[$i]] } | each [e]{ local:i local:v = $@e if ($end $i $v) { break } $cb $i $v } } } fn -ploop [&from=$false &step=1 cb l]{ -indexes &from=$from &step=$step $l | peach [i]{ put [$i $l[$i]] } | peach [e]{ $cb $@e } } fn -reverse [l]{ -indexes &step=-1 $l | each [i]{ put $l[$i] } } fn -reach [cb l]{ -reverse $l | each [v]{ $cb $v } } fn -empty [l]{ eq (count $l) 0 } fn -filter [cb l]{ each [v]{ if ($cb $v) { put $v } } $l } fn -first [&from=$false &reverse=$false cb l]{ local:f = [v]{ if ($cb $v) { put $v break } } if $reverse { if $from { local:end = (-i $from (count $l)) -reach $f $l[:(+ $end 1)] } else { -reach $f $l } } else { if $from { from = (-i $from (count $l)) drop $from $l | each $f } else { each $f $l } } } fn -filter-index [cb l]{ -loop [i v]{ if ($cb $v) { put $i } } $l } fn -first-index [&from=$false &reverse=$false cb l]{ local:idx = -1 -loop &from=$from &step=(condition:set $reverse -1 1) [i v]{ if ($cb $v) { idx = $i break } } $l put $idx } fn -search [cb l]{ -loop [i v]{ if ($cb $i $v) { put $v } } $l } fn -search-first [&from=$false &reverse=$false cb l]{ -loop &from=$from &step=(condition:set $reverse -1 1) [i v]{ if ($cb $i $v) { put $v break } } $l } fn -search-index [cb l]{ -loop [i v]{ if ($cb $i $v) { put $i } } $l } fn -search-first-index [&from=$false &reverse=$false cb l]{ local:idx = -1 -loop &from=$from &step=(condition:set $reverse -1 1) [i v]{ if ($cb $i $v) { idx = $i break } } put $idx } fn -contains [cb l]{ local:e = $false each [v]{ if ($cb $v) { e = $true break } } $l put $e } fn -exists [cb l]{ local:e = $false -loop [i v]{ if ($cb $i $v) { e = $true break } } $l put $e } fn -remove-duplicate [l]{ local:done = [&] each [v]{ put [&v=$v &e=(has-key $done $v)] done[$v] = $nil } $l | each [v]{ assoc $v k (not $v[e]) } | each [v]{ if $v[k] { put $v[v] } } } fn -premove-duplicate [l]{ local:done= [&] peach [v]{ local:v = $v done[$v] = $nil } keys $done } fn -swap [i j l]{ local:c = (count $l) i j = (-i $i $c) (-i $j $c) if (or (eq $i $c) (eq $j $c)) { fail 'Index out of range' } if (eq $i $j) { all $l } else { i j = (condition:mset (< $i $j) [$i $j] [$j $i]) take $i $l put $l[j] all $l[(+ $i 1):$j] put $l[$i] drop (+ $j 1) $l } } fn -p [@argv]{ local:c = (count $argv) if (eq $c 0) { put [(all)] } elif (eq $c 1) { put $argv[0] } else { fail '0 or 1 argument needed' } } fn to-list [@argv]{ try { -p $@argv } except e { put $argv } } fn indexes [&from=$false &step=1 @argv]{ -indexes &from=$from &step=1 (-p $@argv) } fn loop [&from=$false &step=1 &end=$false cb @argv]{ -loop &from=$from &step=$step &end=$end $cb (-p $@argv) } fn rloop [&end=$false cb @argv]{ loop &step=-1 &end=$end $cb $@argv } fn ploop [&from=$false &step=1 cb @argv]{ -ploop &from=$from &step=$step $cb (-p $@argv) } fn reverse [@argv]{ -reverse (-p $@argv) } fn reach [cb @argv]{ -reach $cb (-p $@argv) } fn empty [@argv]{ -empty (-p $@argv) } fn not-empty [@argv]{ not (empty $@argv) } fn filter [cb @argv]{ -filter $cb (-p $@argv) } fn filter-not [cb @argv]{ filter [v]{ not ($cb $v) } $@argv } fn first [&from=$false &reverse=$false cb @argv]{ -first &from=$from &reverse=$reverse $cb (-p $@argv) } fn filter-index [cb @argv]{ -filter-index $cb (-p $@argv) } fn filter-index-not [cb @argv]{ filter-index [v]{ not ($cb $v) } $@argv } fn first-index [&from=$false &reverse=$false cb @argv]{ -first-index &from=$from &reverse=$reverse $cb (-p $@argv) } fn search [cb @argv]{ -search $cb (-p $@argv) } fn search-not [cb @argv]{ search [i v]{ not ($cb $i $v) } $@argv } fn search-first [&from=$false &reverse=$false cb @argv]{ -search-first &from=$from &reverse=$reverse $cb (-p $@argv) } fn search-index [cb @argv]{ -search-index $cb (-p $@argv) } fn search-index-not [cb @argv]{ search-index [i v]{ not ($cb $i $v) } $@argv } fn search-first-index [&from=$false &reverse=$false cb @argv]{ -search-first-index &from=$from &reverse=$reverse $cb (-p $@argv) } fn contains [cb @argv]{ -contains $cb (-p $@argv) } fn contains-not [cb @argv]{ contains [v]{ not ($cb $v) } $@argv } fn exists [cb @argv]{ -exists $cb (-p $@argv) } fn exists-not [cb @argv]{ exists [i v]{ $cb $i $v } $@argv } fn includes [v @argv]{ contains [e]{ is $v $e } $@argv } fn includes-not [v @argv]{ contains-not [e]{ is $v $e } $@argv } fn reduce [v cb @argv]{ each [e]{ v = ($cb $v $e) } (to-list $@argv) put $v } fn remove-duplicate [@argv]{ -remove-duplicate (-p $@argv) } fn premove-duplicate [@argv]{ -premove-duplicate (-p $@argv) } fn swap [i j @argv]{ -swap $i $j (-p $@argv) } fn -s1 [cb l e]{ local:c = (count $l) local:i = (first-index [v]{ $cb $e $v } $l) if (eq $i 0) { put $e all $l } elif (< $i 0) { all $l put $e } else { all $l[:$i] put $e all $l[{$i}:] } } fn less [cb]{ local:l = [a b]{ < ($cb $a $b) 0 } put $l } fn -sort [cb l]{ order &less-than=(less $cb) $l } fn sort [cb @argv]{ -sort $cb (-p $@argv) }