Callable class with block

Discussion in 'Ruby' started by blondinet, Jan 12, 2008.

  1. blondinet

    blondinet Guest

    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
    -----

    When I want to execute this script, the interpreter outputs the
    following error :
    --
    d:/DEV/XRVG/bug.rb:18: parse error, unexpected kDO, expecting $
    A[] do |a|
    --

    If I write "A.[] do |a|" instead of "A[] do |a|", it is OK and
    outputs:
    ----
    a #<A:0x28ee264>
    end
    ----

    Any idea ?
    Any help appreciated !! Thanks in advance.
    blondinet, Jan 12, 2008
    #1
    1. Advertising

  2. blondinet

    ara.t.howard Guest

    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/
    --
    sleep is the best meditation.
    h.h. the 14th dalai lama
    ara.t.howard, Jan 12, 2008
    #2
    1. Advertising

  3. blondinet

    blondinet Guest

    On 12 jan, 22:00, "ara.t.howard" <> wrote:
    > 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/
    > --
    > sleep is the best meditation.
    > h.h. the 14th dalai lama


    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 ?
    blondinet, Jan 12, 2008
    #3
  4. blondinet

    Tim Hunter Guest

    blondinet wrote:
    > On 12 jan, 22:00, "ara.t.howard" <> wrote:
    >> 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/
    >> --
    >> sleep is the best meditation.
    >> h.h. the 14th dalai lama

    >
    > 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 [].


    --
    RMagick: http://rmagick.rubyforge.org/
    RMagick 2: http://rmagick.rubyforge.org/rmagick2.html
    Tim Hunter, Jan 12, 2008
    #4
  5. blondinet

    blondinet Guest

    On 12 jan, 23:06, Tim Hunter <> wrote:
    > blondinet wrote:
    > > On 12 jan, 22:00, "ara.t.howard" <> wrote:
    > >> 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/
    > >> --
    > >> sleep is the best meditation.
    > >> h.h. the 14th dalai lama

    >
    > > 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 [].
    >
    > --
    > RMagick:http://rmagick.rubyforge.org/
    > RMagick 2:http://rmagick.rubyforge.org/rmagick2.html


    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 :-(
    blondinet, Jan 13, 2008
    #5
  6. blondinet

    Todd Benson Guest

    On Jan 12, 2008 11:54 AM, blondinet <> wrote:
    > 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
    Todd Benson, Jan 13, 2008
    #6
  7. blondinet

    blondinet Guest

    On 13 jan, 10:56, Todd Benson <> wrote:
    > On Jan 12, 2008 11:54 AM, blondinet <> wrote:
    >
    >
    >
    > > 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


    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 ...
    blondinet, Jan 13, 2008
    #7
  8. blondinet

    Robert Dober Guest

    On Jan 13, 2008 6:24 PM, blondinet <> wrote:
    > On 13 jan, 10:56, Todd Benson <> wrote:
    >
    > > On Jan 12, 2008 11:54 AM, blondinet <> wrote:
    > >
    > >
    > >
    > > > 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

    >
    > 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

    --
    http://ruby-smalltalk.blogspot.com/

    ---
    Whereof one cannot speak, thereof one must be silent.
    Ludwig Wittgenstein
    Robert Dober, Jan 13, 2008
    #8
  9. blondinet

    Lars Guest

    On Jan 13, 8:16 pm, Robert Dober <> wrote:
    > 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.
    Lars, Jan 14, 2008
    #9
  10. blondinet

    Todd Benson Guest

    On Jan 14, 2008 9:01 AM, Lars <> wrote:
    > On Jan 13, 8:16 pm, Robert Dober <> wrote:
    > > 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.
    Todd Benson, Jan 14, 2008
    #10
  11. blondinet

    fedzor Guest

    On Jan 14, 2008, at 10:25 AM, Todd Benson wrote:

    > 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.
    fedzor, Jan 14, 2008
    #11
  12. blondinet

    Robert Dober Guest

    On Jan 14, 2008 4:01 PM, Lars <> wrote:
    > On Jan 13, 8:16 pm, Robert Dober <> wrote:
    > > 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


    --
    http://ruby-smalltalk.blogspot.com/

    ---
    Whereof one cannot speak, thereof one must be silent.
    Ludwig Wittgenstein
    Robert Dober, Jan 14, 2008
    #12
  13. blondinet

    Lars Guest

    On Jan 14, 5:22 pm, Robert Dober <> wrote:
    > 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 '+'?
    Lars, Jan 15, 2008
    #13
  14. blondinet

    Robert Dober Guest

    On Jan 15, 2008 11:15 AM, Lars <> wrote:
    > On Jan 14, 5:22 pm, Robert Dober <> wrote:
    > > 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.

    Sorry but that just does not make sense to me...
    >
    > > 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 '+'?

    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

    >
    >
    >




    --
    http://ruby-smalltalk.blogspot.com/

    ---
    Whereof one cannot speak, thereof one must be silent.
    Ludwig Wittgenstein
    Robert Dober, Jan 15, 2008
    #14
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ChaosKCW
    Replies:
    1
    Views:
    275
    Larry Bates
    Feb 25, 2006
  2. morrell
    Replies:
    1
    Views:
    933
    roy axenov
    Oct 10, 2006
  3. Nathan Duran
    Replies:
    1
    Views:
    326
    Arnaud Delobelle
    Apr 10, 2008
  4. exiquio
    Replies:
    2
    Views:
    520
    exiquio
    Oct 7, 2008
  5. Ulrich Eckhardt
    Replies:
    6
    Views:
    94
    Peter Otten
    Jul 12, 2013
Loading...

Share This Page