DIP32: Uniform tuple syntax

bearophile bearophileHUGS at lycos.com
Fri Mar 29 15:46:44 PDT 2013


kenji hara:

> http://wiki.dlang.org/DIP32

Regarding case values:

> switch (tup) {
>     case {1, 2}:
>     case {$, 2}:
>     case {1, x}:    // capture tup[1] into 'x' when tup[0] == 1
>     default:        // same as {...}
> }


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

Bye,
bearophile


More information about the Digitalmars-d mailing list