From: Artem Baguinski
Subject: reader macro
Date: 
Message-ID: <42f23507$0$739$5fc3050@dreader2.news.tiscali.nl>
Hello

Today I learned about reader macros and made the following excersize to 
test if i understood it

http://paste.lisp.org/display/10493

the new syntax allows making slightly more concise syntax for making 
very simple anonymous functions. i used $ as a macro symbol and $1, $2, 
... for anonymous function's arguments, hence the name for the new 
syntax: bash-lambda (blamda)

so now, instead of

   #'(lambda (x y) (+ (* x x) (* y y))

i can write

   $(+ (* $1 $1) (* $2 $2))

(I personally find it more readable, but that's of course because I'm a 
corrupted by bash/perl newbie and all)

I just would like to hear the opinions on the code:

1) i feel i could write something similar as a macro, but I'm not really 
sure. Could I?

2) I wrote a "collect" function that returns a list of all leaf nodes of 
the tree for which predicate returns true. Aren't there standard way to 
implement that?

3) I can't nest my construction, and I can live with that (after all 
it's ONLY for simple cases, otherwise it wouldn't be any more readable 
then lambda construction. But may be you see immediately other cases 
where my construction will break? Or even it makes you go "hey, that's 
not what reader macros are for, you can't do that, because ...!"

thanks,
artm

From: Kent M Pitman
Subject: Re: reader macro
Date: 
Message-ID: <uslxp34md.fsf@nhplace.com>
Artem Baguinski <····@v2.nl> writes:

> Today I learned about reader macros and made the following excersize
> to test if i understood it [...]
> so now, instead of
> 
>    #'(lambda (x y) (+ (* x x) (* y y))
> 
> i can write
> 
>    $(+ (* $1 $1) (* $2 $2))
> 
> (I personally find it more readable, but that's of course because I'm
> a corrupted by bash/perl newbie and all)

Heh.  It's cute, and I can understand why it appeals to you, so I won't
try to dissuade you from having fun in this area.  But some reasonable
questions to think about are...

- Is (funcall $(+ $1 $2) 5 6 7) an error? 
  What does it generate?

- Is (funcall $(+ $2 $3) 1 2 3) an error?
  What does it generate?

> 
> 1) i feel i could write something similar as a macro, but I'm not
> really sure. Could I?

You could, but I don't know what it would buy you.  Macros in lisp don't
operate on text, they operate on structure.  And the whole thing you're
doing here is making it easy to type in structure, not making it easy to
process structure already present.  So readmacros seem like the right
vehicle.

> 2) I wrote a "collect" function that returns a list of all leaf nodes
> of the tree for which predicate returns true. Aren't there standard
> way to implement that?

Not really, partly because it's easy to write and partly because there is
no linguistically defined notion of "tree" nor "leaf".  There are various
ways to recurse into a structure and you need to specify a lot of stuff.
I guess there could have been an operator that took all this as keywords
but we were busy with other things in the CL design and never got to it.

See my paper http://www.nhplace.com/kent/PS/EQUAL.html for more thoughts
on this.  The conclusion is that just because something seems obvious
to one person doesn't mean it is to another, and just because something
is useful doesn't mean it's canonical.  There are many useful things that
are arbitrary, but putting something arbitrary in doesn't always make it
useful.

> 3) I can't nest my construction, and I can live with that (after all
> it's ONLY for simple cases, otherwise it wouldn't be any more readable
> then lambda construction. But may be you see immediately other cases
> where my construction will break? Or even it makes you go "hey, that's
> not what reader macros are for, you can't do that, because ...!"

