From: Ron Garret
Subject: A cute reader hack
Date: 
Message-ID: <rNOSPAMon-430B73.13443030042006@news.gha.chartermi.net>
For those who like to program in a functional style without having to 
type FUNCALL all the time:

(defun \_-reader (stream char)
  (declare (ignore char))
  `(lambda (&rest #1=#.(gensym "ARGS")) (apply ,(read stream) #1#)))

(set-macro-character #\_ '\_-reader t)

Now you can call the local version of a function simply by preceding its 
name with an underscore.  (The cost is that you lose the ability to have 
variables and functions whose names begin with underscore.  If you don't 
like that you can choose a different character, or use a dispatching 
macro character.)

e.g.:

(defun foo (list)
  (list 1 (_list 2)))  ; Instead of (list 1 (funcall list 2))

(foo #'vector) --> (1 #(2))

rg

From: Pascal Costanza
Subject: Re: A cute reader hack
Date: 
Message-ID: <4bkqpuF12003mU1@individual.net>
Ron Garret wrote:
> For those who like to program in a functional style without having to 
> type FUNCALL all the time:
> 
> (defun \_-reader (stream char)
>   (declare (ignore char))
>   `(lambda (&rest #1=#.(gensym "ARGS")) (apply ,(read stream) #1#)))
> 
> (set-macro-character #\_ '\_-reader t)
> 

For the (lambda (&rest args) (apply something args)) idiom it's a good 
idea to actually say:

(lambda (&rest args)
   (declare (dynamic-extent args))
   (apply something args))

Just a sidenote...


Pascal


-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Ron Garret
Subject: Re: A cute reader hack
Date: 
Message-ID: <rNOSPAMon-017B8D.16243930042006@news.gha.chartermi.net>
In article <···············@individual.net>,
 Pascal Costanza <··@p-cos.net> wrote:

> Ron Garret wrote:
> > For those who like to program in a functional style without having to 
> > type FUNCALL all the time:
> > 
> > (defun \_-reader (stream char)
> >   (declare (ignore char))
> >   `(lambda (&rest #1=#.(gensym "ARGS")) (apply ,(read stream) #1#)))
> > 
> > (set-macro-character #\_ '\_-reader t)
> > 
> 
> For the (lambda (&rest args) (apply something args)) idiom it's a good 
> idea to actually say:
> 
> (lambda (&rest args)
>    (declare (dynamic-extent args))
>    (apply something args))
> 
> Just a sidenote...

Good point.

rg
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: A cute reader hack
Date: 
Message-ID: <874q09oovf.fsf@qrnik.zagroda>
Pascal Costanza <··@p-cos.net> writes:

> For the (lambda (&rest args) (apply something args)) idiom it's a good
> idea to actually say:
>
> (lambda (&rest args)
>    (declare (dynamic-extent args))
>    (apply something args))

Is the dynamic extent valid if something is #'(lambda (&rest args) args)?

-- 
   __("<         Marcin Kowalczyk
   \__/       ······@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
From: ·······@gmail.com
Subject: Re: A cute reader hack
Date: 
Message-ID: <1146497177.205730.280040@g10g2000cwb.googlegroups.com>
Marcin 'Qrczak' Kowalczyk wrote:
> Pascal Costanza <··@p-cos.net> writes:
>
> > For the (lambda (&rest args) (apply something args)) idiom it's a good
> > idea to actually say:
> >
> > (lambda (&rest args)
> >    (declare (dynamic-extent args))
> >    (apply something args))
>
> Is the dynamic extent valid if something is #'(lambda (&rest args) args)?

Yes, the list is copied in case the called function side-effects its
argument list... Yet another cause of inefficiency :)

Paul Khuong
From: Ron Garret
Subject: Re: A cute reader hack
Date: 
Message-ID: <rNOSPAMon-6573B0.09101701052006@news.gha.chartermi.net>
In article <························@g10g2000cwb.googlegroups.com>,
 ·······@gmail.com wrote:

> Marcin 'Qrczak' Kowalczyk wrote:
> > Pascal Costanza <··@p-cos.net> writes:
> >
> > > For the (lambda (&rest args) (apply something args)) idiom it's a good
> > > idea to actually say:
> > >
> > > (lambda (&rest args)
> > >    (declare (dynamic-extent args))
> > >    (apply something args))
> >
> > Is the dynamic extent valid if something is #'(lambda (&rest args) args)?
> 
> Yes, the list is copied in case the called function side-effects its
> argument list... Yet another cause of inefficiency :)
> 
> Paul Khuong

It depends on the compiler.  It works in SBCL, but MCL returns a #<BOGUS 
OBJECT> if you do this.  I think the spec says this is not required to 
work.

rg
From: Pascal Costanza
Subject: Re: A cute reader hack
Date: 
Message-ID: <4bn3tpF11v384U1@individual.net>
Marcin 'Qrczak' Kowalczyk wrote:
> Pascal Costanza <··@p-cos.net> writes:
> 
>> For the (lambda (&rest args) (apply something args)) idiom it's a good
>> idea to actually say:
>>
>> (lambda (&rest args)
>>    (declare (dynamic-extent args))
>>    (apply something args))
> 
> Is the dynamic extent valid if something is #'(lambda (&rest args) args)?

No, but you can pass the following instead:

(lambda (&rest args)
   (declare (dynamic-extent args))
   (copy-list args))


What do you want to use this for?


Pascal

-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: A cute reader hack
Date: 
Message-ID: <87psiwxm22.fsf@qrnik.zagroda>
Pascal Costanza <··@p-cos.net> writes:

> No, but you can pass the following instead:
>
> (lambda (&rest args)
>    (declare (dynamic-extent args))
>    (copy-list args))
>
> What do you want to use this for?

You seem to have suggested to declare as dynamic-extent the &rest
parameter which is passed down to another function, irrespective
of how the other function is written (if "idiom" is understood as
"any code matching this pattern").

I was just worried that this optimization requires the knowledge about
the other function. In particular it would be unsafe with the _func
reader syntax that this thread is about, because the function might
return its original parameter list as a part of its result.

-- 
   __("<         Marcin Kowalczyk
   \__/       ······@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
From: Bill Atkins
Subject: Re: A cute reader hack
Date: 
Message-ID: <87d5ew412i.fsf@rpi.edu>
Marcin 'Qrczak' Kowalczyk <······@knm.org.pl> writes:

> Pascal Costanza <··@p-cos.net> writes:
>
>> No, but you can pass the following instead:
>>
>> (lambda (&rest args)
>>    (declare (dynamic-extent args))
>>    (copy-list args))
>>
>> What do you want to use this for?
>
> You seem to have suggested to declare as dynamic-extent the &rest
> parameter which is passed down to another function, irrespective
> of how the other function is written (if "idiom" is understood as
> "any code matching this pattern").
>
> I was just worried that this optimization requires the knowledge about
> the other function. In particular it would be unsafe with the _func
> reader syntax that this thread is about, because the function might
> return its original parameter list as a part of its result.
>
> -- 
>    __("<         Marcin Kowalczyk
>    \__/       ······@knm.org.pl
>     ^^     http://qrnik.knm.org.pl/~qrczak/

It is always unsafe to modify &rest arguments.

-- 
This is a song that took me ten years to live and two years to write.
 - Bob Dylan
From: Kaz Kylheku
Subject: Re: A cute reader hack
Date: 
Message-ID: <1146524789.951615.44950@i39g2000cwa.googlegroups.com>
Ron Garret wrote:
> For those who like to program in a functional style without having to
> type FUNCALL all the time:

>   (list 1 (_list 2)))  ; Instead of (list 1 (funcall list 2))

Uh, you know, all you have really done is made _ a synonym for funcall.
Except that a space is not allowed after it, which isn't necessarily
any kind of advantage.

(defmacro _ (f &rest args)
  `(funcall f ,@args))

(_ list 2) ;; instead of (funcall list 2)

But at least we haven't stolen the _ constituent character. Moreover,
we have only claimed the symbol named "_" in one package.

Shortening symbol names to save typing is ... boring.
From: Andras Simon
Subject: Re: A cute reader hack
Date: 
Message-ID: <vcdzmi1fjqy.fsf@csusza.math.bme.hu>
Ron Garret <·········@flownet.com> writes:

> For those who like to program in a functional style without having to 
> type FUNCALL all the time:
> 
> (defun \_-reader (stream char)
>   (declare (ignore char))
>   `(lambda (&rest #1=#.(gensym "ARGS")) (apply ,(read stream) #1#)))
> 
> (set-macro-character #\_ '\_-reader t)
> 
> Now you can call the local version of a function simply by preceding its 
> name with an underscore.  (The cost is that you lose the ability to have 
> variables and functions whose names begin with underscore.  If you don't 
> like that you can choose a different character, or use a dispatching 
> macro character.)
> 
> e.g.:
> 
> (defun foo (list)
>   (list 1 (_list 2)))  ; Instead of (list 1 (funcall list 2))
> 
> (foo #'vector) --> (1 #(2))

Wouldn't 

(defun foo (list)
  (list 1 [list 2]))  ; Instead of (list 1 (funcall list 2))

(foo #'vector) --> (1 #(2))

look a bit less Perl-ish?

(defun open-bracket-macro-character (stream char)
  (declare (ignore char))
  (let ((list (read-delimited-list #\] stream t)))
    `(funcall ,(first list) ,@(rest list))))

(set-macro-character #\[ #'open-bracket-macro-character)

(set-macro-character #\] (get-macro-character #\)))

Andras
From: Kalle Olavi Niemitalo
Subject: Re: A cute reader hack
Date: 
Message-ID: <87r73coicv.fsf@Astalo.kon.iki.fi>
Ron Garret <·········@flownet.com> writes:

> (defun \_-reader (stream char)
>   (declare (ignore char))
>   `(lambda (&rest #1=#.(gensym "ARGS")) (apply ,(read stream) #1#)))

I think the call should in principle be (read stream t nil t),
to support this:

  (let ((#1=#:foo #'cons))
    (_#1# t nil)) 
  
> (set-macro-character #\_ '\_-reader t)

Anyway, the whole thing could be simplified to:

  (set-macro-character #\_ (constantly 'funcall) t)

which doesn't detect misuses like (_) at read time as yours does,
but I expect that would not be a problem.