Callable class with block

B

blondinet

Hi everyone,

I would like to know why the following code does not work :
-----
class A

def A.[](*args,&block)
result = self.new( *args )
if block
yield result
result.end
end
return result
end

def end()
puts "end"
end

end

A[] do |a|
puts "a #{a.inspect}"
end
 
B

blondinet

Any idea ?

[] method can't take block unless you do

A.send '[]' do
end

a @http://drawohara.com/

Thanks for your response. However, I do not really understand why such
a behavior : for me, Class[] is just a shortcut for Class.[], which is
just a shortcut for Class.send '[]' ... Where am I wrong ?
 
T

Tim Hunter

blondinet said:
Any idea ?
[] method can't take block unless you do

A.send '[]' do
end

a @http://drawohara.com/

Thanks for your response. However, I do not really understand why such
a behavior : for me, Class[] is just a shortcut for Class.[], which is
just a shortcut for Class.send '[]' ... Where am I wrong ?

Ruby's parser doesn't allow a block to follow [].
 
B

blondinet

blondinet said:
On Jan 12, 2008, at 10:54 AM, blondinet wrote:
Any idea ?
[] method can't take block unless you do
A.send '[]' do
end
a @http://drawohara.com/
Thanks for your response. However, I do not really understand why such
a behavior : for me, Class[] is just a shortcut for Class.[], which is
just a shortcut for Class.send '[]' ... Where am I wrong ?

Ruby's parser doesn't allow a block to follow [].

Hello Tim, thank you for your response. However I think it is a bit
erroneous, since in my example, "A.[] do |a|" works !!
Anyway, I will go with it, even if it is the first time that I find
Ruby a bit incoherent, and I would like to know why ... (sigh)

