This is one of those e-mails that I know from the start to be futile,
but...
For a while now, the
-> (params) { block }
syntax in Ruby 1.9 has bothered me, but I've never been sure why.
Today, while playing with pure, it struck me. The '->' sequence is in
an unexpected place. Having played with some functional languages, I'm
used to lambdas being written
\ params -> block
That is, the lambda is introduced with a \ (because, presumably, it
looks a bit like λ). The -> sequence separates the parameters from the
block. This had become ingrained into be, in the same way that the
equals sign in an assignment
a = expression
goes between the lvalue and the rvalue.
So, when I come to Ruby 1.9, suddenly there's some dissonance between
what I was used to and what I now have to type. The -> comes before
the parameters, not after. It's as if I had to write assignments
= a expression
So, here's the futile part... :)
Is it too late for Ruby 1.9 to support lambdas that look like
\ p1, p1 -> { block }
I honestly feel this would be more natural, and more in line with the
prevailing idioms. I suspect it's parsable if you make the simplifying
assumption that line continuations must only have whitespace after them.
Dave
on 01.05.2008 05:27
on 01.05.2008 05:46
I agree, I prefer this syntax. Although I'd prefer being consistent with the Haskell convention (and maybe other languages with similar syntax) of discouraging a space between the backslash and the first variable name.
on 01.05.2008 05:56
On Wed, Apr 30, 2008 at 11:26 PM, Dave Thomas <dave@pragprog.com> wrote: > > > \ p1, p1 -> { block } > > I honestly feel this would be more natural, and more in line with the > prevailing idioms. I suspect it's parsable if you make the simplifying > assumption that line continuations must only have whitespace after them. I remember having a slight issue with the syntax as well when it was announced. I remember the round table at the 2005 RubyConf in San Diego where we discussed a number of alternatives. One idea I had proposed was to allow arguments to work within the block like they do now but with -> (more examples below). I believe it was shot down as being to odd (but look where we are now). foo { |a, b| a + b } foo { a, b -> a + b } and thus: lambda { a, b = 3 -> a + b } ... solving the original problem of argument list syntax. If we also wanted a lighter weight notation we could make {->} result in a proc object rather than act as a block parameter. Or if you like unicode: λ { x -> 42 } (Finally, there might be a way to allow syntax w/o {} or do-end but I'm not sure how far we should push -- "lambda x -> 42" looks rather nice though) Brian.
on 01.05.2008 10:53
Dave Thomas schrieb: > -> (params) { block } > ... > That is, the lambda is introduced with a \ (because, presumably, it > looks a bit like λ). As I understood Matz in some slides (don't remember where I've found them), he introduces "->" as looking somehow like "λ" when turning it 45 degrees conterclockwise. It can be read then "λ (params) { block }". Wolfgang Nádasi-Donner
on 01.05.2008 12:23
On Thu, May 1, 2008 at 5:26 AM, Dave Thomas <dave@pragprog.com> wrote: > being written > > \ params -> block > I agree that the new 1.9 syntax for lambdas is somehow peculiar. At least it is not consistent with the "old" syntax where the parameters are inside the block i.e. lambda {|params| block } and especially confusing with the visual appearance of ordinary method parameters i.e (params) ... I like very much how lambda expressions are defined in C# : x => x * x // <--- lambda expression with a single parameter (x, y) => x + y // <--- lambda expression with multiple parameters x => { multi line block } lambdas in C# apparently are syntactically inspired by functional languages. -- henon
on 01.05.2008 15:52
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Wolfgang Nádasi-Donner wrote: > As I understood Matz in some slides (don't remember where I've found > them), he introduces "->" as looking somehow like "λ" when turning it 45 > degrees conterclockwise. It can be read then "λ (params) { block }". > Indeed, that's the first thing I thought of in this thread. If I'm not incredibly mistaken it can be found here: http://youtube.com/watch?v=oEkJvvGEtB4 > Wolfgang Nádasi-Donner > Thanks, Kris Katterjohn -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iQIVAwUBSBnKsP9K37xXYl36AQIiyg/9HOh+T52xwAJWAy3XbUvpxJddrtxK9svG akuKtSN7r6ewX3yIs8jPRNkHMZHIS6DfBTum56gcP0luQZkT6mDRAPPGSsxlTRxk tJ3U0vY7N2J1Dko9Pt9S+Nhif7VIFNoZIdIifmdsCBtdbDDTgqMZHYisRdlUItCQ ohxT+XwnPHwFA3EiZCndBNfuIgVAjFy7HS1j/DQFzNYWaTVGZutM1tgkszxAIm61 Xt7R0Cyqa8MK2AZvqMuSxA3XN+vrCyQfMy5yjT/xBbuPJLKmDnqKq5b3sNQMoVg8 65zcRSsb2Hyi9+YTJas6h3Xz5XJMq3+fjcSvIJGAPzoKNkl2odbnlNXk/EL2dwhF zsy30GlIn8NOKV2ZBYe45C6DI3CrydhHyWqBICy1hw25yQ7XL53SK5NqIGEblitq FnJ13KgSl18Dx3TmHotOJ0TRQaH4IV+/hMDCnKwoxLtqYMxxAkcziWfD/Zom58+c Hoymki3E1+wqlavXnNFm2NjOIom89CV43pHQXJ/EDivTgfYkD7lNe/prjV83Ohfj XwizJBlqaUH8u+/nlPbwV3iNIRaNyX8zndVg2/ZFQLhmFFnRPJ0LorCifgNK0WbD XrKJvc0p98mgUrbnVlsljkxnwz0V4XrKOfmLOQ6yiHVdQPpoIg+Dk5HkF3RpxxuO y2GCFh9hz20= =r2/Y -----END PGP SIGNATURE-----
on 01.05.2008 17:10
Hi -- On Thu, 1 May 2008, Brian Mitchell wrote: >> being written >> goes between the lvalue and the rvalue. >> > One idea I had proposed was to allow arguments to work within the > ... solving the original problem of argument list syntax. If we also > wanted a lighter weight notation we could make {->} result in a proc > object rather than act as a block parameter. Or if you like unicode: > > λ { x -> 42 } > > > (Finally, there might be a way to allow syntax w/o {} or do-end but > I'm not sure how far we should push -- "lambda x -> 42" looks rather > nice though) All I can say is: any of these are preferable, in my opinion, to ->(){}. The -> does not look like a lambda character (apologies to Matz, but it simply doesn't); it looks like an arrow, point from nothing to something, and I find it pretty jarring. @Dave: you once suggested something like this (I think in San Diego): def (a,b,c) # code end as a way to create an anonymous function that used method argument semantics (which I think is what the whole -> thing is about). There was applause and cheering from the room. I'm not sure what happened to that idea. David
on 01.05.2008 17:20
On Thu, May 1, 2008 at 11:06 AM, David A. Black <dblack@rubypal.com> wrote: > @Dave: you once suggested something like this (I think in San Diego): I think you are right. It was San Diego. > def (a,b,c) > # code > end > > as a way to create an anonymous function that used method argument > semantics (which I think is what the whole -> thing is about). There > was applause and cheering from the room. I'm not sure what happened to > that idea. I would love to see this supported regardless of the lambda issue. This would make it a lot easier to avoid unwanted closures as well as make it easy to define a bound Method object (assuming it would bind to the self in scope). I think part of the reason it died was that current def expressions just return nil rather than any reified object representation. This overhead might be able to be avoided in the more advanced implementations though, or at least this could be a special case. Brian.
on 01.05.2008 19:05
Wolfgang Nádasi-Donner wrote:
> Dave Thomas schrieb:
>> -> (params) { block }
>> ...
>> That is, the lambda is introduced with a \ (because, presumably, it
>> looks a bit like λ).
>
> As I understood Matz in some slides (don't remember where I've found
> them), he introduces "->" as looking somehow like "λ" when turning it
45
> degrees conterclockwise. It can be read then "λ (params) { block }".
This is the slide you're talking about:
http://www.rubyist.net/~matz/slides/rc2007/mgp00054.html
When listening to Matz explanation, it becomes pretty easy to
remember :)
Regards,
Michael
on 02.05.2008 04:23
David A. Black wrote:
> The -> does not look like a lambda character
Neither does \. Please be aware of those cultures where \ is assigned
to different figures, such as yen sign.
I doubt there are no such thing that looks like a lambda character,
except lambda itself.
on 02.05.2008 04:38
Urabe Shyouhei wrote:
>
Lisp programmers aren't too lazy to type the word "lambda" -- why should
Ruby or other languages be different in that respect? :)
on 02.05.2008 04:46
M. Edward (Ed) Borasky wrote: > Lisp programmers aren't too lazy to type the word "lambda" -- why should > Ruby or other languages be different in that respect? :) Lisp programmers keep in shape by doing reps of SHIFT-9 and SHIFT-0 ;)
on 02.05.2008 04:47
Hi -- On Fri, 2 May 2008, Urabe Shyouhei wrote: > David A. Black wrote: >> The -> does not look like a lambda character > > Neither does \. Please be aware of those cultures where \ is assigned to > different figures, such as yen sign. I don't think \ looks like a lambda, and of course it doesn't inherently or exclusively mean "lambda" in every context :-) I do like it better than the ->() thing. I'd actually like to see def (a,b,c) or something that uses the lambda keyword. David
on 02.05.2008 04:53
Joel VanderWerf wrote: > M. Edward (Ed) Borasky wrote: >> Lisp programmers aren't too lazy to type the word "lambda" -- why >> should Ruby or other languages be different in that respect? :) > > Lisp programmers keep in shape by doing reps of SHIFT-9 and SHIFT-0 ;) > Actually, most Lisp "IDEs" (emacs et. al.) give you a matching SHIFT-0 when you type the SHIFT-9. You just have to remember to move the entry cursor to the right place. I really should learn emacs. ;)
on 02.05.2008 16:54
Dave Thomas <dave@pragprog.com> writes: > Is it too late for Ruby 1.9 to support lambdas that look like > > \ p1, p1 -> { block } > > I honestly feel this would be more natural, and more in line with the > prevailing idioms. I suspect it's parsable if you make the simplifying > assumption that line continuations must only have whitespace after > them. +1, and line continuations only appear at the end of a line, anyway. *now back to lurking and painting my bikeshed*
on 04.05.2008 19:58
wouldn't
(p1, p2) -> { block_of_code }
solve all the problems?
on 04.05.2008 20:09
On Sun, May 4, 2008 at 1:57 PM, Marcin Raczkowski <mailing.mr@gmail.com> wrote: > wouldn't > > (p1, p2) -> { block_of_code } > > solve all the problems? It certainly wouldn't be simple to parse: (x = 42) VS. (x = 42) -> { p x } Part of the syntax is to make parsing of the argument list a little easier so default arguments can be supported without serious ambiguity problems. This syntax doesn't necessarily help that. Brian.
on 05.05.2008 15:35
On Thu, May 01, 2008 at 12:26:47PM +0900, Dave Thomas wrote:
> used to lambdas being written
I agree. To me the -> looks like an arrow rather than a lambda, so it
reels like it should be between two items.
What if "lambda" were to become a keyword, so one could write:
lambda(params) { block }
as an alternative to the -> syntax?
Paul
on 05.05.2008 18:50
Hi -- On Mon, 5 May 2008, Paul Brannan wrote: >> an unexpected place. Having played with some functional languages, I'm >> used to lambdas being written > > I agree. To me the -> looks like an arrow rather than a lambda, so it > reels like it should be between two items. > > What if "lambda" were to become a keyword, so one could write: > > lambda(params) { block } > > as an alternative to the -> syntax? That would definitely be better. You'd then have, I assume: lambda {|x,y,z| block } # block/yield arg. semantics lambda(x,y,z) { block } # method semantics which would, I think, cover what's needed. David
on 05.05.2008 18:53
David A. Black wrote: > lambda {|x,y,z| block } # block/yield arg. semantics > lambda(x,y,z) { block } # method semantics and you do the same with define_method ? :-) Guy Decoux
on 05.05.2008 19:03
Hi -- On Tue, 6 May 2008, ts wrote: > David A. Black wrote: >> lambda {|x,y,z| block } # block/yield arg. semantics >> lambda(x,y,z) { block } # method semantics > > and you do the same with define_method ? :-) I'm not sure what you mean. Wouldn't you do this: define_method(:m) &lambda(x,y,z) { block } I thought that was one of the purposes of ->(){} -- to let you use method argument semantics in Proc objects. Am I wrong about that? David
on 05.05.2008 19:08
David A. Black wrote: > define_method(:m) &lambda(x,y,z) { block } too complex for me :-) > > I thought that was one of the purposes of ->(){} -- to let you use > method argument semantics in Proc objects. Am I wrong about that? no, probably. This is just me which associate, probably wrongly, lambda and define_method and 1.9 seems have method argument semantics with lambda Guy Decoux
on 05.05.2008 19:14
On Tue, May 06, 2008 at 02:02:34AM +0900, David A. Black wrote:
> define_method(:m) &lambda(x,y,z) { block }
That looks like the binary & operator, not the unary block-pass
operator (or whatever it's called).
Paul
on 05.05.2008 19:16
Hi -- On Tue, 6 May 2008, ts wrote: > David A. Black wrote: >> define_method(:m) &lambda(x,y,z) { block } > > too complex for me :-) For some reason I doubt it :-) >> >> I thought that was one of the purposes of ->(){} -- to let you use >> method argument semantics in Proc objects. Am I wrong about that? > > no, probably. > > This is just me which associate, probably wrongly, lambda and > define_method and 1.9 seems have method argument semantics with > lambda I don't think so -- only ->(){}: $ /usr/local/lib/ruby-trunk/bin/ruby -ve 'lambda {|a=1|}' ruby 1.9.0 (2008-04-30 revision 16244) [i686-darwin9.2.2] -e:1: syntax error, unexpected '=', expecting '|' lambda {|a=1|} ^ $ /usr/local/lib/ruby-trunk/bin/ruby -e '->(a=1){}' $ I think that's why Paul is suggesting lambda(args) {}, where args could be any method-style argument list. David
on 05.05.2008 19:16
Hi -- On Tue, 6 May 2008, Paul Brannan wrote: > On Tue, May 06, 2008 at 02:02:34AM +0900, David A. Black wrote: >> define_method(:m) &lambda(x,y,z) { block } > > That looks like the binary & operator, not the unary block-pass > operator (or whatever it's called). I thought that before a Proc object it was automatically the block-pass, or to_proc, or whatever, operator. David
on 05.05.2008 19:21
On Tue, May 06, 2008 at 02:07:26AM +0900, ts wrote: > This is just me which associate, probably wrongly, lambda and > define_method and 1.9 seems have method argument semantics with > lambda Hmm, you seem (as usual) to be correct. What, then, is the purpose of the -> syntax, if these are equivalent: p = lambda { |x, y, &b| ... } p = ->(x, y, &b) { ... } (or am I mistaken in thinking they are equivalent?) If they are the same, then I'm content to just not use -> in my own code. Paul
on 05.05.2008 19:23
On Mon, May 5, 2008 at 1:16 PM, David A. Black <dblack@rubypal.com> wrote: > > > > > > > That looks like the binary & operator, not the unary block-pass > > operator (or whatever it's called). > > > > I thought that before a Proc object it was automatically the > block-pass, or to_proc, or whatever, operator. In an argument list it takes a Proc or to_proc-able object... so you need to adjust the code like so: define_method(:m, &lambda(x,y,z) { block }) Brian.
on 05.05.2008 19:24
Hi -- On Tue, 6 May 2008, Paul Brannan wrote: > > (or am I mistaken in thinking they are equivalent?) > > If they are the same, then I'm content to just not use -> in my own > code. See my response to Guy. ->() lets you do method-argument semantics: ->(a,b=1) {} whereas this blows up: lambda {|a,b=1| } David
on 05.05.2008 19:27
On Tue, May 06, 2008 at 02:16:20AM +0900, David A. Black wrote: > I thought that before a Proc object it was automatically the > block-pass, or to_proc, or whatever, operator. The parser doesn't know what the type of the argument to & is. It decides whether to interpret it as unary or binary & based on context: irb(main):001:0> def foo(x); end (irb):4: warning: method redefined; discarding old foo => nil irb(main):002:0> foo(&42) TypeError: wrong argument type Fixnum (expected Proc) from (irb):7 from /usr/local/bin/irb1.9:12:in `<main>' irb(main):003:0> foo(42&42) => nil Paul
on 05.05.2008 19:30
On Mon, May 5, 2008 at 1:21 PM, David A. Black <dblack@rubypal.com> wrote: > > > define_method and 1.9 seems have method argument semantics with > > > lambda {|a,b=1| } I guess it should be made clear that you are talking just about argument semantics then because methods have other differences including closures, yield, break and friends, etc.. Brian.
on 05.05.2008 19:37
On Tue, May 06, 2008 at 02:21:58AM +0900, David A. Black wrote: > See my response to Guy. ->() lets you do method-argument semantics: > > ->(a,b=1) {} > > whereas this blows up: > > lambda {|a,b=1| } Ah, right, because this case is ambiguous: lambda { |a, b=1| 6| 4 } Paul
on 05.05.2008 20:58
Doing something completely foreign and, dare I say, Perl-esque seems bizarre just to get a slightly different semantic range. I'd MUCH rather see something like the lambda suggestion or even using def in its place (keep the definition of functions and anonymous functions within the same syntactic range). I use Ruby for its LACK of line noise. Adding $arbitrary -> (things | like) >> this ^*syntax->>(when there are much more consistent and prettier alternatives) puts a bad taste in my mouth. --Jeremy On Mon, May 5, 2008 at 1:16 PM, David A. Black <dblack@rubypal.com> wrote: > > > > > David > > -- > Rails training from David A. Black and Ruby Power and Light: > INTRO TO RAILS June 9-12 Berlin > ADVANCING WITH RAILS June 16-19 Berlin > INTRO TO RAILS June 24-27 London (Skills Matter) > See http://www.rubypal.com for details and updates! > > -- http://jeremymcanally.com/ http://entp.com Read my books: Ruby in Practice (http://manning.com/mcanally/) My free Ruby e-book (http://humblelittlerubybook.com/) Or, my blogs: http://mrneighborly.com http://rubyinpractice.com
on 05.05.2008 21:22
Hi -- On Tue, 6 May 2008, Brian Mitchell wrote: >>>> define_method(:m) &lambda(x,y,z) { block } > need to adjust the code like so: > > define_method(:m, &lambda(x,y,z) { block }) Thank you -- I knew something looked odd about it :-) David
on 05.05.2008 21:23
Hi -- On Tue, 6 May 2008, Paul Brannan wrote: > irb(main):002:0> foo(&42) > TypeError: wrong argument type Fixnum (expected Proc) > from (irb):7 > from /usr/local/bin/irb1.9:12:in `<main>' > irb(main):003:0> foo(42&42) > => nil See Brian's answer -- I had put the &lambda in the wrong place (it should be in the argument list, not in the block position). David
on 06.05.2008 14:08
On Fri, May 2, 2008 at 4:52 AM, M. Edward (Ed) Borasky <znmeb@cesmail.net> wrote: > > > Actually, most Lisp "IDEs" (emacs et. al.) give you a matching SHIFT-0 when > you type the SHIFT-9. You just have to remember to move the entry cursor to > the right place. > > I really should learn emacs. ;) To reply to all of you :-), I noticed that many die-hard lispers are using Paredit, which actually does reduce the need to write parentheses to a minimum (and it does a whole lot more). I can gladly recommend trying Paredit to anyone who would like to experience what "intelligent editor" is actually supposed to mean - it never allows you to have your parentheses unbalanced, it allows you to safely swap and move and transpose and shuffle subexpressions around and so on. The shift modifier might also be unnecessary, it is not difficult to swap '[' and ']' for '(' and ')' in Emacs, which mimics the Lisp Machine keyboard of olde ;-) (http://world.std.com/~jdostale/kbd/SpaceCadet1.jpeg), even doing it just for the Lisp mode of Emacs helps. There is no need to do the unnecessary work. Concerning lambdas: I am also unsure about the ->(){} syntax, but then, I am no expert in languages heavy with syntax. Historically, I have been much more uncomfortable with lambda{|x|} not establishing a new binding for x whenever there was an x in the outer scope already, which is a history now. :-) Lispers do not complain too much about (lambda (...) ...), but again, they are not using it that often anyway - at least in Common Lisp, macros having &body at their end are quite common and you do not need to pass the body as a lambda to them. It is Scheme where the lambdas are more prevalent, I would say, but at least in DrScheme, ë works as lambda anyway, and they even have a keybinding for it - CTRL+\. In Gauche Scheme, I do just (define ë lambda). Hmm, I guess I'm either conservative or not-too-demanding. :-) Regards Jakub Hegenbart
on 08.05.2008 08:13
On Apr 30, 2008, at 9:26 PM, Dave Thomas wrote: > languages, I'm used to lambdas being written > > \ params -> block i like the '->' because it suggests very nice multi-block syntax filter( :before -> { buf.upcase }, :after -> { bug.downcase } ) which doesn't work now, of course, but it can't be that far off. a @ http://codeforpeople.com/
on 08.05.2008 13:18
Hi -- On Thu, 8 May 2008, ara howard wrote: >> while playing with pure, it struck me. The '->' sequence is in an > > :after -> { bug.downcase } > > ) > > which doesn't work now, of course, but it can't be that far off. Consider the big picture, though :-) That's a pretty specific use-case (I don't mean it's unheard-of, but it's not likely to account for the majority of literal lambdas), and if you're right that it's going to be possible, then I guess we'd also have: m(:one "string", :two "other") and m(:one [1,2,3], :two [2,3,4]) In other words, not every case will have an arrow built into it, and I don't think it's worth the line noise and possibly odd semantics of the arrow, in other contexts, just so one class of argument can look like it's being pointed to in argument lists. David
on 08.05.2008 16:50
ara howard wrote: >> Today, while playing with pure, it struck me. The '->' sequence is in > > :after -> { bug.downcase } > > ) Note that this already works in ruby19: filter before: -> { buf.upcase }, after: -> { buf.downcase} Regards, Michael
on 08.05.2008 17:00
On May 8, 2008, at 8:48 AM, Michael Neumann wrote: > Note that this already works in ruby19: > > filter before: -> { buf.upcase }, after: -> { buf.downcase} > > Regards, > > Michael thanks! i thought i remembered that. now, in my mind, this is very nice compare to filter before: => \{buf.upcase}, after: => \{buf.downcase} or something similar. seems like a huge consideration given how useful passing multiple blocks to functions can be. a @ http://codeforpeople.com/
on 08.05.2008 17:36
On May 8, 2008, at 5:18 AM, David A. Black wrote: > In other words, not every case will have an arrow built into it, and I > don't think it's worth the line noise and possibly odd semantics of > the arrow, in other contexts, just so one class of argument can look > like it's being pointed to in argument lists. well, as michael pointed out, it's already there an i that ruby has shown itself to be moving more and more into the functional realm so i can only assume people will leverage this just like other, technically not important, features like hash collection for the last arg of a function. it really is small things like this that make ruby so pretty. for the other cases there is always lambda, which looks fine and only a little heavy. basically i get dave's point but feel that the functional languages should take a page from ruby not the other way around - ruby's syntax is easily among the prettiest on any existing multi-purpose language. cheers. a @ http://codeforpeople.com/
on 08.05.2008 17:37
Hi -- On Thu, 8 May 2008, Michael Neumann wrote: >>> syntax in Ruby 1.9 has bothered me, but I've never been sure why. Today, >> :before -> { buf.upcase }, >> >> :after -> { bug.downcase } >> >> ) > > Note that this already works in ruby19: > > filter before: -> { buf.upcase }, after: -> { buf.downcase} The arrow really looks weird there, since it's not pointing to anything but looks all the more like it is (since there's something on the left). I can imagine people will wonder why: one: -> "string" doesn't mean that "string" goes with one:.... I don't mind people having to learn stuff, but this just seems like asking for trouble. David
on 08.05.2008 17:47
Not only that but don't you think that it's going to cause conflicts with current Hash assignment semantics? --Jeremy On Thu, May 8, 2008 at 11:35 AM, David A. Black <dblack@rubypal.com> wrote: > > > On Apr 30, 2008, at 9:26 PM, Dave Thomas wrote: > unexpected place. Having played with some functional languages, I'm used to > > > > The arrow really looks weird there, since it's not pointing to > > David > > -- > Rails training from David A. Black and Ruby Power and Light: > INTRO TO RAILS June 9-12 Berlin > ADVANCING WITH RAILS June 16-19 Berlin > INTRO TO RAILS June 24-27 London (Skills Matter) > See http://www.rubypal.com for details and updates! > > -- http://jeremymcanally.com/ http://entp.com Read my books: Ruby in Practice (http://manning.com/mcanally/) My free Ruby e-book (http://humblelittlerubybook.com/) Or, my blogs: http://mrneighborly.com http://rubyinpractice.com
on 08.05.2008 17:50
Hi -- On Fri, 9 May 2008, ara.t.howard wrote: > features like hash collection for the last arg of a function. it really is > small things like this that make ruby so pretty. for the other cases there > is always lambda, which looks fine and only a little heavy. basically i get > dave's point but feel that the functional languages should take a page from > ruby not the other way around - ruby's syntax is easily among the prettiest > on any existing multi-purpose language. The arg: -> {} thing isn't, per se, something you'd leverage, though. arg: value is a general technique, but the presence of the arrow in the case of lambda arguments is just serendipitous. I agree about Ruby's prettiness, of course, but I think there's a delicate balance there too. The problems with arg: -> {} would not make me anti-lambda-arrow if I weren't already, but it's certainly not something I'd miss. In fact, as I mentioned before, I believe it has the potential to be confusing. Anyway, I doubt the ->(){} literal will stand or fall based on what it looks like in an argument list. It's really the arrow-ness of it overall that I think is problematic. David
on 08.05.2008 17:57
On May 8, 2008, at 9:35 AM, David A. Black wrote: > The arrow really looks weird there, since it's not pointing to > anything but looks all the more like it is (since there's something on > the left). i'm confused: in what way is this 'not pointing to anything' irb(main):013:0> def pointed(opts) opts[:before].call end => nil irb(main):014:0> pointed before: -> { p 42 } 42 => 42 ?? a @ http://codeforpeople.com/
on 08.05.2008 18:05
Hi -- On Fri, 9 May 2008, ara.t.howard wrote: > irb(main):013:0> def pointed(opts) opts[:before].call end > => nil > > > irb(main):014:0> pointed before: -> { p 42 } > 42 > => 42 Because if the arrow means "I'm pointing", then the {} should be a hash. Of course one can describe that one case as "symbol: plus arrow pointing to curly braces which mean a lambda in this context", but the problem is that the presence of an arrow *in that one case* is just serendipitous. It still leaves you with: my_method(str: "hello") where suddenly the logic of "pointing from the symbol to the object" has vanished. Also, I believe -> was chosen because it's supposed to look like a sideways lambda, not because it looks like an arrow. Unfortunately it looks like an arrow. Again, the oddness of the special-case non-arrow-arrow in argument lists wouldn't be a deal-breaker for me if I had no other problem with the ->(){} syntax, but I'm not a fan of it in general. David
on 08.05.2008 18:34
David A. Black wrote:
> Hi --
>
> On Fri, 9 May 2008, ara.t.howard wrote:
>
>>
>> On May 8, 2008, at 9:35 AM, David A. Black wrote:
>>> The arrow really looks weird there, since it's not pointing to
>>> anything but looks all the more like it is (since there's something
on
>>> the left).
>>
>> i'm confused: in what way is this 'not pointing to anything'
>>
>>
>>
>> irb(main):013:0> def pointed(opts) opts[:before].call end
>> => nil
>>
>>
>> irb(main):014:0> pointed before: -> { p 42 }
>> 42
>> => 42?
I'm starting to like your proposal (if that was yours):
filter before: \{ buf.downcase },
after: \(a,b) { a + b }
vs.
filter before: ->{ buf.downcase },
after: ->(a,b) { a + b }
It just reads better IMHO. Hum, but probably this has been discussed to
death already, and there are good arguments against. Or maybe a "~"
instead of "\"? (I know this will trouble the Ruby parser)
Regards,
Michael
on 08.05.2008 19:21
Hi -- On Fri, 9 May 2008, Michael Neumann wrote: > I'm starting to like your proposal (if that was yours): > > filter before: \{ buf.downcase }, > after: \(a,b) { a + b } > > vs. > > filter before: ->{ buf.downcase }, > after: ->(a,b) { a + b } 'Twas Dave Thomas's proposal. I've just been yapping a lot about -> :-) David
on 08.05.2008 20:19
On May 8, 2008, at 10:04 AM, David A. Black wrote: > Because if the arrow means "I'm pointing", then the {} should be a > hash p :that => 'makes absolutely zero sense to me?' p :arrows => 'point to rhs, not hashes' m{ } m = {} m = %r{} m = %{} m = ->{} so i don't see the fact that the char or two before a {} meaning is 'must be a hash' and standing on very firm ground. anyhow - i'm in the minority so i'll bow out. having made my argument that ruby is prettier than most so to heck with being like the 'others' (sorry dave ;-)). a @ http://codeforpeople.com/
on 08.05.2008 21:44
Hi -- On Fri, 9 May 2008, ara.t.howard wrote: > > so i don't see the fact that the char or two before a {} meaning is 'must be > a hash' and standing on very firm ground. Have another look at my posts; I didn't say anything general about a character or two before a {}, and I didn't say that everything an arrow points to is a hash. (It's humbling to discover that you would consider it possible that I would believe something so idiotic, though, and I guess that's good for my character :-) In this situation: m(sym: value) the entire expression ->(x){x} (or whatever) plays the role of value. That includes the ->. Therefore, the -> is not serving the role of pointing to anything. It is already being consumed, so to speak, by the fact that it is part of the value expression. We've got a symbol and a value, and nothing but space between them (because -> is part of the value). So if someone sees this: m(sym: ->(x) { x }) and you say that there's a symbol, plus an arrow pointing to a lambda literal, they would presumably subtract the -> from the picture and conclude that the lambda literal to which the arrow is pointing is this: (x) { x } So when the next example comes along: m(sym: "string") the question might arise: why don't strings get an arrow pointing to them when they're in this position? The answer is: *nothing* gets an arrow pointing to it. Lambda literals *themselves* contain the arrow -- at least, something that looks like an arrow, though semantically it isn't one; it's just the first two characters of a lambda literal. So even if I thought the arrow somehow looked particularly nice in that position, I would not consider that to weigh in on the side of having the ->(){} syntax, and I would not think it so visually attractive as to be worth the possible confusion. The point about hashes was, of course, that if someone *did* read the arrow as meaning "pointing to" the rhs, and the rhs consisted of {}, then they would presumably conclude that what was being pointed to was a hash. It's really just another gloss on the same point and has nothing to do with generalizations about => being an arrow or hashes having characters in front of them. Now, if that explication comes across as meaning that 2 should be set equal to 1, or that argument lists should be typed backwards, or anything like that, I think I'd rather not know :-) In the end all of this is really just a minor side-point to the whole ->(){} discussion. David
on 09.05.2008 03:09
How about we just move to UTF-8 source files and use the actual lambda character instead of arguing weeks on end about which ASCII representation is least unlike the lambda character?
on 09.05.2008 18:36
"E S" <ruby-ml@kittensoft.org> writes: > How about we just move to UTF-8 source files and > use the actual lambda character instead of arguing > weeks on end about which ASCII representation is > least unlike the lambda character? Actually, you can do this with an alias already for regular lambdas. But it would be great if that alias were set up for you automatically. I've already set up Emacs to render the string "lambda" as λ and have bound C-c l to insert it. It's just a matter of getting proper tool support. =) -Phil (add-hook 'ruby-mode-hook (lambda () (font-lock-add-keywords nil `(("(?\\(lambda\\>\\)" (0 (progn (compose-region (match-beginning 1) (match-end 1) ,(make-char 'greek-iso8859-7 107)) nil)))))) (define-key ruby-mode-map (kbd "C-c l") (lambda () (interactive) (insert "lambda")))
on 09.05.2008 19:32
On Fri, May 9, 2008 at 6:34 PM, Phil Hagelberg <phil@hagelb.org> wrote: > I've already set up Emacs to render the string "lambda" as λ and have > bound C-c l to insert it. It's just a matter of getting proper tool > support. =) > Good point, I agree that good tool support can boost programming in any language. However, this discussion was started with the intend to make the language ruby better/nicer/more readable/etc. -- henon
on 09.05.2008 21:20
On Thu, May 8, 2008 at 9:09 PM, E S <ruby-ml@kittensoft.org> wrote: > How about we just move to UTF-8 source files and > use the actual lambda character instead of arguing > weeks on end about which ASCII representation is > least unlike the lambda character? There be dragons! and the top of the slippery slope leading to turning Ruby into APL! <G> -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/
on 09.05.2008 23:37
Phil Hagelberg wrote: > I've already set up Emacs to render the string "lambda" as λ and have > nil `(("(?\\(lambda\\>\\)" > (0 (progn (compose-region (match-beginning 1) (match-end 1) > ,(make-char 'greek-iso8859-7 107)) > nil)))))) > > (define-key ruby-mode-map (kbd "C-c l") (lambda () (interactive) (insert "lambda"))) Anyone having a vim equivalent? :) Regards, Michael
on 11.05.2008 08:15
Not to throw the whole thread into a tizzy again, but why again is:
->(a,b) { } # stabby proc
better than
def(a,b) { } # anonymous def
Seems like there has been continual talk of the positions of ->, but
none (I may have missed it) on it existing at all (though, I'm quite
aware of them existing before).
IMHO, the anonymous def syntax is consistent, easy to type, and looks
nice.
- Evan
on 11.05.2008 09:08
Am 11 May 2008 um 15:14 hat Evan Phoenix geschrieben: > aware of them existing before). > > IMHO, the anonymous def syntax is consistent, easy to type, and looks > nice. +1 I would def_initely prefer the anonymous def syntax. It is simple, immediately clear and beautyful. '->() {}' introduces something new, which is not obviously a proc. 'def(a,b) {}' is more logical, because it clearly says what it (as a lambda or proc) really is: an anonymous function. Dirk
on 11.05.2008 12:24
Evan Phoenix wrote:
> Not to throw the whole thread into a tizzy again, but why again is:
>
> ->(a,b) { } # stabby proc
>
> better than
>
> def(a,b) { } # anonymous def
shouldn't that be
def(a,b) ... end
otherwise it introduces again a bit of inconsistency. And then "def" is
used for methods, not procs. Despite, I like the syntax :)
Regards,
Michael
on 11.05.2008 16:51
Hi, At Sun, 11 May 2008 15:14:54 +0900, Evan Phoenix wrote in [ruby-core:16705]: > Not to throw the whole thread into a tizzy again, but why again is: > > ->(a,b) { } # stabby proc > > better than > > def(a,b) { } # anonymous def It would conflict with singleton method definitions.
on 11.05.2008 17:53
Hi -- On Sun, 11 May 2008, Nobuyoshi Nakada wrote: >> def(a,b) { } # anonymous def > > It would conflict with singleton method definitions. I can't quite figure that out; can you elaborate? Also, as Michael pointed out, I think Evan meant: def(a,b) ... end though I don't know if that's where the conflict is. David
on 11.05.2008 17:54
On Sun, May 11, 2008 at 9:49 AM, Nobuyoshi Nakada <nobu@ruby-lang.org> wrote: > > def(a,b) { } # anonymous def > > It would conflict with singleton method definitions. > > -- > Nobu Nakada > > I've never seen the ()'s used for the "singleton". i.e. def (a+b).foo ... end Is it necessary to preserve compatibility to do this since nobody really uses it? You could still do the above with: c = a+b def c.foo ... end My personal preference would be to not introduce some brand new block/lambda/proc/def form. I think there is already enough confusion around the topic. Instead, just extend block arguments to allow for defaults and its own block argument. i.e. ... { |a, b=1, c=(d|e), &f| ... } To handle the ambiguity between "|" in the default value vs. the argument list terminator, I think the only thing that you'd need to do is to restrict the default value to be "primary" instead of "arg_value". For a "def", an optional argument in parse.y is: f_opt : tIDENTIFIER '=' arg_value For a block, it would just be: block_f_opt : tIDENTIFIER '=' primary and you'd change block_params to allow block_f_opt like f_args allows for f_opt. Any downside with this? Eric
on 11.05.2008 18:01
2008/5/5 Paul Brannan <pbrannan@atdesk.com>: > > an unexpected place. Having played with some functional languages, I'm > > Paul > > +1 1) Syntax lambda(params) { block } may cause problems with interpreting the following code: block = proc {} lambda(&block) So 'lambda' should become keyword and does not allow passing &block in round parentheses. If parenthesis goes after 'lambda' that it should be treated as special case with method semantics. So lambda(&block) { block.call } is valid. And lambda(&block) gives ArgumentError "Block should be given to lambda implicitly" But still curled brackets block is associated with "block semantics" and not with "method semantics". It's a problem. 2) Proposed define_method's syntax define_method :bar, &lambda(a,b=1){a + b} is too heavy. And again it's unnatural to think about curled brackets block as having "method semantics" (What will 'return' do inside this block?). In fact I prefer something like this: def { :bar } (a, b=1) a+b end {:bar} could be replaced by < :bar > OR \(:bar) OR *(:bar) to simplify parsing. Here we need something absolutely new with semantic "calculate it, call :to_sym, and place it here". Artem
on 11.05.2008 19:07
On Sun, May 11, 2008 at 11:53 AM, Eric Mahurin <eric.mahurin@gmail.com> wrote: >> > >> > > I've never seen the ()'s used for the "singleton". i.e. > > def (a+b).foo > ... > end > > Is it necessary to preserve compatibility to do this since nobody really > uses it? It could be disambiguated by the grammar distinguishing between def(<expr>) or def (<expr>) as the 'lambda' notation and def(<expr>).<identifier> as defining a singleton method on the value of <expr> Now there's a slight issue. It appears that Ruby lets you define a method with the name def irb(main):001:0> def foo(a) irb(main):002:1> a irb(main):003:1> end => nil irb(main):004:0> self.foo(^C irb(main):004:0> quit Macintosh:rixdvds rick$ irb irb(main):001:0> def def(a) irb(main):002:1> a irb(main):003:1> end => nil irb(main):004:0> self.def(:foo) => :foo So it would appear that def(x) is ambiguous, is it a definition or an invocation of self.def(x)? But if we try to use it (this is in irb 1.8): irb(main):005:0> def(a) irb(main):006:1> a+1 irb(main):007:1> end SyntaxError: compile error (irb):5: syntax error, unexpected '\n', expecting tCOLON2 or '.' (irb):7: syntax error, unexpected kEND, expecting $end from (irb):7 It clearly seems to be parsed as a method definition. So I think def(<expr>) <block> could be unambigously defined to be an expression evaluating to a lambda. Whether or not the two (or is it three) meanings of def can be explained clearly enough is a slight question. I'd actually prefer lambda(x,y) {...} to def(x,y) {...} but this would seem to have less easily reconcilable conflicts with the existing lambda method. -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/
on 11.05.2008 20:05
On Sun, May 11, 2008 at 12:06 PM, Rick DeNatale <rick.denatale@gmail.com> wrote: > >> Evan Phoenix wrote in [ruby-core:16705]: > >> -- > > uses it? > > as defining a singleton method on the value of <expr> > Without left-factoring, this would require arbitrary lookahead which the current parser (yacc) won't like. The <expr> for the 2 cases above are different (the first is a list of arguments with possible defaults and the second is an expression), so left-factoring would be ugly. The main purpose of the ->(){} syntax is to support lambdas with default arguments, right? If so, why not just allow defaults with block arguments where the defaults are "primary" so you don't have the "|" ambiguity? Or is there another purpose?
on 11.05.2008 20:45
On May 11, 2008, at 8:52 AM, David A. Black wrote: >>> ->(a,b) { } # stabby proc > def(a,b) > ... > end Yeah, I did. I thought about this a bit more last night, and realized perhaps a reason that matz decided on stabby proc was it makes parens optional (and I've seen a no parens stabby proc example). Anonymous def would be ambiguous without parens with one arg: def a end Everyone can see the ambiguity there. But to push on this a little bit, the stabby proc with no parens is SO hard for my brain to parse. It appears to be a mismatch of random symbols without no cohesive elements pulling them together: -> a, b { a + b } In the name of consistency, I can see why the matz wanted it to be allowed without parens, everything else doesn't require them. But ick, it looks so... ick. So, there are a few options: 1) Anonymous def must have parens. The problem is that it bucks consistency with parens on the rest of the elements in the language. 2) Add something to def to disambiguate it, like def!(...). This is actually the same as the #1 (in #1, the something is '('), just with a different element that doesn't have to be matched. 3) Use a different word for def. lambda has been suggested, and I personally don't think it's too many characters. I think that #1 is the best, but a user may get confused by the fact that: def a; ...; end and def(a); ...; end are 2 completely different things. Nobu says that it conflicts with adding singleton methods, but I'm not sure what he means. Perhaps he's referring to the problem without parens. - Evan
on 11.05.2008 21:13
On May 11, 2008, at 11:53 AM, Eric Mahurin wrote: > Is it necessary to preserve compatibility to do this since nobody > really uses it? [...] IMHO, yes. Otherwise it becomes yet another inconsistency that one must remember.
on 11.05.2008 21:23
Evan Phoenix wrote: > 1) Anonymous def must have parens. The problem is that it bucks > consistency with parens on the rest of the elements in the language. Require that method definitions must have parens if they have arguments. Dan
on 11.05.2008 21:41
On May 11, 2008, at 3:21 PM, Daniel Berger wrote: > Evan Phoenix wrote: > >> 1) Anonymous def must have parens. The problem is that it bucks >> consistency with parens on the rest of the elements in the language. > > Require that method definitions must have parens if they have > arguments. Thanks. Looks like fun. Oh, and here's the latest iPhone rumour: http://gizmodo.com/389327/new-iphone-firmware-beta-has-a-3g-onoff-switch-i-wish-it-was-automatic
on 11.05.2008 22:03
On Sun, May 11, 2008 at 3:21 PM, Daniel Berger <djberg96@gmail.com> wrote: > Evan Phoenix wrote: > >> 1) Anonymous def must have parens. The problem is that it bucks >> consistency with parens on the rest of the elements in the language. > > Require that method definitions must have parens if they have arguments. Shhhh, Don't let Ara hear you talking like that! <G> -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/