mirror of
https://github.com/denisidoro/navi
synced 2024-11-21 19:13:07 +00:00
Improve lib for collections (#82)
This commit is contained in:
parent
1b12ffa330
commit
9dce96a871
9 changed files with 190 additions and 66 deletions
70
src/coll.sh
Normal file
70
src/coll.sh
Normal file
|
@ -0,0 +1,70 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
coll::new() {
|
||||
for x in "$@"; do
|
||||
echo "$x"
|
||||
done
|
||||
}
|
||||
|
||||
coll::first() {
|
||||
head -n1
|
||||
}
|
||||
|
||||
coll::rest() {
|
||||
tail -n +2
|
||||
}
|
||||
|
||||
coll::map() {
|
||||
local -r fn="$1"
|
||||
|
||||
for x in $(cat); do
|
||||
"$fn" "$x"
|
||||
done
|
||||
}
|
||||
|
||||
coll::filter() {
|
||||
local -r pred="$1"
|
||||
|
||||
for x in $(cat); do
|
||||
"$pred" "$x" && echo "$x" || true
|
||||
done
|
||||
}
|
||||
|
||||
coll::remove() {
|
||||
local -r pred="$1"
|
||||
|
||||
for x in $(cat); do
|
||||
"$pred" "$x" || echo "$x"
|
||||
done
|
||||
}
|
||||
|
||||
coll::add() {
|
||||
cat
|
||||
for x in "$@"; do
|
||||
echo "$x"
|
||||
done
|
||||
}
|
||||
|
||||
coll::reverse() {
|
||||
tac
|
||||
}
|
||||
|
||||
coll::set() {
|
||||
sort -u
|
||||
}
|
||||
|
||||
# TODO: implement tailrec
|
||||
coll::reduce() {
|
||||
local -r fn="$1"
|
||||
local state="$2"
|
||||
|
||||
local -r coll="$(cat)"
|
||||
local -r x="$(echo "$coll" | coll::first)"
|
||||
|
||||
if [ -z "$x" ]; then
|
||||
echo "$state"
|
||||
else
|
||||
local -r new_state="$("$fn" "$state" "$x")"
|
||||
echo "$coll" | coll::rest | coll::reduce "$fn" "$new_state"
|
||||
fi
|
||||
}
|
|
@ -107,7 +107,7 @@ dict::update() {
|
|||
local -r input="$(cat)"
|
||||
|
||||
local -r value="$(echo "$input" | dict::get "$key")"
|
||||
local -r updated_value="$(eval "$fn" "$value")"
|
||||
local -r updated_value="$("$fn" "$value")"
|
||||
|
||||
echo "$input" | dict::assoc "$key" "$updated_value"
|
||||
}
|
32
src/func.sh
32
src/func.sh
|
@ -1,32 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
func::list() {
|
||||
for x in "$@"; do
|
||||
echo "$x"
|
||||
done
|
||||
}
|
||||
|
||||
func::map() {
|
||||
local -r fn="$1"
|
||||
shift
|
||||
|
||||
for x in $(cat); do
|
||||
"$fn" "$x"
|
||||
done
|
||||
}
|
||||
|
||||
func::reduce() {
|
||||
local -r fn="$1"
|
||||
local state="$2"
|
||||
|
||||
local -r coll="$(cat)"
|
||||
local -r x="$(echo "$coll" | head -n1)"
|
||||
|
||||
if [ -z "$x" ]; then
|
||||
echo "$state"
|
||||
else
|
||||
local -r new_state="$("$fn" "$state" "$x")"
|
||||
local -r new_coll="$(echo "$coll" | tail -n +2)"
|
||||
echo "$new_coll" | func::reduce "$fn" "$new_state"
|
||||
fi
|
||||
}
|
|
@ -6,8 +6,8 @@ fi
|
|||
|
||||
source "${SCRIPT_DIR}/src/arg.sh"
|
||||
source "${SCRIPT_DIR}/src/cheat.sh"
|
||||
source "${SCRIPT_DIR}/src/coll.sh"
|
||||
source "${SCRIPT_DIR}/src/dict.sh"
|
||||
source "${SCRIPT_DIR}/src/func.sh"
|
||||
source "${SCRIPT_DIR}/src/health.sh"
|
||||
source "${SCRIPT_DIR}/src/misc.sh"
|
||||
source "${SCRIPT_DIR}/src/opts.sh"
|
||||
|
|
|
@ -4,4 +4,5 @@ assert_docker_cheat() {
|
|||
cheat::find | grep -q "docker.cheat"
|
||||
}
|
||||
|
||||
test::set_suite "cheat"
|
||||
test::run "We can find at least one known cheatsheet" assert_docker_cheat
|
||||
|
|
109
test/coll_test.sh
Normal file
109
test/coll_test.sh
Normal file
|
@ -0,0 +1,109 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
test::coll_equals() {
|
||||
local -r actual="$(cat)"
|
||||
local -r expected="$(coll::new "$@")"
|
||||
|
||||
echo "$actual" | test::equals "$expected"
|
||||
}
|
||||
|
||||
inc() {
|
||||
local -r x="$1"
|
||||
echo $((x+1))
|
||||
}
|
||||
|
||||
sum() {
|
||||
local -r x="$1"
|
||||
local -r y="$2"
|
||||
echo $((x*y))
|
||||
}
|
||||
|
||||
powers() {
|
||||
local x="$1"
|
||||
coll::new $((x*10)) $((x*100))
|
||||
}
|
||||
|
||||
odd() {
|
||||
local x="$1"
|
||||
[ $((x%2)) -eq 1 ]
|
||||
}
|
||||
|
||||
coll_map() {
|
||||
coll::new 1 2 3 \
|
||||
| coll::map inc \
|
||||
| test::coll_equals 2 3 4
|
||||
}
|
||||
|
||||
coll_flatmap() {
|
||||
coll::new 1 2 3 \
|
||||
| coll::map powers \
|
||||
| test::coll_equals 10 100 20 200 30 300
|
||||
}
|
||||
|
||||
coll_reduce() {
|
||||
coll::new 1 2 3 \
|
||||
| coll::reduce sum 10 \
|
||||
| test::equals 60
|
||||
}
|
||||
|
||||
coll_filter() {
|
||||
coll::new 1 2 3 4 5 \
|
||||
| coll::filter odd \
|
||||
| test::coll_equals 1 3 5
|
||||
}
|
||||
|
||||
coll_remove() {
|
||||
coll::new 1 2 3 4 5 \
|
||||
| coll::remove odd \
|
||||
| test::coll_equals 2 4
|
||||
}
|
||||
|
||||
coll_first() {
|
||||
coll::new 1 2 3 \
|
||||
| coll::first \
|
||||
| test::coll_equals 1
|
||||
}
|
||||
|
||||
coll_rest() {
|
||||
coll::new 1 2 3 \
|
||||
| coll::rest \
|
||||
| test::coll_equals 2 3
|
||||
}
|
||||
|
||||
coll_add() {
|
||||
coll::new 1 2 3 \
|
||||
| coll::add 4 5 \
|
||||
| coll::add 6 7 \
|
||||
| test::coll_equals 1 2 3 4 5 6 7
|
||||
}
|
||||
|
||||
coll_concat() {
|
||||
coll::new 1 2 3 \
|
||||
| coll::add "$(coll::new 4 5)" \
|
||||
| test::coll_equals 1 2 3 4 5
|
||||
}
|
||||
|
||||
coll_reverse() {
|
||||
coll::new 1 2 3 \
|
||||
| coll::reverse \
|
||||
| test::coll_equals 3 2 1
|
||||
}
|
||||
|
||||
coll_set() {
|
||||
coll::new 1 2 3 2 4 2 \
|
||||
| coll::set \
|
||||
| test::coll_equals 1 2 3 4
|
||||
}
|
||||
|
||||
test::set_suite "coll"
|
||||
test::run "map" coll_map
|
||||
test::run "filter" coll_filter
|
||||
test::run "remove" coll_remove
|
||||
test::run "first" coll_first
|
||||
test::run "rest" coll_rest
|
||||
test::run "add" coll_add
|
||||
test::run "add can be used as concat" coll_concat
|
||||
test::run "reduce" coll_reduce
|
||||
test::run "we can use map as flatmap" coll_flatmap
|
||||
test::run "reverse" coll_reverse
|
||||
test::run "set" coll_set
|
|
@ -7,6 +7,7 @@ opts::eval "$@"
|
|||
|
||||
PASSED=0
|
||||
FAILED=0
|
||||
SUITE=""
|
||||
|
||||
test::success() {
|
||||
PASSED=$((PASSED+1))
|
||||
|
@ -19,9 +20,13 @@ test::fail() {
|
|||
return
|
||||
}
|
||||
|
||||
test::set_suite() {
|
||||
SUITE="$*"
|
||||
}
|
||||
|
||||
test::run() {
|
||||
echo
|
||||
log::note "$1"
|
||||
log::note "${SUITE:-unknown} - ${1:-unknown}"
|
||||
shift
|
||||
eval "$*" && test::success || test::fail
|
||||
}
|
||||
|
|
|
@ -9,10 +9,7 @@ test::map_equals() {
|
|||
local -r actual="$(cat | dict::_unescape_value | sort)"
|
||||
local -r expected="$(dict::new "$@" | dict::_unescape_value | sort)"
|
||||
|
||||
if [[ "$actual" != "$expected" ]]; then
|
||||
log::error "Expected '${expected}' but got '${actual}'"
|
||||
return 2
|
||||
fi
|
||||
echo "$actual" | test::equals "$expected"
|
||||
}
|
||||
|
||||
dict_assoc() {
|
||||
|
@ -103,6 +100,7 @@ dict_update() {
|
|||
| test::map_equals "foo" 42 "bar" 6
|
||||
}
|
||||
|
||||
test::set_suite "dict"
|
||||
test::run "We can assoc a value" dict_assoc
|
||||
test::run "We can assoc multiple values" dict_assoc_multiple
|
||||
test::skip "We can assoc a nested value" dict_assoc_nested
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
inc() {
|
||||
local -r x="$1"
|
||||
echo $((x+1))
|
||||
}
|
||||
|
||||
sum() {
|
||||
local -r x="$1"
|
||||
local -r y="$2"
|
||||
echo $((x*y))
|
||||
}
|
||||
|
||||
func_map() {
|
||||
func::list 1 2 3 \
|
||||
| func::map inc \
|
||||
| test::equals "$(func::list 2 3 4)"
|
||||
}
|
||||
|
||||
func_reduce() {
|
||||
func::list 1 2 3 \
|
||||
| func::reduce sum 10 \
|
||||
| test::equals 60
|
||||
}
|
||||
|
||||
test::run "map works" func_map
|
||||
test::run "reduce works" func_reduce
|
Loading…
Reference in a new issue