use builtin use str fn -p [@argv]{ local:c = (count $argv) if (== $c 0) { put [ (all) ] } elif (== $c 1) { put $argv[0] } else { fail '0 or 1 argument needed given '$c' arguments: ['(each [e]{ put '"'$e'"' } $argv | str:join ', ')']' } } fn -r [step begin end]{ if (> $step 0) { builtin:range &step=$step $begin (+ $end 1) } else { local:d = (+ $begin $end) builtin:range &step=(* $step -1) $end (+ $begin 1) | each [e]{ - $d $e } } } fn to-list [@argv]{ try { -p $@argv } except e { put $argv } } fn range [&step=1 b @r]{ if (== $step 0) { fail 'bad value: step must be positive, but is 0' } local:c = (count $r) if (> $c 1) { fail 'usage: list:range &step=1 begin? end' } local:e = 0 if (== $c 0) { if (> $step 0) { b e = $e $b } } else { e = $r[0] } -r $step $b $e } fn indexes [&from=$false &step=1 @argv]{ if (== $step 0) { fail 'bad value: step must be positive, but is 0' } local:l = (-p $@argv) local:c = (count $l) if (not $from) { range &step=$step (- $c 1) } else { if (< $from 0) { from = (+ $c $from) } if (> $step 0) { if (< $from 0) { from = 0 } range &step=$step $from (- $c 1) } else { if (>= $from $c) { from = (- $c 1) } range &step=$step $from 0 } } } fn -for [&from=$false &step=1 @argv]{ local:l = (-p $@argv) indexes &from=$from &step=$step $l | each [i]{ put [ $i $l[$i] ] } } fn loop [&from=$false &step=1 &end=$false cb @argv]{ if (not $end) { -for &from=$from &step=$step $@argv | each [e]{ $cb $@e } } else { -for &from=$from &step=$step $@argv | each [e]{ local:i local:v = $@e if ($end $i $v) { break } $cb $i $v } } } fn ploop [&from=$false &step=1 cb @argv]{ -for &from=$from &step=$step $@argv | peach [e]{ $cb $@e } } fn reverse [@argv]{ loop &step=-1 [_ e]{ put $e } $@argv } fn reach [cb @argv]{ reverse $@argv | each [e]{ cb $e } } fn empty [@argv]{ == (count (-p $@argv)) 0 } fn not-empty [@argv]{ not (empty $@argv) } fn filter [cb @argv]{ each [v]{ if ($cb $v) { put $v } } (-p $@argv) } fn filter-not [cb @argv]{ filter [v]{ not ($cb $v) } $@argv } fn first [&from=$false &reverse=$false cb @argv]{ local:f = [v]{ if ($cb $v) { put $v break } } local:l = (-p $@argv) if (not $from) { if $reverse { reach $f $l } else { each $f $l } } else { local:c = (count $l) if (< $from 0) { from = (+ $c $from) } if $reverse { local:e = (+ $from 1) if (> $e $c) { e = $c } elif (< $e 0) { e = 0 } reach $f $l[..$e] } else { local:b = $from if (> $b $c) { b = $c } elif (< $b 0) { b = 0 } each $f $l[$b..] } } } fn filter-index [cb @argv]{ loop [i v]{ if ($cb $v) { put $i } } $@argv } fn filter-index-not [cb @argv]{ filter-index [v]{ not ($cb $v) } $@argv } fn first-index [&from=$false &reverse=$false cb @argv]{ local:idx = -1 local:step = 1 if $reverse { step = -1 } loop &from=$from &step=$step [i v]{ if ($cb $v) { idx = $i break } } $@argv put $idx } fn search [cb @argv]{ loop [i v]{ if ($cb $i $v) { put $v } } $@argv } fn search-not [cb @argv]{ search [i v]{ not ($cb $i $v) } $@argv } fn search-first [&from=$false &reverse=$false cb @argv]{ local:step = 1 if $reverse { step = -1 } loop &from=$from &step=$step [i v]{ if ($cb $i $v) { put $v break } } $@argv } fn search-index [cb @argv]{ loop [i v]{ if ($cb $i $v) { put $i } } $@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]{ local:idx = -1 local:step = 1 if $reverse { step = -1 } loop &from=$from &step=$step [i v]{ if ($cb $i $v) { idx = $i break } } $@argv put $idx } fn contains [cb @argv]{ local:e = $false each [v]{ if ($cb $v) { e = $true break } } (-p $@argv) put $e } fn contains-not [cb @argv]{ contains [v]{ not ($cb $v) } $@argv } fn exists [cb @argv]{ local:e = $false loop [i v]{ if ($cb $i $v) { e = $true break } } $@argv put $e } 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]{ local:done = [&] each [v]{ put [&v=$v &e=(has-key $done $v)] done[$v] = $nil } (-p $@argv) | each [v]{ assoc $v k (not $v[e]) } | each [v]{ if $v[k] { put $v[v] } } } fn premove-duplicate [@argv]{ local:done= [&] peach [v]{ local:v = $v done[$v] = $nil } (-p $@argv) keys $done } fn swap [i j @argv]{ local:l = (-p $@argv) local:c = (count $l) i j = (-i $i $c) (-i $j $c) if (or (== $i $c) (== $j $c)) { fail 'Index out of range' } if (== $i $j) { all $l } else { if (> $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 less [cb]{ local:l = [a b]{ < ($cb $a $b) 0 } put $l } fn sort [cb @argv]{ order &less-than=(less $cb) (-p $@argv) }