[Issue 596] Support array, arrayliteral and struct in switch and case

d-bugmail at puremagic.com d-bugmail at puremagic.com
Fri Mar 29 15:51:07 PDT 2013


http://d.puremagic.com/issues/show_bug.cgi?id=596



--- Comment #13 from bearophile_hugs at 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: -------


More information about the Digitalmars-d-bugs mailing list