(eval-when (:load-toplevel :compile-toplevel :execute)
(defun simple-lambda-list-p (lambda-list)
(notany (lambda (x)
(member x '(&optional &rest &key)))
lambda-list))
(defmacro spicy-lambda ((&rest args) &body body)
(assert (simple-lambda-list-p args) (args))
(reduce (lambda (arg form)
`(lambda (,arg) ,form))
args :from-end t :initial-value `(progn ,@body)))
(defmacro defspicy (name (&rest args) &body body)
(if (<= (length args) 1)
`(defun ,name ,args ,@body)
`(defun ,name (,(first args))
(spicy-lambda ,(rest args) ,@body))))
(defun $-reader (stream subchar arg)
(destructuring-bind (function &rest args) (read stream t nil t)
(let ((init-expr
`(,@(cond ((eq function 'funcall) `(funcall ,(pop args)))
((eq function 'apply) (error "`apply' is not implemented yet"))
((symbolp function) `(,function))
((listp function) `(funcall ,function)))
,@(and args `(,(pop args))))))
(reduce (lambda (fn x) `(funcall ,fn ,x)) args :initial-value init-expr))))
(set-dispatch-macro-character #\# #\$ '$-reader))
(defspicy compose (f g x)
(funcall f (funcall g x)))
(defspicy const (x y) x)
(defspicy plus (x y) (+ x y))
;; yoba dx = (dx +) . length
(defspicy yoba (dx)
#$(compose (plus dx) 'length))
(map 'nil #$(compose 'print (yoba 111))
'(() (1) (3 2 3)))
KGV2YWwtd2hlbiAoOmxvYWQtdG9wbGV2ZWwgOmNvbXBpbGUtdG9wbGV2ZWwgOmV4ZWN1dGUpCihkZWZ1biBzaW1wbGUtbGFtYmRhLWxpc3QtcCAobGFtYmRhLWxpc3QpCiAgKG5vdGFueSAobGFtYmRhICh4KQogICAgICAgICAgICAobWVtYmVyIHggJygmb3B0aW9uYWwgJnJlc3QgJmtleSkpKQogICAgICAgICAgbGFtYmRhLWxpc3QpKQoKKGRlZm1hY3JvIHNwaWN5LWxhbWJkYSAoKCZyZXN0IGFyZ3MpICZib2R5IGJvZHkpCiAgKGFzc2VydCAoc2ltcGxlLWxhbWJkYS1saXN0LXAgYXJncykgKGFyZ3MpKQogIChyZWR1Y2UgKGxhbWJkYSAoYXJnIGZvcm0pCiAgICAgICAgICAgIGAobGFtYmRhICgsYXJnKSAsZm9ybSkpCiAgICAgICAgICBhcmdzIDpmcm9tLWVuZCB0IDppbml0aWFsLXZhbHVlIGAocHJvZ24gLEBib2R5KSkpCgooZGVmbWFjcm8gZGVmc3BpY3kgKG5hbWUgKCZyZXN0IGFyZ3MpICZib2R5IGJvZHkpCiAgKGlmICg8PSAobGVuZ3RoIGFyZ3MpIDEpCiAgICAgIGAoZGVmdW4gLG5hbWUgLGFyZ3MgLEBib2R5KQogICAgICBgKGRlZnVuICxuYW1lICgsKGZpcnN0IGFyZ3MpKQogICAgICAgICAoc3BpY3ktbGFtYmRhICwocmVzdCBhcmdzKSAsQGJvZHkpKSkpCgooZGVmdW4gJC1yZWFkZXIgKHN0cmVhbSBzdWJjaGFyIGFyZykKICAoZGVzdHJ1Y3R1cmluZy1iaW5kIChmdW5jdGlvbiAmcmVzdCBhcmdzKSAocmVhZCBzdHJlYW0gdCBuaWwgdCkKICAgIChsZXQgKChpbml0LWV4cHIKICAgICAgICAgICAgYCgsQChjb25kICgoZXEgZnVuY3Rpb24gJ2Z1bmNhbGwpIGAoZnVuY2FsbCAsKHBvcCBhcmdzKSkpCiAgICAgICAgICAgICAgICAgICAgICAoKGVxIGZ1bmN0aW9uICdhcHBseSkgICAoZXJyb3IgImBhcHBseScgaXMgbm90IGltcGxlbWVudGVkIHlldCIpKQogICAgICAgICAgICAgICAgICAgICAgKChzeW1ib2xwIGZ1bmN0aW9uKSAgICAgYCgsZnVuY3Rpb24pKQogICAgICAgICAgICAgICAgICAgICAgKChsaXN0cCBmdW5jdGlvbikgICAgICAgYChmdW5jYWxsICxmdW5jdGlvbikpKQogICAgICAgICAgICAgICxAKGFuZCBhcmdzIGAoLChwb3AgYXJncykpKSkpKQogICAgICAocmVkdWNlIChsYW1iZGEgKGZuIHgpIGAoZnVuY2FsbCAsZm4gLHgpKSBhcmdzIDppbml0aWFsLXZhbHVlIGluaXQtZXhwcikpKSkKCihzZXQtZGlzcGF0Y2gtbWFjcm8tY2hhcmFjdGVyICNcIyAjXCQgJyQtcmVhZGVyKSkKCgoKKGRlZnNwaWN5IGNvbXBvc2UgKGYgZyB4KQogIChmdW5jYWxsIGYgKGZ1bmNhbGwgZyB4KSkpCgooZGVmc3BpY3kgY29uc3QgKHggeSkgeCkKCihkZWZzcGljeSBwbHVzICh4IHkpICgrIHggeSkpCgo7OyB5b2JhIGR4ID0gKGR4ICspIC4gbGVuZ3RoCihkZWZzcGljeSB5b2JhIChkeCkKICAjJChjb21wb3NlIChwbHVzIGR4KSAnbGVuZ3RoKSkKCihtYXAgJ25pbCAjJChjb21wb3NlICdwcmludCAoeW9iYSAxMTEpKQogICAgICcoKCkgKDEpICgzIDIgMykpKQ==