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

option.fz


# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# The Fuzion language implementation is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License along with The
# Fuzion language implementation.  If not, see <https://www.gnu.org/licenses/>.


# -----------------------------------------------------------------------
#
#  Tokiwa Software GmbH, Germany
#
#  Source code of Fuzion standard library feature option
#
#  Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------

# option -- feature wrapping a value or nothing
#
# option represents an optional value of type T
#
public option(public T type)
  : choice T nil,
    monad T (option T),
    Sequence T
is

  # Does this option contain a value of type T?
  #
  public exists => (option.this ? T   => true
                                | nil => false)


  # short-hand postfix operator for 'exists'
  #
  public postfix ?? => exists


  # Does this option contain no value of type T?
  #
  public is_nil => !exists


  # short-hand postfix operator for 'is_nil'
  #
  public postfix !! => is_nil


  # value of an option that is known to contain a value
  #
  # this can only be called in cases where it is known for sure that this option
  # is not nil.  A runtime error will be created otherwise.
  #
  public val T
    pre
      safety: (option.this??) # NYI: REGRESSION: parantheses currently necessary, due to PR #2572
  =>
    option.this ? v T => v
                | nil => fuzion.std.panic "option.val called on nil"


  # monadic operator
  #
  # This is handy to implement functions on optional values. As an example,
  # take an option string and you would like to add a filename suffix to
  # this string if it is present. Then you can do this as follows:
  #
  #   add_txt(o option string) => o >>= s -> s + ".txt"
  #
  # NYI: Should maybe have generic parameter B and result in option B
  #
  public redef infix >>= (f T -> option T) => option.this.bind f


  # monadic operator
  #
  # Same as non-generic >>=, but also maps to a different type B.
  #
  public bind(B type, f T -> option B) option B =>
    option.this ? v T => f v
                | nil => nil


  # synonym for infix >>=
  public and_then (f T -> option T) => option.this >>= f


  # map this option using f, i.e., map nil to nil and any value v to f v
  #
  public map_to_option(B type, f T -> B) option B =>
    option.this ? v T => f v
                | nil => nil


  # converts option to a string
  #
  # returns the result of $T for an option containing an instance
  # of T, alternatively returns $nil for an option that is nil.
  #
  public redef as_string String =>
    option.this ? v T => $v
                | nil => $nil


  # unwraps an option that is known to contain a value
  #
  # this can only be called in cases where it is known for sure that this option
  # is not nil.  A runtime error will be created otherwise.
  #
  public get
  pre
    safety: (option.this??)
  =>
    option.this ? v T => v
                | nil => fuzion.std.panic "option.get called on nil"


  # unwraps an option if it exists, returns default value otherwise.
  #
  public get(default Lazy T)
  =>
    option.this ? v T => v
                | nil => default


  # converts option into a list of either a single element in case
  # option.this.exists or `nil`otherwise
  #
  public redef as_list list T
  =>
    option.this ? v T => v : nil
                | nil => nil


  # return function
  #
  public fixed type.return (a T) => option a


# option with 1 argument provides an short-hand to wrap a value into an option
#
# Using this enables to write
#
#   o := option x
#
# insted of
#
#   o option TypeOfX := x
#
public option(T type, o option T) => o