RFC: FUNCALL reader macro

Discussion of Common Lisp

RFC: FUNCALL reader macro

Postby Harleqin » Sun Jun 21, 2009 6:27 pm

After recently seeing some more discussions about the separation of function and value namespaces, I thought "If they want to save typing, they should use a macro". There is already the #' reader macro for FUNCTION, which refers to something from the function namespace where the default would be the value namespace. There should also be a reader macro for FUNCALL, which allows to execute something from the value namespace. I wanted to use #" for symmetry reasons, but this seems to confuse something, so I used #^:

Code: Select all
(set-dispatch-macro-character #\# #\^
                              (lambda (stream subchar number)
                                (declare (ignore stream subchar number))
                                'funcall))


Is using #^ OK, or is there some CL implementation that already uses it? I know that only !, [, ], {, }, and ? are explicitly reserved for the user, but my reasoning here is that this is rather a general language extension.

Comments?
"Just throw more hardware at it" is the root of all evil.
Svante
Harleqin
 
Posts: 71
Joined: Wed Dec 17, 2008 5:18 am
Location: Bonn, Germany

Re: RFC: FUNCALL reader macro

Postby nuntius » Sun Jun 21, 2009 11:02 pm

Comments:

- Read macros are best reserved for syntax which cannot be parsed by the normal lisp reader. Or at least very frequently used shorthand.

- 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.

- Wouldn't a symbol macro named FC be equivalently useful?

- I never thought separate function and value namespaces had anything to do with more or less typing.

- 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.
User avatar
nuntius
 
Posts: 497
Joined: Sat Aug 09, 2008 10:44 am
Location: Burlington, MA

Re: RFC: FUNCALL reader macro

Postby Harleqin » Mon Jun 22, 2009 5:40 am

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.


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.

- 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.


Example:
Code: Select all
(#^fun arg) ; expands to (funcall fun arg)


I agree that the savings with the #' reader macro are bigger. However, what lies underneath the macro is not my concern, my goal is to express the symmetry of "exceptionally executing something from the value namespace" and "exceptionally referring to something from the function namespace as a value".

- Wouldn't a symbol macro named FC be equivalently useful?


Yes, you could even call it "^". However, my thought is symmetry:

When calling higher order functions (which is much more common), there is already the reader macro #':

Code: Select all
(mapcar #'zerop list) ; expands to (mapcar (function 'zerop) list)


The concept I see embodied in this reader macro is "referring to things from the 'other' namespace". Therefore, I think that a visually similar thing should be existent for the (in a sense) reverse case:

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 never thought separate function and value namespaces had anything to do with more or less typing.


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:

Code: Select all
(defun hof (fun arg)
  (funcall fun arg))

versus
Code: Select all
(define (hof fun arg)
  (fun arg))



- 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.


Actually, there are quite a few undefined subchars, they just aren't explicitly reserved for the user: http://www.lispworks.com/documentation/HyperSpec/Body/02_dh.htm. I guess that the rest is meant to be used by implementations.
"Just throw more hardware at it" is the root of all evil.
Svante
Harleqin
 
Posts: 71
Joined: Wed Dec 17, 2008 5:18 am
Location: Bonn, Germany

Re: RFC: FUNCALL reader macro

Postby gugamilare » Mon Jun 22, 2009 10:28 am

I actually think this is not a bad idea. I was once suggested to use [, ] instead of (, ), like this:

Code: Select all
[foo ...] => (funcall foo ...)

Maybe a better simetry would be to use #, instead of #" so it would look like backquote and unquote, since.

Code: Select all
(#,#'foo) <=> (funcall (function foo)) <=> (foo)

The following code would enforce even more this idea:

Code: Select all
(#,(compose #'bar #'foo) ...)

And, not that this is actually a good idea, but, if the expansion was

Code: Select all
(#,foo ...) => ((lambda (&rest args) (apply foo args)) ...)

the reverse would also be true:

Code: Select all
(bar #'#,foo) <=> (bar (function (lambda (&rest args) (apply foo args)))) <=> (bar foo)

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).
gugamilare
 
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil

Re: RFC: FUNCALL reader macro

Postby Harleqin » Mon Jun 22, 2009 5:21 pm

gugamilare wrote:Maybe a better symmetry would be to use #, instead of #" so it would look like backquote and unquote [...]


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.

And, not that this is actually a good idea, but, if the expansion was

Code: Select all
(#,foo ...) => ((lambda (&rest args) (apply foo args)) ...)



Funny, I had this on my scrap paper, too.

the reverse would also be true:

Code: Select all
(bar #'#,foo) <=> (bar (function (lambda (&rest args) (apply foo args)))) <=> (bar foo)


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).


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.
"Just throw more hardware at it" is the root of all evil.
Svante
Harleqin
 
Posts: 71
Joined: Wed Dec 17, 2008 5:18 am
Location: Bonn, Germany

Re: RFC: FUNCALL reader macro

Postby findinglisp » Tue Jun 23, 2009 9:51 am

IMO, typing out FUNCALL when necessary isn't that big of a deal. You end up wanting to use FUNCTION a lot more since you pass functions to many standard library routines more often than you actually use FUNCALL. Hence, it makes sense to use #' for that. Just for grins, I did a little counting on the SBCL sources:
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


Note that the density of FUNCALL in SBCL is also probably higher than in normal application code because it's implementing all the standard high-order library functions.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/
findinglisp
 
Posts: 440
Joined: Sat Jun 28, 2008 7:49 am
Location: Austin, TX

Re: RFC: FUNCALL reader macro

Postby Harleqin » Tue Jun 23, 2009 4:13 pm

Well, you need FUNCALL every time you make a new higher order function. How often you do that depends on the field you are working on and also a bit on your style. However, when someone goes that way, I'd like Lisp to be as convenient as possible.

I reflected a bit on why I find this important. It is not a big change, after all. I think that the main advantage is that the reader macro "is not a symbol". Function application in Lisp is usually just (operator arg). When I use (funcall funvar arg), there is an additional symbol that just effects something normally already implied by the s-expression syntax. With the reader macro, I get back to a "single symbol" denoting the operator: (#,funvar arg). This makes understanding a higher order function at a glance much easier, I think.
"Just throw more hardware at it" is the root of all evil.
Svante
Harleqin
 
Posts: 71
Joined: Wed Dec 17, 2008 5:18 am
Location: Bonn, Germany


Return to Common Lisp

Who is online

Users browsing this forum: No registered users and 4 guests

cron