Verse lacks `guard` statement

Summary

The language only offers an if statement which often times not enough and still can lead to pyramids of doom (nested if statements). In non-decides context there can be times where one wants to extract an value through optional unwrapping or via a decides call and in case of absence of a result value return from the entire function.

some_class := class {
  var SomeProperty: ?some_type = false

  SomeMethod(): some_return_type = {
    # guarded property
    GSomeProperty := if (USomeProperty := SomeProperty?) {
      USomeProperty
    } else {
      return SomeReturnTypeFallback
    }
    ...
  }
}

This if statement dance is very inconvenient and requires multiple similarly named properties just to obtain a value into the current context or exit from it.

Sometimes there’s an alternative way by defaulting to a value, but it’s not always an option: GSomeProperty := SomeProperty? or SomeDefaultValue.

A proper guard statement would be much more pleasant to use.

# pseudocode
SomeMethod(): some_return_type = {
  # guarded property
  guard GSomeProperty := SomeProperty? else {
    return SomeReturnTypeFallback
  }
  # use `GSomeProperty` here
  ...
}

The showcased if statement dance is very common in my own code base, especially where I need to perform typed error handling for example.

Please select what you are reporting on:

Verse

What Type of Bug are you experiencing?

Other

Steps to Reproduce

N/A

Expected Result

N/A

Observed Result

The language feature does not exist yet.

Platform(s)

UEFN

One thing I forgot to mention. The if statement does not allow to extract multiple values into the same context compared to a guard statement. It would require at least another missing feature, which would be “tuple destructuring”.

Tuple := if:
  PropertyA := GetPropertyA[]
  PropertyB := GetPropertyB[]
then {
  (PropertyA, PropertyB)
} else {
  return SomeValue
}
GPropertyA := Tuple(0)
GPropertyB := Tuple(1)

vs.

guard:
  PropertyA := GetPropertyA[]
  PropertyB := GetPropertyB[]
else {
  return SomeValue
}
# use PropertyA and PropertyB here 

To be clear, an alternative syntax that I would happy with would be

Property := GetProperty[] or return SomeValue

However I think a proper guard statement might still be superior as the guard-condition would be a failable context that can revert a failed transaction within it compared to this single line version. Additionally it might also suffer from the lack of “tuple destructuring”.

To give a visual example:

Tuple := ( PropertyA := GetPropertyA[], PropertyB := GetPropertyB[]) or return SomeValue
GPropertyA := Tuple(0)
GPropertyB := Tuple(1)

To be clear, an alternative syntax that I would be happy with would be

Property := GetProperty[] or return SomeValue

FORT-911610 has been added to our ‘To Do’ list. Someone’s been assigned this task.