BEGIN and END vs. blocks

L

leonardo.pires

I know that { ... } and do ... end have differente precedente. But,
using the latter, I got a syntax error. (I'm using version 1.8)

IMHO, because there's something implicit?


Regards
 
E

Eric Hodel

I know that { ... } and do ... end have differente precedente. But,
using the latter, I got a syntax error. (I'm using version 1.8)

IMHO, because there's something implicit?

$ ruby
p 5 do end
p(5) { }
p 5 { }
-:2: syntax error
p 5 { }
^

{} blocks require parens if you have arguments other than the block.
 
L

leonardo.pires

I think that's partially true. The curly form has a higher precedence
then the do ... end one. So, I can code:

def foo(duh)
duh
end

def goo
puts yield
end

foo goo { 'bar' }

In this case, goo is a argument, right?
 
R

Robert Klemme

I think that's partially true. The curly form has a higher precedence
then the do ... end one. So, I can code:

def foo(duh)
duh
end

def goo
puts yield
end

foo goo { 'bar' }

In this case, goo is a argument, right?

It's evaluated and the result is the argument to foo: your code is
equivalent to this version

foo( goo() { 'bar' } )

Kind regards

robert
 
C

Chris Game

I think that's partially true. The curly form has a higher precedence
then the do ... end one. So, I can code:

def foo(duh)
duh
end

def goo
puts yield
end

foo goo { 'bar' }

In this case, goo is a argument, right?

So where does precedence come in?
 
L

leonardo.pires

From PickAxe (2nd, ed. pg 341):
"Braces have a high precedence; do has a low precedence. If the method
invocation has
parameters that are not enclosed in parentheses, the brace form of a
block will bind to
the last parameter, not to the overall invocation. The do form will
bind to the invocation."

Since the there isn't parentheses, the braces bind to goo (a argument
to foo). Using the do form, a error is generated (but it's ok: you're
passing a block to foo).


I forgot to say what I want to know in my first email (sorry!) and
noticed this only now: why I can't use the do form with BEGIN or END?

END do
puts 'wow'
end

It's invalid! Because there's something implicit?
 
G

Gavin Kistner

So where does precedence come in?

foo goo { 'bar' }
foo goo do 'bar' end

The first is the same as:
foo( goo(){ 'bar' } )
foo( goo do 'bar' end )

The second is the same as:
foo( goo ){ 'bar' }
foo( goo ) do 'bar' end


def foo( *args )
puts "foo args: #{args}"
puts "foo block result: #{yield}" if block_given?
"foo return value"
end

def goo( *args )
puts "goo args: #{args}"
puts "goo block result: #{yield}" if block_given?
"goo return value"
end

foo goo { 'bar' }
puts '-' * 40
foo goo do 'bar' end

#=> goo args:
#=> goo block result: bar
#=> foo args: goo return value
#=> ----------------------------------------
#=> goo args:
#=> foo args: goo return value
#=> foo block result: bar
 
R

Randy Kramer

So where does precedence come in?

Maybe this will help (this is Hal Fulton's reply to me from about a month
ago(August 19, 2005) (on the similar question):

<quote>
Re: Newbie question
From: Hal Fulton <[email protected]>
To: (e-mail address removed) (ruby-talk ML)
Date: Yesterday 11:13:45 pm (20050819)

Randy said:
I'm not clear on what binding tighter means, or to what--any further hints
appreciated.
=
What he means is, it's a matter of precedence.

Observe the examples:
=
puts %w{cat bat rat}.map { |w| w.capitalize }

puts %w{cat bat rat}.map do |w|
w.capitalize
end
=
They mean essentially the same as:
=
puts(%w{cat bat rat}.map { |w| w.capitalize })

puts(%w{cat bat rat}.map) do |w|
w.capitalize
end
=
In the second one, the map doesn't have a block associated with it --
the block is associated with the puts instead. The map with the
empty block effectively does nothing, and the puts never calls the
block given to it.
</quote>

Randy Kramer
 
E

Eric Hodel

I forgot to say what I want to know in my first email (sorry!) and
noticed this only now: why I can't use the do form with BEGIN or END?

END do
puts 'wow'
end

It's invalid! Because there's something implicit?

It is required to use { }, from parse.y:

| klBEGIN
{
if (in_def || in_single) {
yyerror("BEGIN in method");
}
local_push(0);
}
'{' compstmt '}'
{
ruby_eval_tree_begin = block_append
(ruby_eval_tree_begin,

NEW_PREEXE($4));
local_pop();
$$ = 0;
}
| klEND '{' compstmt '}'
{
if (in_def || in_single) {
rb_warn("END in method; use at_exit");
}

$$ = NEW_ITER(0, NEW_POSTEXE(), $3);
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,183
Messages
2,570,966
Members
47,513
Latest member
JeremyLabo

Latest Threads

Top