Functional programming in bash
912b3f2491
maybe - return a tuple of (Nothing) or (Just,value) maybemap - apply map function when maybe has a value and wrap in another maybe; else when nothing return nothing maybevalue - return value of maybe; else when nothing return optional default args |
||
---|---|---|
examples | ||
src | ||
test | ||
.gitignore | ||
.version | ||
README.md | ||
release.sh |
Introduction
Introduction to fun.sh library
Quick start
#!/bin/bash
. <(test -e fun.sh || curl -Ls https://raw.githubusercontent.com/ssledz/bash-fun/master/src/fun.sh > fun.sh; cat fun.sh)
seq 1 4 | sum
Functions overview
plus | append | buff | curry | div | drop |
factorial | filter | foldl | foldr | head | join |
lambda | last | list | map | mod | mul |
prepend | product | ret | revers_str | revers | scanl |
splitc | strip | sub | sum | tail | take |
catch | try | tupl | tupr | tup | tupx |
unlist | zip | λ | with_trampoline | res | call |
list/unlist
$ list 1 2 3
1
2
3
$ list 1 2 3 4 5 | unlist
1 2 3 4 5
take/drop/tail/head/last
$ list 1 2 3 4 | drop 2
3
4
$ list 1 2 3 4 5 | head
1
$ list 1 2 3 4 | tail
2
3
4
$ list 1 2 3 4 5 | last
5
$ list 1 2 3 4 5 | take 2
1
2
join
$ list 1 2 3 4 5 | join ,
1,2,3,4,5
$ list 1 2 3 4 5 | join , [ ]
[1,2,3,4,5]
map
$ seq 1 5 | map λ a . 'echo $((a + 5))'
6
7
8
9
10
$ list a b s d e | map λ a . 'echo $a$(echo $a | tr a-z A-Z)'
aA
bB
sS
dD
eE
$ list 1 2 3 | map echo
1
2
3
$ list 1 2 3 | map 'echo $ is a number'
1 is a number
2 is a number
3 is a number
$ list 1 2 3 4 | map 'echo \($,$\) is a point'
(1,1) is a point
(2,2) is a point
(3,3) is a point
(4,4) is a point
flat map
$ seq 2 3 | map λ a . 'seq 1 $a' | join , [ ]
[1,2,1,2,3]
$ list a b c | map λ a . 'echo $a; echo $a | tr a-z A-z' | join , [ ]
[a,A,b,B,c,C]
filter
$ seq 1 10 | filter λ a . '[[ $(mod $a 2) -eq 0 ]] && ret true || ret false'
2
4
6
8
10
foldl/foldr
$ list a b c d | foldl λ acc el . 'echo -n $acc-$el'
a-b-c-d
$ list '' a b c d | foldr λ acc el .\
'if [[ ! -z $acc ]]; then echo -n $acc-$el; else echo -n $el; fi'
d-c-b-a
$ seq 1 4 | foldl λ acc el . 'echo $(($acc + $el))'
10
$ seq 1 4 | foldl λ acc el . 'echo $(mul $(($acc + 1)) $el)'
64 # 1 + (1 + 1) * 2 + (4 + 1) * 3 + (15 + 1) * 4 = 64
$ seq 1 4 | foldr λ acc el . 'echo $(mul $(($acc + 1)) $el)'
56 # 1 + (1 + 1) * 4 + (8 + 1) * 3 + (27 + 1) * 2 = 56
tup/tupx/tupl/tupr
$ tup a 1
(a,1)
$ tup 'foo bar' 1 'one' 2
(foo bar,1,one,2)
$ tup , 1 3
(u002c,1,3)
$ tupl $(tup a 1)
a
$ tupr $(tup a 1)
1
$ tup , 1 3 | tupl
,
$ tup 'foo bar' 1 'one' 2 | tupl
foo bar
$ tup 'foo bar' 1 'one' 2 | tupr
2
$ tup 'foo bar' 1 'one' 2 | tupx 2
1
$ tup 'foo bar' 1 'one' 2 | tupx 1,3
foo bar
one
$ tup 'foo bar' 1 'one' 2 | tupx 2-4
1
one
2
buff
$ seq 1 10 | buff λ a b . 'echo $(($a + $b))'
3
7
11
15
19
$ seq 1 10 | buff λ a b c d e . 'echo $(($a + $b + $c + $d + $e))'
15
40
zip
$ list a b c d e f | zip $(seq 1 10)
(a,1)
(b,2)
(c,3)
(d,4)
(e,5)
(f,6)
$ list a b c d e f | zip $(seq 1 10) | last | tupr
6
curry
add2() {
echo $(($1 + $2))
}
$ curry inc add2 1
$ inc 2
3
$ seq 1 3 | map λ a . 'inc $a'
2
3
4
try/catch
$ echo 'expr 2 / 0' | try λ _ . 'echo 0'
0
$ echo 'expr 2 / 0' | try λ status . 'echo $status'
2
$ echo 'expr 2 / 2' | try λ _ . 'echo 0'
1
try λ _ . 'echo some errors during pull; exit 1' < <(echo git pull)
$ echo 'expr 2 / 0' \
| LANG=en catch λ cmd status val . 'echo cmd=$cmd,status=$status,val=$val'
cmd=expr 2 / 0,status=2,val=(expr:,division,by,zero)
$ echo 'expr 2 / 2' | catch λ _ _ val . 'tupl $val'
1
scanl
$ seq 1 5 | scanl lambda acc el . 'echo $(($acc + $el))'
1
3
6
10
15
$ seq 1 5 | scanl lambda a b . 'echo $(($a + $b))' | last
15
with_trampoline/res/call
factorial() {
fact_iter() {
local product=$1
local counter=$2
local max_count=$3
if [[ $counter -gt $max_count ]]; then
res $product
else
call fact_iter $(echo $counter\*$product | bc) $(($counter + 1)) $max_count
fi
}
with_trampoline fact_iter 1 1 $1
}
$ time factorial 30 | fold -w 70
265252859812191058636308480000000
real 0m1.854s
user 0m0.072s
sys 0m0.368s
time factorial 60 | fold -w 70
8320987112741390144276341183223364380754172606361245952449277696409600
000000000000
real 0m3.635s
user 0m0.148s
sys 0m0.692s
$ time factorial 90 | fold -w 70
1485715964481761497309522733620825737885569961284688766942216863704985
393094065876545992131370884059645617234469978112000000000000000000000
real 0m4.371s
user 0m0.108s
sys 0m0.436s
Examples
processNames() {
uppercase() {
local str=$1
echo $(tr 'a-z' 'A-Z' <<< ${str:0:1})${str:1}
}
list $@ \
| filter λ name . '[[ ${#name} -gt 1 ]] && ret true || ret false' \
| map λ name . 'uppercase $name' \
| foldl λ acc el . 'echo $acc,$el'
}
processNames adam monika s slawek d daniel Bartek j k
Adam,Monika,Slawek,Daniel,Bartek