February 20, 2013 [Issue 596] Support array, arrayliteral and struct in switch and case | ||||
---|---|---|---|---|
| ||||
Posted in reply to d-bugmail | http://d.puremagic.com/issues/show_bug.cgi?id=596 --- Comment #9 from bearophile_hugs@eml.cc 2013-02-19 16:22:06 PST --- To match classes Scala uses the standard method "unapply": http://www.scala-lang.org/node/112 object Twice { def apply(x: Int): Int = x * 2 def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None } object TwiceTest extends Application { val x = Twice(21) x match { case Twice(n) => Console.println(n) } // prints 21 } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
March 03, 2013 [Issue 596] Support array, arrayliteral and struct in switch and case | ||||
---|---|---|---|---|
| ||||
Posted in reply to d-bugmail | http://d.puremagic.com/issues/show_bug.cgi?id=596 --- Comment #10 from bearophile_hugs@eml.cc 2013-03-03 04:24:29 PST --- When final switch supports structs, writing a fizzBuzz (http://imranontech.com/2007/01/24/using-fizzbuzz-to-find-developers-who-grok-coding/ ) gets simpler and safer: import std.stdio, std.typecons; void main() { foreach (immutable i; 1 .. 101) { final switch (tuple(i % 3 == 0, i % 5 == 0)) { case tuple(false, false): writeln(num); break; case tuple(false, true): writeln("Buzz"); break; case tuple( true, false): writeln("Fizz"); break; case tuple( true, true): writeln("FizzBuzz"); break; } } } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
March 03, 2013 [Issue 596] Support array, arrayliteral and struct in switch and case | ||||
---|---|---|---|---|
| ||||
Posted in reply to d-bugmail | http://d.puremagic.com/issues/show_bug.cgi?id=596 Simen Kjaeraas <simen.kjaras@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |simen.kjaras@gmail.com --- Comment #11 from Simen Kjaeraas <simen.kjaras@gmail.com> 2013-03-03 10:16:01 PST --- The problem of your proposed pattern matching is that there is not necessarily a simple correlation between constructor parameters and runtime values. For instance, for this struct declaration: struct Foo { int n; this( int a, int b ) { n = a * b; } } , Foo( 12, void ) just doesn't make any sense. For tuples however, this works: struct DontCare { bool opEquals( T )( T other ) const { return true; } } enum DontCare dontCare = DontCare( ); unittest { import std.typecons : Tuple, tuple; static class A {} auto a = tuple( 12, "foo" ); assert( a == tuple( 12, dontCare ) ); assert( a == tuple( dontCare, "foo" ) ); assert( a != tuple( 42, dontCare ) ); assert( a != tuple( dontCare, "bar" ) ); assert( tuple( 12, dontCare ) == a ); assert( tuple( dontCare, "foo" ) == a ); assert( tuple( 42, dontCare ) != a ); assert( tuple( dontCare, "bar" ) != a ); auto aa = new A( ); auto b = tuple( 1.5f, aa ); assert( tuple( 1.5f, dontCare ) == b ); assert( tuple( dontCare, aa ) == b ); assert( tuple( 3.5f, dontCare ) != b ); assert( tuple( dontCare, cast(A)null ) != b ); assert( b == tuple( 1.5f, dontCare ) ); assert( b == tuple( dontCare, aa ) ); assert( b != tuple( 3.5f, dontCare ) ); assert( b != tuple( dontCare, cast(A)null ) ); } This would allow switch statements like this: switch (myTuple) { case tuple( 3, dontCare ): // A break; case tuple( dontCare, "foo" ): // B break; } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
March 03, 2013 [Issue 596] Support array, arrayliteral and struct in switch and case | ||||
---|---|---|---|---|
| ||||
Posted in reply to d-bugmail | http://d.puremagic.com/issues/show_bug.cgi?id=596 --- Comment #12 from bearophile_hugs@eml.cc 2013-03-03 10:50:27 PST --- (In reply to comment #11) > The problem of your proposed pattern matching is that there is not necessarily a simple correlation between constructor parameters and runtime values. For instance, for this struct declaration: > > struct Foo { > int n; > this( int a, int b ) { > n = a * b; > } > } > > , Foo( 12, void ) just doesn't make any sense. For tuples however, this works: Arrays don't have a constructor, so they don't have this problem in a switch. Regarding structs, the problem has some solutions (both are needed): 1) Don't accept structs that have one or more constructors, and special-case std.typecons.Tuple in the compiler so tuples are accepted (the compiler assumes their constructor is just a series of field assignments). 2) If you want to support the general case of structs that have a constructor, then such structs must have a standard method like "unapply", that is used by the switch itself. This is the solution used by Scala language, it's shown in the Comment 9: http://d.puremagic.com/issues/show_bug.cgi?id=596#c9 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
March 29, 2013 [Issue 596] Support array, arrayliteral and struct in switch and case | ||||
---|---|---|---|---|
| ||||
Posted in reply to d-bugmail | http://d.puremagic.com/issues/show_bug.cgi?id=596 --- Comment #13 from bearophile_hugs@eml.cc 2013-03-29 15:51:03 PDT --- It's useful to switch on struct values: import std.bigint; void main() { auto x = BigInt(3); switch (x) { case BigInt(0): break; default: break; } } Other examples of Phobos structs that is useful to switch on are Nullable, Algebraic, etc. Switching on structs is more easy if the struct has no ctor. So it's a POD (despite having some other method). To support the general case of structs that have a constructor such structs need a standard method named like "unapply", that is used by the switch itself. This is the solution used by Scala language: http://www.scala-lang.org/node/112 This example is in Scala language: object Twice { def apply(x: Int): Int = x * 2 def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None } object TwiceTest extends Application { val x = Twice(21) x match { case Twice(n) => Console.println(n) } // prints 21 } It's equivalent to the D code: import std.stdio; import std.typecons: Nullable; struct Twice { int static opCall(int x) { return x * 2; } Nullable!int unapply(int z) { if (z % 2 == 0) return typeof(return)(z / 2); else return typeof(return).init; } } void main() { immutable int x = Twice(21); assert(x == 42); switch (x) { case Twice(n): writeln(n); // prints 21 break; default: } } A different example: import std.stdio; import std.typecons: Nullable; struct Foo { int x; this(int x_) { this.x = x_ * 2; } Nullable!int unapply(Foo f1) const { return typeof(return)(f1.x / 2); } } void main() { immutable Foo f2 = Foo(10); assert(f1.x == 20); switch (f2) { case Foo(5): writeln("First case: 5"); break; case Foo(n): writeln(n); // Prints: 10 break; default: } } A third example: import std.stdio; struct Even { bool unapply(int x) { return x % 2 == 0; } } void main() { int x = 17; switch (x) { case Even(): writeln("even"); break; default: writeln("odd"); } } unapply() is allowed to return a bool or a Nullable (including a Nullable of a tuple). For more info: http://lamp.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- |
Copyright © 1999-2021 by the D Language Foundation