I don't see any obvious reason why it can't nest, though there's a notational
ambiguity you have to address, just as it must be addressed in backquote
when you use it nested.  Forgetting my suggestion above about the use of the
numeric arg, one way to do it is to do this:

 $(+ $1 $2) means (lambda (v1 v2) (+ v1 v2))

 $(funcall $(* $1 3) $1) means 
 (lambda (v1) (funcall (lambda (v1) (* v1 3)) v1))

 $(funcall $(* $1 #1$2) $1) means
 (lambda (v1-1 v2-1) (funcall (lambda (v2-1) (* v2-1 v1-2)) v1-1))

Or even if you just us $ and not #$ could just specially parse a 
notation like $3:4 in various ways.
From: Artem Baguinski
Subject: Re: reader macro
Date: 
Message-ID: <42f26bb5$0$724$5fc3050@dreader2.news.tiscali.nl>
Kent M Pitman wrote:
> Artem Baguinski <····@v2.nl> writes:

>>so now, instead of
>>
>>   #'(lambda (x y) (+ (* x x) (* y y))
>>
>>i can write
>>
>>   $(+ (* $1 $1) (* $2 $2))
>>
>>(I personally find it more readable, but that's of course because I'm
>>a corrupted by bash/perl newbie and all)
> 
> 
> Heh.  It's cute, and I can understand why it appeals to you, so I won't
> try to dissuade you from having fun in this area.  But some reasonable
> questions to think about are...
> 
> - Is (funcall $(+ $1 $2) 5 6 7) an error? 
>   What does it generate?

invalid number of arguments: 3
    [Condition of type SB-INT:SIMPLE-PROGRAM-ERROR]

> - Is (funcall $(+ $2 $3) 1 2 3) an error?
>   What does it generate?

There's a gap in the bash-lambda list of the $(+ $2 $3)
    [Condition of type SIMPLE-ERROR]

(that's my own error)

> I don't see any obvious reason why it can't nest, though there's a notational
> ambiguity you have to address, just as it must be addressed in backquote
> when you use it nested.  Forgetting my suggestion above about the use of the
> numeric arg, one way to do it is to do this:
> 
>  $(+ $1 $2) means (lambda (v1 v2) (+ v1 v2))
> 
>  $(funcall $(* $1 3) $1) means 
>  (lambda (v1) (funcall (lambda (v1) (* v1 3)) v1))
> 
>  $(funcall $(* $1 #1$2) $1) means
>  (lambda (v1-1 v2-1) (funcall (lambda (v2-1) (* v2-1 v1-2)) v1-1))
> 
> Or even if you just us $ and not #$ could just specially parse a 
> notation like $3:4 in various ways.

That would have made it less readable. I'd stick to my simple not 
nesting construction.
From: Pascal Bourguignon
Subject: Re: reader macro
Date: 
Message-ID: <87zmrxxy5v.fsf@thalassa.informatimago.com>
Artem Baguinski <····@v2.nl> writes:

> Kent M Pitman wrote:
>> Artem Baguinski <····@v2.nl> writes:
>
>>>so now, instead of
>>>
>>>   #'(lambda (x y) (+ (* x x) (* y y))
>>>
>>>i can write
>>>
>>>   $(+ (* $1 $1) (* $2 $2))
>>>
>>>(I personally find it more readable, but that's of course because I'm
>>>a corrupted by bash/perl newbie and all)
>> Heh.  It's cute, and I can understand why it appeals to you, so I
>> won't
>> try to dissuade you from having fun in this area.  But some reasonable
>> questions to think about are...
>> - Is (funcall $(+ $1 $2) 5 6 7) an error?   What does it generate?
>
> invalid number of arguments: 3
>     [Condition of type SB-INT:SIMPLE-PROGRAM-ERROR]

I assume that   (funcall $(+ $1 $3) 5 6 7) --> 13
then why should (funcall $(+ $1 $2) 5 6 7) be an error?


>> - Is (funcall $(+ $2 $3) 1 2 3) an error?
>>   What does it generate?
>
> There's a gap in the bash-lambda list of the $(+ $2 $3)

So what?

>     [Condition of type SIMPLE-ERROR]
>
> (that's my own error)

-- 
"Debugging?  Klingons do not debug! Our software does not coddle the
weak."
From: Artem Baguinski
Subject: Re: reader macro
Date: 
Message-ID: <42f2790b$0$727$5fc3050@dreader2.news.tiscali.nl>
Pascal Bourguignon wrote:
> Artem Baguinski <····@v2.nl> writes:
>>invalid number of arguments: 3
>>    [Condition of type SB-INT:SIMPLE-PROGRAM-ERROR]
> 
> I assume that   (funcall $(+ $1 $3) 5 6 7) --> 13
> then why should (funcall $(+ $1 $2) 5 6 7) be an error?
> 

I didn't assume that, but I like it

>>>- Is (funcall $(+ $2 $3) 1 2 3) an error?
>>>  What does it generate?
>>
>>There's a gap in the bash-lambda list of the $(+ $2 $3)
> 
> 
> So what?
> 

good point, thanks for pointing

I'll be filling them gaps then
From: Kent M Pitman
Subject: Re: reader macro
Date: 
Message-ID: <uoe8dxnn6.fsf@nhplace.com>
Artem Baguinski <····@v2.nl> writes:

> Pascal Bourguignon wrote:
> > Artem Baguinski <····@v2.nl> writes:
> >>invalid number of arguments: 3
> >>    [Condition of type SB-INT:SIMPLE-PROGRAM-ERROR]
> > I assume that   (funcall $(+ $1 $3) 5 6 7) --> 13
> > then why should (funcall $(+ $1 $2) 5 6 7) be an error?
> >
> 
> I didn't assume that, but I like it
> 
> >>>- Is (funcall $(+ $2 $3) 1 2 3) an error?
> >>>  What does it generate?
> >>
> >>There's a gap in the bash-lambda list of the $(+ $2 $3)
> > So what?
> >
> 
> good point, thanks for pointing
> 
> I'll be filling them gaps then

If you expand to 
 (lambda (#:v1 #:v2 ... &rest #:more)
   (declare (ignorable #:v1 #:v2 ... #:more))
   ...)
and just keep track of the highest value, generating variables for all
values up to there, then you can make it ignore initial, middle, or 
after-end values that are not named.
From: Artem Baguinski
Subject: Re: reader macro
Date: 
Message-ID: <42f30ed8$0$754$5fc3050@dreader2.news.tiscali.nl>
Kent M Pitman wrote:
> If you expand to 
>  (lambda (#:v1 #:v2 ... &rest #:more)
>    (declare (ignorable #:v1 #:v2 ... #:more))
>    ...)
> and just keep track of the highest value, generating variables for all
> values up to there, then you can make it ignore initial, middle, or 
> after-end values that are not named.

yes, i thought about that but i went to sleep (on it?) first :-)
From: Pascal Bourguignon
Subject: Re: reader macro
Date: 
Message-ID: <874qa5zkpl.fsf@thalassa.informatimago.com>
Artem Baguinski <····@v2.nl> writes:

> Hello
>
> Today I learned about reader macros and made the following excersize
> to test if i understood it
>
> http://paste.lisp.org/display/10493
>
> the new syntax allows making slightly more concise syntax for making
> very simple anonymous functions. i used $ as a macro symbol and $1,
> $2, ... for anonymous function's arguments, hence the name for the new
> syntax: bash-lambda (blamda)
>
> so now, instead of
>
>    #'(lambda (x y) (+ (* x x) (* y y))
>
> i can write
>
>    $(+ (* $1 $1) (* $2 $2))
>
> (I personally find it more readable, but that's of course because I'm
> a corrupted by bash/perl newbie and all)
>
> I just would like to hear the opinions on the code:
>


> 2) I wrote a "collect" function that returns a list of all leaf
> nodes of the tree for which predicate returns true. Aren't there
> standard way to implement that?

No, because there's no standard definition of a tree.


> 1) i feel i could write something similar as a macro, but I'm not
> really sure. Could I?

> 3) I can't nest my construction, and I can live with that (after all
> it's ONLY for simple cases, otherwise it wouldn't be any more readable
> then lambda construction. But may be you see immediately other cases
> where my construction will break? Or even it makes you go "hey, that's
> not what reader macros are for, you can't do that, because ...!"

Yes, it could be possible to write a similar macro.  To allow
encapsulating use, you'd have to walk the code inside the macro to
collect the anonymous arguments.

The difficulty of code walking comes from implementation specific
special operators. 

But since the language of recursive anonymously-argumented anonymous
functions is not clear, it's not worth the effort:

Does:        ($ (mapcar ($ (+ $1 $2 $3)) $1 $2 $2))
mean:  (lambda (a b)   (mapcar (lambda (a b d) (+ a b d)) a b b))
or:    (lambda (a b c) (mapcar (lambda (a b d) (+ a b c)) a b b))
or:    (lambda (a b c) (mapcar (lambda (a b)   (+ a b c)) a b b))
or something else?

As a language designer, you can decide on a semantic, but how will it
be obvious to the reader of:

             ($ (mapcar ($ (+ $1 $2 $3)) $1 $2 $2))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Wanna go outside.
Oh, no! Help! I got outside!
Let me back inside!
From: Marco Baringer
Subject: Re: reader macro
Date: 
Message-ID: <m2zmrxvb4r.fsf@soma.local>
Artem Baguinski <····@v2.nl> writes:

> (I personally find it more readable, but that's of course because I'm
> a corrupted by bash/perl newbie and all)

if your lisp accepts unicode chars you could write a macro called
λ and use it like so:

(λ (+ (* $1 $1) (* $2 $2)))

that's one extra space and an extra set of parens. (your code would
now walk the code tree looking for symbols whose names strats with the
char #\$ instead of using a read macro, but other than that it'd be
the same).

ps - i once wrote this exact same macro. though i eventually just
stopped using it because i found the cases where it really bought me
something were very very few, while the cases where i did end up using
lambda anyway so that i could name the arguments were far more. that
said i, personally, see nothing wrong with this use of read macros.

-- 
-Marco
Ring the bells that still can ring.
Forget the perfect offering.
There is a crack in everything.
That's how the light gets in.
	-Leonard Cohen
From: Artem Baguinski
Subject: Re: reader macro
Date: 
Message-ID: <42f262b4$0$712$5fc3050@dreader2.news.tiscali.nl>
Marco Baringer wrote:
> Artem Baguinski <····@v2.nl> writes:
> 
> 
>>(I personally find it more readable, but that's of course because I'm
>>a corrupted by bash/perl newbie and all)
> 
> 
> if your lisp accepts unicode chars you could write a macro called
> λ and use it like so:
> 
> (λ (+ (* $1 $1) (* $2 $2)))
> 
> that's one extra space and an extra set of parens. (your code would
> now walk the code tree looking for symbols whose names strats with the
> char #\$ instead of using a read macro, but other than that it'd be
> the same).

Thanks Marco & Pascal

(also being able to type λ easily will require some extra configuration, 
but I agree, it looks nicer and definitelly less bash-y)

> ps - i once wrote this exact same macro. though i eventually just
> stopped using it because i found the cases where it really bought me
> something were very very few, while the cases where i did end up using
> lambda anyway so that i could name the arguments were far more. that
> said i, personally, see nothing wrong with this use of read macros.

Well, for one this macro could be used as an example in some tutorial. I 
guess many new lispers feel that #'(lambda (a b c) ...) is a bit too 
much (for the simple uses of lambda new lispers come up with). They'd 
feel relieved when they'll discover that it's so easy to modify lisp 
syntax, they'll start using it and evntually abandon it for these same 
reasons you did ;-)