num_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 num_option
#
# Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------
# num_option -- optional numeric values
#
# This is a pseudo-numeric type that handles one additional
# value: nil. Any operation on nil will result in nil for a
# numeric result or false for a boolean result.
#
public num_option(public T type : numeric)
: choice T nil,
monad T (num_option T)
is
# Does this option contain a value of type T?
#
public exists => (num_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: (num_option.this??)
=>
num_option.this ? v T => v
| nil => fuzion.std.panic "num_option.val called on nil"
# unwrap value or get default
#
public get (default Lazy T) =>
num_option.this ? v T => v
| nil => default
# monadic operator
public redef infix >>= (f T -> num_option T) => num_option.this.bind T f
# monadic operator
#
# Same as non-generic >>=, but also maps to a different type B.
#
public bind(B type : numeric, f T -> num_option B) num_option B =>
num_option.this ? v T => f v
| nil => nil
# monadic operator for bool result, false for nil
public infix >>? (f T -> bool) =>
num_option.this ? v T => f v
| nil => false
# basic prefix operations
public prefix +? num_option T => num_option.this >>= v -> +v
public prefix -? num_option T => num_option.this >>= v -> -?v
# basic infix operations
public infix +? (other num_option T) num_option T => num_option.this >>= v -> other >>= w -> v +? w
public infix -? (other num_option T) num_option T => num_option.this >>= v -> other >>= w -> v -? w
public infix *? (other num_option T) num_option T => num_option.this >>= v -> other >>= w -> v *? w
public infix **?(other num_option T) num_option T => num_option.this >>= v -> other >>= w -> v **? w
public infix /? (other num_option T) num_option T
pre
safety: !other.is_zero
=>
num_option.this >>= v -> other >>= w -> v / w
public infix %? (other num_option T) num_option T
pre
safety: !other.is_zero
=>
num_option.this >>= v -> other >>= w -> v % w
# comparison
public infix ==? (other num_option T) bool => num_option.this >>? v -> other >>? w -> v = w
public infix !=? (other num_option T) bool => num_option.this >>? v -> other >>? w -> v != w
public infix <? (other num_option T) bool => num_option.this >>? v -> other >>? w -> v < w
public infix <=? (other num_option T) bool => num_option.this >>? v -> other >>? w -> v ≤ w
public infix >? (other num_option T) bool => num_option.this >>? v -> other >>? w -> v > w
public infix >=? (other num_option T) bool => num_option.this >>? v -> other >>? w -> v ≥ w
public is_zero => sign ==? 0
public sign num_option i32 =>
num_option.this ? v T => v.sign
| nil => nil
public abs num_option T =>
num_option.this >>= v -> if v.sign ≥ 0 v else -?v
# converts num_option into a list of either a single element in case
# num_option.this.exists or `nil`otherwise
#
public as_list list T
=>
num_option.this ? v T => v : nil
| nil => nil
public redef as_string String =>
num_option.this ? v T => v.as_string
| nil => "--no value--"
# return function
#
public fixed type.return (a T) => num_option a
# num_option with 1 argument provides an short-hand to wrap a value into a
# num_option
#
# Using this enables to write
#
# o := num_option x
#
# instead of
#
# o num_option TypeOfX := x
#
public num_option(T type : numeric, o num_option T) => o
last changed: 2024-03-07