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

Matches in Expressions

We need an 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"