hoodwink.d enhanced
RSS
2.0
XHTML
1.0

RedHanded

Matz is on the Plane, Weighing Dots and Arrows #

by why in inspect

Dots or arrows? Dots or arrows? See, he said he was leaving for RubyConf and on the way he’d figure out this whole dots and arrows business. Currently, arrows are winning, since they’re checked into 1.9.

Nobu gives some examples in ruby-talk:160170:

 >> 1.times -> (foo="bar") { puts foo }
 => 0

 >> def y
 >>   yield
 >> end
 >> y -> (foo="bar") { puts foo }

The two dotted suggestions (err.. one one-dotted and one two-dotted!) come from Christophe Grandsire, who suggests a colon, and Eric Mahurin, who offers a period (which semantically jives with method calling):

 collection.each:(foo="bar){puts foo} 
 collection.each.(foo="bar){puts foo} 

I don’t envy the Yacc’ry ahead for Nobu and Matz. But it’s fun to see everyone’s ears go up when the syntactical frosting comes out. Even when it’s only a couple sprinkles.

said on 12 Oct 2005 at 15:01

ARTIST : Harry Nilsson

TITLE : Me and My Arrow

The Point

Me and my arrow Straighter than narrow Wherever we go, everyone knows It’s me and my arrow

Me and my arrow Taking the high road Wherever we go, everyone knows It’s me and my arrow

And in the morning when I wake up She may be gone, I don’t know And if we make up just to break up I’ll carry on, oh yes I will

Me and my arrow, Do-do-loo-do, do-do do-do do do Straighter than narrow Wherever we go, everyone knows It’s me and my arrow

Me and my arrow (5X)

said on 12 Oct 2005 at 15:18

Even though \ has been thrown out because of problems with some encodings (turns up as a yen symbol sometimes), I still think it should be considered. Possibly one of two ways to do it?

I guess I’ve grown too fond of

\x y -> x + y 

in Haskell.

said on 12 Oct 2005 at 15:23

OK, what was the problem we were trying to solve with this new syntax again?

Oh, yeah, it’s so we can give default values to block params. Something I don’t think I’ve ever really needed…. (something I have needed, though, is to be able to give a block-scoped variable an initial value so that… oh, forget about that)

I’m hoping this doesn’t mean that the old ’|var|’ thing isn’t going away… So would this still be valid: collection.each {|item| puts item } ?

If not, I’m really going to miss it. And I’m really not going to be happy. I really hope this is being proposed as an alternative syntax, not a replacement for the current one. I really, really hope… What’s Matz’s number so I can call him on the plane?

said on 12 Oct 2005 at 15:57

I vote arrow, myself.

said on 12 Oct 2005 at 15:58
I haven’t really been following this either, but I agree, it would be sad if we lost:
collection.each {|item| ... }
That form certainly looks more elegant (and seems more intuitive) than:
collection.each -> (item) { ... }

Or maybe I’m just so accustomed to it…

said on 12 Oct 2005 at 15:58

And yes, I would be truly sad to see the demise of goalposts, if it came to that.

said on 12 Oct 2005 at 15:59

I agree mostly with <|:{. I really like the current “collection.each {|item| puts item }” style. Along with the ”|var| do” blocks.

Of the three new styles mentioned here, I think I prefer the colon approach. It is probably me overreacting, but → is a bit awkward and speed robbing.

said on 12 Oct 2005 at 17:28

Wow, matz wasn’t kidding when he said he wants to maximize breakage before 2.0. This affects every thing in ruby I’ve ever done. Unless I am reading this the wrong way, and we are keeping—

object.method { |item| ... }

Which I think is the case here…

said on 12 Oct 2005 at 17:53

If the goalposts are going, I can see the headlines now: REVOLT at RUBYCONF !

Save the goalposts! Default block params just aren’t worth it.

said on 12 Oct 2005 at 17:55

Please Help! I’m endangered!

said on 12 Oct 2005 at 18:00

Now that a syntactic face has been put on this impending tragedy ‘{|..|}’ maybe Matz will have mercy. How could he eliminate this cute little fellow:

{|..|}

Now we just need to give him a name.

said on 12 Oct 2005 at 18:20

Oh god, just fix the parser instead of tearing up the syntax, please!

said on 12 Oct 2005 at 18:34

DEATH TO DOTS AND ARROWS !

GOALPOSTS FOR LIFE !

said on 12 Oct 2005 at 18:40

I trust Matz will duly take into account the potential havoc his decision might wreak on the Poignant Guide.

To wit:

I like to think of the pipe characters as representing a tunnel. They give the appearance of a chute that the variables are sliding down. (An x goes down spread eagle, while the y neatly crosses her legs.) This chute acts as a passageway between blocks and the world around them.

Variables are passed through this chute (or tunnel) into the block.

PoignantGuide.Chapter(3).BlockArguments

said on 12 Oct 2005 at 18:57

The beauty of that passage from the PoignantGuide would be mared by dots and arrows. Perhaps it would have to be changed to read something like:

I like to think of the arrow being shot into the variables x and y killing them… but all is not lost, they are resurrected to start a new life in the block ahead….

No, that just doesn’t work. The arrow operator is just too violent and reminicent of that barbaric language C.

said on 12 Oct 2005 at 19:49

What’s the point of this? To make it easier for the computer to parse and harder for the human to parse? I could have sworn that the readability was half the point of using Ruby in the first place.

said on 12 Oct 2005 at 19:59

{|..|} looks rather like the Prince from Katamari Damacy, minus antenna.

said on 12 Oct 2005 at 20:01

Aha! I found the “reason.”

said on 12 Oct 2005 at 20:18

Perhaps this is extreme but why not get rid of bitwise or. I don’t think it’s used often enough to justify its own symbol, and we could just use bitor (or something equivalent) to do the same thing.

said on 12 Oct 2005 at 20:44

Or, why not just make the parser say that the first | is the end of the block parameters, period… if you want to use bitwise or inside a default parameter (which is pretty bloody unlikely, IMO ) you can put it in (..).

said on 12 Oct 2005 at 21:00

Albert: No, we should not get rid of bitwise OR. I would suggest that this whole idea of needing to create a mechanism for default arguments to blocks is a solution in search of a problem. I think the whole idea should be dropped because it is of such limited use. Sure it might come in handy in some very special cases that might crop up less than 1% of the of the time – why mess up Ruby’s syntax just for such a small gain? In my five years of Ruby programming I can think of one time where I said, “Gee, it would be nice to have default arguments to blocks” – and then I worked around it (not very hard to do). Better to have some inconvenience for that very special case than to make this kind of change that inconveniences a lot of people and totally breaks current code.

said on 12 Oct 2005 at 21:24
forever {|..|}: so apparently yacc is keeping us from having this nice syntax:

lambda { |foo = bar| puts foo }

This seems like the ‘correct’ syntax for default block arguments. It looks great. But yacc doesn’t like it apparently. Should yacc dictate our language design? I say NO!

If we can’t have something nice and intuitive like:

lambda { |foo = bar| puts foo }

then we should either: 1) wait for a better yacc that could handle it (probably not possible) 2)find another parser generator for Ruby (ANTLR?) or perhaps even have the Ruby parser written in Ruby (that would have lots of advantages – though a disadvantage could be slowness.)

Actually, come to think of it, why can’t yacc handle:

lambda { |foo = bar| puts foo }

?

We all know Matz is brilliant, but maybe yacc isn’t his thing. Any yacc experts out there who can help us out? I’d hate to see Ruby’s syntax get messed up because of yacc limitations (or perceived limitations)... come to think of it, it probably isn’t possible in yacc because of the bitwise OR thing. Would it be too require that bitwise OR not be allowed between the goalposts? They aren’t allowed now, so what’s the big deal? Or, we could say that you have to use ‘or’ not ’|’. Or if you insist on using a bitwise OR between the goalposts you’ve gotta enclose the whole experession in ‘(..)’. Doesn’t seem like much to ask.

Or what if an alternate syntax were allowed:

lambda {(foo=bar|baz) puts foo }

...Ah, but now they’ve got me playing their game. I say we just say NO.

said on 12 Oct 2005 at 21:37

To explain why they’re looking at default parameters in blocks, suppose you want to dynamically define a method (such as what all that metaprogramming jazz does.) A nice, sensible way to do that is to pass the method logic as a block.

Now, what do suppose you would do if the method you wanted to define had default values for some parameters?

But I agree that if YACC is really the problem here, then off with its head. Isn’t the Perl parser/lexer written in Perl? Maybe that was an urban legend… ;-)

