Vsevolod <vseloved@gmail.com> wrote:
+---------------
| Slobodan Blazeski <slobodan.blaze...@gmail.com> wrote:
| > I want to make bind symbol _ to represent omitteed parameter so I
| > could make automatical currying using CLOS...
...
| For this purpose I have a reader macro, that implements what's present
| in Arc and Closure -- automatic variable substitution for one-argument
| lambdas. It's not, strictly speaking, currying, but it works for most
| of the practical cases (I use it very often):
| (set-dispatch-macro-character #\# #\` ...[etc]... )
| So you get (funcall #`(plus 2 _) 3)
| A good feature is that it resembles (and thus reminds of) the simple
| function reader macro (#')...
+---------------
This seems to be a common meme!! ;-} My version of this hack
[appended below], which I too use very often in the REPL [but *NEVER*
in code files!!], is much more gross, but gives you up to nine args
plus a &REST arg, flagging both the reader macro and the args with "$"
[in homage to the Bourne Shell], e.g.:
> (mapcar #$(/ $2 $1) '(1 2 3 4 5 6) '#1=(60 . #1#))
(60 30 20 15 12 10)
>
The main reason I prefer it to a multiple-"_" style which some poeple
have proposed is that you can re-order the args as you choose [as above],
which also makes it convenient as a shorthand for simple instances of
DESTRUCTURING-BIND, e.g. (#$$3 12 34 56 78) ==> 56. It's also a shorthand
for CONSTANTLY:
> (mapcar #$17.2 '(1 2 3 4) '#1=(60 . #1#))
(17.2 17.2 17.2 17.2)
>
Its biggest current shortcoming is that the &REST arg "$*" [again,
copied from the Bourne Shell] only applies to args greater than "$9".
There was a long discussion thread here on this very topic a while
back [sorry, I don't remember when] in which it was proposed that
[and someone may have even posted code for!] the macro should do a
full tree walk of its body and collect both the highest "${n}" in the
code and also whether "$*" were used. That way, #$(list* $4 $1 $*)
would expand to:
(lambda ($1 $2 $3 $4 &rest $*)
(declare (ignore $2 $3)) ; or simpler, (ignorable $1 $2 $3 $4 $*)
(list* $4 $1 $*))
Unfortunately, I don't remember when that better version was proposed
[or by whom], so all I have is my own crude hack [which I nevertheless
very often find useful when noodling around in the REPL]:
;;; SET-SHARP-DOLLAR-READER -- Experimental LAMBDA abbreviation
;;; SYNTAX: #$FORM
;;; Abbreviates (lambda (&optional $1 $2 $3 $4 $5 $6 $7 $8 $9 &rest $*) FORM)
;;; Within the FORM, args $1 ... $9 and $* are lambda-bound as positional
;;; and &REST parameters, respectively. Usually, but not always, FORM will be
;;; an S-expr, e.g. #$(car $3), but this is legal: #$FOO ==> (lambda () FOO),
;;; that is, (CONSTANTLY FOO). Likewise, #$$3 ==> #'THIRD.
;;;
;;; As a convenience for interactive use, in the special case that FORM is a
;;; list and (car FORM) is also a list, then an implicit PROGN is provided,
;;; e.g., #$((foo) (bar)) ==> (lambda (args...) (foo) (bar)).
;;;
(defun set-sharp-dollar-reader ()
(flet ((sharp-dollar-reader (s c p)
(declare (ignore c p))
(let* ((form (read s t nil t)))
`(lambda (&optional $1 $2 $3 $4 $5 $6 $7 $8 $9 &rest $*)
(declare (ignorable $1 $2 $3 $4 $5 $6 $7 $8 $9 $*))
,@(if (and (consp form) (consp (car form)))
form
(list form))))))
(set-dispatch-macro-character #\# #\$ #'sharp-dollar-reader)))
Enjoy.(?) ;-}
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607