RCR draft for enhanced "case..when..else..end" syntax

Discussion in 'Ruby' started by Guoliang Cao, Feb 3, 2004.

  1. Guoliang Cao

    Guoliang Cao Guest

    Hi,

    I'm thinking of submitting a RCR. Here is the draft. Comments are welcome.

    Thanks,
    Cao

    ====================================================

    RCR title: An enhanced case..when..else..end syntax

    This RCR involves (check all that apply):
    ... a new feature x
    ... a syntax change x
    ... refactoring only
    ... backwards incompatibility

    Abstract....
    This RCR proposes an enhanced case..when..else..end syntax.

    Problem....
    It's a very common task to group code based on a combination of values of
    multiple variables. However, the current Ruby syntax only allows one
    expression/variable being used in "case" clause. People have to use
    if..else..end which requires more typing and is less intuitive.

    For example, suppose I'm generating a image, the color of each point is
    defined based on its x and y coordinates.

    0 ... 50...100...200
    0 +----------------+
    | white |
    50 |----------------|
    | | grey |
    100 |blue +----------|
    | | black |
    150 |----------------|
    | white |
    200 +----------------+


    Use if..else..end:

    if 0..50 === x || 150..200 === x
    color = white
    elsif 0..50 === y
    color = blue
    elsif 50..100 === x and 50..200 === y
    color = grey
    else
    color = black
    end

    Use new case..when..else..end:

    case x : y
    when 0..50, 150..200 # x in 0..50 or 150..200
    color = white
    when _ : 0..50 # y in 0..50
    color = blue
    when 50..100 : 50..200 # x in 50..100 and y in 50..200
    color = grey
    else # otherwise
    color = black
    end

    Note: If the color is only dependent on x, we can use the current "case"
    syntax. However if it's dependent on more than one variable, "case" is
    incapable of handling it.

    Proposal....
    The enhanced syntax looks like below:

    case expr1 : expr2
    when expr3 : _ : expr4
    do_something
    when expr5
    do_different_thing
    else
    do_default_thing
    end

    1. "case" takes 0 or any number of expressions separated by ":";

    If there's no expression, each clause separated by ":" in "when" is
    evaluated to true or false and ":" is treated the same way as "and".

    2. "when" takes 1 or more clauses separated by ":"; each clause by itself
    can be separated by "," (this is supported in current syntax).

    If there are less clauses than the number of "case" expressions, the
    rest of "case" expressions are not evaluated.

    If there are more clauses than the number of "case" expressions, the
    rest of "when" clauses are evaluated to true or false. ":" is treated
    the same way as "and"

    3. "else" remains the same.

    4. "_" means skipping evaluation of the corresponding "case" expression.


    Analysis....
    What benefits do we get?
    1. It's a more general form, which means it can be used much wider than
    what "case..when" is used for today;
    2. less typing; there's no need to type x, y, === in the when clause;
    3. this syntax change is backward compatible with Ruby 1.x

    Implementation....
    Because this request proposes syntax enhancement, it can't be achieved
    without changing Ruby interpreter.

    The code below demonstrated the idea by extending Object class and
    utilizing thread-local variables. It uses "ccase..cwhen..celse..end" to
    simulate the proposed syntax. It uses "," to separate ccase/cwhen clauses
    which are just arguments. It uses "true" instead of "_" to indicate
    skipping evaluation.


    Source:

    #!/usr/bin/ruby
    #
    # To utilize Ruby's existing functionality to demonstrate the idea, I'm doing
    # this:
    # add instance methods "ccase", "cwhen", "celse" to class Object which is the
    # top one in the hierarchy so all classes inherit them.
    #
    # Its usage is like this:
    # ccase a, b do
    # cwhen [1,2], 1..3 do
    # ...
    # end
    # cwhen 3, true do
    # ...
    # end
    # celse do
    # ...
    # end
    # end
    #
    # Problems so far:
    # 1. how to let "cwhen" method body to access "ccase" arguments and
    # intermediate objects;
    # Solution: use thread-local variable
    #
    # 2. how to make it work in multi-threaded program;
    # Solution: use thread-local variable
    #
    # 3. "do...end" or "{...}" is needed to pass block to ccase/cwhen/celse.
    # Solution: ???
    #
    # ccase = "customized case"
    # cwhen = "customized when"
    # celse = "customized else"
    #

    class Object

    # customized case
    def ccase arg0, *args
    begin
    args.unshift arg0
    Thread.current["in_ccase"] = true
    Thread.current["ccase_args"] = args
    Thread.current["hit_cwhen"] = nil
    if block_given?
    yield
    end
    ensure
    Thread.current["in_ccase"] = nil
    Thread.current["ccase_args"] = nil
    Thread.current["hit_cwhen"] = nil
    end
    end

    # customized when
    def cwhen arg0, *args
    # skip if already matched
    return if Thread.current["hit_cwhen"]

    args.unshift arg0
    hit = true # hit or not?
    ccase_args = Thread.current["ccase_args"]

    if ccase_args and ccase_args.length > 0
    ccase_args.each_index do |idx|
    ccase_arg = ccase_args[idx]
    cwhen_arg = args[idx]

    # cwhen_arg is not present, hit = true
    # cwhen_arg is true and ccase_arg is not false, hit = true
    # ccase_arg is not present, hit = if cwhen_arg evaluates to true
    # both ccase_arg and cwhen_arg are present, hit = if cwhen_arg === ccase_arg
    if (not cwhen_arg) or (not ccase_arg and cwhen_arg) or (cwhen_arg == true and not ccase_arg == false) or (cwhen_arg === ccase_arg)
    # hit = true
    elsif cwhen_arg.is_a? Array
    hit = false
    cwhen_arg.each do |arg|
    if arg === ccase_arg
    hit = true
    break
    end
    end
    else
    hit = false
    end
    s = if cwhen_arg.nil? then "nil" else cwhen_arg.to_s end
    s1 = if ccase_arg.nil? then "nil" else ccase_arg.to_s end
    print "#{s} === #{s1} : #{hit.to_s}\n"

    break if not hit
    end
    else
    args.each {|arg| hit &= arg}
    end

    return if not hit
    Thread.current["hit_cwhen"] = true

    if block_given?
    yield
    end
    end

    # customized else to be combined with ccase/cwhen
    def celse
    return if Thread.current["hit_cwhen"]
    if block_given?
    yield
    end
    end

    end

    if __FILE__ == $0
    def test a,b,c
    ccase a,b,c do
    cwhen [1, 3, 6], 1..2 do
    # if a is in [1,3,6] and b === 1..2
    print "hit 1\n"
    end
    cwhen 4, 3, 1 do
    # if a === 4 and b === 4 and c === 1
    print "hit 2\n"
    end
    cwhen 5, true, 7 do
    # if a === 5 and c === 7
    print "hit 3\n"
    end
    celse do
    # otherwise
    print "no hit\n"
    end
    end
    end

    test 1,2,3 # hit 1
    test 4,3,0 # no hit
    test 4,3,1 # hit 2
    test 5,6,7 # hit 3

    end
    Guoliang Cao, Feb 3, 2004
    #1
    1. Advertising

  2. "Guoliang Cao" <> schrieb im Newsbeitrag
    news:...
    > Hi,
    >
    > I'm thinking of submitting a RCR. Here is the draft. Comments are

    welcome.

    [snip]

    Do we need this?

    16:41:55 [ruby]: ./ccase.rb
    [#<struct Point x=0, y=0>, "white"]
    [#<struct Point x=100, y=0>, "blue"]
    [#<struct Point x=55, y=55>, "grey"]
    [#<struct Point x=120, y=210>, "black"]
    16:41:57 [ruby]: cat ccase.rb
    #!/usr/bin/ruby

    Point = Struct.new( :x, :y )

    class CondWhite
    def self.===(point); (0..50) === point.x or (150..200) === point.x; end
    end

    class CondBlue
    def self.===(point); (50..150) === point.x and (0..50) === point.y; end
    end

    class CondGrey
    def self.===(point); (50..100) === point.x and (50..200) === point.y;
    end
    end


    points = [
    Point.new( 0, 0 ),
    Point.new( 100, 0 ),
    Point.new( 55, 55 ),
    Point.new( 120, 210 ),
    ]

    points.each do |point|
    case point
    when CondWhite; p [point, "white"]
    when CondBlue; p [point, "blue"]
    when CondGrey; p [point, "grey"]
    else; p [point, "black"]
    end
    end
    16:42:00 [ruby]:

    Regards

    robert
    Robert Klemme, Feb 3, 2004
    #2
    1. Advertising

  3. Guoliang Cao

    Guest

    Hi,

    At Tue, 3 Feb 2004 23:35:25 +0900,
    Guoliang Cao wrote:
    > ... backwards incompatibility

    ?

    > 2. "when" takes 1 or more clauses separated by ":"; each clause by itself
    > can be separated by "," (this is supported in current syntax).


    "when" clause can be terminated by ":" now. It can conflict.

    > 4. "_" means skipping evaluation of the corresponding "case" expression.


    It feels ugly a bit, to me.

    --
    Nobu Nakada
    , Feb 3, 2004
    #3
  4. Guoliang Cao

    Gennady Guest

    Guoliang Cao wrote:
    > Hi,
    >
    > I'm thinking of submitting a RCR. Here is the draft. Comments are welcome.
    >
    > Thanks,
    > Cao


    Do you know about this syntax currently available?

    a = "aaa"
    b = "bbb"
    case
    when a == "aaa", b == "bbb"
    puts "Lowercase detected"
    when a == "AAA", b == "BBB"
    puts "Uppercase detected"
    else
    puts "Detection failed"
    end

    >
    > ====================================================
    >
    > RCR title: An enhanced case..when..else..end syntax
    >
    > This RCR involves (check all that apply):
    > ... a new feature x
    > ... a syntax change x
    > ... refactoring only
    > ... backwards incompatibility
    >
    > Abstract....
    > This RCR proposes an enhanced case..when..else..end syntax.
    >
    > Problem....
    > It's a very common task to group code based on a combination of values of
    > multiple variables. However, the current Ruby syntax only allows one
    > expression/variable being used in "case" clause. People have to use
    > if..else..end which requires more typing and is less intuitive.
    >
    > For example, suppose I'm generating a image, the color of each point is
    > defined based on its x and y coordinates.
    >
    > 0 ... 50...100...200
    > 0 +----------------+
    > | white |
    > 50 |----------------|
    > | | grey |
    > 100 |blue +----------|
    > | | black |
    > 150 |----------------|
    > | white |
    > 200 +----------------+
    >
    >
    > Use if..else..end:
    >
    > if 0..50 === x || 150..200 === x
    > color = white
    > elsif 0..50 === y
    > color = blue
    > elsif 50..100 === x and 50..200 === y
    > color = grey
    > else
    > color = black
    > end
    >
    > Use new case..when..else..end:
    >
    > case x : y
    > when 0..50, 150..200 # x in 0..50 or 150..200
    > color = white
    > when _ : 0..50 # y in 0..50
    > color = blue
    > when 50..100 : 50..200 # x in 50..100 and y in 50..200
    > color = grey
    > else # otherwise
    > color = black
    > end
    >
    > Note: If the color is only dependent on x, we can use the current "case"
    > syntax. However if it's dependent on more than one variable, "case" is
    > incapable of handling it.
    >
    > Proposal....
    > The enhanced syntax looks like below:
    >
    > case expr1 : expr2
    > when expr3 : _ : expr4
    > do_something
    > when expr5
    > do_different_thing
    > else
    > do_default_thing
    > end
    >
    > 1. "case" takes 0 or any number of expressions separated by ":";
    >
    > If there's no expression, each clause separated by ":" in "when" is
    > evaluated to true or false and ":" is treated the same way as "and".
    >
    > 2. "when" takes 1 or more clauses separated by ":"; each clause by itself
    > can be separated by "," (this is supported in current syntax).
    >
    > If there are less clauses than the number of "case" expressions, the
    > rest of "case" expressions are not evaluated.
    >
    > If there are more clauses than the number of "case" expressions, the
    > rest of "when" clauses are evaluated to true or false. ":" is treated
    > the same way as "and"
    >
    > 3. "else" remains the same.
    >
    > 4. "_" means skipping evaluation of the corresponding "case" expression.
    >
    >
    > Analysis....
    > What benefits do we get?
    > 1. It's a more general form, which means it can be used much wider than
    > what "case..when" is used for today;
    > 2. less typing; there's no need to type x, y, === in the when clause;
    > 3. this syntax change is backward compatible with Ruby 1.x
    >
    > Implementation....
    > Because this request proposes syntax enhancement, it can't be achieved
    > without changing Ruby interpreter.
    >
    > The code below demonstrated the idea by extending Object class and
    > utilizing thread-local variables. It uses "ccase..cwhen..celse..end" to
    > simulate the proposed syntax. It uses "," to separate ccase/cwhen clauses
    > which are just arguments. It uses "true" instead of "_" to indicate
    > skipping evaluation.
    >
    >
    > Source:
    >
    > #!/usr/bin/ruby
    > #
    > # To utilize Ruby's existing functionality to demonstrate the idea, I'm doing
    > # this:
    > # add instance methods "ccase", "cwhen", "celse" to class Object which is the
    > # top one in the hierarchy so all classes inherit them.
    > #
    > # Its usage is like this:
    > # ccase a, b do
    > # cwhen [1,2], 1..3 do
    > # ...
    > # end
    > # cwhen 3, true do
    > # ...
    > # end
    > # celse do
    > # ...
    > # end
    > # end
    > #
    > # Problems so far:
    > # 1. how to let "cwhen" method body to access "ccase" arguments and
    > # intermediate objects;
    > # Solution: use thread-local variable
    > #
    > # 2. how to make it work in multi-threaded program;
    > # Solution: use thread-local variable
    > #
    > # 3. "do...end" or "{...}" is needed to pass block to ccase/cwhen/celse.
    > # Solution: ???
    > #
    > # ccase = "customized case"
    > # cwhen = "customized when"
    > # celse = "customized else"
    > #
    >
    > class Object
    >
    > # customized case
    > def ccase arg0, *args
    > begin
    > args.unshift arg0
    > Thread.current["in_ccase"] = true
    > Thread.current["ccase_args"] = args
    > Thread.current["hit_cwhen"] = nil
    > if block_given?
    > yield
    > end
    > ensure
    > Thread.current["in_ccase"] = nil
    > Thread.current["ccase_args"] = nil
    > Thread.current["hit_cwhen"] = nil
    > end
    > end
    >
    > # customized when
    > def cwhen arg0, *args
    > # skip if already matched
    > return if Thread.current["hit_cwhen"]
    >
    > args.unshift arg0
    > hit = true # hit or not?
    > ccase_args = Thread.current["ccase_args"]
    >
    > if ccase_args and ccase_args.length > 0
    > ccase_args.each_index do |idx|
    > ccase_arg = ccase_args[idx]
    > cwhen_arg = args[idx]
    >
    > # cwhen_arg is not present, hit = true
    > # cwhen_arg is true and ccase_arg is not false, hit = true
    > # ccase_arg is not present, hit = if cwhen_arg evaluates to true
    > # both ccase_arg and cwhen_arg are present, hit = if cwhen_arg === ccase_arg
    > if (not cwhen_arg) or (not ccase_arg and cwhen_arg) or (cwhen_arg == true and not ccase_arg == false) or (cwhen_arg === ccase_arg)
    > # hit = true
    > elsif cwhen_arg.is_a? Array
    > hit = false
    > cwhen_arg.each do |arg|
    > if arg === ccase_arg
    > hit = true
    > break
    > end
    > end
    > else
    > hit = false
    > end
    > s = if cwhen_arg.nil? then "nil" else cwhen_arg.to_s end
    > s1 = if ccase_arg.nil? then "nil" else ccase_arg.to_s end
    > print "#{s} === #{s1} : #{hit.to_s}\n"
    >
    > break if not hit
    > end
    > else
    > args.each {|arg| hit &= arg}
    > end
    >
    > return if not hit
    > Thread.current["hit_cwhen"] = true
    >
    > if block_given?
    > yield
    > end
    > end
    >
    > # customized else to be combined with ccase/cwhen
    > def celse
    > return if Thread.current["hit_cwhen"]
    > if block_given?
    > yield
    > end
    > end
    >
    > end
    >
    > if __FILE__ == $0
    > def test a,b,c
    > ccase a,b,c do
    > cwhen [1, 3, 6], 1..2 do
    > # if a is in [1,3,6] and b === 1..2
    > print "hit 1\n"
    > end
    > cwhen 4, 3, 1 do
    > # if a === 4 and b === 4 and c === 1
    > print "hit 2\n"
    > end
    > cwhen 5, true, 7 do
    > # if a === 5 and c === 7
    > print "hit 3\n"
    > end
    > celse do
    > # otherwise
    > print "no hit\n"
    > end
    > end
    > end
    >
    > test 1,2,3 # hit 1
    > test 4,3,0 # no hit
    > test 4,3,1 # hit 2
    > test 5,6,7 # hit 3
    >
    > end
    >
    >
    Gennady, Feb 3, 2004
    #4
  5. Guoliang Cao

    Guoliang Cao Guest

    ---- Original Message ----
    > Hi,


    > At Tue, 3 Feb 2004 23:35:25 +0900,
    > Guoliang Cao wrote:
    >> ... backwards incompatibility

    > ?


    >> 2. "when" takes 1 or more clauses separated by ":"; each clause by itself
    >> can be separated by "," (this is supported in current syntax).


    > "when" clause can be terminated by ":" now. It can conflict.


    Really? In the Pragmatic Programmer's Guide, it didn't mention ":" but uses
    "then":

    "...and you also need a then keyword if the expression is on the same line
    as the condition."

    >> 4. "_" means skipping evaluation of the corresponding "case" expression.


    > It feels ugly a bit, to me.


    "~" or whichever looks good to most people and doesn't cause backward
    incompatibility problem.

    Cao
    Guoliang Cao, Feb 3, 2004
    #5
  6. Guoliang Cao

    Guoliang Cao Guest

    ---- Original Message ----
    > Guoliang Cao wrote:
    >> Hi,
    >>
    >> I'm thinking of submitting a RCR. Here is the draft. Comments are welcome.
    >>
    >> Thanks,
    >> Cao


    > Do you know about this syntax currently available?


    > a = "aaa"
    > b = "bbb"
    > case
    > when a == "aaa", b == "bbb"
    > puts "Lowercase detected"
    > when a == "AAA", b == "BBB"
    > puts "Uppercase detected"
    > else
    > puts "Detection failed"
    > end


    No. This is close to what I want though. The only drawback is you still
    have to type "a", "b" in each when clause.

    Cao
    Guoliang Cao, Feb 3, 2004
    #6
  7. "Gennady" <> schrieb im Newsbeitrag
    news:...
    > Guoliang Cao wrote:
    > > Hi,
    > >
    > > I'm thinking of submitting a RCR. Here is the draft. Comments are

    welcome.
    > >
    > > Thanks,
    > > Cao

    >
    > Do you know about this syntax currently available?
    >
    > a = "aaa"
    > b = "bbb"
    > case
    > when a == "aaa", b == "bbb"
    > puts "Lowercase detected"
    > when a == "AAA", b == "BBB"
    > puts "Uppercase detected"
    > else
    > puts "Detection failed"
    > end


    Since which version of Ruby? Thx!

    robert
    Robert Klemme, Feb 3, 2004
    #7
  8. Guoliang Cao

    Gennady Guest

    Robert Klemme wrote:
    > "Gennady" <> schrieb im Newsbeitrag
    > news:...
    >
    >>Guoliang Cao wrote:
    >>
    >>>Hi,
    >>>
    >>>I'm thinking of submitting a RCR. Here is the draft. Comments are

    >
    > welcome.
    >
    >>>Thanks,
    >>>Cao

    >>
    >>Do you know about this syntax currently available?
    >>
    >>a = "aaa"
    >>b = "bbb"
    >>case
    >> when a == "aaa", b == "bbb"
    >> puts "Lowercase detected"
    >> when a == "AAA", b == "BBB"
    >> puts "Uppercase detected"
    >> else
    >> puts "Detection failed"
    >>end

    >
    >
    > Since which version of Ruby? Thx!
    >
    > robert
    >
    >


    I checked that it works in 1.6.8. I remember somebody (Nobu?) mentioning
    it on ruby-talk some time ago.

    Gennady.
    Gennady, Feb 3, 2004
    #8
  9. Guoliang Cao

    Guoliang Cao Guest

    ---- Original Message ----


    > ---- Original Message ----
    >> Hi,


    >> At Tue, 3 Feb 2004 23:35:25 +0900,
    >> Guoliang Cao wrote:
    >>> ... backwards incompatibility

    >> ?


    >>> 2. "when" takes 1 or more clauses separated by ":"; each clause by itself
    >>> can be separated by "," (this is supported in current syntax).


    >> "when" clause can be terminated by ":" now. It can conflict.


    > Really? In the Pragmatic Programmer's Guide, it didn't mention ":" but uses
    > "then":


    > "...and you also need a then keyword if the expression is on the same line
    > as the condition."


    Just tried on Ruby 1.6.8. It uses "then" instead of ":". So there's no
    backward incompatibility.

    Cao


    >>> 4. "_" means skipping evaluation of the corresponding "case" expression.


    >> It feels ugly a bit, to me.


    > "~" or whichever looks good to most people and doesn't cause backward
    > incompatibility problem.


    > Cao
    Guoliang Cao, Feb 3, 2004
    #9
  10. Guoliang Cao

    Guest

    Hi,

    At Wed, 4 Feb 2004 03:11:35 +0900,
    Guoliang Cao wrote:
    > Just tried on Ruby 1.6.8. It uses "then" instead of ":". So there's no
    > backward incompatibility.


    $ ruby-1.8 -e 'if /^\w+/ =~ "abc": puts $& end'
    abc
    $ ruby-1.8 -e 'case "abc" when /^\w+/: puts $& end'
    abc
    $ ruby-1.8 -e 'while l = gets: p l end'
    abc
    "abc\n"

    Now ":" can be placed anywhere instead of "then", and "do" for
    loops.

    --
    Nobu Nakada
    , Feb 3, 2004
    #10
  11. "Gennady" <> schrieb im Newsbeitrag
    news:...
    > Robert Klemme wrote:
    > > "Gennady" <> schrieb im Newsbeitrag
    > > news:...
    > >
    > >>Guoliang Cao wrote:
    > >>
    > >>>Hi,
    > >>>
    > >>>I'm thinking of submitting a RCR. Here is the draft. Comments are

    > >
    > > welcome.
    > >
    > >>>Thanks,
    > >>>Cao
    > >>
    > >>Do you know about this syntax currently available?
    > >>
    > >>a = "aaa"
    > >>b = "bbb"
    > >>case
    > >> when a == "aaa", b == "bbb"
    > >> puts "Lowercase detected"
    > >> when a == "AAA", b == "BBB"
    > >> puts "Uppercase detected"
    > >> else
    > >> puts "Detection failed"
    > >>end

    > >
    > >
    > > Since which version of Ruby? Thx!
    > >
    > > robert
    > >
    > >

    >
    > I checked that it works in 1.6.8. I remember somebody (Nobu?) mentioning
    > it on ruby-talk some time ago.


    I couldn't find it in the Pickaxe - I'll file it under "Hidden Treasures
    of Ruby"... :)

    Thanks!

    robert
    Robert Klemme, Feb 4, 2004
    #11
  12. Guoliang Cao

    Gennady Guest

    Sam Roberts wrote:
    > Quoteing , on Wed, Feb 04, 2004 at 05:35:03PM +0900:
    >
    >>>>>Do you know about this syntax currently available?
    >>>>>
    >>>>>a = "aaa"
    >>>>>b = "bbb"
    >>>>>case
    >>>>> when a == "aaa", b == "bbb"
    >>>>> puts "Lowercase detected"
    >>>>> when a == "AAA", b == "BBB"
    >>>>> puts "Uppercase detected"
    >>>>> else
    >>>>> puts "Detection failed"
    >>>>>end

    >>
    >>I couldn't find it in the Pickaxe - I'll file it under "Hidden Treasures
    >>of Ruby"... :)

    >
    >
    > There's a lot of info jammed into the corners of the pickaxe book!
    >
    > For this syntax, there's an example in the section "Case Expressions",
    > p84, and then in chapter 18 it shows the syntax:
    >
    > case target
    > when comparison [, comparison]]... [then]
    > body
    > when comparison [, comparison]]... [then]
    > body
    > ...
    > [ else
    > body ]
    > end
    >
    >
    > Cheers,
    > Sam
    >
    >

    We are not talking about general "case" syntax, most of folks here are
    well aware of it (thanks for refreshing it anyway ;-)). It is rather
    about a special case when <target> is not specified in "case" clause. It
    looks like it defaults to "true" so that <comparison> may contain
    logical operators like "a == <something>". And I could not find it
    mentioned in the Pickaxe either.

    Gennady.
    Gennady, Feb 4, 2004
    #12
  13. Guoliang Cao

    Guoliang Cao Guest

    ---- Original Message ----
    > On Wed, 4 Feb 2004 00:45:07 +0900, Robert Klemme wrote:
    >> Do we need this?


    > No. It's ugly and (IMO) not needed. Any program which seems to need it is in
    > need of a redesign. The specific case can be handled as you suggested it, or


    Robert's code looks good, but a bit over-engineering to me.

    > better yet with a lookup table. This sort of problem is handled easily by
    > intelligent data-driven design.


    Don't mix system design with language capabilities please. I think it's not
    a bad thing to let "case" to take more than one expressions. Just like a
    function can take any number of arguments. Why does "case" have to be
    limited to zero or one? Because all our languages are designed this way?
    (AFAIK only Ruby "case" can take 0 expressions. That's some good stuff
    introduced by Ruby, right? So why not go one step further?) Or because it's
    impossible?

    > There is no need for a new or modified language construct here.


    Since 2.0 is a major update to 1.x, why can't we introduce new language
    constructs if they really makes sense?

    Cao

    > -austin
    > --
    > austin ziegler * * Toronto, ON, Canada
    > software designer * pragmatic programmer * 2004.02.04
    > * 11.49.59
    Guoliang Cao, Feb 4, 2004
    #13
  14. Hi,

    In message "Re: RCR draft for enhanced "case..when..else..end" syntax"
    on 04/02/05, Guoliang Cao <> writes:

    |Don't mix system design with language capabilities please. I think it's not
    |a bad thing to let "case" to take more than one expressions. Just like a
    |function can take any number of arguments. Why does "case" have to be
    |limited to zero or one? Because all our languages are designed this way?
    |(AFAIK only Ruby "case" can take 0 expressions. That's some good stuff
    |introduced by Ruby, right? So why not go one step further?) Or because it's
    |impossible?

    Natural extension is not always a good thing. We can inherit from one
    class, hey, why not inheriting from multiple classes? Because it
    introduces complexity, mix-in is a better solution.

    |Since 2.0 is a major update to 1.x, why can't we introduce new language
    |constructs if they really makes sense?

    You are right, we can, when (and only when) I agree with the new
    design. I personally don't see much usage of your new syntax.

    matz.
    Yukihiro Matsumoto, Feb 4, 2004
    #14
  15. Guoliang Cao

    Guoliang Cao Guest

    ---- Original Message ----
    > Hi,


    > In message "Re: RCR draft for enhanced "case..when..else..end" syntax"
    > on 04/02/05, Guoliang Cao <> writes:


    > |Don't mix system design with language capabilities please. I think it's not
    > |a bad thing to let "case" to take more than one expressions. Just like a
    > |function can take any number of arguments. Why does "case" have to be
    > |limited to zero or one? Because all our languages are designed this way?
    > |(AFAIK only Ruby "case" can take 0 expressions. That's some good stuff
    > |introduced by Ruby, right? So why not go one step further?) Or because it's
    > |impossible?


    > Natural extension is not always a good thing. We can inherit from one
    > class, hey, why not inheriting from multiple classes? Because it
    > introduces complexity, mix-in is a better solution.


    > |Since 2.0 is a major update to 1.x, why can't we introduce new language
    > |constructs if they really makes sense?


    > You are right, we can, when (and only when) I agree with the new
    > design. I personally don't see much usage of your new syntax.


    I'm fine with that. Thanks for taking a look, Matz.

    Cao
    Guoliang Cao, Feb 4, 2004
    #15
  16. Guoliang Cao

    Guoliang Cao Guest

    ---- Original Message ----
    > On Wed, 4 Feb 2004 12:55:42 -0500, Guoliang Cao wrote:
    >>> better yet with a lookup table. This sort of problem is handled easily
    >>> by intelligent data-driven design.

    >> Don't mix system design with language capabilities please.


    > I'm not. This proposal does. What you're wanting to do is effectively make
    > it so that case operates in parallel on multiple conditions. I can count on
    > zero hands the number of times that I've needed this capability. I have


    When you are thinking it's not something you'll need, the count is always
    zero.

    > found it more useful to worry about my data design and make sure that I
    > have a proper lookup table. Robert's design does exactly that with multiple
    > custom objects instead of a lookup table.


    >> I think it's not a bad thing to let "case" to take more than one
    >> expressions. Just like a function can take any number of arguments. Why
    >> does "case" have to be limited to zero or one? Because all our languages
    >> are designed this way? (AFAIK only Ruby "case" can take 0 expressions.
    >> That's some good stuff introduced by Ruby, right? So why not go one step
    >> further?) Or because it's impossible?


    > Nothing is impossible. It's a question as to whether it's a good idea.
    > Frankly, your proposal is a bad idea. I said as much to your initial posting
    > on RubyGarden.


    It might be. I can accept that. ;-)

    >>> There is no need for a new or modified language construct here.

    >> Since 2.0 is a major update to 1.x, why can't we introduce new language
    >> constructs if they really makes sense?


    > Except that your construct doesn't make sense.


    > 1. It introduces unnecessary complexity.


    I can't see how complex it is. It might be though. I might have mixed too
    many things in one proposal.

    > 2. It adds a lot of "magic" that isn't clear (_ or ~ -- both are really
    > ugly). Ruby2 seems to be getting rid of a lot of that silly magic.


    Once it's clear, it's clear.

    > 3. It adds a language "feature" that is better handled by proper program
    > design.


    About my example, I don't think people should do a complex design.
    "if..elsif" is the answer in current Ruby capability.

    Cao

    > -austin
    > --
    > austin ziegler * * Toronto, ON, Canada
    > software designer * pragmatic programmer * 2004.02.04
    > * 13.31.26
    Guoliang Cao, Feb 4, 2004
    #16
  17. Guoliang Cao

    Sean O'Dell Guest

    On Wednesday 04 February 2004 11:07 am, Guoliang Cao wrote:
    > About my example, I don't think people should do a complex design.
    > "if..elsif" is the answer in current Ruby capability.


    Personally, I like the idea of a more readable way to replace the if...elsif
    paradigm. It's a great idea!

    Sean O'Dell
    Sean O'Dell, Feb 4, 2004
    #17
  18. "Sean O'Dell" <> schrieb im Newsbeitrag
    news:...
    > On Wednesday 04 February 2004 11:07 am, Guoliang Cao wrote:
    > > About my example, I don't think people should do a complex design.
    > > "if..elsif" is the answer in current Ruby capability.

    >
    > Personally, I like the idea of a more readable way to replace the

    if...elsif
    > paradigm. It's a great idea!


    Hmm... As someone else pointed out, if you are in excessive need of such
    a construct, you should consider redesign. Case constructs (or
    if...elsif...end cascades) are regarded to be not very OO IMHO.

    Regards

    robert
    Robert Klemme, Feb 5, 2004
    #18
  19. In Message-Id: <>
    Guoliang Cao <> writes:

    > About my example, I don't think people should do a complex design.
    > "if..elsif" is the answer in current Ruby capability.


    I wonder why those who have informed that case which has no following
    expressions is equivalent to `case true', and when clause can take an
    arbitrary expression, doesn't try:

    case
    when a == "aaa" && b == "bbb"
    puts "lowercase"
    when a == "AAA" && b == "BBB"
    puts "uppercase"
    else
    puts "???"
    end

    That looks nice, doesn't it?


    --
    February 5, 2004
    It is comparison that makes men happy or miserable.
    YANAGAWA Kazuhisa, Feb 5, 2004
    #19
    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. Remi Bastide
    Replies:
    5
    Views:
    13,535
    elizas
    Mar 29, 2010
  2. Christian Schlichtherle
    Replies:
    8
    Views:
    465
    John Currier
    Jul 5, 2005
  3. Marc Schellens

    enhanced file info

    Marc Schellens, Aug 24, 2004, in forum: C++
    Replies:
    2
    Views:
    323
    Thomas Matthews
    Aug 24, 2004
  4. Andrew Koenig
    Replies:
    46
    Views:
    973
    Peter Maas
    Feb 24, 2004
  5. Stefan Rusterholz
    Replies:
    34
    Views:
    320
    Robert Dober
    Jul 21, 2007
Loading...

Share This Page