said on 12 Oct 2005 at 23:48

IMO , lambda { |foo = bar| puts foo } is by far the best.

If yacc truly can’t handle it, than maybe an alternative to yacc needs to be found.

said on 13 Oct 2005 at 00:04

The arrows they’re just stealing from perl. And in perl they do like kind of nice:

for @list -> $item {...}

or

@list.map -> $i { f $i }

or even

while readline() -> $line { ... }

From the perspective of someone who doesn’t live and breathe ruby, the arrow visually puts the parameter list between the block-caller and the block, which is where it belongs semantically. Plus this way blocks looks visually more like functions.

said on 13 Oct 2005 at 00:12

There was a big duscussion about this stuff on ruby-talk back in August. Matz said the {|..|} would never go away. And I quote:

|I think one of the first things that attracted me to ruby is the {| |x|...} syntax. So please leave my happy little blocks alone. Or at |least leave them as an option.

Don’t worry. The block syntax will not be changed. Never.

matz.
said on 13 Oct 2005 at 00:18

I say we all learn Python. Just to see how hell really looks like.

said on 13 Oct 2005 at 00:52
Everyone would rather have:

{|foo=bar| ... }

That much is clear. But yacc makes it impossible, and more important matz seems unwilling to change parser. So discussions about the parser itself are likely to lead to nothing (short of someone making a patch to make yacc work in a way that would allow the above syntax).

