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
last changed: 2024-03-07