Skip to content

Commit cfee4f3

Browse files
committed
move any, every
1 parent da98437 commit cfee4f3

File tree

1 file changed

+93
-91
lines changed

1 file changed

+93
-91
lines changed

book.org

Lines changed: 93 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,99 @@ EOF
15351535

15361536
Extra explanations: [[https://stackoverflow.com/questions/1250079/how-to-escape-single-quotes-within-single-quoted-strings][StackOverflow]]
15371537

1538+
** any, every, lambdas, closures, and eval
1539+
Bash has no closures, and it's not "functional", but we're going to
1540+
see how we can combine some tricks and get decent high-level functions
1541+
1542+
Here's an implementation of =any= and =every=
1543+
1544+
#+begin_src bash
1545+
any() {
1546+
local pred="$1"; shift
1547+
for i in "$@"; do
1548+
if $pred $i; then
1549+
return 0
1550+
fi
1551+
done
1552+
return 1
1553+
}
1554+
1555+
every() {
1556+
local pred="$1"; shift
1557+
for i in "$@"; do
1558+
if ! $pred $i; then
1559+
return 1
1560+
fi
1561+
done
1562+
return 0
1563+
}
1564+
#+end_src
1565+
1566+
The usage is by passing a callback function that will return 0 or 1.
1567+
1568+
#+begin_src bash
1569+
usage() {
1570+
echo "help message"
1571+
}
1572+
1573+
is_help() {
1574+
[ "$1" = "--help" ]
1575+
}
1576+
1577+
any is_help "$@" && usage
1578+
#+end_src
1579+
1580+
That's already cool.
1581+
1582+
Did you know that functions can start also with dashes?
1583+
1584+
#+begin_src bash
1585+
usage() {
1586+
echo "help message"
1587+
}
1588+
1589+
--help() {
1590+
[ "$1" = "--help" ]
1591+
}
1592+
1593+
any --help "$@" && usage
1594+
#+end_src
1595+
1596+
That also works. It's kinda obfuscated a bit, but hey....
1597+
1598+
We can also, with the help of =eval=, create on demand functions. They
1599+
are global, but as we're not going to multithread, we can assume it's
1600+
ok.
1601+
1602+
#+begin_src bash
1603+
usage() {
1604+
echo "help message"
1605+
}
1606+
1607+
any_eq() {
1608+
eval "_() { [ $1 = \$1 ] ; }"
1609+
shift
1610+
any _ "$@"
1611+
}
1612+
1613+
any_eq "--help" "$@" && usage
1614+
# or,
1615+
any_eq --help "$@" && usage
1616+
#+end_src
1617+
1618+
And the last trick, using =command_not_found_handle=, we can get into
1619+
a kind of rails generators for these helpers
1620+
1621+
#+begin_src bash
1622+
command_not_found_handle() {
1623+
IFS=_ read -a cmd <<<"$1"
1624+
[ "eq" = "${cmd[0]}" ] && eval "$1() { [ \"${cmd[1]}\" = \"\$1\" ] ; }"
1625+
"$@"
1626+
}
1627+
any eq_--help "$@" && usage
1628+
#+end_src
1629+
1630+
15381631
* Interactive
15391632
** Save your small scripts
15401633
Rome wasn't built in a day, and like having a journal log, most of
@@ -1773,97 +1866,6 @@ EOF
17731866
echo "This bit will only be executed on the first foo call"
17741867
}
17751868
#+end_src
1776-
** any, every, lambdas, closures, and eval
1777-
Bash has no closures, and it's not "functional", but we're going to
1778-
see how we can combine some tricks and get decent high-level functions
1779-
1780-
Here's an implementation of =any= and =every=
1781-
1782-
#+begin_src bash
1783-
any() {
1784-
local pred="$1"; shift
1785-
for i in "$@"; do
1786-
if $pred $i; then
1787-
return 0
1788-
fi
1789-
done
1790-
return 1
1791-
}
1792-
1793-
every() {
1794-
local pred="$1"; shift
1795-
for i in "$@"; do
1796-
if ! $pred $i; then
1797-
return 1
1798-
fi
1799-
done
1800-
return 0
1801-
}
1802-
#+end_src
1803-
1804-
The usage is by passing a callback function that will return 0 or 1.
1805-
1806-
#+begin_src bash
1807-
usage() {
1808-
echo "help message"
1809-
}
1810-
1811-
is_help() {
1812-
[ "$1" = "--help" ]
1813-
}
1814-
1815-
any is_help "$@" && usage
1816-
#+end_src
1817-
1818-
That's already cool.
1819-
1820-
Did you know that functions can start also with dashes?
1821-
1822-
#+begin_src bash
1823-
usage() {
1824-
echo "help message"
1825-
}
1826-
1827-
--help() {
1828-
[ "$1" = "--help" ]
1829-
}
1830-
1831-
any --help "$@" && usage
1832-
#+end_src
1833-
1834-
That also works. It's kinda obfuscated a bit, but hey....
1835-
1836-
We can also, with the help of =eval=, create on demand functions. They
1837-
are global, but as we're not going to multithread, we can assume it's
1838-
ok.
1839-
1840-
#+begin_src bash
1841-
usage() {
1842-
echo "help message"
1843-
}
1844-
1845-
any_eq() {
1846-
eval "_() { [ $1 = \$1 ] ; }"
1847-
shift
1848-
any _ "$@"
1849-
}
1850-
1851-
any_eq "--help" "$@" && usage
1852-
# or,
1853-
any_eq --help "$@" && usage
1854-
#+end_src
1855-
1856-
And the last trick, using =command_not_found_handle=, we can get into
1857-
a kind of rails generators for these helpers
1858-
1859-
#+begin_src bash
1860-
command_not_found_handle() {
1861-
IFS=_ read -a cmd <<<"$1"
1862-
[ "eq" = "${cmd[0]}" ] && eval "$1() { [ \"${cmd[1]}\" = \"\$1\" ] ; }"
1863-
"$@"
1864-
}
1865-
any eq_--help "$@" && usage
1866-
#+end_src
18671869

18681870
* Debugging
18691871
** adding =bash= to a script to debug

0 commit comments

Comments
 (0)