/
/f-underscore.lisp
 1 ; `F-UNDERSCORE' is a tiny library of functional programming utilities placed into the
 2 ; public domain
 3 ;
 4 ; the idea is to make functional programs shorter and easier to read without resorting
 5 ; to syntax [like arc's square bracket unary function syntax]
 6 ;
 7 ;   (f (x) ..) -> (lambda (x) ..)
 8 ;
 9 ;   (f0 ..)    -> (lambda () ..)
10 ;
11 ;   (f_ ..)    -> (lambda (_) ..)
12 ;
13 ;   (f_n ..)   -> (lambda (&rest _) ..)
14 ;
15 ;   (f_% ..)   ~= (lambda (&rest #:%) (declare (ignore #:%)) ..)
16 ;
17 ;   (setf (macro-function 'foo) (m args ..)) ~= (defmacro foo args ..)
18 ;
19 
20 (defpackage :f-underscore
21   (:use :cl)
22   (:export ; functional programming utils
23            :f
24            :f0
25 	   :f_
26 	   :f_n
27 	   :_
28 	   :f_%
29 	   :m))
30 
31 (in-package :f-underscore)
32 
33 ; functional programming utils
34 
35 (defmacro f (args &body body)
36   "a synonym for LAMBDA"
37   `(lambda ,args ,@body))
38 
39 (defmacro f0 (&body body)
40   "a LAMBDA that takes 0 arguments (aka a 'thunk')"
41   `(lambda () ,@body))
42 
43 (defmacro f_ (&body body)
44   "a LAMBDA that takes 1 argument: `_'"
45   `(lambda (_) ,@body))
46 
47 (defmacro f_n (&body body)
48   "a LAMBDA that takes 1 &REST argument: `_'"
49   `(lambda (&rest _) ,@body))
50 
51 (defmacro f_% (&body body)
52   "a LAMBDA that takes 1 &REST that it ignores"
53   (let ((% (gensym "ignore")))
54     `(lambda (&rest ,%)
55        (declare (ignore ,%))
56        ,@body)))
57 
58 (defmacro m (macro-lambda-list &body body)
59   "a LAMBDA that has a macro-lambda-list instead of an ordinary lambda-list"
60   (let ((% (gensym "macro-lambda-list")))
61     (if (and (stringp (first body))
62 	     (rest body))
63 
64 	;; there is a doc string
65 	`(lambda (&rest ,%)
66 	   ,(first body)
67 	   (destructuring-bind ,macro-lambda-list ,%
68 	     ,@(rest body)))
69 
70 	;; there is no doc string
71 	`(lambda (&rest ,%)
72 	   (destructuring-bind ,macro-lambda-list ,%
73 	     ,@body)))))