How to "break" a "case-when" ?

Discussion in 'Ruby' started by Iñaki Baz Castillo, Apr 17, 2008.

  1. SGksIGlzIG5vdCBwb3NzaWJsZSB0byB0ZXJtaW5hdGUgdGhlIGJvZHkgb2YgYSAid2hlbiIgc3Rh
    bWVudD8KCkkgbWVhbjoKCiAgY2FzZSBudW0KICB3aGVuIDE6CiAgICBwdXRzICJJcyAxICEhISEi
    CiAgICBicmVhawogICAgcHV0cyAiRG9uJ3Qgd3JpdGUgaXQiCiAgZW5kCgogIHB1dHMgIldyaXRl
    IGl0IgoKYnV0IHVuZm9ydHVuYXRlbGx5IHRoZSAiYnJlYWsiIGdpdmVzIGFuIGVycm9yLgoKVGhh
    bmtzIGZvciBhbnkgc3VnZ2VzdGlvbi4KCi0tIApJw7Fha2kgQmF6IENhc3RpbGxvCjxpYmNAYWxp
    YXgubmV0Pgo=
    Iñaki Baz Castillo, Apr 17, 2008
    #1
    1. Advertising

  2. RnJvbTogScOxYWtpIEJheiBDYXN0aWxsbyBbbWFpbHRvOmliY0BhbGlheC5uZXRdIA0KIyBIaSwg
    aXMgbm90IHBvc3NpYmxlIHRvIHRlcm1pbmF0ZSB0aGUgYm9keSBvZiBhICJ3aGVuIiBzdGFtZW50
    Pw0KIyAgIGNhc2UgbnVtDQojICAgd2hlbiAxOg0KIyAgICAgcHV0cyAiSXMgMSAhISEhIg0KIyAg
    ICAgYnJlYWsNCiMgICAgIHB1dHMgIkRvbid0IHdyaXRlIGl0Ig0KIyAgIGVuZA0KIyAgIHB1dHMg
    IldyaXRlIGl0Ig0KDQphZmFpaywgbm8uIGJ1dCB3aHkgd291bGQgeW91IHdhbnQgdG8gZG8gdGhh
    dD8gYXJlIHlvdSBwb3J0aW5nIGMgY29kZXM/DQoNCmtpbmQgcmVnYXJkcyAtYm90cA0K
    Peña, Botp, Apr 17, 2008
    #2
    1. Advertising

  3. Iñaki Baz Castillo

    Stefan Lang Guest

    2008/4/17, I=F1aki Baz Castillo <>:
    > Hi, is not possible to terminate the body of a "when" stament?
    >
    > I mean:
    >
    > case num
    > when 1:
    > puts "Is 1 !!!!"
    > break
    > puts "Don't write it"
    > end
    >
    > puts "Write it"
    >
    > but unfortunatelly the "break" gives an error.


    break is only for iteration. What are you trying to do?
    The example you've given is not a compelling use case,
    since you can simply remove the line after break.

    Also, Ruby's case/when doesn't fall through when clauses.

    case 1
    when 1
    puts "it's 1"
    when 2
    puts "this is not printed"
    end

    Stefan
    Stefan Lang, Apr 17, 2008
    #3
  4. MjAwOC80LzE3LCBTdGVmYW4gTGFuZyA8cGVyZmVjdGx5Lm5vcm1hbC5oYWNrZXJAZ21haWwuY29t
    PjoKCj4gYnJlYWsgaXMgb25seSBmb3IgaXRlcmF0aW9uLiBXaGF0IGFyZSB5b3UgdHJ5aW5nIHRv
    IGRvPwo+ICBUaGUgZXhhbXBsZSB5b3UndmUgZ2l2ZW4gaXMgbm90IGEgY29tcGVsbGluZyB1c2Ug
    Y2FzZSwKPiAgc2luY2UgeW91IGNhbiBzaW1wbHkgcmVtb3ZlIHRoZSBsaW5lIGFmdGVyIGJyZWFr
    LgoKT2ssIEkgd3JpdGUgYSBiZXR0ZXIgZXhhbXBsZToKCgogIHZhciA9IC4uLnNvbWV0aGluZy4u
    LgoKIGNhc2UgbnVtCiAgd2hlbiAxOgogICAgcHV0cyAidmFyIG5vdCB2YWxpZCAhISEhISIgaWYg
    KCB2YXIgPCAwIHx8IHZhciA+IDEwICkKICAgIGJyZWFrCiAgICBkb19ub3JtYWxfc3R1ZmYKICAg
    IC4uLgogICAgLi4uCiAgICBlbmRfbm9ybWFsX3N0dWZmCiAgZW5kCgogIHB1dHMgIldyaXRlIGl0
    IgoKCkkganVzdCB3YW50IGRvX25vcm1hbF9zdHVmZiBpbiBjYXNlICJ2YXIiIGlzIHZhbGlkLgpZ
    ZXMsIEkgY2FuIHB1dCBhIGJpZyAiaWYiIHN0YW1lbnQgYW5kIHNvIGJ1dCBJIHdvdWxkIGxpa2Ug
    bm90IHRvIGRvIGl0CnNpbmNlIGl0IG1ha2VzIGEgYml0IHVnbHkgdGhlIGNvZGUuCgoKLS0gCknD
    sWFraSBCYXogQ2FzdGlsbG8KPGliY0BhbGlheC5uZXQ+Cg==
    Iñaki Baz Castillo, Apr 17, 2008
    #4
  5. Iñaki Baz Castillo wrote:
    > 2008/4/17, Stefan Lang <>:
    >
    >
    >> break is only for iteration. What are you trying to do?
    >> The example you've given is not a compelling use case,
    >> since you can simply remove the line after break.
    >>

    >
    > Ok, I write a better example:
    >
    >
    > var = ...something...
    >
    > case num
    > when 1:
    > puts "var not valid !!!!!" if ( var < 0 || var > 10 )
    > break
    > do_normal_stuff
    > ...
    > ...
    > end_normal_stuff
    > end
    >
    > puts "Write it"
    >
    >
    > I just want do_normal_stuff in case "var" is valid.
    > Yes, I can put a big "if" stament and so but I would like not to do it
    > since it makes a bit ugly the code.
    >
    >
    >


    But in this example the code between do_normal_stuff and
    end_normal_stuff would never be executed, not even in C!

    Why not write something simpler

    case num
    when 1:
    if 0 <= var and var <= 10) then
    do_normal_stuff
    ...
    ...
    end_normal_stuff
    puts "Write it"
    end


    I think you are trying to be too clever here. Stick to the simple stuff.
    Peter Hickman, Apr 17, 2008
    #5
  6. MjAwOC80LzE3LCBQZXRlciBIaWNrbWFuIDxwZXRlckBzZW1hbnRpY28uY29tPjoKCj4gIEJ1dCBp
    biB0aGlzIGV4YW1wbGUgdGhlIGNvZGUgYmV0d2VlbiBkb19ub3JtYWxfc3R1ZmYgYW5kIGVuZF9u
    b3JtYWxfc3R1ZmYKPiB3b3VsZCBuZXZlciBiZSBleGVjdXRlZCwgbm90IGV2ZW4gaW4gQyEKCk9w
    c3MsIHNvcnJ5LCBteSBtaXN0YWtlLiBUaGlzIHdvdWxkIGJlOgoKdmFyID0gLi4uc29tZXRoaW5n
    Li4uCgogIGNhc2UgbnVtCiAgd2hlbiAxOgogICAgaWYgKCB2YXIgPCAwIHx8IHZhciA+IDEwICkK
    ICAgICAgICBwdXRzICJ2YXIgbm90IHZhbGlkICEhISEhIgogICAgICAgIGJyZWFrCiAgICBlbmQK
    ICAgIGRvX25vcm1hbF9zdHVmZgogICAgLi4uCiAgICAuLi4KICAgIGVuZF9ub3JtYWxfc3R1ZmYK
    ICBlbmQKCiAgcHV0cyAiV3JpdGUgaXQiCgoKCj4gIFdoeSBub3Qgd3JpdGUgc29tZXRoaW5nIHNp
    bXBsZXIKPgo+ICBjYXNlIG51bQo+ICB3aGVuIDE6Cj4gICBpZiAwIDw9IHZhciBhbmQgdmFyIDw9
    IDEwKSB0aGVuCj4gICAgZG9fbm9ybWFsX3N0dWZmCj4gICAgLi4uCj4gICAgLi4uCj4gICAgZW5k
    X25vcm1hbF9zdHVmZgo+ICAgIHB1dHMgIldyaXRlIGl0Igo+ICAgZW5kCgpZZXMsIGJ1dCB3aGF0
    IEkgd2FzIHRyeWluZyB0byBhdm9pZCBpcyB0byBlbmNsb3NlIGFsbCB0aGUgInJlYWwiIHN0dWZm
    Cm5pIGEgImlmIiBzdGFtZW50IHNpbmNlIGl0J3MgaW4gZmFjdCB0aGUgZGVmYXVsdCBiZWhhdmlv
    dXIgYW5kIHRoYXQKd2lsbCBiZSBleGVjdXRlZCA5OSUgb2YgdGltZXMuCgpBbnl3YXkgSSB1bmRl
    cnN0YW5kIHRoYXQgaXMgdGhlIG9ubHkgd2F5LgoKVGhhbmtzIGEgbG90IGZvciBhbGwuIDopCgoK
    LS0gCknDsWFraSBCYXogQ2FzdGlsbG8KPGliY0BhbGlheC5uZXQ+Cg==
    Iñaki Baz Castillo, Apr 17, 2008
    #6
  7. Iñaki Baz Castillo

    Stefan Lang Guest

    2008/4/17, I=F1aki Baz Castillo <>:
    > 2008/4/17, Stefan Lang <>:
    >
    >
    > > break is only for iteration. What are you trying to do?
    > > The example you've given is not a compelling use case,
    > > since you can simply remove the line after break.

    >
    >
    > Ok, I write a better example:
    >
    >
    > var =3D ...something...
    >
    > case num
    > when 1:
    > puts "var not valid !!!!!" if ( var < 0 || var > 10 )
    > break
    > do_normal_stuff
    > ...
    > ...
    > end_normal_stuff
    > end
    >
    > puts "Write it"
    >
    >
    > I just want do_normal_stuff in case "var" is valid.
    > Yes, I can put a big "if" stament and so but I would like not to do it
    > since it makes a bit ugly the code.


    Well, since Ruby doesn't support it, you must find other
    ways to structure the code in each case. Exceptions might
    help in the bigger picture, splitting it up in smaller methods, etc.

    You can use catch/throw for this:

    catch:)invalid_var) {
    case num
    when 1
    if var < 0 || var > 10
    puts "var not valid !!!!!"
    throw:)invalid_var)
    end
    do_normal_stuff
    ...
    ...
    end_normal_stuff
    end
    }
    puts "Write it"

    But be careful, catch/throw is dynamically scoped.
    "ri catch" has more info.

    Stefan
    Stefan Lang, Apr 17, 2008
    #7
  8. MjAwOC80LzE3LCBTdGVmYW4gTGFuZyA8cGVyZmVjdGx5Lm5vcm1hbC5oYWNrZXJAZ21haWwuY29t
    PjoKPiBCdXQgYmUgY2FyZWZ1bCwgY2F0Y2gvdGhyb3cgaXMgZHluYW1pY2FsbHkgc2NvcGVkLgo+
    ICAicmkgY2F0Y2giIGhhcyBtb3JlIGluZm8uCgp0aGFua3MgZm9yIHRoYXQgaW5mbyA7KQoKLS0g
    CknDsWFraSBCYXogQ2FzdGlsbG8KPGliY0BhbGlheC5uZXQ+Cg==
    Iñaki Baz Castillo, Apr 17, 2008
    #8
  9. 2008/4/17, Stefan Lang <>:
    > 2008/4/17, I=F1aki Baz Castillo <>:
    >
    > > 2008/4/17, Stefan Lang <>:


    > Well, since Ruby doesn't support it, you must find other
    > ways to structure the code in each case. Exceptions might
    > help in the bigger picture, splitting it up in smaller methods, etc.
    >
    > You can use catch/throw for this:


    I would recommend using an "ordinary" exception - because that's what it is=
    Robert Klemme, Apr 17, 2008
    #9
  10. RnJvbTogScOxYWtpIEJheiBDYXN0aWxsbyBbbWFpbHRvOmliY0BhbGlheC5uZXRdIA0KIyB2YXIg
    PSAuLi5zb21ldGhpbmcuLi4NCiMgICBjYXNlIG51bQ0KIyAgIHdoZW4gMToNCiMgICAgIGlmICgg
    dmFyIDwgMCB8fCB2YXIgPiAxMCApDQojICAgICAgICAgcHV0cyAidmFyIG5vdCB2YWxpZCAhISEh
    ISINCiMgICAgICAgICBicmVhaw0KIyAgICAgZW5kDQojICAgICBkb19ub3JtYWxfc3R1ZmYNCiMg
    ICAgIC4uLg0KIyAgICAgLi4uDQojICAgICBlbmRfbm9ybWFsX3N0dWZmDQojICAgZW5kDQojICAg
    cHV0cyAiV3JpdGUgaXQiDQojLi4uLg0KIyBZZXMsIGJ1dCB3aGF0IEkgd2FzIHRyeWluZyB0byBh
    dm9pZCBpcyB0byBlbmNsb3NlIGFsbCB0aGUgInJlYWwiIHN0dWZmDQojIG5pIGEgImlmIiBzdGFt
    ZW50IHNpbmNlIGl0J3MgaW4gZmFjdCB0aGUgZGVmYXVsdCBiZWhhdmlvdXIgYW5kIHRoYXQNCiMg
    d2lsbCBiZSBleGVjdXRlZCA5OSUgb2YgdGltZXMuDQojIEFueXdheSBJIHVuZGVyc3RhbmQgdGhh
    dCBpcyB0aGUgb25seSB3YXkuDQoNCmhvdyBhYm91dCBhbm90aGVyIGNhc2Ugd2F5LCANCg0KdmFy
    ID0gLi4uc29tZXRoaW5nLi4uDQpjYXNlIA0KICB3aGVuIG51bT09MSBhbmQgKCB2YXIgPCAwIHx8
    IHZhciA+IDEwICkNCiAgICAgcHV0cyAidmFyIG5vdCB2YWxpZCBmb3IgbnVtPT0xICEhISEhIg0K
    ICB3aGVuIG90aGVyX3N0dWZmX2NvbmRpdGlvbg0KICB3aGVuIC4uLi4NCiAgICAgLi4uDQogIGVs
    c2UNCiAgICBlbHNlX3N0dWZmDQplbmQNCnB1dHMgIldyaXRlIGl0Ig0KDQpraW5kIHJlZ2FyZHMg
    LWJvdHANCg==
    Peña, Botp, Apr 18, 2008
    #10
  11. El Viernes, 18 de Abril de 2008, Pe=C3=B1a, Botp escribi=C3=B3:

    > how about another case way,
    >
    > var =3D ...something...
    > case
    > when num=3D=3D1 and ( var < 0 || var > 10 )
    > puts "var not valid for num=3D=3D1 !!!!!"
    > when other_stuff_condition
    > when ....
    > ...
    > else
    > else_stuff
    > end
    > puts "Write it"


    opss, I didn't know that a "when" can contain a comparision, nice to know!

    Thanks.


    =2D-=20
    I=C3=B1aki Baz Castillo
    Iñaki Baz Castillo, Apr 18, 2008
    #11
  12. Iñaki Baz Castillo

    Robert Dober Guest

    On Thu, Apr 17, 2008 at 4:14 PM, Robert Klemme
    <> wrote:
    > 2008/4/17, Stefan Lang <>:
    > > 2008/4/17, I=F1aki Baz Castillo <>:
    > >
    > > > 2008/4/17, Stefan Lang <>:

    >
    >
    > > Well, since Ruby doesn't support it, you must find other
    > > ways to structure the code in each case. Exceptions might
    > > help in the bigger picture, splitting it up in smaller methods, etc.
    > >
    > > You can use catch/throw for this:

    >
    > I would recommend using an "ordinary" exception - because that's what it=

    is.
    I would recommend not to use an exception at all.

    If I had the problem I would try to the following things in that order:
    (a) restructure your case if this makes it more readable
    (b) if not a local exit might make the code quite readable,
    if the case is used in a loop that well be "next", if the case is
    a method body, which is often the case use "return"
    (c) if neither (a) or (b) provide some appealing code, try to refactor
    the case into a method
    (d) and only if (c) makes no sense either use
    catch:)mylocalexit){
    case....
    throw :mylocalexit
    }

    HTH
    Robert

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

    ---
    Whereof one cannot speak, thereof one must be silent.
    Ludwig Wittgenstein
    Robert Dober, Apr 18, 2008
    #12
  13. Iñaki Baz Castillo

    Robert Dober Guest

    On Fri, Apr 18, 2008 at 8:52 PM, I=F1aki Baz Castillo <> wrote=
    :
    > El Viernes, 18 de Abril de 2008, Pe=F1a, Botp escribi=F3:
    >
    >
    > > how about another case way,
    > >
    > > var =3D ...something...
    > > case
    > > when num=3D=3D1 and ( var < 0 || var > 10 )
    > > puts "var not valid for num=3D=3D1 !!!!!"
    > > when other_stuff_condition
    > > when ....
    > > ...
    > > else
    > > else_stuff
    > > end
    > > puts "Write it"

    >
    > opss, I didn't know that a "when" can contain a comparision, nice to kno=

    w!
    It can contain any expression, but it will not do what you want.
    The semantics of case is the following

    case e
    when e1
    a1
    when e2
    a2
    else
    a3
    end

    if e1 =3D=3D=3D e then
    a1
    elsif e2 =3D=3D=3D e then
    a2
    else
    a3
    end

    unfortunately
    case e
    when true
    a

    will only work for e =3D=3D true as
    true =3D=3D=3D Object.new --> false

    maybe Matz did not want to allow logical comparision in case ;)

    but he gave us the power to overrule

    try the following code with the line commented and then uncommented and
    you will see what is going on

    class TrueClass
    # def =3D=3D=3D any; true end
    end

    case 42
    when true
    p true
    else
    p :else
    end
    HTH
    R.
    --=20
    http://ruby-smalltalk.blogspot.com/

    ---
    Whereof one cannot speak, thereof one must be silent.
    Ludwig Wittgenstein
    Robert Dober, Apr 18, 2008
    #13
  14. El Viernes, 18 de Abril de 2008, Robert Dober escribi=F3:

    > try the following code with the line commented and then uncommented and
    > you will see what is going on
    >
    > class TrueClass
    > # def =3D=3D=3D any; true end
    > end
    >
    > case 42
    > when true
    > p true
    > else
    > p :else
    > end


    Interesting, nice to know :)


    =2D-=20
    I=F1aki Baz Castillo
    Iñaki Baz Castillo, Apr 18, 2008
    #14
  15. On Fri, Apr 18, 2008 at 1:40 PM, Robert Dober <> wrot=
    e:
    >
    > On Fri, Apr 18, 2008 at 8:52 PM, I=F1aki Baz Castillo <> wro=

    te:
    > > El Viernes, 18 de Abril de 2008, Pe=F1a, Botp escribi=F3:
    > >
    > >
    > > > how about another case way,
    > > >
    > > > var =3D ...something...
    > > > case
    > > > when num=3D=3D1 and ( var < 0 || var > 10 )
    > > > puts "var not valid for num=3D=3D1 !!!!!"
    > > > when other_stuff_condition
    > > > when ....
    > > > ...
    > > > else
    > > > else_stuff
    > > > end
    > > > puts "Write it"

    > >
    > > opss, I didn't know that a "when" can contain a comparision, nice to =

    know!
    > It can contain any expression, but it will not do what you want.


    Sure it will. There are two different forms of case, the form
    case
    when foo1 then bar1
    when foo2 then bar2
    ...
    else baz
    end

    Works exactly as described above.

    You could do it with the other kind of case (the one whose semantics
    you describe),
    but it would be a bit uglier. E.g.,

    case num
    when (if var.between? 0, 10 then 1 else Object.new) then do_normal_stuff
    when 1 then do_error_stuff
    ...
    end
    Christopher Dicely, Apr 19, 2008
    #15
  16. Iñaki Baz Castillo

    Robert Dober Guest

    On Sat, Apr 19, 2008 at 7:59 PM, Christopher Dicely <> wr=
    ote:
    > On Fri, Apr 18, 2008 at 1:40 PM, Robert Dober <> wr=

    ote:
    > >
    > > On Fri, Apr 18, 2008 at 8:52 PM, I=F1aki Baz Castillo <> =

    wrote:
    > > > El Viernes, 18 de Abril de 2008, Pe=F1a, Botp escribi=F3:
    > > >
    > > >
    > > > > how about another case way,
    > > > >
    > > > > var =3D ...something...
    > > > > case
    > > > > when num=3D=3D1 and ( var < 0 || var > 10 )
    > > > > puts "var not valid for num=3D=3D1 !!!!!"
    > > > > when other_stuff_condition
    > > > > when ....
    > > > > ...
    > > > > else
    > > > > else_stuff
    > > > > end
    > > > > puts "Write it"
    > > >
    > > > opss, I didn't know that a "when" can contain a comparision, nice =

    to know!
    > > It can contain any expression, but it will not do what you want.

    >
    > Sure it will. There are two different forms of case, the form

    First my appologies for my error, I did not see that the case part was
    empty, my fault
    > case
    > when foo1 then bar1
    > when foo2 then bar2
    > ...
    > else baz
    > end
    >
    > Works exactly as described above.
    >
    > You could do it with the other kind of case (the one whose semantics
    > you describe),
    > but it would be a bit uglier. E.g.,
    >
    > case num
    > when (if var.between? 0, 10 then 1 else Object.new) then do_normal_stuf=

    f
    > when 1 then do_error_stuff
    > ...
    > end
    >
    >

    my point is however that of course you lose the basic feature you
    wanted but we have two possibilities here, either monkeypatching
    TrueClass and using the !! form to convert any logical true value to
    the real single true value, than the code might look like this

    case expression
    when /abc/
    ...
    when !! get_an_object(expression)
    ...

    I have to admit that the monkey patch is just not an option if you are
    writing a library and is a feature too often abused anyway.

    I therefore suggest to follow Christopher's approach even if the code
    gets a little bit uglier (but beauty lies in the eyes of the
    beholder).

    case
    when /abc/ =3D=3D=3D expression
    ...
    when get_an_object( expression )
    ...
    end

    Sorry again, I outsmarted myself ;)

    Cheers
    Robert


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

    ---
    Whereof one cannot speak, thereof one must be silent.
    Ludwig Wittgenstein
    Robert Dober, Apr 19, 2008
    #16
    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. Jason Coyne  Gaijin42

    Word wrap line break code and algorithm for c#

    Jason Coyne Gaijin42, Apr 8, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    24,179
    Jason Coyne Gaijin42
    Apr 8, 2004
  2. Jeremy Morton

    Perl loops should use break, not last

    Jeremy Morton, Jan 29, 2005, in forum: Perl
    Replies:
    1
    Views:
    5,141
    Big and Blue
    Jan 30, 2005
  3. Jaco

    Client Side Break Mode

    Jaco, Jul 17, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    324
  4. Andrew
    Replies:
    3
    Views:
    372
    Andrew
    Aug 22, 2003
  5. Replies:
    12
    Views:
    960
Loading...

Share This Page