When-case

Hi
How can I best get a when/case with fallthrough?
Would be nice if there were an option like when(:fallthrough)... for that.
Whats your opinion? Is this needed often?

Thx Berg

I think, there is no fallthrough like in C. You have to state things explicitly.
AFAIK "when" accepts a comma-separated list of values

IMO fallthrough is a design weakness, because 99% of the users want it.

cheers
ralf

···

On 07/26/2016 03:37 PM, A Berger wrote:

Hi
How can I best get a when/case with fallthrough?
Would be nice if there were an option like when(:fallthrough)... for that.
Whats your opinion? Is this needed often?

Thx Berg

You can specify multiple cases in a single when statement.
If that is not sufficient for you please elaborate your use
case with a code example; there is probably a better way
to structure the logic.

My impression is that fall through with execution of multiple
logic branches - like in various other languages - is often
considered more harmful than useful.

Regards,
Marcus

···

Am 26.07.2016 um 15:37 schrieb A Berger:

How can I best get a when/case with fallthrough?

--
GitHub: stomar (Marcus Stollsteimer) · GitHub
PGP: 0x6B3A101A

You can just use IF for that:

    def foo(x)
      bar(x) if x.kind_of? Fixnum
      baz(x) if x > 1000
    end

foo(1001) will call both bar and baz…

···

From: ruby-talk [mailto:ruby-talk-bounces@ruby-lang.org] On Behalf Of A Berger
Sent: 26 July 2016 2:38 pm
To: Ruby-Talk Mailingliste
Subject: when-case

Hi
How can I best get a when/case with fallthrough?
Would be nice if there were an option like when(:fallthrough)... for that.
Whats your opinion? Is this needed often?

Thx Berg

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer>

​That's not how fallthrough works. Imagine this:

    def foo(x)
      case x
      when Fixnum
        bar(x)
        __goto__ :fallthrough
      when Numeric
        __label__ :fallthrough
        baz(x)
      end
    end

If you call `foo(1)` it calls `bar(1); baz(1)`
If you call `foo(1.0)` it just calls `baz(1.0)`

Clearly a Ruby `case` expression is not a C `switch` statement.

(I suppose if I had __goto__ I could write this:

    def foo(x)
      *# the switch*
      case x
      when Fixnum
        __goto__ :case1
      when Numeric
        __goto__ :case2
      end
      *# the cases*
      __label__ :case1
        bar(x)
      __label__ :case2
        baz(x)
    end

...for the full C nostalgia hit, including the implicit fallthrough and the
footgun of forgetting a 'break')

Cheers

···

On 1 August 2016 at 21:54, Andy Jones <Andy.Jones@jameshall.co.uk> wrote:

You can just use IF for that:

    def foo(x)

      bar(x) if x.kind_of? Fixnum

      baz(x) if x > 1000

    end

foo(1001) will call both bar and baz…

--
  Matthew Kerwin
  http://matthew.kerwin.net.au/

I don’t think I am understanding you. Isn’t this equivalent to your example?

    def foo(x)
      bar(x) if x === Fixnum
      baz(x) if x === Numeric
    end

   If you call `foo(1)` it calls `bar(1); baz(1)`
   If you call `foo(1.0)` it just calls `baz(1.0)`

(Since 1 is both a Numeric and a Fixnum.)

···

From: ruby-talk [mailto:ruby-talk-bounces@ruby-lang.org] On Behalf Of Matthew Kerwin
Sent: 01 August 2016 2:55 pm
To: Ruby users
Subject: Re: when-case

On 1 August 2016 at 21:54, Andy Jones <Andy.Jones@jameshall.co.uk<mailto:Andy.Jones@jameshall.co.uk>> wrote:

You can just use IF for that:

    def foo(x)

      bar(x) if x.kind_of? Fixnum

      baz(x) if x > 1000

    end

foo(1001) will call both bar and baz…

​That's not how fallthrough works. Imagine this:

    def foo(x)
      case x
      when Fixnum
        bar(x)
        __goto__ :fallthrough
      when Numeric
        __label__ :fallthrough
        baz(x)
      end
    end

If you call `foo(1)` it calls `bar(1); baz(1)`
If you call `foo(1.0)` it just calls `baz(1.0)`

Clearly a Ruby `case` expression is not a C `switch` statement.

(I suppose if I had __goto__ I could write this:

    def foo(x)
      # the switch
      case x
      when Fixnum
        __goto__ :case1
      when Numeric
        __goto__ :case2
      end
      # the cases
      __label__ :case1
        bar(x)
      __label__ :case2
        baz(x)
    end

...for the full C nostalgia hit, including the implicit fallthrough and the footgun of forgetting a 'break')

Cheers
--
  Matthew Kerwin
  http://matthew.kerwin.net.au/

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer&gt;

In this case it looks nice but consider the generic form:

def f(x)
  a(x) if cond1(x)
  b(x) if cond1(x) || cond2(x)
  c(x) if cond1(x) || cond2(x) || cond3(x)
end

Assuming you want to fall through completely. Granted, that is an
extreme case. OTOH it really makes it obvious what complex logic is in
play. :wink:

Kind regards

robert

···

On Mon, Aug 1, 2016 at 4:59 PM, Andy Jones <Andy.Jones@jameshall.co.uk> wrote:

I don’t think I am understanding you. Isn’t this equivalent to your
example?

    def foo(x)
      bar(x) if x === Fixnum
      baz(x) if x === Numeric
    end

> If you call `foo(1)` it calls `bar(1); baz(1)`
> If you call `foo(1.0)` it just calls `baz(1.0)`

(Since 1 is both a Numeric and a Fixnum.)

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can
- without end}
http://blog.rubybestpractices.com/

Indeed, as Robert says, imagine my example but replace Fixnum with
String. I chose poorly originally. :frowning:

Cheers

···

On 02/08/2016, Robert Klemme <shortcutter@googlemail.com> wrote:

On Mon, Aug 1, 2016 at 4:59 PM, Andy Jones <Andy.Jones@jameshall.co.uk> > wrote:

I don’t think I am understanding you. Isn’t this equivalent to your
example?

    def foo(x)
      bar(x) if x === Fixnum
      baz(x) if x === Numeric
    end

> If you call `foo(1)` it calls `bar(1); baz(1)`
> If you call `foo(1.0)` it just calls `baz(1.0)`

(Since 1 is both a Numeric and a Fixnum.)

In this case it looks nice but consider the generic form:

def f(x)
  a(x) if cond1(x)
  b(x) if cond1(x) || cond2(x)
  c(x) if cond1(x) || cond2(x) || cond3(x)
end

Assuming you want to fall through completely. Granted, that is an
extreme case. OTOH it really makes it obvious what complex logic is in
play. :wink:

Kind regards

robert

--
  Matthew Kerwin
  http://matthew.kerwin.net.au/

> def f(x)
> a(x) if cond1(x)
> b(x) if cond1(x) || cond2(x)
> c(x) if cond1(x) || cond2(x) || cond3(x)
> end
>
> Assuming you want to fall through completely. Granted, that is an
> extreme case. OTOH it really makes it obvious what complex logic is in
> play. :wink:

I suppose I must have blanked how switch worked in horror; what little C I did was a long time ago.

I confess I have no idea why anyone would want that functionality!

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer&gt;

​Remember two things: C is a procedural language, and a 'switch' is
(potentially) a really very powerful branching mechanism.

In a purely procedural environment, the second-fastest way to execute an
instruction is to jump straight to it. (The fastest is to already have it
under your execution pointer.) That's partly why C still has a 'goto'
instruction.

With a true 'switch' statement and a sufficiently clever compiler you can
turn a clunky if-else-if-else-if-then sequence into a little bit of
arithmetic and a single jump instruction -- from O(n) to O(1). Imagine that
you're switching on a single-byte-sized value; it's quite easy for the
compiler to build a table of 256 memory locations, where each location is
the address of the first instruction after a 'case' label, then implement
the switch statement as:
goto case_table[the_byte].
As a result, once you've jumped to one of those locations there's nothing
to tell the execution pointer not to keep on incrementing after each
instruction, and you 'fall through' the sequence of labels. (Hence needing
a 'break' to jump to the end of the 'switch' block.)

It's very powerful, as long as you're aware of what it actually does. Going
in with the wrong preconceptions can be ... dangerous. That's also why Matz
decided Ruby's similar-looking construct would be called 'case' (not
'switch'): because it's *not* a switch, it's a mechanism for choosing a
matching *case* from a list of possible alternatives.

Cheers

···

On 2 August 2016 at 17:45, Andy Jones <Andy.Jones@jameshall.co.uk> wrote:

> > def f(x)
> > a(x) if cond1(x)
> > b(x) if cond1(x) || cond2(x)
> > c(x) if cond1(x) || cond2(x) || cond3(x)
> > end
> >
> > Assuming you want to fall through completely. Granted, that is an
> > extreme case. OTOH it really makes it obvious what complex logic is in
> > play. :wink:

I suppose I must have blanked how switch worked in horror; what little C I
did was a long time ago.

I confess I have no idea why anyone would want that functionality!

--
  Matthew Kerwin
  http://matthew.kerwin.net.au/

Probably also because it has quite a lot similarities with SQL's CASE,
for example the use with a value immediately following CASE as well as
no value and instead conditions at the WHENs.

Kind regards

robert

···

On Tue, Aug 2, 2016 at 10:18 AM, Matthew Kerwin <matthew@kerwin.net.au> wrote:

That's also why Matz
decided Ruby's similar-looking construct would be called 'case' (not
'switch'): because it's not a switch, it's a mechanism for choosing a
matching case from a list of possible alternatives.

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can
- without end}
http://blog.rubybestpractices.com/

I'm going to guess it was lisp's case:

https://docs.racket-lang.org/reference/case.html

Regardless, a number of languages have such a construct because it's incredibly useful.

···

On Aug 2, 2016, at 04:54, Robert Klemme <shortcutter@googlemail.com> wrote:

On Tue, Aug 2, 2016 at 10:18 AM, Matthew Kerwin <matthew@kerwin.net.au> wrote:

That's also why Matz
decided Ruby's similar-looking construct would be called 'case' (not
'switch'): because it's not a switch, it's a mechanism for choosing a
matching case from a list of possible alternatives.

Probably also because it has quite a lot similarities with SQL's CASE,
for example the use with a value immediately following CASE as well as
no value and instead conditions at the WHENs.