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

Matches in Expressions

We need a compact alternative for match statements that can be used within expression.

Other languages

Rust

Rust uses the postfix ? operator to obtain a value from a Result or an Option and aborts the current function in case this value does not exists: The ? operator for easier error handling.

fn read_username_from_file() -> Result {
    let mut f = File::open("username.txt")?;
    let mut s = String::new();

    f.read_to_string(&mut s)?;

    Ok(s)
}

C/C++/Java/C#

The C-like languages know the ternary operator b ? a : b to distinguish the two values of a boolean expression.

Java

With JEP 305, Java introduced "pattern matching for instanceof" in OpenJDK 14 with a syntax as follows:

  if (obj instanceof String s && s.length() > 5) {.. s.contains(..) ..}

While a Java enum can be checked using simple == and !=<7code> comparisons.

Python

Python has a few alternatives to the ternary operator:

  min = a if a < b else b    # equivalent to ternary op a < b ? a : b

  print( (b, a) [a < b] )    # selecting item from tuple

  print({True: a, False: b} [a < b]) # using dictionary

Go

Go has type-switches that declare a new variable that can be used for different types:

switch v := i.(type) {
case T:
    // here v has type T
case S:
    // here v has type S
default:
    // no match; here v has the same type as i
}

Possible syntax using Operators ?, | and !

As an example, say we have a choice type that can be V or W or some error and we want to work with the value if it is V or W and otherwise return the error:

match x
  v V => printV(v)
  w W => printW(w)
  x * => return x  // pseudo-code, Fuzion does not have return

Using Operators ?, | and !

A first step could be to

So we get:

x ? v V => printV(v)
  | w W => printW(W)
  !

Omitting Variables

We could use the same variable name in all cases, then there it would be sufficient to have a single declaration:

x ?
  v V => printV(v)
  | W => printW(v)
  !

Using a pre-declared variable it in groovy-style.

x ? V => printV(it)
  | W => printW(it)
  !

Omitting Types

Next, we can make the types optional and automatically use the types in the order given in the choice type declaration:

x ? v => printV(v)
  | w => printW(w)
  !

Omitting Variables and Types

Combinding both, we would get:

x ? v => printV(v)
    | => printW(v)
    !

or even

x ? printV(it)
  | printW(it)
  !

Performing calls on case elements

A common use case would be to perform a call on the elements of a choice (in particular, if there is only one element of interest, and the remaining being errors):

match x
  v V => v.printV
  w W => w.printW
  x * => return x  // pseudo-code, Fuzion does not have return

This case could be simplified by allowing a dot directly following the ? or | as follows:

x ?.printV |.printW !

A Single Case of Interest

If there is only one case of interest, as in an Option or a choice between a value and error cases:

match x
  v V     => v.print
  x Error => return x  // pseudo-code, Fuzion does not have return

The expression form

x ?.printV !

Could allow omitting the ! since it is clear that we do not handle any of the other cases.

x ?.printV

Even simpler, if all we are interested in is the value of the first element in a choice type

res := match x
         v V => v
         x * => return x  // pseudo-code, Fuzion does not have return

we could simplify the expression to

res := x?

Ternary Operation on bool

With these simplifications, a switch over the values of a bool

match a == b
  t TRUE => "same"
  f FALSE => "different"

turns into an expression very similar to the ternary ? : operator known from C or Java:

a == b ? "same" | "different"

Using | instead of : avoids conflicts with : used as boolean implication operator (e.g., in pre and postconditions like pre debug: a.isValid) or with : used for inheritance or anonymous inner features.

Solution for Fuzion

Here is what I consider reasonable

So we end up allowing these expressions:

  x ? v V => v.printV
    | w W => w.printW
    !

  x ? v => v.printV
    | w => w.printW
    !

  x?.printV
   |.printW
   !

  x?.printV

  res := x?

  str := a == b ? "same" | "different"