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

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

  1. “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”

  1. “else” remains the same.

  2. “_” 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” gcao@lemurnetworks.net schrieb im Newsbeitrag
news:15010631647.20040203093520@lemurnetworks.net

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
[#, “white”]
[#, “blue”]
[#, “grey”]
[#, “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

Hi,

… backwards incompatibility
?

  1. “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.

  1. “_” means skipping evaluation of the corresponding “case” expression.

It feels ugly a bit, to me.

···

At Tue, 3 Feb 2004 23:35:25 +0900, Guoliang Cao wrote:


Nobu Nakada

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

  1. “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”

  1. “else” remains the same.

  2. “_” 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

Hi,

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

···

---- Original Message ----

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

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

···

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

“Gennady” gfb@tonesoft.com schrieb im Newsbeitrag
news:401FC5BB.10809@tonesoft.com

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

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
better yet with a lookup table. This sort of problem is handled easily by
intelligent data-driven design.

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

-austin

···

On Wed, 4 Feb 2004 00:45:07 +0900, Robert Klemme wrote:

Do we need this?


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2004.02.04
* 11.49.59

What you’ve written here will do alternatives checks. Thus, if you have:

a = “aaa”
b = “BBB”

then “Lowercase detected” will be printed. With “AAA” and “bbb”, “Lowercase
detected” will still be printed.

irb(main):001:0> def ct(a, b)
irb(main):002:1> case
irb(main):003:2* when a == “aaa”, b == “bbb”
irb(main):004:2> puts “Lowercase”
irb(main):005:2> when a == “AAA”, b == “BBB”
irb(main):006:2> puts “Uppercase”
irb(main):007:2> else
irb(main):008:2* puts “Failed”
irb(main):009:2> end
irb(main):010:1> end # => nil
irb(main):011:0> ct(“aaa”, “bbb”) # Lowercase => nil
irb(main):012:0> ct(“aaa”, “BBB”) # Lowercase => nil
irb(main):013:0> ct(“AAA”, “BBB”) # Uppercase => nil
irb(main):014:0> ct(“AAA”, “bbb”) # Lowercase => nil

-austin

···

On Wed, 4 Feb 2004 01:00:25 +0900, Gennady wrote:

Guoliang Cao wrote:
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


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2004.02.04
* 11.53.52

Robert Klemme wrote:

“Gennady” gfb@tonesoft.com schrieb im Newsbeitrag
news:401FC5BB.10809@tonesoft.com

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.

Hi,

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

···

---- Original Message ----

---- Original Message ----

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

  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

That’s not a drawback. That’s a feature.

-austin

···

On Wed, 4 Feb 2004 01:11:56 +0900, Guoliang Cao wrote:

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


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2004.02.04
* 11.58.41

Austin Ziegler wrote:

Guoliang Cao wrote:
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

What you’ve written here will do alternatives checks. Thus, if you have:

a = “aaa”
b = “BBB”

then “Lowercase detected” will be printed. With “AAA” and “bbb”, “Lowercase
detected” will still be printed.

Nice investigative job ;-). But remember that it was only a quick
demonstration of a “hidden” case syntax.

irb(main):001:0> def ct(a, b)
irb(main):002:1> case
irb(main):003:2* when a == “aaa”, b == “bbb”
irb(main):004:2> puts “Lowercase”
irb(main):005:2> when a == “AAA”, b == “BBB”
irb(main):006:2> puts “Uppercase”
irb(main):007:2> else
irb(main):008:2* puts “Failed”
irb(main):009:2> end
irb(main):010:1> end # => nil
irb(main):011:0> ct(“aaa”, “bbb”) # Lowercase => nil
irb(main):012:0> ct(“aaa”, “BBB”) # Lowercase => nil
irb(main):013:0> ct(“AAA”, “BBB”) # Uppercase => nil
irb(main):014:0> ct(“AAA”, “bbb”) # Lowercase => nil

-austin

austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2004.02.04
* 11.53.52

Gennady.

···

On Wed, 4 Feb 2004 01:00:25 +0900, Gennady 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

···

---- Original Message ----

On Wed, 4 Feb 2004 00:45:07 +0900, Robert Klemme wrote:

-austin
--
austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2004.02.04
                                         * 11.49.59

Hi,

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.

···

At Wed, 4 Feb 2004 03:11:35 +0900, Guoliang Cao wrote:


Nobu Nakada

“Gennady” gfb@tonesoft.com schrieb im Newsbeitrag
news:401FD2C6.1010703@tonesoft.com

Robert Klemme wrote:

“Gennady” gfb@tonesoft.com schrieb im Newsbeitrag
news:401FC5BB.10809@tonesoft.com

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”… :slight_smile:

Thanks!

robert

Austin Ziegler wrote:

Guoliang Cao wrote:
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

What you've written here will do alternatives checks. Thus, if you have:

a = "aaa"
b = "BBB"

then "Lowercase detected" will be printed. With "AAA" and "bbb", "Lowercase
detected" will still be printed.

I think this is very tricky. ',' equals to '||' here. This should be made
very clear otherwise people should avoid use this form.

Cao

···

---- Original Message ----

On Wed, 4 Feb 2004 01:00:25 +0900, Gennady wrote:

Nice investigative job ;-). But remember that it was only a quick
demonstration of a "hidden" case syntax.

irb(main):001:0> def ct(a, b)
irb(main):002:1> case
irb(main):003:2* when a == "aaa", b == "bbb"
irb(main):004:2> puts "Lowercase"
irb(main):005:2> when a == "AAA", b == "BBB"
irb(main):006:2> puts "Uppercase"
irb(main):007:2> else
irb(main):008:2* puts "Failed"
irb(main):009:2> end
irb(main):010:1> end # => nil
irb(main):011:0> ct("aaa", "bbb") # Lowercase => nil
irb(main):012:0> ct("aaa", "BBB") # Lowercase => nil
irb(main):013:0> ct("AAA", "BBB") # Uppercase => nil
irb(main):014:0> ct("AAA", "bbb") # Lowercase => nil

-austin
--
austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2004.02.04
                                         * 11.53.52

Gennady.

Hi,

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

In message “Re: RCR draft for enhanced “case…when…else…end” syntax” on 04/02/05, Guoliang Cao gcao@lemurnetworks.net writes:

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. :wink:

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

···

---- Original Message ----

On Wed, 4 Feb 2004 12:55:42 -0500, Guoliang Cao wrote:

-austin
--
austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2004.02.04
* 13.31.26

Quoteing bob.news@gmx.net, 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”… :slight_smile:

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