So if we are going to have a new syntax for blocks with default argument values (and we are going to, despite what the opponents might have liked), let’s have a nice one at least. It may not be used often (thank God!), but at least one’s eyes won’t jump out of their sockets if they come across code using it. And the current syntax stays, so nobody has to change their habits if they don’t want to.

BTW , I am Christophe Grandsire, the one that proposed the colon syntax. I just want to make clear that I have no big attachment to this subject. I just want every feature of Ruby’s syntax to fit in the whole, even if this is a controversial one. And that arrow just jumps out and bites your nose. At least there are precedents in Ruby for the use of the colon, so it doesn’t hurt as much.

Anyway, the important thing at least is this: Do not worry: {|..|} is not going away! The new syntax is just an alternative syntax (with one additional feature), not a replacement of the current one.

said on 13 Oct 2005 at 01:30

Hug and Kisses lads. Me thinks, I’ve been struck by Cupids Arrow.

    _ _
   ( V ) 
 <--\ /--<<
     V 

I love arrows.

said on 13 Oct 2005 at 02:59
And why was
x = def (x,y) { ... }
rejected ? Or just add a block keyword. I also like javascript’s way of using lambdas. If you want to change the scope, just use the base method. Like :
var x = function(x,y) { js-code }.base(this)
said on 13 Oct 2005 at 03:30

Why not just use := for assignment of defaults in blocks, eg

lambda { |foo := ‘bar’| puts foo }

It reminds me of good ol’ Pascal.

said on 13 Oct 2005 at 03:53

I really don’t want \ because escaping things is already done with \ so it crops up everywhere in the regexp %Q(world). [Without looking it up, what’s the gsub expression for substituting \\ for \ again?] Even !^ would be better: a kit of parts to make a lambda.

Maybe if block, lambda and proc are so subtle in their difference we should just have a block keyword and do:

block(param = "default")
  p param
end
said on 13 Oct 2005 at 04:43

Can anyone give a good example of when a block needs a default value? The example given in the article, 1.times -> (foo="bar") { puts foo }, is not that great (just do puts "bar"!. Same with #each—when the hell would “bar” be printed?

said on 13 Oct 2005 at 05:54
Thomas: because the problem is not the equal sign but the goalpost ”|”. Your proposal would still not make: {|foo:=(a|b)| puts foo} possible. Yacc doesn’t seem to be able to handle that.

Dan: when you want to create a method with define_method and a block, the block arguments become the method arguments. What if you want to create a method with default argument values? You can’t right now. Another possibility I can think of (but it may be a bit contrived) is a hash where some values are nil, and you want to loop through it with all nil’s replaced by some valid value. And then there’s registering callbacks, where it may be of some use (I’m out on a limb here, having just begun to toy with Ruby-Gnome :) ).

said on 13 Oct 2005 at 08:05

Groovy had this exact same problem. This is what they used:

{ foo = 1|2 -> puts foo }

If we’re going to insist on default parameters within blocks, I think everything should stay within the braces.

said on 13 Oct 2005 at 08:12

A question:

Would yacc complain if we demanded that all default parameters within block be surrounded by parens?

For example:

{ |foo = (1|2)| puts foo }

and

{ |foo = (2)| puts foo }
said on 13 Oct 2005 at 08:36

“Should yacc dictate our language design? I say NO!”

Couldn’t agree more. Computers are slaves – we are masters. That being said, we still live in the real world. Is YACC patchable?

said on 13 Oct 2005 at 08:53

Not that I’m qualified as a language designer, but how about:

{|foo ~ bar| puts foo}

said on 13 Oct 2005 at 10:29

Now that I’ve seen that Groovy example, I’m wondering why the chute was ever necessary. A wall would have worked fine.

{ x, y | x * y }

Not that it much matters at this point :)

said on 13 Oct 2005 at 11:58
jvoorhis: the most common case is the block without parameters? If so, then you are wrong; if not, then you are right:

a.each { puts "one more" }
would become

a.each {| puts "one more" }
and

a.each { | e | puts e }
would become

a.each { e | puts e }
but anyway you are not attacking the problem: matz is having some difficulty in making yacc swallow

a.each { |c = (b|d)| puts c }
because yacc stops reading the arglist at the second pipe symbol (|)
said on 13 Oct 2005 at 12:41

people may ignore this, but yacc already dictated our language. the reason Why ruby does not have if a > b > c meaning if(b <a>c) is that yacc is not able to parse it. Come one ANTLR guys, let’s remove the ugly parse.y!

said on 13 Oct 2005 at 12:43
sorry, meant to hit preview.. I was saying:
 if a > b > c 
meaning
 if (a>b) and (b>c)
said on 13 Oct 2005 at 17:21

It seems like part of the rationale behind this is that default values for block variables would let define_method do everything a def can.

def x( a, b = 332332, * c )

would be identical to

define_method :x do |a, b = 332332, *c |

That said, I think the arrow syntax is way ugly, and is a lose.

But is it really YACC ’s fault that bitwise-OR’s inside goalposts cause problems? That seems like a difficult situation to resolve no matter what parsing software you’re using.

And, whoa, ANTLR is not the answer. Why make the entire muckiness of Java a requirement for building Ruby?

said on 13 Oct 2005 at 20:40

Oh, yeah, ANTLR is written in Java now instead of C++.

said on 14 Oct 2005 at 01:06

brasilian_guy:

The point wasn’t to attack the problem, it was just a thought I had on the block syntax. Also, what I was thinking was that the pipe character would only be there if there were parameters, otherwise no pipes.

I’ve never played with YACC although I would like to. Maybe RACC would be a fun place to start.

said on 14 Oct 2005 at 12:01

Parsers can also be written in OCaml (cf. cil.sf.net or nekovm.org).

said on 14 Oct 2005 at 16:12

“Drop-kick me Jesus through the goalposts of life, end over end through them righteous uprights.”

I envy anyone with serious YACC -fu, but I am not among them.

I’m with JB. I like the current syntax. Of the alternates, I dislike them nearly equally, but have a slight preference for the arrow and the colon (in that order).

said on 15 Oct 2005 at 03:41

How about adding a colon to the last pipe symbol? lineofcode = ‘a.each {|c=(b|d)|: puts c}’; puts m = (/(?:[ |\{])(\|.*?\|:)/).match(lineofcode)

said on 15 Oct 2005 at 09:16

It’s pity that, while the groups of developer can solve all the problem in implementing Ruby, e.g., Thread, Continuation, Porting ruby to many platform , uses of YAML ; we just can’t get the syntax we want simply because Yacc doesn’t allow it.

said on 15 Oct 2005 at 11:31

If someone wants to check out a LexerInRuby go to www.rubygarden.org/ruby?RubyOnlineCookbook. Another text scanning tool is www.rubyhacker.com/code/scanf/ (a C tool which may be optimized by cil.sf.net).

said on 15 Oct 2005 at 22:17

Incidentally, jvoorhis, Groovy used to have just the single goalpost before they discovered the bitwise-or problem. Identical syntax to what you were just saying.

Curious, how would Matz’s current syntax plan look with do..end blocks?

1.times -> (foo="bar") do
  puts foo
end

If so, that just made me hate the idea even more I think.

said on 16 Oct 2005 at 03:20

Another option to get the parser reach the last pipe symbol would be to add a colon to bitwise-or: ”|:” (instead of adding a colon to the last pipe symbol). Each of the two enclosing ”|” must then be followed by a [^:] in the regexp.

said on 16 Oct 2005 at 16:55

John McCarthy figured out the solution back in 1958: get rid of syntax completely.

Lisp forever!

said on 30 Jan 2006 at 04:29

Isn’t there a formal BNF for Ruby anywhere? If so, then switching to ANTLER shouldn’t be too difficult.

If not, then I suggest making one before starting to hack like this. I think this problem can be solved by making a BNF : (note: I don;t know BNF very well so this is probably not correct!!)

block_decl := 
     '{' '|' block_var_decl '|' block_code '}'
block_var_decl :=
     EMPTY
     var_assignment
     var_assignment ',' block_var_decl
var_assignment := 
     var_decl "=" expression 
expression := 
     decl
     '(' decl '|' more_decl ')'
Hopefully this is valid…

I think the problem with the ’->’ vs ’:’ vs ’.’ syntaxes is they don’t give you any context about what they are supposed to do. Why not use proc or function or def instead?

Cheers, Ben

Comments are closed for this entry.