Professional Web Applications Themes

break in yield/block - Ruby

Is there any reason that break acts differently in a block passed to a method depending on whether yield is used? Code: def meow(doyield, &block) puts "in meow #{doyield}" if doyield then yield else block[] end puts "leaving meow" end b = proc { puts "in proc" break puts "leaving proc" } meow(true, &b) puts meow(false, &b) [run] bash-2.05$ ruby test.rb in meow true in proc in meow false in proc leaving meow bash-2.05$ ruby --version ruby 1.6.7 (2002-03-01) [sparc-solaris2.7] [/run] [run] [mattlinux1 matt]$ ruby test.rb in meow true in proc in meow false in proc leaving meow [mattlinux1 matt]$ ...

  1. #1

    Default break in yield/block

    Is there any reason that break acts differently in a block passed to a
    method depending on whether yield is used?

    Code:
    def meow(doyield, &block)
    puts "in meow #{doyield}"
    if doyield then yield else block[] end
    puts "leaving meow"
    end
    
    b = proc {
    puts "in proc"
    break
    puts "leaving proc"
    }
    
    meow(true, &b)
    puts
    meow(false, &b)
    [run]
    bash-2.05$ ruby test.rb
    in meow true
    in proc

    in meow false
    in proc
    leaving meow
    bash-2.05$ ruby --version
    ruby 1.6.7 (2002-03-01) [sparc-solaris2.7]
    [/run]

    [run]
    [mattlinux1 matt]$ ruby test.rb
    in meow true
    in proc

    in meow false
    in proc
    leaving meow
    [mattlinux1 matt]$ ruby --version
    ruby 1.8.0 (2003-08-04) [i586-linux]
    [/run]
    matt Guest

  2. #2

    Default Re: break in yield/block

    Hi,

    In message "break in yield/block"
    on 03/11/20, matt <mhm26drexel.edu> writes:

    |Is there any reason that break acts differently in a block passed to a
    |method depending on whether yield is used?

    Because they are different. "break" in a block terminates a method
    that the block is attached to. In your example, it is "meow" when
    doyield, and "[]" when not.

    I'm not sure what you think they should be.

    matz.


    Yukihiro Matsumoto Guest

  3. #3

    Default Re: break in yield/block

    [email]matzruby-lang.org[/email] (Yukihiro Matsumoto) wrote in message news:<1069269880.596357.859.nullmailerpicachu.net lab.jp>...
    > Hi,
    >
    > In message "break in yield/block"
    > on 03/11/20, matt <mhm26drexel.edu> writes:
    >
    > |Is there any reason that break acts differently in a block passed to a
    > |method depending on whether yield is used?
    >
    > Because they are different. "break" in a block terminates a method
    > that the block is attached to. In your example, it is "meow" when
    > doyield, and "[]" when not.
    >
    > I'm not sure what you think they should be.
    >
    > matz.
    I figured that was why break was terminating in #[] - but why not have
    yield act as a `method' in this sense? My guess is that in this
    respect, they should be the same. Should I really be writing my
    blocks to work a certain way depending on whether the implementor
    decided to use yield or [], or whether I'm doing something like
    list_of_methods_args.each {|meth, *args| meth.call(args,
    &special_magic)}
    (this is assuming that there are stand alone methods attached to
    instances - I heard there are in 1.8.x - otherwise, rework code yadda
    yadda)

    - then I have to worry about how blocks are used in each one if
    special_magic uses break - what if the list was made dynamically from
    reflection, etc? Granted, I generally don't use break - especially in
    lambdas - but its still something I didn't expect.

    ~Me!
    matt Guest

  4. #4

    Default Re: break in yield/block

    >>>>> "m" == matt <mhm26drexel.edu> writes:

    m> - then I have to worry about how blocks are used in each one if
    m> special_magic uses break - what if the list was made dynamically from
    m> reflection, etc? Granted, I generally don't use break - especially in
    m> lambdas - but its still something I didn't expect.

    well, the problem is that you have written something strange.

    Your first example was

    def meow
    yield
    end

    meow do
    puts "in block"
    break
    puts "leaving block"
    end

    Your second example was

    p = proc do
    puts "in proc"
    break
    puts "leaving proc"
    end

    def meow(block)
    block[]
    end

    meow(p)



    Guy Decoux





    ts Guest

  5. #5

    Default Re: break in yield/block

    > well, the problem is that you have written something strange.
    >
    > Your first example was
    >
    > def meow
    > yield
    > end
    >
    > meow do
    > puts "in block"
    > break
    > puts "leaving block"
    > end
    >
    > Your second example was
    >
    > p = proc do
    > puts "in proc"
    > break
    > puts "leaving proc"
    > end
    >
    > def meow(block)
    > block[]
    > end
    >
    > meow(p)
    The first example is the same as
    def meow
    yield
    end

    meow {
    puts "in proc"
    break
    puts "leaving proc"
    }

    The second example is more akin to

    def meow(&block)
    block[]
    end

    meow {
    puts "in proc"
    break
    puts "leaving proc"
    }

    than what you gave. Note that the only thing that changed is the
    definition of meow - not the invocation.

    Also - for my list example, I of course meant
    list_of_methods_args.each {|meth, *args|
    meth.call(*args, &special_magic)
    }
    as opposed to the original
    list_of_methods_args.each {|meth, *args|
    meth.call(args, &special_magic)
    }
    -- change is `meth.call(args' to meth.call(*args' --
    matt Guest

  6. #6

    Default Re: break in yield/block

    Hi,

    In message "Re: break in yield/block"
    on 03/11/20, matt <mhm26drexel.edu> writes:

    |I figured that was why break was terminating in #[] - but why not have
    |yield act as a `method' in this sense? My guess is that in this
    |respect, they should be the same.

    They cannot be same. I would surprise if calling Proc#[] terminates
    meow(). But I prepared the way to make meow behave as you expect:

    def meow(doyield, &block)
    puts "in meow #{doyield}"
    if doyield
    yield
    else
    block[]
    end
    puts "leaving meow"
    rescue LocalJumpError
    return
    end

    b = Proc.new {
    puts "in proc"
    break
    puts "leaving proc"
    }

    meow(true, &b)
    puts
    meow(false, &b)

    Tip: do not use "proc" nor "lambda" when you want objectified Block.

    matz.


    Yukihiro Matsumoto Guest

  7. #7

    Default Re: break in yield/block

    [email]matzruby-lang.org[/email] (Yukihiro Matsumoto) wrote in message news:<1069395225.856100.31032.nullmailerpicachu.n etlab.jp>...
    > Hi,
    >
    > In message "Re: break in yield/block"
    > on 03/11/20, matt <mhm26drexel.edu> writes:
    >
    > |I figured that was why break was terminating in #[] - but why not have
    > |yield act as a `method' in this sense? My guess is that in this
    > |respect, they should be the same.
    >
    > They cannot be same. I would surprise if calling Proc#[] terminates
    > meow(). But I prepared the way to make meow behave as you expect:
    I was actually desiring the other way - that break from yield act like
    break from Proc#[].

    > def meow(doyield, &block)
    > puts "in meow #{doyield}"
    > if doyield
    > yield
    > else
    > block[]
    > end
    > puts "leaving meow"
    > rescue LocalJumpError
    > return
    > end
    >
    > b = Proc.new {
    > puts "in proc"
    > break
    > puts "leaving proc"
    > }
    >
    > meow(true, &b)
    > puts
    > meow(false, &b)
    >
    > Tip: do not use "proc" nor "lambda" when you want objectified Block.
    >
    > matz.
    Is there a reason that Proc#[] is different wrt this depending on
    whether or not proc/lambda was used, and are there any other
    differences?

    I still don't see why the break works the way it does (well, I can
    understand the reasoning) - but if I break inside a block, then I want
    that block to terminate, not the method.

    My current plans are to just do something like this
    method_invoke(*args) {|*block_args|
    callcc {|block_break|
    code - yadda yadda yadda
    block_break.call if want break / return from block
    other code...
    }
    }

    Any better ideas?
    matt Guest

  8. #8

    Default Re: break in yield/block

    Hi,

    In message "Re: break in yield/block"
    on 03/11/22, matt <mhm26drexel.edu> writes:

    |I still don't see why the break works the way it does (well, I can
    |understand the reasoning) - but if I break inside a block, then I want
    |that block to terminate, not the method.

    That's how break is defined to work. Use "next" instead to terminates
    block execution.

    matz.


    Yukihiro Matsumoto Guest

Similar Threads

  1. Thoughts on yield
    By Nolan J. Darilek in forum Ruby
    Replies: 16
    Last Post: September 30th, 05:05 PM
  2. Replies: 6
    Last Post: July 17th, 01:19 PM
  3. Replies: 0
    Last Post: January 8th, 08:52 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139