P.S : by the way, Tim, thanks for your work on RMagick, it is quite
helpfull !!
You may find interesting the following link http://xrvg.rubyforge.org/,
even if it just a beginning :-(
 
T

Todd Benson

Hi everyone,

I would like to know why the following code does not work :
-----
class A

def A.[](*args,&block)
result = self.new( *args )
if block
yield result
result.end
end
return result
end

def end()
puts "end"
end

end

A[] do |a|
puts "a #{a.inspect}"
end

That is interesting. With 1.8.6, I get results like this...

irb(main):001:0> class C
irb(main):002:1> def []
irb(main):003:2> yield
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0 c = C.new
=> #<C:0x2dfac1c>
irb(main):007:0> c[]
LocalJumpError: no block given <<<interesting part
from (irb):3:in `[]'
from (irb):7
irb(main):008:0> c[] {}
SyntaxError: compile error
(irb):8: syntax error, unexpected '{', expecting $end
c[] {}
^
from(irb):8
irb(main):009:0> c.[] {}
=> nil


Bug maybe? I can't think of a reason why the parser would need to
separate [] from .[]
Hmm...

Todd
 
B

blondinet

Hi everyone,
I would like to know why the following code does not work :
def A.[](*args,&block)
result = self.new( *args )
if block
yield result
result.end
end
return result
end
def end()
puts "end"
end

A[] do |a|
puts "a #{a.inspect}"
end

That is interesting. With 1.8.6, I get results like this...

irb(main):001:0> class C
irb(main):002:1> def []
irb(main):003:2> yield
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0 c = C.new
=> #<C:0x2dfac1c>
irb(main):007:0> c[]
LocalJumpError: no block given <<<interesting part
from (irb):3:in `[]'
from (irb):7
irb(main):008:0> c[] {}
SyntaxError: compile error
(irb):8: syntax error, unexpected '{', expecting $end
c[] {}
^
from(irb):8
irb(main):009:0> c.[] {}
=> nil

Bug maybe? I can't think of a reason why the parser would need to
separate [] from .[]
Hmm...

Todd

Thanks Todd for your analysis.
Your example is even striking than mine, and I share your opinion on
this strange "feature" : that a block is required and cannot be given
with the same syntax seems to me a bit "ugly".
Any other opinion ? As a beginner on this forum, I do not know yet
what to do with this ...
 
R

Robert Dober

Hi everyone,
I would like to know why the following code does not work :
def A.[](*args,&block)
result = self.new( *args )
if block
yield result
result.end
end
return result
end
def end()
puts "end"
end

A[] do |a|
puts "a #{a.inspect}"
end

That is interesting. With 1.8.6, I get results like this...

irb(main):001:0> class C
irb(main):002:1> def []
irb(main):003:2> yield
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0 c = C.new
=> #<C:0x2dfac1c>
irb(main):007:0> c[]
LocalJumpError: no block given <<<interesting part
from (irb):3:in `[]'
from (irb):7
irb(main):008:0> c[] {}
SyntaxError: compile error
(irb):8: syntax error, unexpected '{', expecting $end
c[] {}
^
from(irb):8
irb(main):009:0> c.[] {}
=> nil

Bug maybe? I can't think of a reason why the parser would need to
separate [] from .[]
Hmm...

Todd

Thanks Todd for your analysis.
Your example is even striking than mine, and I share your opinion on
this strange "feature" : that a block is required and cannot be given
with the same syntax seems to me a bit "ugly".
Any other opinion ? As a beginner on this forum, I do not know yet
what to do with this ...
As this behavior is inherited in 1.9 too :(, I'd say somebody cross
posting this to ruby-core maybe.
Personally I'd love to have that changed.

Cheers
Robert
 
L

Lars

Personally I'd love to have that changed.

[] is an operator (the index operator). I would expect [] to have
higher precedence than anything that follows it. Although implemented
as such, it should not be seen as a function call, IMHO.

If

foo #=> 42

Then I would expect

foo { }

to be the same as

42 { }

which makes little sense.
 
T

Todd Benson

Personally I'd love to have that changed.

[] is an operator (the index operator). I would expect [] to have
higher precedence than anything that follows it. Although implemented
as such, it should not be seen as a function call, IMHO.

If

foo #=> 42

Then I would expect

foo { }

to be the same as

42 { }

which makes little sense.


So operators that you can redefine and execute as a method cannot
except a block as a general rule of thumb?

I would think foo { } would be parsed as (foo { }) as a single
piece, especially if you defined it to receive a block.
 
F

fedzor

So operators that you can redefine and execute as a method cannot
except a block as a general rule of thumb?

I would think foo { } would be parsed as (foo { }) as a single
piece, especially if you defined it to receive a block.



Ruby is smart so you don't have to be. But here, it works against us.

foo.[](i) do
puts 42
end

Mess around with removing the dot, putting the i in between the
brackets, etfc.
 
R

Robert Dober

Personally I'd love to have that changed.

[] is an operator (the index operator). I would expect [] to have
higher precedence than anything that follows it. Although implemented
as such, it should not be seen as a function call, IMHO.

If

foo #=> 42

Then I would expect

foo { }

to be the same as

42 { }

which makes little sense.

I am not sure I follow you, but as an anecdote I once wrote the
following method definition

def + x, &blk
...
end

when I realized that I could not go
anything + 42 { 42 }
I was quite disappointed ...

Robert
 
L

Lars

I am not sure I follow you

I'm just trying to say that I don't think that what you suggest is
intuitive behaviour to everyone. I personally think that it doesn't
make sense from a syntax point-of-view. Operators and function calls
are syntactically different things. Function calls take optional block
arguments, operator don't. I doubt its even possible to construct an
unambigious syntax.
when I realized that I could not go
anything + 42 { 42 }
I was quite disappointed ...

Consider

def something; 42; end

anything + something { 42 }

Would the block be passed to 'something' or the '+'?
 
R

Robert Dober

I'm just trying to say that I don't think that what you suggest is
intuitive behaviour to everyone. I personally think that it doesn't
make sense from a syntax point-of-view. Operators and function calls
are syntactically different things. Function calls take optional block
arguments, operator don't. I doubt its even possible to construct an
unambigious syntax.
Sorry but that just does not make sense to me...
Consider

def something; 42; end

anything + something { 42 }

Would the block be passed to 'something' or the '+'?
Well this is for the parser to decide, right? But
a + s &b being a.send:)+,s,&b) would make more sense as we still could
easily override this via the following

a + s(&b)
a + s(){}
a + (s {})
Robert
 

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
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top