Code: Select all
(set-dispatch-macro-character #\# #\^
(lambda (stream subchar number)
(declare (ignore stream subchar number))
'funcall))
Comments?
Code: Select all
(set-dispatch-macro-character #\# #\^
(lambda (stream subchar number)
(declare (ignore stream subchar number))
'funcall))
I agree that read macros should be used sparsely, but everything can be parsed by the normal lisp reader. I know that defining new higher order functions is not so frequent as using existing ones, but it is a good way to express a concept often enough.nuntius wrote:Comments:
- Read macros are best reserved for syntax which cannot be parsed by the normal lisp reader. Or at least very frequently used shorthand.
Example:- Post an example use of your read macro; I suspect it only saves a few characters. While FUNCTION only has one more character, it often appears more frequently than FUNCALL. Also FUNCTION always takes a single argument; so the #' macro saves a set of parens as well. Finally, both QUOTE and FUNCTION are special operators, whereas FUNCALL is a mere function.
Code: Select all
(#^fun arg) ; expands to (funcall fun arg)
Yes, you could even call it "^". However, my thought is symmetry:- Wouldn't a symbol macro named FC be equivalently useful?
Code: Select all
(mapcar #'zerop list) ; expands to (mapcar (function 'zerop) list)
Code: Select all
(foo #'bar baz) ; the function thing of foo is applied to the function thing of bar and the value thing of baz
(#^foo bar baz) ; the value thing of foo is applied to the value thing of bar and the value thing of baz
I encountered the argument that when defining a new higher order function, you often have to type out the FUNCALL in a Lisp-n, while this is not needed in a Lisp-1:- I never thought separate function and value namespaces had anything to do with more or less typing.
Code: Select all
(defun hof (fun arg)
(funcall fun arg))
Code: Select all
(define (hof fun arg)
(fun arg))
Actually, there are quite a few undefined subchars, they just aren't explicitly reserved for the user: http://www.lispworks.com/documentation/ ... /02_dh.htm. I guess that the rest is meant to be used by implementations.- Since # is "the" dispatch character and there aren't many remaining subchars, read-macro collisions are common. Hence they shouldn't be used lightly in libraries; but application code can use them liberally.
Code: Select all
[foo ...] => (funcall foo ...)
Code: Select all
(#,#'foo) <=> (funcall (function foo)) <=> (foo)
Code: Select all
(#,(compose #'bar #'foo) ...)
Code: Select all
(#,foo ...) => ((lambda (&rest args) (apply foo args)) ...)
Code: Select all
(bar #'#,foo) <=> (bar (function (lambda (&rest args) (apply foo args)))) <=> (bar foo)
I thought about this too, but I was a bit unsure because there was some cleanup issue related to this subchar mentioned in the hyperspec.gugamilare wrote: Maybe a better symmetry would be to use #, instead of #" so it would look like backquote and unquote [...]
Funny, I had this on my scrap paper, too.And, not that this is actually a good idea, but, if the expansion was
Code: Select all
(#,foo ...) => ((lambda (&rest args) (apply foo args)) ...)
Well, that's why I decided on the simple 'funcall expansion, even though I am pretty sure that this slightly convoluted expansion would be optimized away by almost any current compiler. Exceptionally referring to the value namespace should be only needed from the operator position of an s-expression anyway.the reverse would also be true:
But may not be a good idea because it would be useless and expand into potencially slower code (although some implementations might optimize it away).Code: Select all
(bar #'#,foo) <=> (bar (function (lambda (&rest args) (apply foo args)))) <=> (bar foo)
Code: Select all
[dave@droberts src]$ find -name \*.lisp -print | xargs grep -i funcall | wc -l
1484
[dave@droberts src]$ find -name \*.lisp -print | xargs grep -i "#'" | wc -l
2327