Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

Destructuring

Destructuring is syntax sugar that allows splitting of a value of a conjunction (product) type like point(x, y i32) into two variabes a, b holding the two components of the conjunction value.

Destructuring in other languages

Haskell

Haskell's where statement can be used to destructure as follows:


first tuple = x
  where
    (x, y) = tuple

Java

Several JDK Enhancement Proposals have recently added destructuring to Java (JEP405, JEP406, JEP420, JEP427, JEP432, JEP433, JEP440, JEP441). Here are examples using from JEP440:

In a switch case:


// As of Java 21
record MyPair(S fst, T snd){};

static void recordInference(MyPair pair){
    switch (pair) {
        case MyPair(var f, var s) ->
            ... // Inferred record pattern MyPair(var f, var s)
        ...
    }
}

In an instanceof expression:


// As of Java 21
record Box(T t) {}

static void test1(Box> bbs) {
    if (bbs instanceof Box>(Box(var s))) {
        System.out.println("String " + s);
    }
}

In an instanceof expression, type parameters can be inferred:


// As of Java 21
static void test2(Box> bbs) {
    if (bbs instanceof Box(Box(var s))) {
        System.out.println("String " + s);
    }
}

Rust

Here is an example for a triple taken from the Rust documentation:


fn main() {
    let triple = (0, -2, 3);
    // TODO ^ Try different values for `triple`

    println!("Tell me about {:?}", triple);
    // Match can be used to destructure a tuple
    match triple {
        // Destructure the second and third elements
        (0, y, z) => println!("First is `0`, `y` is {:?}, and `z` is {:?}", y, z),
        (1, ..)  => println!("First is `1` and the rest doesn't matter"),
        (.., 2)  => println!("last is `2` and the rest doesn't matter"),
        (3, .., 4)  => println!("First is `3`, last is `4`, and the rest doesn't matter"),
        // `..` can be used to ignore the rest of the tuple
        _      => println!("It doesn't matter what they are"),
        // `_` means don't bind the value to a variable
    }
}

And for a struct from the Rust documentation:


fn main() {
    struct Foo {
        x: (u32, u32),
        y: u32,
    }

    // Try changing the values in the struct to see what happens
    let foo = Foo { x: (1, 2), y: 3 };

    match foo {
        Foo { x: (1, b), y } => println!("First of x is 1, b = {},  y = {} ", b, y),

        // you can destructure structs and rename the variables,
        // the order is not important
        Foo { y: 2, x: i } => println!("y is 2, i = {:?}", i),

        // and you can also ignore some variables:
        Foo { y, .. } => println!("y = {}, we don't care about x", y),
        // this will give an error: pattern does not mention field `x`
        //Foo { y } => println!("y = {}", y),
    }
}

Syntax alternatives for Fuzion

Destructuring is useful in different contexts, e.g.

  • Assignments
    
    p := point x1 y1
    px, py := p
        
  • Loop index variable assignment
    
    ps Set point := ...
    for
      p in points
      px, py := p
    do
      say "$px,$py"
        
  • Loop iterator variable assignment
    
    ps Set point := ...
    for
      px, py in points
    do
      say "$px,$py"
        
  • lambdas
    
    filter_points(pred point -> bool) is ...
    filter_points (x,y -> x*x+y*y <= 100)
        
  • matches with explicit type
    
    x option point := ...
    match x
      point px py -> say "$px $px"
      nil         -> say "no point"
        
  • matches without explicit type
    
    x option point := ...
    match x
      px, py -> say "$px $px"
      nil    -> say "no point"
        

Problems to be solved

  • syntax should best be the same for all these uses
  • we need syntax for destructuring without explicit type px, py
  • we need syntax for destructuring with explicit type point px py