-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy patharrows.el
65 lines (55 loc) · 2.28 KB
/
arrows.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
;;; -*- lexical-binding: t -*-
;;; https://github.com/nightfly19/cl-arrows/blob/master/arrows.lisp
(defun simple-inserter (insert-fun)
(lambda (acc next)
(if (listp next)
(funcall insert-fun acc next)
(list next acc))))
(defmacro -> (initial-form &rest forms)
"Inserts INITIAL-FORM as first argument into the first of FORMS, the result
into the next, etc., before evaluation. FORMS are treated as list designators."
(reduce (simple-inserter #'insert-first)
forms
:initial-value initial-form))
(defmacro ->> (initial-form &rest forms)
"Like ->, but the forms are inserted as last argument instead of first."
(reduce (simple-inserter #'insert-last)
forms
:initial-value initial-form))
(defun diamond-inserter (insert-fun)
(simple-inserter (lambda (acc next)
(cl-case (count-if #'<>p next)
(0 (funcall insert-fun acc next))
(1 (substitute-if acc #'<>p next))
(t (let ((r (gensym "R")))
`(let ((,r ,acc))
,(substitute-if r #'<>p next))))))))
(defmacro -<> (initial-form &rest forms)
"Like ->, but if a form in FORMS has one or more symbols named <> as top-level
element, each such symbol is substituted by the primary result of the form
accumulated so far, instead of it being inserted as first argument. Also known
as diamond wand."
(reduce (diamond-inserter #'insert-first)
forms
:initial-value initial-form))
(defmacro -<>> (initial-form &rest forms)
"Like -<>, but if a form has no symbol named <>, the insertion is done at the
end like in ->>. Also known as diamond spear."
(reduce (diamond-inserter #'insert-last)
forms
:initial-value initial-form))
(defun <>p (form)
"Predicate identifying the placeholders for the -<> and -<>> macros."
(and (symbolp form)
(string= form "<>")))
(defun insert-first (arg surround)
"Inserts ARG into the list form SURROUND as its first argument, after the
operator."
(list* (car surround)
arg
(cdr surround)))
(defun insert-last (arg surround)
"Inserts ARG into the list form SURROUND as its last argument."
(append surround (list arg)))
(provide 'arrows)
;;; arrows.el ends here