parent
754dd0d1fb
commit
ec27b47648
8 changed files with 303 additions and 124 deletions
@ -0,0 +1,7 @@ |
||||
#!/usr/bin/env bash |
||||
|
||||
if [ -z "$EMACS" ] ; then |
||||
EMACS="emacs" |
||||
fi |
||||
|
||||
$EMACS -batch -l examples-to-docs.el -l bang.el -l examples.el -f create-docs-file |
||||
@ -0,0 +1,144 @@ |
||||
## !map `(fn list)` |
||||
|
||||
Returns a new list consisting of the result of applying FN to the items in list. |
||||
|
||||
```cl |
||||
(!map (lambda (num) (* num num)) (quote (1 2 3 4))) ;; => (quote (1 4 9 16)) |
||||
(!map (quote square) (quote (1 2 3 4))) ;; => (quote (1 4 9 16)) |
||||
(!!map (* it it) (quote (1 2 3 4))) ;; => (quote (1 4 9 16)) |
||||
``` |
||||
|
||||
## !reduce-from `(fn initial-value list)` |
||||
|
||||
Returns the result of applying FN to INITIAL-VALUE and the |
||||
first item in LIST, then applying FN to that result and the 2nd |
||||
item, etc. If LIST contains no items, returns INITIAL-VALUE and |
||||
FN is not called. |
||||
|
||||
```cl |
||||
(!reduce-from (quote +) 7 (quote nil)) ;; => 7 |
||||
(!reduce-from (quote +) 7 (quote (1))) ;; => 8 |
||||
(!reduce-from (quote +) 7 (quote (1 2))) ;; => 10 |
||||
(!!reduce-from (+ acc it) 7 (quote (1 2 3))) ;; => 13 |
||||
``` |
||||
|
||||
## !reduce `(fn list)` |
||||
|
||||
Returns the result of applying FN to the first 2 items in LIST, |
||||
then applying FN to that result and the 3rd item, etc. If LIST |
||||
contains no items, FN must accept no arguments as well, and |
||||
reduce returns the result of calling FN with no arguments. If |
||||
LIST has only 1 item, it is returned and FN is not called. |
||||
|
||||
```cl |
||||
(!reduce (quote +) (quote nil)) ;; => 0 |
||||
(!reduce (quote +) (quote (1))) ;; => 1 |
||||
(!reduce (quote +) (quote (1 2))) ;; => 3 |
||||
(!reduce (lambda (memo item) (format %s-%s memo item)) (quote (1 2 3))) ;; => 1-2-3 |
||||
(!!reduce (format %s-%s acc it) (quote (1 2 3))) ;; => 1-2-3 |
||||
(!!reduce (format %s-%s acc it) (quote nil)) ;; => nil-nil |
||||
``` |
||||
|
||||
## !filter `(fn list)` |
||||
|
||||
Returns a new list of the items in LIST for which FN returns a non-nil value. |
||||
|
||||
```cl |
||||
(!filter (lambda (num) (= 0 (% num 2))) (quote (1 2 3 4))) ;; => (quote (2 4)) |
||||
(!filter (quote even?) (quote (1 2 3 4))) ;; => (quote (2 4)) |
||||
(!!filter (= 0 (% it 2)) (quote (1 2 3 4))) ;; => (quote (2 4)) |
||||
``` |
||||
|
||||
## !remove `(fn list)` |
||||
|
||||
Returns a new list of the items in LIST for which FN returns nil. |
||||
|
||||
```cl |
||||
(!remove (lambda (num) (= 0 (% num 2))) (quote (1 2 3 4))) ;; => (quote (1 3)) |
||||
(!remove (quote even?) (quote (1 2 3 4))) ;; => (quote (1 3)) |
||||
(!!remove (= 0 (% it 2)) (quote (1 2 3 4))) ;; => (quote (1 3)) |
||||
``` |
||||
|
||||
## !concat `(&rest lists)` |
||||
|
||||
Returns a new list with the concatenation of the elements in |
||||
the supplied LISTS. |
||||
|
||||
```cl |
||||
(!concat) ;; => nil |
||||
(!concat (quote (1))) ;; => (quote (1)) |
||||
(!concat (quote (1)) (quote (2))) ;; => (quote (1 2)) |
||||
(!concat (quote (1)) (quote (2 3)) (quote (4))) ;; => (quote (1 2 3 4)) |
||||
``` |
||||
|
||||
## !mapcat `(fn list)` |
||||
|
||||
Returns the result of applying concat to the result of applying map to FN and LIST. |
||||
Thus function FN should return a collection. |
||||
|
||||
```cl |
||||
(!mapcat (quote list) (quote (1 2 3))) ;; => (quote (1 2 3)) |
||||
(!mapcat (lambda (item) (list 0 item)) (quote (1 2 3))) ;; => (quote (0 1 0 2 0 3)) |
||||
(!!mapcat (list 0 it) (quote (1 2 3))) ;; => (quote (0 1 0 2 0 3)) |
||||
``` |
||||
|
||||
## !partial `(fn &rest args)` |
||||
|
||||
Takes a function FN and fewer than the normal arguments to FN, |
||||
and returns a fn that takes a variable number of additional ARGS. |
||||
When called, the returned function calls FN with args + |
||||
additional args. |
||||
|
||||
```cl |
||||
(funcall (!partial (quote +) 5) 3) ;; => 8 |
||||
(funcall (!partial (quote +) 5 2) 3) ;; => 10 |
||||
``` |
||||
|
||||
## !difference `(list list2)` |
||||
|
||||
Return a new list with only the members of LIST that are not in LIST2. |
||||
The test for equality is done with `equal', |
||||
or with `!compare-fn' if that's non-nil. |
||||
|
||||
```cl |
||||
(!difference (quote nil) (quote nil)) ;; => (quote nil) |
||||
(!difference (quote (1 2 3)) (quote (4 5 6))) ;; => (quote (1 2 3)) |
||||
(!difference (quote (1 2 3 4)) (quote (3 4 5 6))) ;; => (quote (1 2)) |
||||
``` |
||||
|
||||
## !intersection `(list list2)` |
||||
|
||||
Return a new list containing only the elements that are members of both LIST and LIST2. |
||||
The test for equality is done with `equal', |
||||
or with `!compare-fn' if that's non-nil. |
||||
|
||||
```cl |
||||
(!intersection (quote nil) (quote nil)) ;; => (quote nil) |
||||
(!intersection (quote (1 2 3)) (quote (4 5 6))) ;; => (quote nil) |
||||
(!intersection (quote (1 2 3 4)) (quote (3 4 5 6))) ;; => (quote (3 4)) |
||||
``` |
||||
|
||||
## !uniq `(list)` |
||||
|
||||
Return a new list with all duplicates removed. |
||||
The test for equality is done with `equal', |
||||
or with `!compare-fn' if that's non-nil. |
||||
|
||||
```cl |
||||
(!uniq (quote nil)) ;; => (quote nil) |
||||
(!uniq (quote (1 2 2 4))) ;; => (quote (1 2 4)) |
||||
``` |
||||
|
||||
## !contains? `(list element)` |
||||
|
||||
Return whether LIST contains ELEMENT. |
||||
The test for equality is done with `equal', |
||||
or with `!compare-fn' if that's non-nil. |
||||
|
||||
```cl |
||||
(!contains? (quote (1 2 3)) 1) ;; => t |
||||
(!contains? (quote (1 2 3)) 2) ;; => t |
||||
(!contains? (quote nil) (quote nil)) ;; => nil |
||||
(!contains? (quote nil) 1) ;; => nil |
||||
(!contains? (quote (1 2 4)) 3) ;; => nil |
||||
``` |
||||
@ -0,0 +1,31 @@ |
||||
(defvar functions '()) |
||||
|
||||
(defun example-to-string (example) |
||||
(let ((actual (car example)) |
||||
(expected (cadr (cdr example)))) |
||||
(format "%s ;; => %s" actual expected))) |
||||
|
||||
(defun examples-to-strings (examples) |
||||
(let (result) |
||||
(while examples |
||||
(setq result (cons (example-to-string examples) result)) |
||||
(setq examples (cddr (cdr examples)))) |
||||
(nreverse result))) |
||||
|
||||
(defmacro defexamples (cmd &rest examples) |
||||
`(add-to-list 'functions (list |
||||
',cmd ;; command name |
||||
(cadr (symbol-function ',cmd)) ;; signature |
||||
(car (cddr (symbol-function ',cmd))) ;; docstring |
||||
(examples-to-strings ',examples)))) ;; examples |
||||
|
||||
(defun function-to-md (function) |
||||
(let ((command-name (car function)) |
||||
(signature (cadr function)) |
||||
(docstring (cadr (cdr function))) |
||||
(examples (mapconcat 'identity (cadr (cddr function)) "\n"))) |
||||
(format "## %s `%s`\n\n%s\n\n```cl\n%s\n```\n" command-name signature docstring examples))) |
||||
|
||||
(defun create-docs-file () |
||||
(with-temp-file "./docs.md" |
||||
(insert (mapconcat 'function-to-md (nreverse functions) "\n")))) |
||||
@ -0,0 +1,19 @@ |
||||
(require 'ert) |
||||
|
||||
(defun examples-to-should-1 (examples) |
||||
(let ((actual (car examples)) |
||||
(expected (cadr (cdr examples)))) |
||||
`(should (equal ,actual ,expected)))) |
||||
|
||||
(defun examples-to-should (examples) |
||||
(let (result) |
||||
(while examples |
||||
(setq result (cons (examples-to-should-1 examples) result)) |
||||
(setq examples (cddr (cdr examples)))) |
||||
(nreverse result))) |
||||
|
||||
(defmacro defexamples (cmd &rest examples) |
||||
`(ert-deftest ,cmd () |
||||
,@(examples-to-should examples))) |
||||
|
||||
(provide 'examples-to-tests) |
||||
@ -0,0 +1,69 @@ |
||||
(require 'bang) |
||||
|
||||
(defun even? (num) (= 0 (% num 2))) |
||||
(defun square (num) (* num num)) |
||||
|
||||
(defexamples !map |
||||
(!map (lambda (num) (* num num)) '(1 2 3 4)) => '(1 4 9 16) |
||||
(!map 'square '(1 2 3 4)) => '(1 4 9 16) |
||||
(!!map (* it it) '(1 2 3 4)) => '(1 4 9 16)) |
||||
|
||||
(defexamples !reduce-from |
||||
(!reduce-from '+ 7 '()) => 7 |
||||
(!reduce-from '+ 7 '(1)) => 8 |
||||
(!reduce-from '+ 7 '(1 2)) => 10 |
||||
(!!reduce-from (+ acc it) 7 '(1 2 3)) => 13) |
||||
|
||||
(defexamples !reduce |
||||
(!reduce '+ '()) => 0 |
||||
(!reduce '+ '(1)) => 1 |
||||
(!reduce '+ '(1 2)) => 3 |
||||
(!reduce (lambda (memo item) (format "%s-%s" memo item)) '(1 2 3)) => "1-2-3" |
||||
(!!reduce (format "%s-%s" acc it) '(1 2 3)) => "1-2-3" |
||||
(!!reduce (format "%s-%s" acc it) '()) => "nil-nil") |
||||
|
||||
(defexamples !filter |
||||
(!filter (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) => '(2 4) |
||||
(!filter 'even? '(1 2 3 4)) => '(2 4) |
||||
(!!filter (= 0 (% it 2)) '(1 2 3 4)) => '(2 4)) |
||||
|
||||
(defexamples !remove |
||||
(!remove (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) => '(1 3) |
||||
(!remove 'even? '(1 2 3 4)) => '(1 3) |
||||
(!!remove (= 0 (% it 2)) '(1 2 3 4)) => '(1 3)) |
||||
|
||||
(defexamples !concat |
||||
(!concat) => nil |
||||
(!concat '(1)) => '(1) |
||||
(!concat '(1) '(2)) => '(1 2) |
||||
(!concat '(1) '(2 3) '(4)) => '(1 2 3 4)) |
||||
|
||||
(defexamples !mapcat |
||||
(!mapcat 'list '(1 2 3)) => '(1 2 3) |
||||
(!mapcat (lambda (item) (list 0 item)) '(1 2 3)) => '(0 1 0 2 0 3) |
||||
(!!mapcat (list 0 it) '(1 2 3)) => '(0 1 0 2 0 3)) |
||||
|
||||
(defexamples !partial |
||||
(funcall (!partial '+ 5) 3) => 8 |
||||
(funcall (!partial '+ 5 2) 3) => 10) |
||||
|
||||
(defexamples !difference |
||||
(!difference '() '()) => '() |
||||
(!difference '(1 2 3) '(4 5 6)) => '(1 2 3) |
||||
(!difference '(1 2 3 4) '(3 4 5 6)) => '(1 2)) |
||||
|
||||
(defexamples !intersection |
||||
(!intersection '() '()) => '() |
||||
(!intersection '(1 2 3) '(4 5 6)) => '() |
||||
(!intersection '(1 2 3 4) '(3 4 5 6)) => '(3 4)) |
||||
|
||||
(defexamples !uniq |
||||
(!uniq '()) => '() |
||||
(!uniq '(1 2 2 4)) => '(1 2 4)) |
||||
|
||||
(defexamples !contains? |
||||
(!contains? '(1 2 3) 1) => t |
||||
(!contains? '(1 2 3) 2) => t |
||||
(!contains? '() '()) => nil |
||||
(!contains? '() 1) => nil |
||||
(!contains? '(1 2 4) 3) => nil) |
||||
@ -1,94 +0,0 @@ |
||||
(require 'ert) |
||||
(require 'bang) |
||||
|
||||
(defun even? (num) (= 0 (% num 2))) |
||||
(defun square (num) (* num num)) |
||||
|
||||
(ert-deftest map () |
||||
"`!map' returns a new list with the results of calling the function on each element." |
||||
(should (equal (!map (lambda (num) (* num num)) '(1 2 3 4)) '(1 4 9 16))) |
||||
(should (equal (!map 'square '(1 2 3 4)) '(1 4 9 16))) |
||||
(should (equal (!!map (* it it) '(1 2 3 4)) '(1 4 9 16))) |
||||
) |
||||
|
||||
(ert-deftest reduce-from () |
||||
"`!reduce-from' takes a list and an initial value, and applies the function over them to create one result" |
||||
(should (equal (!reduce '+ '()) 0)) |
||||
(should (equal (!reduce '+ '(1)) 1)) |
||||
(should (equal (!reduce '+ '(1 2)) 3)) |
||||
(should (equal (!reduce-from '+ 7 '()) 7)) |
||||
(should (equal (!reduce-from '+ 7 '(1)) 8)) |
||||
(should (equal (!reduce-from '+ 7 '(1 2)) 10)) |
||||
(should (equal (!!reduce-from (+ acc it) 7 '(1 2 3)) 13)) |
||||
) |
||||
|
||||
(ert-deftest reduce () |
||||
"`!reduce' takes a list and applies the function over the elements to create one result" |
||||
(should (equal (!reduce (lambda (memo item) (format "%s-%s" memo item)) '(1 2 3)) "1-2-3")) |
||||
(should (equal (!!reduce (format "%s-%s" acc it) '(1 2 3)) "1-2-3")) |
||||
(should (equal (!!reduce (format "%s-%s" acc it) '()) "nil-nil")) |
||||
) |
||||
|
||||
(ert-deftest filter () |
||||
"`!filter' returns a new list of only those elements where the predicate was non-nil." |
||||
(should (equal (!filter (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) '(2 4))) |
||||
(should (equal (!filter 'even? '(1 2 3 4)) '(2 4))) |
||||
(should (equal (!!filter (= 0 (% it 2)) '(1 2 3 4)) '(2 4))) |
||||
) |
||||
|
||||
(ert-deftest remove () |
||||
"`!remove' returns a new list of only those elements where the predicate was nil." |
||||
(should (equal (!remove (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) '(1 3))) |
||||
(should (equal (!remove 'even? '(1 2 3 4)) '(1 3))) |
||||
(should (equal (!!remove (= 0 (% it 2)) '(1 2 3 4)) '(1 3))) |
||||
) |
||||
|
||||
(ert-deftest concat () |
||||
"`!concat' returns the concatenation of the elements in the supplied lists" |
||||
(should (equal (!concat) nil)) |
||||
(should (equal (!concat '(1)) '(1))) |
||||
(should (equal (!concat '(1) '(2)) '(1 2))) |
||||
(should (equal (!concat '(1) '(2 3) '(4)) '(1 2 3 4))) |
||||
) |
||||
|
||||
(ert-deftest mapcat () |
||||
"`!mapcat' applies the function to all elements of the list and then concatenates the result" |
||||
(should (equal (!mapcat 'list '(1 2 3)) '(1 2 3))) |
||||
(should (equal (!mapcat (lambda (item) (list 0 item)) '(1 2 3)) '(0 1 0 2 0 3))) |
||||
(should (equal (!!mapcat (list 0 it) '(1 2 3)) '(0 1 0 2 0 3))) |
||||
) |
||||
|
||||
(ert-deftest partial () |
||||
"`!partial' returns a function like fn where the first arguments are filled in" |
||||
(should (equal (funcall (!partial '+ 5) 3) 8)) |
||||
(should (equal (funcall (!partial '+ 5 2) 3) 10)) |
||||
) |
||||
|
||||
(ert-deftest difference () |
||||
"`!difference' returns a new list of only elements in list1 that are not in list2." |
||||
(should (equal (!difference '() '()) '())) |
||||
(should (equal (!difference '(1 2 3) '(4 5 6)) '(1 2 3))) |
||||
(should (equal (!difference '(1 2 3 4) '(3 4 5 6)) '(1 2))) |
||||
) |
||||
|
||||
(ert-deftest intersection () |
||||
"`!intersection' returns a new list of only elements that are in both given lists." |
||||
(should (equal (!intersection '() '()) '())) |
||||
(should (equal (!intersection '(1 2 3) '(4 5 6)) '())) |
||||
(should (equal (!intersection '(1 2 3 4) '(3 4 5 6)) '(3 4))) |
||||
) |
||||
|
||||
(ert-deftest uniq () |
||||
"`!uniq' returns a new list of only unique elements." |
||||
(should (equal (!uniq '()) '())) |
||||
(should (equal (!uniq '(1 2 2 4)) '(1 2 4))) |
||||
) |
||||
|
||||
(ert-deftest contains? () |
||||
"`!contains?' returns t if the list contains the element." |
||||
(should (!contains? '(1 2 3) 1)) |
||||
(should (!contains? '(1 2 3) 2)) |
||||
(should (not (!contains? '() '()))) |
||||
(should (not (!contains? '() 1))) |
||||
(should (not (!contains? '(1 2 4) 3))) |
||||
) |
||||
Loading…
Reference in new issue