handles2.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 handles2
#
# Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------
# handles2 provide a means to create handles that refer to update-able
# cells.
#
# handles is a state monad. It provides features to create several
# handles that refer to modifiable value and features to 'get', 'put' or
# 'update' this value.
#
# For performance, this implementation uses mutable state. It can consequently
# only be used as a one-way monad.
#
private:public handles2(
T, X type,
# the inner value of this monad
public v X,
last_opt option (handle2_0 T),
# action to be taken: plain monad, install or replace?
redef r effect_mode.val
) : oneway_monad X (handles2 T X) r
is
# create a new instance with one additional handle
#
# the new handle can be accessed by 'result.last'
#
public new (
# initial value refered to by the new handle
w T
) handles2 T X
post
result.has_last
=>
handles2 T X v (handle2_0 w) mode
# has one element been created using 'new'?
#
public has_last => last_opt??
# return the last handle that was created by 'new'
#
public last
pre
has_last
=>
last_opt.get
# a one-way feature to create a new handle and update the monad
# in the current environment
#
/* env */
public create (
# initial value refered to by the new handle
w T
)
=>
(new w).last
# get the value refered to by a given handle
#
public get (
# a handle created by 'new'
h handle2_0 T
)
=>
h.get
# create a new instance with new value refered to by a given handle
#
public put (
# a handle created by 'new'
h handle2_0 T,
# the new value to be stored with 'h'
w T)
pre
match mode
effect_mode.plain => false # must be used as oneway_monad only
effect_mode.default => false
effect_mode.new => false
effect_mode.inst, effect_mode.repl => true
=>
h.put w
handles2 T X v last_opt mode
# create a new instance with the value refered to by a given handle read and
# updated.
#
public update (
# a handle created by 'new'
h handle2_0 T,
# function calculcating the new value from the old value
f T->T
)
pre
match mode
effect_mode.plain => false # must be used as oneway_monad only
effect_mode.default => false
effect_mode.new => false
effect_mode.inst, effect_mode.repl => true
=>
h.put (f h.get)
handles2 T X v last_opt mode
public infix >>= (f X -> handles2 T X) => bind X f
public bind(B type, f X -> handles2 T B) handles2 T B =>
handles2 T B (f v).v last_opt effect_mode.plain
public return(B type, w B) => handles2 T B w last_opt effect_mode.plain
# short-hand for creating and installing an empty set of handles2 of given type.
#
handles2(T type, rr ()->unit) =>
handles2 T unit unit nil (effect_mode.inst rr)
unit
# short-hand for creating an empty set of handles2 of given type.
#
handles2_(T type) => handles2 T unit unit nil effect_mode.plain
# short-hand for accessing handles monad for given type in current environment
#
handles2(T type) =>
(handles2_type T).install_default
(handles2 T unit).env
# handle value created by 'handles2.new'
#
private:public handle2_0(
T type,
# get value stored in this handle
#
get T
) ref
is
# set value stored in this handle to new_val
#
public put(new_val T) is
set get := new_val
(handles2 T unit).env.replace
# update value stored in this handle using f.
#
public update(f T->T) =>
set get := f get
(handles2 T unit).env.replace
get
# unit type containing features related to handles but nor requiring an instance
#
handles2_type(T type) is
# install default instance of handles2
#
install_default unit =>
handles2 T unit unit nil effect_mode.default
unit
# create a new handle2 using the handles2 instance from the current environment
#
public handle2(T type, v T) => (handles2 T).create v
last changed: 2024-03-07