☰
API-Documentation
Reference Constructors
Cons -- feature used to define abstract Cons cells
A Cons is a ref to a cell that contains a head and a tail
A Cons is a ref to a cell that contains a head and a tail
Exit_Handler -- abstract exit
Function -- generic function with arbitrary number of arguments and result
R is the result type of the function, A are the argument types of the function
R is the result type of the function, A are the argument types of the function
Lazy has special compiler support.
It can be used to require lazy evaluation of arguments.
A good example is `or` in bool:
In the following example the expression
`4+5>10` will never be executed:
It can be used to require lazy evaluation of arguments.
A good example is `or` in bool:
In the following example the expression
`4+5>10` will never be executed:
Monoid -- parent feature for monoids
A monoid is an abstraction for a type with an associative operation and
an identity element. Examples are (integers/infix +/0), (float/infix *,1),
(string/concat/""), etc.
A monoid is an abstraction for a type with an associative operation and
an identity element. Examples are (integers/infix +/0), (float/infix *,1),
(string/concat/""), etc.
Random_Handler -- abstract source of random numbers
This provides the random number input to be used by the 'random' effect.
Implementation may be dumb sequences of pseudo-random numbers or high-quality
cryptographic random number generators
A Random_Handler contains an immutable state, repeated calls to 'get' result
in the same value. To produce a sequence of different random numbers, 'next'
must be used to create a new instance of 'Random_Handler' before 'get' can be
used to obtain the new random number.
This provides the random number input to be used by the 'random' effect.
Implementation may be dumb sequences of pseudo-random numbers or high-quality
cryptographic random number generators
A Random_Handler contains an immutable state, repeated calls to 'get' result
in the same value. To produce a sequence of different random numbers, 'next'
must be used to create a new instance of 'Random_Handler' before 'get' can be
used to obtain the new random number.
Sequence -- ancestor for features that can be converted to a 'list'
Sequences are empty, finite or infinite ordered collections of instances
of a given type. Sequences may calculate elements lazily on demand.
Sequence is a 'ref' type, i.e., different sub-features may be assigned
to a field of type 'Sequence'.
Heirs of Sequence must implement 'as_list'.
Sequences are empty, finite or infinite ordered collections of instances
of a given type. Sequences may calculate elements lazily on demand.
Sequence is a 'ref' type, i.e., different sub-features may be assigned
to a field of type 'Sequence'.
Heirs of Sequence must implement 'as_list'.
string -- immutable sequences of utf8 encoded unicode characters
Unary -- function that takes exactly one argument and returns a result
T is the result type of the function, U is the argument type of the function
For unary functions, function composition is possible if the result type of
the first function matches the argument type of the second function.
T is the result type of the function, U is the argument type of the function
For unary functions, function composition is possible if the result type of
the first function matches the argument type of the second function.
Value Constructors
feature to signal an abort of a computation.
contains the final value of a computation.
used e.g. in Sequence.reduce
contains the final value of a computation.
used e.g. in Sequence.reduce
composition -- a collection of features for function composition
see https://mlochbaum.github.io/BQN/tutorial/combinator.html
Talk at Strange Loop 2016 by Amar Shah: Point-Free or Die: Tacit Programming in Haskell and Beyond
https://www.youtube.com/watch?v=seVSlKazsNk
Talk at CppNorth 2023 by Conor Hoekstra: Function Composition in Programming Languages - Conor Hoekstra - CppNorth 2023
https://www.youtube.com/watch?v=JELcdZLre3s
Paper by Conor Hoekstra: Combinatory Logic and Combinators in Array Languages
https://web.archive.org/web/20220617020347id_/https://dl.acm.org/doi/pdf/10.1145/3520306.3534504
BQN tutorial: https://mlochbaum.github.io/BQN/tutorial/index.html
Talk for Fullstack Academy by Gabriel Lebec: Lambda Calculus - Fundamentals of Lambda Calculus & Functional
Pragramming in JavaScript
https://www.youtube.com/watch?v=3VQ382QG-y4
David C Keenan
To Dissect a Mockingbird: A Graphical Notation for the Lambda Calculus with Animated Reduction
https://dkeenan.com/Lambda/
Haskell package data.aviary.birds:
https://hackage.haskell.org/package/data-aviary-0.4.0/docs/Data-Aviary-Birds.html
Bird names from Raymond M Smullyan. 2000. To Mock a Mockingbird: and other
logic puzzles including an amazing adventure in combinatory logic. Oxford
University Press, USA.
Combinator birds: https://www.angelfire.com/tx4/cus/combinator/birds.html
see https://mlochbaum.github.io/BQN/tutorial/combinator.html
Talk at Strange Loop 2016 by Amar Shah: Point-Free or Die: Tacit Programming in Haskell and Beyond
https://www.youtube.com/watch?v=seVSlKazsNk
Talk at CppNorth 2023 by Conor Hoekstra: Function Composition in Programming Languages - Conor Hoekstra - CppNorth 2023
https://www.youtube.com/watch?v=JELcdZLre3s
Paper by Conor Hoekstra: Combinatory Logic and Combinators in Array Languages
https://web.archive.org/web/20220617020347id_/https://dl.acm.org/doi/pdf/10.1145/3520306.3534504
BQN tutorial: https://mlochbaum.github.io/BQN/tutorial/index.html
Talk for Fullstack Academy by Gabriel Lebec: Lambda Calculus - Fundamentals of Lambda Calculus & Functional
Pragramming in JavaScript
https://www.youtube.com/watch?v=3VQ382QG-y4
David C Keenan
To Dissect a Mockingbird: A Graphical Notation for the Lambda Calculus with Animated Reduction
https://dkeenan.com/Lambda/
Haskell package data.aviary.birds:
https://hackage.haskell.org/package/data-aviary-0.4.0/docs/Data-Aviary-Birds.html
Bird names from Raymond M Smullyan. 2000. To Mock a Mockingbird: and other
logic puzzles including an amazing adventure in combinatory logic. Oxford
University Press, USA.
Combinator birds: https://www.angelfire.com/tx4/cus/combinator/birds.html
cons -- feature used to define simple, non-lazy Cons cells
A cons is a cell that contains a head and a tail
A cons is a cell that contains a head and a tail
container -- unit feature to group features that provide some kind of
data structure to store and retrieve values
data structure to store and retrieve values
effect -- abstract parent feature for effects
effect provides a means to perform effectful operations. Instances
of effect are instated in the current environment while their code is
executed. The code may perform operations of the instated effect
via <type>.env. These operations may either return normally (resume) or
abort the current computation, i.e., return directly to the call that
instated the effect.
Effects are identified by their type, including any actual type parameters.
Effect instances must be assignable to the effect type. This means that if
the effect type is a value type, the instance must be an instance of exactly
that type while if the effect type is a ref type, the instance might be of
a type that inherits from the effect type that is --possibly after boxing--
assignable to that type.
Effect operations may replace an instated instance by a new value.
This gives operations a means to become stateful.
In case an effect performs an abort, the code the effect was instated for
will be abandoned and the function passed via tha `def` argument to
`instate` will be used to produce a result from the last effect instance.
Effects may redefine the `finally` feature that is executed directly after
an instated effect was removed, independent of the reason why it is removed.
This means, finally is executed after code running in the effect returns
normally, after a call to an operation that results in an abort or when
a surrounding effect is aborted.
effect provides a means to perform effectful operations. Instances
of effect are instated in the current environment while their code is
executed. The code may perform operations of the instated effect
via <type>.env. These operations may either return normally (resume) or
abort the current computation, i.e., return directly to the call that
instated the effect.
Effects are identified by their type, including any actual type parameters.
Effect instances must be assignable to the effect type. This means that if
the effect type is a value type, the instance must be an instance of exactly
that type while if the effect type is a ref type, the instance might be of
a type that inherits from the effect type that is --possibly after boxing--
assignable to that type.
Effect operations may replace an instated instance by a new value.
This gives operations a means to become stateful.
In case an effect performs an abort, the code the effect was instated for
will be abandoned and the function passed via tha `def` argument to
`instate` will be used to produce a result from the last effect instance.
Effects may redefine the `finally` feature that is executed directly after
an instated effect was removed, independent of the reason why it is removed.
This means, finally is executed after code running in the effect returns
normally, after a call to an operation that results in an abort or when
a surrounding effect is aborted.
error represents an error condition described by a message string
NYI: Future versions of error might be equipped with a stack trace if
debugging is enabled
NYI: Future versions of error might be equipped with a stack trace if
debugging is enabled
f32 -- 32 bit floating point values
f32 are binary32-numbers as defined in the IEEE 754-2019 standard, see
https://ieeexplore.ieee.org/servlet/opac?punumber=8766227
f32 are binary32-numbers as defined in the IEEE 754-2019 standard, see
https://ieeexplore.ieee.org/servlet/opac?punumber=8766227
f64 -- 64 bit floating point values
f64 are binary64-numbers as defined in the IEEE 754-2019 standard, see
https://ieeexplore.ieee.org/servlet/opac?punumber=8766227
f64 are binary64-numbers as defined in the IEEE 754-2019 standard, see
https://ieeexplore.ieee.org/servlet/opac?punumber=8766227
float -- floating point values
float is the abstract parent of concrete floating point features such as
f32 or f64.
float is the abstract parent of concrete floating point features such as
f32 or f64.
has_interval -- feature for integers that can define an interval
i16 -- 16-bit signed integer values
i32 -- 32-bit signed integer values
i64 -- 64-bit signed integer values
i8 -- 8-bit signed integer values
internationalization -- unit feature to group features related to specific
geographical, political, or cultural regions such as formatting of dates,
numbers, currencies, etc.
geographical, political, or cultural regions such as formatting of dates,
numbers, currencies, etc.
An interval `from..through` that includes `from`, `from+step`, `from+step+step`,
etc. up to and including `through`.
In case step is positive (negative), the first value larger (smaller) than
through will not be included.
In case `step.sign = (from ⋄ through).sign`, this `Set` is empty, e.g.,
`interval 1 2 -1` and `interval 2 1 1` are both empty.
etc. up to and including `through`.
In case step is positive (negative), the first value larger (smaller) than
through will not be included.
In case `step.sign = (from ⋄ through).sign`, this `Set` is empty, e.g.,
`interval 1 2 -1` and `interval 2 1 1` are both empty.
lock_free -- unit type feature grouping lock-free
data structures and algorithms
data structures and algorithms
monad -- generic monad
A monad in X is just a monoid in the category of endofunctors of X, with
product × replaced by composition of endofunctors and unit set by the
identity endofunctor.
Don't be scared, in Java terms: A monad is a means to compose functions
applied to generic types.
A monad in X is just a monoid in the category of endofunctors of X, with
product × replaced by composition of endofunctors and unit set by the
identity endofunctor.
Don't be scared, in Java terms: A monad is a means to compose functions
applied to generic types.
mutate -- an effect that permits creation and mutation of mutable values.
This effect is typically used to work with mutable values. You can create
a mutable value as follows
v := mutate.env.new i32 42
and then modify it using
v <- 666
To read it, call 'get' as in
say "v is {v.get}"
Convenience feature 'mut' and type inference allow the creation to be
written as
v := mut 42
NYI: syntax sugar to read mutable field using
w := v + 1
instead of
w := v.get + 1
is not supported yet.
This effect is typically used to work with mutable values. You can create
a mutable value as follows
v := mutate.env.new i32 42
and then modify it using
v <- 666
To read it, call 'get' as in
say "v is {v.get}"
Convenience feature 'mut' and type inference allow the creation to be
written as
v := mut 42
NYI: syntax sugar to read mutable field using
w := v + 1
instead of
w := v.get + 1
is not supported yet.
nil -- value for options that are not present
This is a unit type that is preferred to represent instances that are
not present, e.g, in an option.
This is a unit type that is preferred to represent instances that are
not present, e.g, in an option.
executes `f` only the first time when
calling `get` caching its result.
calling `get` caching its result.
§(A type, OMA type :oneway_monad oneway_monad.A oneway_monad.OMA, mode oneway_monad_mode.val):monad oneway_monad.A, oneway_monad.OMA,effect is [Contains abstract features]
§(A
type
, OMA type
:oneway_monad oneway_monad.A oneway_monad.OMA, mode oneway_monad_mode.val):
monad oneway_monad.A, oneway_monad.OMA,effect is
[Contains abstract features]
oneway_monad -- heir feature of all one-way monads.
oneway_monad is the heir feature of all one-way monads. A one-way monad is
a monadic feature that can be accessed as a effect through the environment
and that will be replaced in the environment whenever a new instance is
created. Alternatively, this can be used as a monad that wraps around a
function result type A.
oneway_monad is the heir feature of all one-way monads. A one-way monad is
a monadic feature that can be accessed as a effect through the environment
and that will be replaced in the environment whenever a new instance is
created. Alternatively, this can be used as a monad that wraps around a
function result type A.
enum of the mode argument.
panic -- effect that terminates a computation in panic
property -- unit feature to group features that can be inherited by other
features if they fulfill certain properties such as defining a partial
order
features if they fulfill certain properties such as defining a partial
order
quantor -- unit type feature containing quantors ∀ and ∃.
quantor provides for_all and exists-quantors for use in contracts qualified
for analysis.
quantor provides for_all and exists-quantors for use in contracts qualified
for analysis.
random -- effect that provides random numbers
§(T type, S type, val state.T, get state.S, mode oneway_monad_mode.val):oneway_monad state.T, state state.T state.S is [Contains abstract features]
§(T
type
, S type
, val state.T, get state.S, mode oneway_monad_mode.val):
oneway_monad state.T, state state.T state.S is
[Contains abstract features]
state -- represent a state using a monad
this can be used both as plain or as a oneway monad to store a state
in a way orthogonal to the actual computation.
this can be used both as plain or as a oneway monad to store a state
in a way orthogonal to the actual computation.
terminal -- unit type feature providing ANSI terminal control codes
Terminal provides constants to modify the text output style and color.
Thanks to Bruno Penteado who collected these codes at
https://gist.github.com/bcap/5682077#file-terminal-control-sh
but this also includes input from
https://en.wikipedia.org/wiki/ANSI_escape_code
and
man console_codes
Terminal provides constants to modify the text output style and color.
Thanks to Bruno Penteado who collected these codes at
https://gist.github.com/bcap/5682077#file-terminal-control-sh
but this also includes input from
https://en.wikipedia.org/wiki/ANSI_escape_code
and
man console_codes
§(TA type, B type, C type, td Unary (Function transducer.TA transducer.TA transducer.C) (Function transducer.TA transducer.TA transducer.B)):Any is
§(TA
type
, B type
, C type
, td Unary (Function transducer.TA transducer.TA transducer.C) (Function transducer.TA transducer.TA transducer.B)):
Any is
transducers map one reducing function to
another reducing function. this enables composition
and reuse of map, filter, reduce etc.
see https://clojure.org/reference/transducers
for in depth information on transducers
usage example:
human(age i32) is
td := (transducer (Sequence i32) i32 human).type
ages := td.map (x -> x.age)
gt_ten := td.filter (x -> x > 10)
xf := ages ∘ gt_ten
say ([human 4, human 12, human 30].into xf) # [12,30]
TA result type
B input type
C transduced type
another reducing function. this enables composition
and reuse of map, filter, reduce etc.
see https://clojure.org/reference/transducers
for in depth information on transducers
usage example:
human(age i32) is
td := (transducer (Sequence i32) i32 human).type
ages := td.map (x -> x.age)
gt_ten := td.filter (x -> x > 10)
xf := ages ∘ gt_ten
say ([human 4, human 12, human 30].into xf) # [12,30]
TA result type
B input type
C transduced type
try -- simple exception effect
try provides an operation 'cause' that immediately stops execution and
returns an 'error' wrapped in an 'outcome'.
try provides an operation 'cause' that immediately stops execution and
returns an 'error' wrapped in an 'outcome'.
tuple -- feature used to define tuple types
tuple types provide algebraic product types of all the generic arguments
provided to tuple.
The values within a tuple 'tuple A B C' can be accessed via the tuple's
argument field 'values' followed by a selector referring to the generic
argument's position: 'values.0', 'values.1' and 'values.2', respectively.
Syntactic sugar of the Fuzion language permits an alternative notation
to create values of tuple types as follows
t := (a, b, c, ... )
is equivalent to
t := tuple a b c ...
The actual generic types are inferred from the static types of the values
'a', 'b', 'c', ... the tuple is created from.
Similarly, syntactic sugar for the destructuring of tuples can be used
to access the values as in
(a, b, c, ...) := t
In destructurings, we can denote values we are not interested in using
'_' as in
(_, b) := ("first", "second")
which will set 'b' to '"second"' and drop the first element of the tuple.
As an example, say we want to identify a person by its name and its age,
so we can define
a := ("Alice" , 11)
b := ("Bob" , 22)
c := ("Claire", 33)
Then, we could extract Bob's age using
(_, age) := b
or Claire's name using
(name, _) := c
Destructuring also works for general features, e.g.
point (x,y i32) is {}
p := point 3, 4
(px, py) := p # will set px to 3 and py to 4
and the destructured value can then be used to create a tuple
t := (px, py) # will create tuple<i32,i32> instance
however, tuples are not assignment compatible with general features even
if they would destructure into the same types, i.e.,
u tuple i32 i32 = p # will cause compile time error
q point = (7, 12) # will cause compile time error
The unit tuple '()' can be used as a short-hand to create the empty tuple
'tuple'. The empty tuple can be destructured like any other tuple
using
() := ()
even though this has no effect.
An instance of the single tuple 'tuple A' with sole element 'a' can not
be created using syntactic sugar '(a)', this will produce the plain
value of 'a' instead. However, destructuring of a single tuple is possible:
(a0) := tuple a
which is equivalent to
a0 := a
NYI: A single tuple 'tuple A' is currently not assignment compatible with
type 'A', which would make handling of general tuples easier.
tuples and destructuring can be used to swap two elements or create a
permutation as in
(a, b) := (b, a)
(o, t, a, n) := (n, a, t, o)
A tuple type with no actual generic arguments is isomorphic to 'unit', i.e, it
is a type that has only one single value: '()'.
tuple types provide algebraic product types of all the generic arguments
provided to tuple.
The values within a tuple 'tuple A B C' can be accessed via the tuple's
argument field 'values' followed by a selector referring to the generic
argument's position: 'values.0', 'values.1' and 'values.2', respectively.
Syntactic sugar of the Fuzion language permits an alternative notation
to create values of tuple types as follows
t := (a, b, c, ... )
is equivalent to
t := tuple a b c ...
The actual generic types are inferred from the static types of the values
'a', 'b', 'c', ... the tuple is created from.
Similarly, syntactic sugar for the destructuring of tuples can be used
to access the values as in
(a, b, c, ...) := t
In destructurings, we can denote values we are not interested in using
'_' as in
(_, b) := ("first", "second")
which will set 'b' to '"second"' and drop the first element of the tuple.
As an example, say we want to identify a person by its name and its age,
so we can define
a := ("Alice" , 11)
b := ("Bob" , 22)
c := ("Claire", 33)
Then, we could extract Bob's age using
(_, age) := b
or Claire's name using
(name, _) := c
Destructuring also works for general features, e.g.
point (x,y i32) is {}
p := point 3, 4
(px, py) := p # will set px to 3 and py to 4
and the destructured value can then be used to create a tuple
t := (px, py) # will create tuple<i32,i32> instance
however, tuples are not assignment compatible with general features even
if they would destructure into the same types, i.e.,
u tuple i32 i32 = p # will cause compile time error
q point = (7, 12) # will cause compile time error
The unit tuple '()' can be used as a short-hand to create the empty tuple
'tuple'. The empty tuple can be destructured like any other tuple
using
() := ()
even though this has no effect.
An instance of the single tuple 'tuple A' with sole element 'a' can not
be created using syntactic sugar '(a)', this will produce the plain
value of 'a' instead. However, destructuring of a single tuple is possible:
(a0) := tuple a
which is equivalent to
a0 := a
NYI: A single tuple 'tuple A' is currently not assignment compatible with
type 'A', which would make handling of general tuples easier.
tuples and destructuring can be used to swap two elements or create a
permutation as in
(a, b) := (b, a)
(o, t, a, n) := (n, a, t, o)
A tuple type with no actual generic arguments is isomorphic to 'unit', i.e, it
is a type that has only one single value: '()'.
u128 -- 128-bit unsigned integer values
u16 -- 16-bit unsigned integer values
u32 -- 32-bit unsigned integer values
u64 -- 64-bit unsigned integer values
u8 -- 8-bit unsigned integer values
unique_id -- effect that generates a unique id
unit -- value to be used as result of features that do not return a result
NOTE: unit corresponds to type void in C, Java, etc.
unit is the preferred result type for features that return without producing
a result value. These are features that typically have an outside effect
such as
println(String s) unit => ...
or features that change the state of an instance such as
increment(delta i64) unit =>
The Fuzion language implementation automatically inserts code that returns the
unit value as a result of these features, there is no need for an explicit unit
result as in
increment(delta i64) unit =>
but it is allowed to return unit explicitly if desired.
Another application of the unit type are generic features when certain generic
values are not needed and can be ignored. An example could be a generic map
implementation map K V that maps values of type K to values of type V. Using
unit as the actual generic argument for V, e.g., map string unit creates a
map that stores no data for each key, which essentially turns the map into a
set of the map's keys.
The Fuzion library knows several different unit types. Another example is nil,
which is used as the alternative type in an option. This enables the use of
option void, which can store two distinct values, void and nil.
Other unit types in Fuzion are TRUE and FALSE.
The simplest syntax to create a value of unit type is an empty block '{}'. Note
that an empty tuple 'tuple' is a different unit value of a different type and
the syntax '()' is (at least for now) not supported.
Please note the fundamental difference between
red is {}
red => {}
The first declares a feature red that defines a new unit type red, the second
declares a feature red with result type unit, i.e., a synonym for unit as in
red unit => {}
The memory required to store a value of unit type is 0 bits, so you can use
plenty without worrying about space constraints. The Fuzion code generators
typically will not generate any code for returning or assigning a value of unit
type, so these are very efficient as well.
NOTE: unit corresponds to type void in C, Java, etc.
unit is the preferred result type for features that return without producing
a result value. These are features that typically have an outside effect
such as
println(String s) unit => ...
or features that change the state of an instance such as
increment(delta i64) unit =>
The Fuzion language implementation automatically inserts code that returns the
unit value as a result of these features, there is no need for an explicit unit
result as in
increment(delta i64) unit =>
but it is allowed to return unit explicitly if desired.
Another application of the unit type are generic features when certain generic
values are not needed and can be ignored. An example could be a generic map
implementation map K V that maps values of type K to values of type V. Using
unit as the actual generic argument for V, e.g., map string unit creates a
map that stores no data for each key, which essentially turns the map into a
set of the map's keys.
The Fuzion library knows several different unit types. Another example is nil,
which is used as the alternative type in an option. This enables the use of
option void, which can store two distinct values, void and nil.
Other unit types in Fuzion are TRUE and FALSE.
The simplest syntax to create a value of unit type is an empty block '{}'. Note
that an empty tuple 'tuple' is a different unit value of a different type and
the syntax '()' is (at least for now) not supported.
Please note the fundamental difference between
red is {}
red => {}
The first declares a feature red that defines a new unit type red, the second
declares a feature red with result type unit, i.e., a synonym for unit as in
red unit => {}
The memory required to store a value of unit type is 0 bits, so you can use
plenty without worrying about space constraints. The Fuzion code generators
typically will not generate any code for returning or assigning a value of unit
type, so these are very efficient as well.
Functions
analysis -- condition qualifier for conditions used by static analysis tools
analysis is a condition qualifier that is used for conditions that are
not intended to be checked at run time but only by static analysis tools.
analysis is a condition qualifier that is used for conditions that are
not intended to be checked at run time but only by static analysis tools.
array -- create initialized one-dimensional immutable array
array(length0, length1) -- two-dimensional immutable array
array provides two-dimensional immutable arrays. These are actually
one-dimensional immutable arrays with an additional access function with
two index parameters.
array provides two-dimensional immutable arrays. These are actually
one-dimensional immutable arrays with an additional access function with
two index parameters.
§(T type, length0 i32, length1 i32, length2 i32, init3 Function array3.T i32 i32 i32):Any => array3 array3.T
§(T
type
, length0 i32, length1 i32, length2 i32, init3 Function array3.T i32 i32 i32):
Any =>
array3 array3.Tarray(length0, length1, length2) -- three-dimensional immutable array
array provides three-dimensional immutable arrays. These are actually
one-dimensional immutable arrays with an additional access function with
three index parameters.
array provides three-dimensional immutable arrays. These are actually
one-dimensional immutable arrays with an additional access function with
three index parameters.
benchmark f for milli_seconds (1s warm up)
only completed iterations are counted, any iterations started before
the one second warmup has elapsed are not counted either
returns: iterations per second
only completed iterations are counted, any iterations started before
the one second warmup has elapsed are not counted either
returns: iterations per second
benchmark f by iterating it for nano_seconds
only completed iterations are counted, any iterations started before
warm_up_nano_seconds has elapsed are not counted either
returns: iterations per second
only completed iterations are counted, any iterations started before
warm_up_nano_seconds has elapsed are not counted either
returns: iterations per second
cache result of f for cache key T
This is best explained by the following example:
The cache implemented works on a global level.
This is best explained by the following example:
The cache implemented works on a global level.
debug -- features related to debug setting
debug is a condition qualifier that enables conditions if debugging is
enabled.
this is true if and only if the debug level is greater than zero.
debug is a condition qualifier that enables conditions if debugging is
enabled.
this is true if and only if the debug level is greater than zero.
debug(i32) is a condition qualifier that enables conditions if debugging is
enabled at the given debug-level.
enabled at the given debug-level.
Current debug level, used by condition qualified debug(i32)
This can be controlled using the "-debug=" option to the fz tool:
Whatever option was set at compile time will be used when running a
compile program.
This can be controlled using the "-debug=" option to the fz tool:
Whatever option was set at compile time will be used when running a
compile program.
equals -- feature that compares two values using the equality relation
defined in their type
defined in their type
exit with a code argument calls exit.exit code, i.e., it uses the
current exit effect to exit with the given message.
current exit effect to exit with the given message.
install given exit handler and run code with it.
In case the handler aborts this effect, this feature will
return normally after a call to `exit.env.exit n`.
In case the handler aborts this effect, this feature will
return normally after a call to `exit.env.exit n`.
initializes a new handle with the given initial value
this uses the handles instance from the current environment
this uses the handles instance from the current environment
create a new handle2 using the handles2 instance from the current environment
short-hand for accessing handles monad for given type in current environment
short-hand for creating and installing an empty set of handles of given type.
short-hand for creating an empty set of handles of given type.
id -- routine implementing the identity function
When called, this feature returns its argument
When called, this feature returns its argument
identity -- feature returing the unary identity function
When called, this feature returns a unary function that implements the
identity for the given type.
In most cases, you can use `id` instead and rely on partial application to
create a Function instance, e.g. you can use any of these to produce the same
result
all_true(s Sequence bool) => s ∀ id
all_true(s Sequence bool) => s ∀ (x -> id bool x)
all_true(s Sequence bool) => s ∀ (x -> id x)
all_true(s Sequence bool) => s ∀ (identity bool)
or, using an intermediate field,
all_true(s Sequence bool) => { f (bool)->bool := id; s ∀ f }
all_true(s Sequence bool) => { f (bool)->bool := (x -> id bool x); s ∀ f }
all_true(s Sequence bool) => { f (bool)->bool := (x -> id x); s ∀ f }
all_true(s Sequence bool) => { f (bool)->bool := identity bool; s ∀ f }
When called, this feature returns a unary function that implements the
identity for the given type.
In most cases, you can use `id` instead and rely on partial application to
create a Function instance, e.g. you can use any of these to produce the same
result
all_true(s Sequence bool) => s ∀ id
all_true(s Sequence bool) => s ∀ (x -> id bool x)
all_true(s Sequence bool) => s ∀ (x -> id x)
all_true(s Sequence bool) => s ∀ (identity bool)
or, using an intermediate field,
all_true(s Sequence bool) => { f (bool)->bool := id; s ∀ f }
all_true(s Sequence bool) => { f (bool)->bool := (x -> id bool x); s ∀ f }
all_true(s Sequence bool) => { f (bool)->bool := (x -> id x); s ∀ f }
all_true(s Sequence bool) => { f (bool)->bool := identity bool; s ∀ f }
ignore -- function mapping any value to unit
This can be used to ignore the result of an expression, e.g. the
instance returned by a constructor or the value returned by a fuction.
Ex. with these features
hello is
say_and_inc(x i32) i32 =>
the results can be ignored as follows
hello |> ignore
(say_and_inc 42) |> ignore
ignore hello
ignore (say_and_inc 42)
_ := hello
_ := say_and_inc 42
This can be used to ignore the result of an expression, e.g. the
instance returned by a constructor or the value returned by a fuction.
Ex. with these features
hello is
say_and_inc(x i32) i32 =>
the results can be ignored as follows
hello |> ignore
(say_and_inc 42) |> ignore
ignore hello
ignore (say_and_inc 42)
_ := hello
_ := say_and_inc 42
infix = -- infix operation as short-hand for 'equals'
infix operator to create a list from head h and lazy tail t.
This is convenient to append an element before a list as in
0 : [1,2,3,4].as_list
or to create lists by recursion, e.g., a an endless list containing
integer 1 repeatedly is
ones => 1 : ones
This is convenient to append an element before a list as in
0 : [1,2,3,4].as_list
or to create lists by recursion, e.g., a an endless list containing
integer 1 repeatedly is
ones => 1 : ones
infix operator to create a list from head h and a production
function f
This can be used, e.g., as follows:
Ex1: the identity can be used to repeat the same element
1 :: x->x
will create 1,1,1,1,...
Ex2: To create a list of all integers, use
0 :: +1
which will produce 0,1,2,3,4,5,...
Ex3: The call
1 :: p->p+p
will produce the powers of two: 1,2,4,8,16,32,...
function f
This can be used, e.g., as follows:
Ex1: the identity can be used to repeat the same element
1 :: x->x
will create 1,1,1,1,...
Ex2: To create a list of all integers, use
0 :: +1
which will produce 0,1,2,3,4,5,...
Ex3: The call
1 :: p->p+p
will produce the powers of two: 1,2,4,8,16,32,...
infix <= -- infix operation as short-hand for 'lteq'
three-way comparison between this and other.
result is < 0 if this < other
result is > 0 if this > other
result is = 0 if this = other
result is < 0 if this < other
result is > 0 if this > other
result is = 0 if this = other
infix <| -- backwards pipe with one argument
This operation is seldom useful, it is provided only for reasons of symmetry with |>.
Instead of
l := [1,2,3,4].map **2 |> sum
you can also write
l := sum <| [1,2,3,4].map **2
which often correponds more naturally to the data flow through the code.
This operation is seldom useful, it is provided only for reasons of symmetry with |>.
Instead of
l := [1,2,3,4].map **2 |> sum
you can also write
l := sum <| [1,2,3,4].map **2
which often correponds more naturally to the data flow through the code.
§(A type, B type, R type, f Function (infix <||.R) (infix <||.A) (infix <||.B), a tuple (infix <||.A) (infix <||.B)):Any => infix <||.R
§(A
type
, B type
, R type
, f Function (infix <||.R) (infix <||.A) (infix <||.B), a tuple (infix <||.A) (infix <||.B)):
Any =>
infix <||.Rinfix <|| -- backwards pipe with a two-tuple argument, destructuring the tuple into arguments
This allows destructuring of tuples as actual arguments: instead of
f(a,b i32) => a+b
l1 := [1,2,3,4]
l2 := [4,3,2,1]
l := l1.pairs l2
you can write
l1 := [1,2,3,4]
l2 := [4,3,2,1]
l := l1.pairs l2
.
This allows destructuring of tuples as actual arguments: instead of
f(a,b i32) => a+b
l1 := [1,2,3,4]
l2 := [4,3,2,1]
l := l1.pairs l2
you can write
l1 := [1,2,3,4]
l2 := [4,3,2,1]
l := l1.pairs l2
.
§(A type, B type, C type, R type, f Function (infix <|||.R) (infix <|||.A) (infix <|||.B) (infix <|||.C), a tuple (infix <|||.A) (infix <|||.B) (infix <|||.C)):Any => infix <|||.R
§(A
type
, B type
, C type
, R type
, f Function (infix <|||.R) (infix <|||.A) (infix <|||.B) (infix <|||.C), a tuple (infix <|||.A) (infix <|||.B) (infix <|||.C)):
Any =>
infix <|||.Rinfix <||| -- backwards pipe with a three-tuple argument, destructuring the tuple into arguments
This allows destructuring of 3-tuples as actual arguments: instead of
f(a,b,c i32) => a+b+c
t := (1,2,3)
r := f t.0 t.1 t.2
you can write
f(a,b,c i32) => a+b+c
t := (1,2,3)
r := f <||| t
which often correponds more naturally to the data flow through the code.
This allows destructuring of 3-tuples as actual arguments: instead of
f(a,b,c i32) => a+b+c
t := (1,2,3)
r := f t.0 t.1 t.2
you can write
f(a,b,c i32) => a+b+c
t := (1,2,3)
r := f <||| t
which often correponds more naturally to the data flow through the code.
§(A type, B type, C type, D type, R type, f Function (infix <||||.R) (infix <||||.A) (infix <||||.B) (infix <||||.C) (infix <||||.D), a tuple (infix <||||.A) (infix <||||.B) (infix <||||.C) (infix <||||.D)):Any => infix <||||.R
§(A
type
, B type
, C type
, D type
, R type
, f Function (infix <||||.R) (infix <||||.A) (infix <||||.B) (infix <||||.C) (infix <||||.D), a tuple (infix <||||.A) (infix <||||.B) (infix <||||.C) (infix <||||.D)):
Any =>
infix <||||.Rinfix <|||| -- backwards pipe with a four-tuple argument, destructuring the tuple into arguments
This allows destructuring of 4-tuples as actual arguments: instead of
f(a,b,c,d i32) => a+b+c+d
t := (1,2,3,4)
r := f t.0 t.1 t.2 t.3
you can write
f(a,b,c,d i32) => a+b+c+d
t := (1,2,3,4)
r := f <|||| t
which often correponds more naturally to the data flow through the code.
This allows destructuring of 4-tuples as actual arguments: instead of
f(a,b,c,d i32) => a+b+c+d
t := (1,2,3,4)
r := f t.0 t.1 t.2 t.3
you can write
f(a,b,c,d i32) => a+b+c+d
t := (1,2,3,4)
r := f <|||| t
which often correponds more naturally to the data flow through the code.
§(A type, B type, C type, D type, E type, R type, f Function (infix <|||||.R) (infix <|||||.A) (infix <|||||.B) (infix <|||||.C) (infix <|||||.D) (infix <|||||.E), a tuple (infix <|||||.A) (infix <|||||.B) (infix <|||||.C) (infix <|||||.D) (infix <|||||.E)):Any => infix <|||||.R
§(A
type
, B type
, C type
, D type
, E type
, R type
, f Function (infix <|||||.R) (infix <|||||.A) (infix <|||||.B) (infix <|||||.C) (infix <|||||.D) (infix <|||||.E), a tuple (infix <|||||.A) (infix <|||||.B) (infix <|||||.C) (infix <|||||.D) (infix <|||||.E)):
Any =>
infix <|||||.Rinfix <||||| -- backwards pipe with a five-tuple argument, destructuring the tuple into arguments
This allows destructuring of 5-tuples as actual arguments: instead of
f(a,b,c,d,e i32) => a+b+c+d+e
t := (1,2,3,4,5)
r := f t.0 t.1 t.2 t.3 t.4
you can write
f(a,b,c,d,e i32) => a+b+c+d+e
t := (1,2,3,4,5)
r := f <||||| t
which often correponds more naturally to the data flow through the code.
This allows destructuring of 5-tuples as actual arguments: instead of
f(a,b,c,d,e i32) => a+b+c+d+e
t := (1,2,3,4,5)
r := f t.0 t.1 t.2 t.3 t.4
you can write
f(a,b,c,d,e i32) => a+b+c+d+e
t := (1,2,3,4,5)
r := f <||||| t
which often correponds more naturally to the data flow through the code.
§(A type, B type, C type, D type, E type, F type, R type, f Function (infix <||||||.R) (infix <||||||.A) (infix <||||||.B) (infix <||||||.C) (infix <||||||.D) (infix <||||||.E) (infix <||||||.F), a tuple (infix <||||||.A) (infix <||||||.B) (infix <||||||.C) (infix <||||||.D) (infix <||||||.E) (infix <||||||.F)):Any => infix <||||||.R
§(A
type
, B type
, C type
, D type
, E type
, F type
, R type
, f Function (infix <||||||.R) (infix <||||||.A) (infix <||||||.B) (infix <||||||.C) (infix <||||||.D) (infix <||||||.E) (infix <||||||.F), a tuple (infix <||||||.A) (infix <||||||.B) (infix <||||||.C) (infix <||||||.D) (infix <||||||.E) (infix <||||||.F)):
Any =>
infix <||||||.Rinfix <|||||| -- backwards pipe with a six-tuple argument, destructuring the tuple into arguments
This allows destructuring of 6-tuples as actual arguments: instead of
f(a,b,c,d,e,f i32) => a+b+c+d+e+f
t := (1,2,3,4,5,6)
r := f t.0 t.1 t.2 t.3 t.4 t.5
you can write
f(a,b,c,d,e,f i32) => a+b+c+d+e+f
t := (1,2,3,4,5,6)
r := f <|||||| t
which often correponds more naturally to the data flow through the code.
This allows destructuring of 6-tuples as actual arguments: instead of
f(a,b,c,d,e,f i32) => a+b+c+d+e+f
t := (1,2,3,4,5,6)
r := f t.0 t.1 t.2 t.3 t.4 t.5
you can write
f(a,b,c,d,e,f i32) => a+b+c+d+e+f
t := (1,2,3,4,5,6)
r := f <|||||| t
which often correponds more naturally to the data flow through the code.
infix = -- infix operation as short-hand for 'equals'
infix |> -- pipe with one argument
This allows changing the order of function application: instead of
l := sum ([1,2,3,4].map **2)
you can write
l := [1,2,3,4].map **2 |> sum
which often correponds more naturally to the data flow through the code.
This allows changing the order of function application: instead of
l := sum ([1,2,3,4].map **2)
you can write
l := [1,2,3,4].map **2 |> sum
which often correponds more naturally to the data flow through the code.
§(A type, B type, R type, a tuple (infix ||>.A) (infix ||>.B), f Function (infix ||>.R) (infix ||>.A) (infix ||>.B)):Any => infix ||>.R
§(A
type
, B type
, R type
, a tuple (infix ||>.A) (infix ||>.B), f Function (infix ||>.R) (infix ||>.A) (infix ||>.B)):
Any =>
infix ||>.Rinfix ||> -- pipe with a two-tuple argument, destructuring the tuple into arguments
This allows changing the order of function application: instead of
f(a,b i32) => a+b
l1 := [1,2,3,4]
l2 := [4,3,2,1]
l := l1.pairs l2
you can write
l1 := [1,2,3,4]
l2 := [4,3,2,1]
l := l1.pairs l2
which often correponds more naturally to the data flow through the code.
This allows changing the order of function application: instead of
f(a,b i32) => a+b
l1 := [1,2,3,4]
l2 := [4,3,2,1]
l := l1.pairs l2
you can write
l1 := [1,2,3,4]
l2 := [4,3,2,1]
l := l1.pairs l2
which often correponds more naturally to the data flow through the code.
§(A type, B type, C type, R type, a tuple (infix |||>.A) (infix |||>.B) (infix |||>.C), f Function (infix |||>.R) (infix |||>.A) (infix |||>.B) (infix |||>.C)):Any => infix |||>.R
§(A
type
, B type
, C type
, R type
, a tuple (infix |||>.A) (infix |||>.B) (infix |||>.C), f Function (infix |||>.R) (infix |||>.A) (infix |||>.B) (infix |||>.C)):
Any =>
infix |||>.Rinfix |||> -- pipe with a three-tuple argument, destructuring the tuple into arguments
This allows changing the order of function application: instead of
f(a,b,c i32) => a+b+c
t := (1,2,3)
r := f t.0 t.1 t.2
you can write
f(a,b,c i32) => a+b+c
t := (1,2,3)
r := t |||> f
which often correponds more naturally to the data flow through the code.
This allows changing the order of function application: instead of
f(a,b,c i32) => a+b+c
t := (1,2,3)
r := f t.0 t.1 t.2
you can write
f(a,b,c i32) => a+b+c
t := (1,2,3)
r := t |||> f
which often correponds more naturally to the data flow through the code.
§(A type, B type, C type, D type, R type, a tuple (infix ||||>.A) (infix ||||>.B) (infix ||||>.C) (infix ||||>.D), f Function (infix ||||>.R) (infix ||||>.A) (infix ||||>.B) (infix ||||>.C) (infix ||||>.D)):Any => infix ||||>.R
§(A
type
, B type
, C type
, D type
, R type
, a tuple (infix ||||>.A) (infix ||||>.B) (infix ||||>.C) (infix ||||>.D), f Function (infix ||||>.R) (infix ||||>.A) (infix ||||>.B) (infix ||||>.C) (infix ||||>.D)):
Any =>
infix ||||>.Rinfix ||||> -- pipe with a four-tuple argument, destructuring the tuple into arguments
This allows changing the order of function application: instead of
f(a,b,c,d i32) => a+b+c+d
t := (1,2,3,4)
r := f t.0 t.1 t.2 t.3
you can write
f(a,b,c,d i32) => a+b+c+d
t := (1,2,3,4)
r := t ||||> f
which often correponds more naturally to the data flow through the code.
This allows changing the order of function application: instead of
f(a,b,c,d i32) => a+b+c+d
t := (1,2,3,4)
r := f t.0 t.1 t.2 t.3
you can write
f(a,b,c,d i32) => a+b+c+d
t := (1,2,3,4)
r := t ||||> f
which often correponds more naturally to the data flow through the code.
§(A type, B type, C type, D type, E type, R type, a tuple (infix |||||>.A) (infix |||||>.B) (infix |||||>.C) (infix |||||>.D) (infix |||||>.E), f Function (infix |||||>.R) (infix |||||>.A) (infix |||||>.B) (infix |||||>.C) (infix |||||>.D) (infix |||||>.E)):Any => infix |||||>.R
§(A
type
, B type
, C type
, D type
, E type
, R type
, a tuple (infix |||||>.A) (infix |||||>.B) (infix |||||>.C) (infix |||||>.D) (infix |||||>.E), f Function (infix |||||>.R) (infix |||||>.A) (infix |||||>.B) (infix |||||>.C) (infix |||||>.D) (infix |||||>.E)):
Any =>
infix |||||>.Rinfix |||||> -- pipe with a five-tuple argument, destructuring the tuple into arguments
This allows changing the order of function application: instead of
f(a,b,c,d,e i32) => a+b+c+d+e
t := (1,2,3,4,5)
r := f t.0 t.1 t.2 t.3 t.4
you can write
f(a,b,c,d,e i32) => a+b+c+d+e
t := (1,2,3,4,5)
r := t |||||> f
which often correponds more naturally to the data flow through the code.
This allows changing the order of function application: instead of
f(a,b,c,d,e i32) => a+b+c+d+e
t := (1,2,3,4,5)
r := f t.0 t.1 t.2 t.3 t.4
you can write
f(a,b,c,d,e i32) => a+b+c+d+e
t := (1,2,3,4,5)
r := t |||||> f
which often correponds more naturally to the data flow through the code.
§(A type, B type, C type, D type, E type, F type, R type, a tuple (infix ||||||>.A) (infix ||||||>.B) (infix ||||||>.C) (infix ||||||>.D) (infix ||||||>.E) (infix ||||||>.F), f Function (infix ||||||>.R) (infix ||||||>.A) (infix ||||||>.B) (infix ||||||>.C) (infix ||||||>.D) (infix ||||||>.E) (infix ||||||>.F)):Any => infix ||||||>.R
§(A
type
, B type
, C type
, D type
, E type
, F type
, R type
, a tuple (infix ||||||>.A) (infix ||||||>.B) (infix ||||||>.C) (infix ||||||>.D) (infix ||||||>.E) (infix ||||||>.F), f Function (infix ||||||>.R) (infix ||||||>.A) (infix ||||||>.B) (infix ||||||>.C) (infix ||||||>.D) (infix ||||||>.E) (infix ||||||>.F)):
Any =>
infix ||||||>.Rinfix ||||||> -- pipe with a six-tuple argument, destructuring the tuple into arguments
This allows changing the order of function application: instead of
f(a,b,c,d,e,f i32) => a+b+c+d+e+f
t := (1,2,3,4,5,6)
r := f t.0 t.1 t.2 t.3 t.4 t.5
you can write
f(a,b,c,d,e,f i32) => a+b+c+d+e+f
t := (1,2,3,4,5,6)
r := t ||||||> f
which often correponds more naturally to the data flow through the code.
This allows changing the order of function application: instead of
f(a,b,c,d,e,f i32) => a+b+c+d+e+f
t := (1,2,3,4,5,6)
r := f t.0 t.1 t.2 t.3 t.4 t.5
you can write
f(a,b,c,d,e,f i32) => a+b+c+d+e+f
t := (1,2,3,4,5,6)
r := t ||||||> f
which often correponds more naturally to the data flow through the code.
is `a` contained in `Set` `s`?
This should usually be called using type inference as in
my_set := set_of ["A","B","C"]
say ("B" ∈ my_set)
say ("D" ∈ my_set)
This should usually be called using type inference as in
my_set := set_of ["A","B","C"]
say ("B" ∈ my_set)
say ("D" ∈ my_set)
is `a` not contained in `Set` `s`?
This should usually be called using type inference as in
my_set := set_of ["A","B","C"]
say ("B" ∉ my_set)
say ("D" ∉ my_set)
This should usually be called using type inference as in
my_set := set_of ["A","B","C"]
say ("B" ∉ my_set)
say ("D" ∉ my_set)
infix ≟ -- infix operation as short-hand for 'equals'
infix ≤ -- infix operation as short-hand for 'lteq'
three-way comparison between this and other.
result is < 0 if this < other
result is > 0 if this > other
result is = 0 if this = other
result is < 0 if this < other
result is > 0 if this > other
result is = 0 if this = other
convenience routine to create a list from head h and lazy tail t.
Use say to print `s` to stdout and return `s`.
In contrast to `say`, `log` returns its argument
which makes `log` compose better in same cases.
In contrast to `say`, `log` returns its argument
which makes `log` compose better in same cases.
lteq -- feature that compares two values using the lteq relation
defined in their type
defined in their type
§(MM type :container.Mutable_Map memoize.T memoize.R, T type, R type, f Unary memoize.R memoize.T):Any => Unary memoize.R memoize.T
§(MM
type
:container.Mutable_Map memoize.T memoize.R, T type
, R type
, f Unary memoize.R memoize.T):
Any =>
Unary memoize.R memoize.Tmemoize `f`.
wraps f so that f will only be called once for every unique input.
The term "memoization" was coined by Donald Michie in 1968 and
is derived from the Latin word "memorandum" ("to be remembered"),
usually truncated as "memo" in American English, and thus carries
the meaning of "turning a function into something to be remembered".
https://en.wikipedia.org/wiki/Memoization
example:
wraps f so that f will only be called once for every unique input.
The term "memoization" was coined by Donald Michie in 1968 and
is derived from the Latin word "memorandum" ("to be remembered"),
usually truncated as "memo" in American English, and thus carries
the meaning of "turning a function into something to be remembered".
https://en.wikipedia.org/wiki/Memoization
example:
create a new mutable value of type T with initial value v
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
num_option
Using this enables to write
o := num_option x
instead of
o num_option TypeOfX := x
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
Using this enables to write
o := option x
insted of
o option TypeOfX := x
outcome with 1 argument provides an short-hand to wrap a value into a
outcome
Using this enables to write
o := outcome x
instead of
o outcome TypeOfX := x
outcome
Using this enables to write
o := outcome x
instead of
o outcome TypeOfX := x
panic with no argument returns panic.env, the currently installed
panic handler.
panic handler.
panic with a msg argument calls panic.cause msg, i.e., it uses the
current panic effect to panic with the given message.
current panic effect to panic with the given message.
pedantic -- condition qualifier for conditions that are pedantic
pedantic is a condition qualifier for conditions a pedantic purist would require,
but that a more relaxed hacker would prefer to do without.
currently, pedantic always returns true.
pedantic is a condition qualifier for conditions a pedantic purist would require,
but that a more relaxed hacker would prefer to do without.
currently, pedantic always returns true.
random with no argument returns random.env, i.e., the currently installed
source of randomness.
source of randomness.
safety -- condition qualifier for conditions that are required for safety
safety is a condition qualifier that is used for conditions that are
absolutely required to ensure safety.
This must never be disabled if safety is of any concern. Applications
run with safety disabled typically have security vulnerabilities that
allow system takeover via manipulated input data.
Currently, the value of this can be controlled by setting the fuzion.safety
Java property when calling the fz tool, for example like this:
If the program is compiled, not interpreted, then the value of this option
at compile time will be used.
safety is a condition qualifier that is used for conditions that are
absolutely required to ensure safety.
This must never be disabled if safety is of any concern. Applications
run with safety disabled typically have security vulnerabilities that
allow system takeover via manipulated input data.
Currently, the value of this can be controlled by setting the fuzion.safety
Java property when calling the fz tool, for example like this:
If the program is compiled, not interpreted, then the value of this option
at compile time will be used.
say -- shortcut for io.out.println
A handy shortcut for io.out.println, output string representation of
an object followed by a line break.
A handy shortcut for io.out.println, output string representation of
an object followed by a line break.
change the currently stored exit code
state with 1 argument is short hand for a state containing unit and
initial_value
initial_value
install new state monad for type S and run r within that state monad
return result of r.
return result of r.
short-hand for getting state monad for given type in current environment
short-hand for modifying state monad for given type in current environment
short-hand for accessing state monad for given type in current environment
short-hand for setting state monad for given type in current environment
sum -- generic sum of the elements of a Sequence of numeric.
This allows summing the elements of a list, as in
l := [1,2,3]
say (sum l) # '6'
This allows summing the elements of a list, as in
l := [1,2,3]
say (sum l) # '6'
convenience routine to create a new instance of 'try T' and run 'f' in
it. The result will be an `outcome R` that, in case of success, contains
the result of `f`, or, in case of `(try T).env.raise`, contains the error.
it. The result will be an `outcome R` that, in case of success, contains
the result of `f`, or, in case of `(try T).env.raise`, contains the error.
convenience routine to create a new instance of 'try T' and run 'f' in
it. Return the result of 'f' directly or panic in case 'f' calls
'(try T).env.raise'.
it. Return the result of 'f' directly or panic in case 'f' calls
'(try T).env.raise'.
Get the Type instance corresponding to a given type
The result of `type_as_value x` is the same as `x.type`.
Internally, Fuzion's front end implements `x.type` using
`type_as_value x`. The middle end then replaces calls to
`type_as_value` by `T`'s type clazz.
The result of `type_as_value x` is the same as `x.type`.
Internally, Fuzion's front end implements `x.type` using
`type_as_value x`. The middle end then replaces calls to
`type_as_value` by `T`'s type clazz.
universe feature to determine the compile-time type of an expression.
This is to be called without an actual type passed to `T`, but `T` should be
inferred from the actual value argument `_`.
The value argument is evaluated and ignored.
The result is the type of the value argument boxed into a ref value and returned
as a value of type `Type`.
examples:
`type_of "bla"` is `String`
`type_of (panic "***")` will terminate
This is to be called without an actual type passed to `T`, but `T` should be
inferred from the actual value argument `_`.
The value argument is evaluated and ignored.
The result is the type of the value argument boxed into a ref value and returned
as a value of type `Type`.
examples:
`type_of "bla"` is `String`
`type_of (panic "***")` will terminate
universe feature to determine the compile-time type of an expression.
This is to be called without an actual type passed to `T`, but `T` should be
inferred from the result type of the actual value argument `_`.
The function passed as value argument is ignored, it is not called.
The result is the result type of the value argument boxed into a ref value and
returned as a value of type `Type`.
examples:
`type_of_lazy ()->"bla"` is Type of `String`
`type_of_lazy ()->(panic "***")` is Type of `void`.
NYI: Fuzion should have better syntax sugar for lazy value arguments such that
we do not need the `()->` prefix to create a lambda. Then, `type_of` could
have a lazy argument and `type_of_lazy` could be removed.
This is to be called without an actual type passed to `T`, but `T` should be
inferred from the result type of the actual value argument `_`.
The function passed as value argument is ignored, it is not called.
The result is the result type of the value argument boxed into a ref value and
returned as a value of type `Type`.
examples:
`type_of_lazy ()->"bla"` is Type of `String`
`type_of_lazy ()->(panic "***")` is Type of `void`.
NYI: Fuzion should have better syntax sugar for lazy value arguments such that
we do not need the `()->` prefix to create a lambda. Then, `type_of` could
have a lazy argument and `type_of_lazy` could be removed.
get a unique id > 0
this can be used to add a unique identifier to compare instances.
sine there are 2^64-1 possible values, you can safely assume that these are
in fact unique. Assuming one unique id is consumed every nanosecond, it
would take more than 500 years before we run out of values
(2^64/10^9/3600/24/365.25).
this can be used to add a unique identifier to compare instances.
sine there are 2^64-1 possible values, you can safely assume that these are
in fact unique. Assuming one unique id is consumed every nanosecond, it
would take more than 500 years before we run out of values
(2^64/10^9/3600/24/365.25).
yak -- shortcut for io.out.print
A handy shortcut for io.out.print, output string representation of
an object, do not add a line break at the end.
The term 'yak' was taken from the expression 'Yakety Yak' as in the
song by The Coasters.
A handy shortcut for io.out.print, output string representation of
an object, do not add a line break at the end.
The term 'yak' was taken from the expression 'Yakety Yak' as in the
song by The Coasters.
Reference Types
Cons -- feature used to define abstract Cons cells
A Cons is a ref to a cell that contains a head and a tail
A Cons is a ref to a cell that contains a head and a tail
Const_String -- feature used for string constants in Fuzion source code
Const_String cannot be called directly, instances are created implicitly by the
backend.
Const_String cannot be called directly, instances are created implicitly by the
backend.
Exit_Handler -- abstract exit
Function -- generic function with arbitrary number of arguments and result
R is the result type of the function, A are the argument types of the function
R is the result type of the function, A are the argument types of the function
Lazy has special compiler support.
It can be used to require lazy evaluation of arguments.
A good example is `or` in bool:
In the following example the expression
`4+5>10` will never be executed:
It can be used to require lazy evaluation of arguments.
A good example is `or` in bool:
In the following example the expression
`4+5>10` will never be executed:
Monoid -- parent feature for monoids
A monoid is an abstraction for a type with an associative operation and
an identity element. Examples are (integers/infix +/0), (float/infix *,1),
(string/concat/""), etc.
A monoid is an abstraction for a type with an associative operation and
an identity element. Examples are (integers/infix +/0), (float/infix *,1),
(string/concat/""), etc.
Random_Handler -- abstract source of random numbers
This provides the random number input to be used by the 'random' effect.
Implementation may be dumb sequences of pseudo-random numbers or high-quality
cryptographic random number generators
A Random_Handler contains an immutable state, repeated calls to 'get' result
in the same value. To produce a sequence of different random numbers, 'next'
must be used to create a new instance of 'Random_Handler' before 'get' can be
used to obtain the new random number.
This provides the random number input to be used by the 'random' effect.
Implementation may be dumb sequences of pseudo-random numbers or high-quality
cryptographic random number generators
A Random_Handler contains an immutable state, repeated calls to 'get' result
in the same value. To produce a sequence of different random numbers, 'next'
must be used to create a new instance of 'Random_Handler' before 'get' can be
used to obtain the new random number.
Sequence -- ancestor for features that can be converted to a 'list'
Sequences are empty, finite or infinite ordered collections of instances
of a given type. Sequences may calculate elements lazily on demand.
Sequence is a 'ref' type, i.e., different sub-features may be assigned
to a field of type 'Sequence'.
Heirs of Sequence must implement 'as_list'.
Sequences are empty, finite or infinite ordered collections of instances
of a given type. Sequences may calculate elements lazily on demand.
Sequence is a 'ref' type, i.e., different sub-features may be assigned
to a field of type 'Sequence'.
Heirs of Sequence must implement 'as_list'.
string -- immutable sequences of utf8 encoded unicode characters
Type -- parent feature of all type features
type features 'f.type' are declared implicitly for every feature f.
Type features do not contain state, they are unit types.
All type features inherit directly (Any.type) or indirectly (all
others type features) from this feature.
type features 'f.type' are declared implicitly for every feature f.
Type features do not contain state, they are unit types.
All type features inherit directly (Any.type) or indirectly (all
others type features) from this feature.
Unary -- function that takes exactly one argument and returns a result
T is the result type of the function, U is the argument type of the function
For unary functions, function composition is possible if the result type of
the first function matches the argument type of the second function.
T is the result type of the function, U is the argument type of the function
For unary functions, function composition is possible if the result type of
the first function matches the argument type of the second function.
Value Types
feature to signal an abort of a computation.
contains the final value of a computation.
used e.g. in Sequence.reduce
contains the final value of a computation.
used e.g. in Sequence.reduce
array -- one-dimensional immutable array
This is the result type of array(type, i32, i32 -> T) which creates an
initialized immutable array
Note: This uses dummy unit-type args to avoid
name clash with routine array(T,length,init).
This is the result type of array(type, i32, i32 -> T) which creates an
initialized immutable array
Note: This uses dummy unit-type args to avoid
name clash with routine array(T,length,init).
array(length0, length1) -- two-dimensional immutable array
array provides two-dimensional immutable arrays. These are actually
one-dimensional immutable arrays with an additional access function with
two index parameters.
array provides two-dimensional immutable arrays. These are actually
one-dimensional immutable arrays with an additional access function with
two index parameters.
array(length0, length1, length2) -- three-dimensional immutable array
array provides three-dimensional immutable arrays. These are actually
one-dimensional immutable arrays with an additional access function with
three index parameters.
array provides three-dimensional immutable arrays. These are actually
one-dimensional immutable arrays with an additional access function with
three index parameters.
bitset -- persistent set of unsigned integers
bool -- Standard Fuzion type 'bool'
We need to apologize to George Boole for crippling his name a bit,
just to safe us from typing one more letter. But at least we stop
here and do not use boo, bo or similar.
bool is a choice type that can either be TRUE of FALSE.
Note that 'TRUE' and 'FALSE' themselves are not of type 'bool'.
Routines 'true' and 'false' are the preferred way to get a constant
value of type 'bool'.
We need to apologize to George Boole for crippling his name a bit,
just to safe us from typing one more letter. But at least we stop
here and do not use boo, bo or similar.
bool is a choice type that can either be TRUE of FALSE.
Note that 'TRUE' and 'FALSE' themselves are not of type 'bool'.
Routines 'true' and 'false' are the preferred way to get a constant
value of type 'bool'.
choice -- feature used for choice types
choice types provide algebraic sum types of all the generic arguments
provided to choice. A instance of a choice type is a tagged union of
the types provided as actual generic type parameters. This concept is
also called variant, sum type or coproduct in other contexts.
Syntactic sugar of the Fuzion language permits an alternative notation
for choice types with actual generics as follows
A | B | C | ...
which is equivalent to
choice A B C ...
The parser will directly convert the first notation into a choice type
with actual generics.
A field of choice type can be assigned a value of the same choice type
or of any of the actual generic type arguments provided to the choice
feature.
Two choice types choice A B and choice B A that differ only in the order
of their actual generic arguments are treated as different types.
Named choice types can be constructed through inheritance, i.e.,
C : choice A B is {}
creates a choice type of A and B with the name C. Two named choice types
D and E that inherit from choice with the same actual generic arguments in
the same order are nevertheless different types and their values are not
assignable to one another.
Named choice types may declare or inherit additional inner features as long
as these features are not fields. Also, declared inner features must not
build a closure that accesses outer features. Additional parents must be
unit types, i.e., they must not declare fields nor access features of any
of their outer features.
Note that all types provided must be distinct, it is not possible to
repeat the same type as in choice i32 i32 or float | float. If a sum
type of two or more equal types is desired, these types must first be
wrapped into a new type as illustrated in the following example:
Say we want to store a temperature that is given as a 32 bit integer
in degrees centigrade or degrees Fahrenheit. So we define two wrapper
features
centigrade(degrees i32) is {}
fahrenheit(degrees i32) is {}
Now we define the choice type using the wrapped i32 types, which are
distinct:
has_fever(temp centigrade | fahrenheit) bool is ...
When passing arguments to this feature, we need to wrap them accordingly:
has_fever (centigrade 37)
has_fever (fahrenheit 99)
When matching the choice type, we use the wrapper types and access the
argument field 'degrees' to access the i32 stored inside
match temp
NYI: Once Fuzion's match expression supports destructuring as well, we should
be able to extract the degrees directly as in
match temp
A choice type with no actual generic arguments is isomorphic to 'void', i.e, it
is a type that has an empty set of possible values.
choice types provide algebraic sum types of all the generic arguments
provided to choice. A instance of a choice type is a tagged union of
the types provided as actual generic type parameters. This concept is
also called variant, sum type or coproduct in other contexts.
Syntactic sugar of the Fuzion language permits an alternative notation
for choice types with actual generics as follows
A | B | C | ...
which is equivalent to
choice A B C ...
The parser will directly convert the first notation into a choice type
with actual generics.
A field of choice type can be assigned a value of the same choice type
or of any of the actual generic type arguments provided to the choice
feature.
Two choice types choice A B and choice B A that differ only in the order
of their actual generic arguments are treated as different types.
Named choice types can be constructed through inheritance, i.e.,
C : choice A B is {}
creates a choice type of A and B with the name C. Two named choice types
D and E that inherit from choice with the same actual generic arguments in
the same order are nevertheless different types and their values are not
assignable to one another.
Named choice types may declare or inherit additional inner features as long
as these features are not fields. Also, declared inner features must not
build a closure that accesses outer features. Additional parents must be
unit types, i.e., they must not declare fields nor access features of any
of their outer features.
Note that all types provided must be distinct, it is not possible to
repeat the same type as in choice i32 i32 or float | float. If a sum
type of two or more equal types is desired, these types must first be
wrapped into a new type as illustrated in the following example:
Say we want to store a temperature that is given as a 32 bit integer
in degrees centigrade or degrees Fahrenheit. So we define two wrapper
features
centigrade(degrees i32) is {}
fahrenheit(degrees i32) is {}
Now we define the choice type using the wrapped i32 types, which are
distinct:
has_fever(temp centigrade | fahrenheit) bool is ...
When passing arguments to this feature, we need to wrap them accordingly:
has_fever (centigrade 37)
has_fever (fahrenheit 99)
When matching the choice type, we use the wrapper types and access the
argument field 'degrees' to access the i32 stored inside
match temp
NYI: Once Fuzion's match expression supports destructuring as well, we should
be able to extract the degrees directly as in
match temp
A choice type with no actual generic arguments is isomorphic to 'void', i.e, it
is a type that has an empty set of possible values.
composition -- a collection of features for function composition
see https://mlochbaum.github.io/BQN/tutorial/combinator.html
Talk at Strange Loop 2016 by Amar Shah: Point-Free or Die: Tacit Programming in Haskell and Beyond
https://www.youtube.com/watch?v=seVSlKazsNk
Talk at CppNorth 2023 by Conor Hoekstra: Function Composition in Programming Languages - Conor Hoekstra - CppNorth 2023
https://www.youtube.com/watch?v=JELcdZLre3s
Paper by Conor Hoekstra: Combinatory Logic and Combinators in Array Languages
https://web.archive.org/web/20220617020347id_/https://dl.acm.org/doi/pdf/10.1145/3520306.3534504
BQN tutorial: https://mlochbaum.github.io/BQN/tutorial/index.html
Talk for Fullstack Academy by Gabriel Lebec: Lambda Calculus - Fundamentals of Lambda Calculus & Functional
Pragramming in JavaScript
https://www.youtube.com/watch?v=3VQ382QG-y4
David C Keenan
To Dissect a Mockingbird: A Graphical Notation for the Lambda Calculus with Animated Reduction
https://dkeenan.com/Lambda/
Haskell package data.aviary.birds:
https://hackage.haskell.org/package/data-aviary-0.4.0/docs/Data-Aviary-Birds.html
Bird names from Raymond M Smullyan. 2000. To Mock a Mockingbird: and other
logic puzzles including an amazing adventure in combinatory logic. Oxford
University Press, USA.
Combinator birds: https://www.angelfire.com/tx4/cus/combinator/birds.html
see https://mlochbaum.github.io/BQN/tutorial/combinator.html
Talk at Strange Loop 2016 by Amar Shah: Point-Free or Die: Tacit Programming in Haskell and Beyond
https://www.youtube.com/watch?v=seVSlKazsNk
Talk at CppNorth 2023 by Conor Hoekstra: Function Composition in Programming Languages - Conor Hoekstra - CppNorth 2023
https://www.youtube.com/watch?v=JELcdZLre3s
Paper by Conor Hoekstra: Combinatory Logic and Combinators in Array Languages
https://web.archive.org/web/20220617020347id_/https://dl.acm.org/doi/pdf/10.1145/3520306.3534504
BQN tutorial: https://mlochbaum.github.io/BQN/tutorial/index.html
Talk for Fullstack Academy by Gabriel Lebec: Lambda Calculus - Fundamentals of Lambda Calculus & Functional
Pragramming in JavaScript
https://www.youtube.com/watch?v=3VQ382QG-y4
David C Keenan
To Dissect a Mockingbird: A Graphical Notation for the Lambda Calculus with Animated Reduction
https://dkeenan.com/Lambda/
Haskell package data.aviary.birds:
https://hackage.haskell.org/package/data-aviary-0.4.0/docs/Data-Aviary-Birds.html
Bird names from Raymond M Smullyan. 2000. To Mock a Mockingbird: and other
logic puzzles including an amazing adventure in combinatory logic. Oxford
University Press, USA.
Combinator birds: https://www.angelfire.com/tx4/cus/combinator/birds.html
cons -- feature used to define simple, non-lazy Cons cells
A cons is a cell that contains a head and a tail
A cons is a cell that contains a head and a tail
container -- unit feature to group features that provide some kind of
data structure to store and retrieve values
data structure to store and retrieve values
effect -- abstract parent feature for effects
effect provides a means to perform effectful operations. Instances
of effect are instated in the current environment while their code is
executed. The code may perform operations of the instated effect
via <type>.env. These operations may either return normally (resume) or
abort the current computation, i.e., return directly to the call that
instated the effect.
Effects are identified by their type, including any actual type parameters.
Effect instances must be assignable to the effect type. This means that if
the effect type is a value type, the instance must be an instance of exactly
that type while if the effect type is a ref type, the instance might be of
a type that inherits from the effect type that is --possibly after boxing--
assignable to that type.
Effect operations may replace an instated instance by a new value.
This gives operations a means to become stateful.
In case an effect performs an abort, the code the effect was instated for
will be abandoned and the function passed via tha `def` argument to
`instate` will be used to produce a result from the last effect instance.
Effects may redefine the `finally` feature that is executed directly after
an instated effect was removed, independent of the reason why it is removed.
This means, finally is executed after code running in the effect returns
normally, after a call to an operation that results in an abort or when
a surrounding effect is aborted.
effect provides a means to perform effectful operations. Instances
of effect are instated in the current environment while their code is
executed. The code may perform operations of the instated effect
via <type>.env. These operations may either return normally (resume) or
abort the current computation, i.e., return directly to the call that
instated the effect.
Effects are identified by their type, including any actual type parameters.
Effect instances must be assignable to the effect type. This means that if
the effect type is a value type, the instance must be an instance of exactly
that type while if the effect type is a ref type, the instance might be of
a type that inherits from the effect type that is --possibly after boxing--
assignable to that type.
Effect operations may replace an instated instance by a new value.
This gives operations a means to become stateful.
In case an effect performs an abort, the code the effect was instated for
will be abandoned and the function passed via tha `def` argument to
`instate` will be used to produce a result from the last effect instance.
Effects may redefine the `finally` feature that is executed directly after
an instated effect was removed, independent of the reason why it is removed.
This means, finally is executed after code running in the effect returns
normally, after a call to an operation that results in an abort or when
a surrounding effect is aborted.
error represents an error condition described by a message string
NYI: Future versions of error might be equipped with a stack trace if
debugging is enabled
NYI: Future versions of error might be equipped with a stack trace if
debugging is enabled
f32 -- 32 bit floating point values
f32 are binary32-numbers as defined in the IEEE 754-2019 standard, see
https://ieeexplore.ieee.org/servlet/opac?punumber=8766227
f32 are binary32-numbers as defined in the IEEE 754-2019 standard, see
https://ieeexplore.ieee.org/servlet/opac?punumber=8766227
f64 -- 64 bit floating point values
f64 are binary64-numbers as defined in the IEEE 754-2019 standard, see
https://ieeexplore.ieee.org/servlet/opac?punumber=8766227
f64 are binary64-numbers as defined in the IEEE 754-2019 standard, see
https://ieeexplore.ieee.org/servlet/opac?punumber=8766227
boolean value "false"
Note that this value is of unit type >>FALSE<<, not of type >>bool<<, i.e.,
if it is used for type inference as in
my_boolean := FALSE
you will get a variable of type >>FALSE<<, it will not be possible to assign
>>TRUE<< to it. You can use >>false<< as an alternative to get type >>bool<<.
Note that this value is of unit type >>FALSE<<, not of type >>bool<<, i.e.,
if it is used for type inference as in
my_boolean := FALSE
you will get a variable of type >>FALSE<<, it will not be possible to assign
>>TRUE<< to it. You can use >>false<< as an alternative to get type >>bool<<.
float -- floating point values
float is the abstract parent of concrete floating point features such as
f32 or f64.
float is the abstract parent of concrete floating point features such as
f32 or f64.
type of the reference to the cell that holds a value of type T which can be updated
using the handles interface
using the handles interface
§(T type, X type):oneway_monad handles.X, handles handles.T handles.X is [Contains abstract features]
§(T
type
, X type
):
oneway_monad handles.X, handles handles.T handles.X is
[Contains abstract features]
handles 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.
an example of using handles is shown below, handle (singular) is an
alias to initialize a new handle with the given initial value. handle0 T
is the type that allows passing around handles.
the example also shows the difference between handles and the mutate effect:
while both provide a way to store and update a mutable value, a handle can be
passed around between features. meanwhile, mutables are not a type that can be
given to other features, only values can. handles essentially provide an
abstraction of pointers, implemented natively in Fuzion.
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.
an example of using handles is shown below, handle (singular) is an
alias to initialize a new handle with the given initial value. handle0 T
is the type that allows passing around handles.
the example also shows the difference between handles and the mutate effect:
while both provide a way to store and update a mutable value, a handle can be
passed around between features. meanwhile, mutables are not a type that can be
given to other features, only values can. handles essentially provide an
abstraction of pointers, implemented natively in Fuzion.
§(T type, X type):oneway_monad handles2.X, handles2 handles2.T handles2.X is [Contains abstract features]
§(T
type
, X type
):
oneway_monad handles2.X, handles2 handles2.T handles2.X is
[Contains abstract features]
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.
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.
has_interval -- feature for integers that can define an interval
i16 -- 16-bit signed integer values
i32 -- 32-bit signed integer values
i64 -- 64-bit signed integer values
i8 -- 8-bit signed integer values
int -- signed integer values of arbitrary size
integer -- abstract ancestor of integer numbers
integer is the abstract ancestor of integer numbers that provides operations
from numeric plus a division remainder operation %, bitwise logical operations,
shift operations and gcd. Also, integers can be used to build fractions.
integer is the abstract ancestor of integer numbers that provides operations
from numeric plus a division remainder operation %, bitwise logical operations,
shift operations and gcd. Also, integers can be used to build fractions.
internationalization -- unit feature to group features related to specific
geographical, political, or cultural regions such as formatting of dates,
numbers, currencies, etc.
geographical, political, or cultural regions such as formatting of dates,
numbers, currencies, etc.
An interval `from..through` that includes `from`, `from+step`, `from+step+step`,
etc. up to and including `through`.
In case step is positive (negative), the first value larger (smaller) than
through will not be included.
In case `step.sign = (from ⋄ through).sign`, this `Set` is empty, e.g.,
`interval 1 2 -1` and `interval 2 1 1` are both empty.
etc. up to and including `through`.
In case step is positive (negative), the first value larger (smaller) than
through will not be included.
In case `step.sign = (from ⋄ through).sign`, this `Set` is empty, e.g.,
`interval 1 2 -1` and `interval 2 1 1` are both empty.
list -- feature used to define lists
list provides an abstract type for a sequence of elements of the same type.
A list sequence may be empty and contain no element, or it may have a fixed
or even an infinite number of elements.
The core of the implementation of an actual list lies in the implementation
of the actual Cons cell a non-empty list consists of.
Lists can typically be traversed using only immutable data. This makes them
more flexible than streams that require to store and update their state.
A list is immutable, so it can be reused and shared between threads.
Due to the nature of lists, in which many Cons cells are used, a list
may require more (heap) allocation than an array.
list provides an abstract type for a sequence of elements of the same type.
A list sequence may be empty and contain no element, or it may have a fixed
or even an infinite number of elements.
The core of the implementation of an actual list lies in the implementation
of the actual Cons cell a non-empty list consists of.
Lists can typically be traversed using only immutable data. This makes them
more flexible than streams that require to store and update their state.
A list is immutable, so it can be reused and shared between threads.
Due to the nature of lists, in which many Cons cells are used, a list
may require more (heap) allocation than an array.
lock_free -- unit type feature grouping lock-free
data structures and algorithms
data structures and algorithms
monad -- generic monad
A monad in X is just a monoid in the category of endofunctors of X, with
product × replaced by composition of endofunctors and unit set by the
identity endofunctor.
Don't be scared, in Java terms: A monad is a means to compose functions
applied to generic types.
A monad in X is just a monoid in the category of endofunctors of X, with
product × replaced by composition of endofunctors and unit set by the
identity endofunctor.
Don't be scared, in Java terms: A monad is a means to compose functions
applied to generic types.
mutate -- an effect that permits creation and mutation of mutable values.
This effect is typically used to work with mutable values. You can create
a mutable value as follows
v := mutate.env.new i32 42
and then modify it using
v <- 666
To read it, call 'get' as in
say "v is {v.get}"
Convenience feature 'mut' and type inference allow the creation to be
written as
v := mut 42
NYI: syntax sugar to read mutable field using
w := v + 1
instead of
w := v.get + 1
is not supported yet.
This effect is typically used to work with mutable values. You can create
a mutable value as follows
v := mutate.env.new i32 42
and then modify it using
v <- 666
To read it, call 'get' as in
say "v is {v.get}"
Convenience feature 'mut' and type inference allow the creation to be
written as
v := mut 42
NYI: syntax sugar to read mutable field using
w := v + 1
instead of
w := v.get + 1
is not supported yet.
nil -- value for options that are not present
This is a unit type that is preferred to represent instances that are
not present, e.g, in an option.
This is a unit type that is preferred to represent instances that are
not present, e.g, in an option.
§(T type):switch num_option.T, nil,monad num_option.T, num_option num_option.T is [Contains abstract features]
§(T
type
):
switch num_option.T, nil,monad num_option.T, num_option num_option.T is
[Contains abstract features]
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.
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.
numeric -- parent of all numeric features
executes `f` only the first time when
calling `get` caching its result.
calling `get` caching its result.
§(A type, OMA type :oneway_monad oneway_monad.A oneway_monad.OMA):monad oneway_monad.A, oneway_monad.OMA,effect is [Contains abstract features]
§(A
type
, OMA type
:oneway_monad oneway_monad.A oneway_monad.OMA):
monad oneway_monad.A, oneway_monad.OMA,effect is
[Contains abstract features]
oneway_monad -- heir feature of all one-way monads.
oneway_monad is the heir feature of all one-way monads. A one-way monad is
a monadic feature that can be accessed as a effect through the environment
and that will be replaced in the environment whenever a new instance is
created. Alternatively, this can be used as a monad that wraps around a
function result type A.
oneway_monad is the heir feature of all one-way monads. A one-way monad is
a monadic feature that can be accessed as a effect through the environment
and that will be replaced in the environment whenever a new instance is
created. Alternatively, this can be used as a monad that wraps around a
function result type A.
enum of the mode argument.
option -- feature wrapping a value or nothing
option represents an optional value of type T
option represents an optional value of type T
§(T type):switch outcome.T, error,monad outcome.T, outcome outcome.T is [Contains abstract features]
§(T
type
):
switch outcome.T, error,monad outcome.T, outcome outcome.T is
[Contains abstract features]
outcome -- result type for functions that may return an error
outcome is a choice type that represents the result of a routine that
may either produce something useful or fail producing an error condition.
Several error conditions are needed if there are several very different
reasons for an operation to fail, e.g.
get_data (u User, t Type) outcome data IO_Error Permission_Error is
read_file t Type outcome data IO_Error is
Note that 'outcome data IO_Error' is not assignment compatible with
'outcome data IO_Error Permission_Error', it has to be unwrapped first.
This unwrapping, however, requires very little boilerplate, it is done
using the '?' on the result of the call to 'read_file': This unwraps
'outcome data IO_Error' into 'IO_Error', which would be returned abruptly,
and 'data', which would be returned normally. Both are assignment
compatible to 'outcome data IO_Error Permission_Error', so everything
is fine.
outcome is a choice type that represents the result of a routine that
may either produce something useful or fail producing an error condition.
Several error conditions are needed if there are several very different
reasons for an operation to fail, e.g.
get_data (u User, t Type) outcome data IO_Error Permission_Error is
read_file t Type outcome data IO_Error is
Note that 'outcome data IO_Error' is not assignment compatible with
'outcome data IO_Error Permission_Error', it has to be unwrapped first.
This unwrapping, however, requires very little boilerplate, it is done
using the '?' on the result of the call to 'read_file': This unwraps
'outcome data IO_Error' into 'IO_Error', which would be returned abruptly,
and 'data', which would be returned normally. Both are assignment
compatible to 'outcome data IO_Error Permission_Error', so everything
is fine.
panic -- effect that terminates a computation in panic
property -- unit feature to group features that can be inherited by other
features if they fulfill certain properties such as defining a partial
order
features if they fulfill certain properties such as defining a partial
order
quantor -- unit type feature containing quantors ∀ and ∃.
quantor provides for_all and exists-quantors for use in contracts qualified
for analysis.
quantor provides for_all and exists-quantors for use in contracts qualified
for analysis.
state -- represent a state using a monad
this can be used both as plain or as a oneway monad to store a state
in a way orthogonal to the actual computation.
this can be used both as plain or as a oneway monad to store a state
in a way orthogonal to the actual computation.
switch is the parent feature of all choices
that encode success and failure,
e.g. option (something/nil)
that encode success and failure,
e.g. option (something/nil)
terminal -- unit type feature providing ANSI terminal control codes
Terminal provides constants to modify the text output style and color.
Thanks to Bruno Penteado who collected these codes at
https://gist.github.com/bcap/5682077#file-terminal-control-sh
but this also includes input from
https://en.wikipedia.org/wiki/ANSI_escape_code
and
man console_codes
Terminal provides constants to modify the text output style and color.
Thanks to Bruno Penteado who collected these codes at
https://gist.github.com/bcap/5682077#file-terminal-control-sh
but this also includes input from
https://en.wikipedia.org/wiki/ANSI_escape_code
and
man console_codes
transducers map one reducing function to
another reducing function. this enables composition
and reuse of map, filter, reduce etc.
see https://clojure.org/reference/transducers
for in depth information on transducers
usage example:
human(age i32) is
td := (transducer (Sequence i32) i32 human).type
ages := td.map (x -> x.age)
gt_ten := td.filter (x -> x > 10)
xf := ages ∘ gt_ten
say ([human 4, human 12, human 30].into xf) # [12,30]
TA result type
B input type
C transduced type
another reducing function. this enables composition
and reuse of map, filter, reduce etc.
see https://clojure.org/reference/transducers
for in depth information on transducers
usage example:
human(age i32) is
td := (transducer (Sequence i32) i32 human).type
ages := td.map (x -> x.age)
gt_ten := td.filter (x -> x > 10)
xf := ages ∘ gt_ten
say ([human 4, human 12, human 30].into xf) # [12,30]
TA result type
B input type
C transduced type
boolean value "true"
Note that this value is of unit type >>TRUE<<, not of type >>bool<<, i.e.,
if it is used for type inference as in
my_boolean := TRUE
you will get a variable of type >>TRUE<<, it will not be possible to assign
>>FALSE<< to it. You can use >>true<< as an alternative to get type >>bool<<.
Note that this value is of unit type >>TRUE<<, not of type >>bool<<, i.e.,
if it is used for type inference as in
my_boolean := TRUE
you will get a variable of type >>TRUE<<, it will not be possible to assign
>>FALSE<< to it. You can use >>true<< as an alternative to get type >>bool<<.
try -- simple exception effect
try provides an operation 'cause' that immediately stops execution and
returns an 'error' wrapped in an 'outcome'.
try provides an operation 'cause' that immediately stops execution and
returns an 'error' wrapped in an 'outcome'.
tuple -- feature used to define tuple types
tuple types provide algebraic product types of all the generic arguments
provided to tuple.
The values within a tuple 'tuple A B C' can be accessed via the tuple's
argument field 'values' followed by a selector referring to the generic
argument's position: 'values.0', 'values.1' and 'values.2', respectively.
Syntactic sugar of the Fuzion language permits an alternative notation
to create values of tuple types as follows
t := (a, b, c, ... )
is equivalent to
t := tuple a b c ...
The actual generic types are inferred from the static types of the values
'a', 'b', 'c', ... the tuple is created from.
Similarly, syntactic sugar for the destructuring of tuples can be used
to access the values as in
(a, b, c, ...) := t
In destructurings, we can denote values we are not interested in using
'_' as in
(_, b) := ("first", "second")
which will set 'b' to '"second"' and drop the first element of the tuple.
As an example, say we want to identify a person by its name and its age,
so we can define
a := ("Alice" , 11)
b := ("Bob" , 22)
c := ("Claire", 33)
Then, we could extract Bob's age using
(_, age) := b
or Claire's name using
(name, _) := c
Destructuring also works for general features, e.g.
point (x,y i32) is {}
p := point 3, 4
(px, py) := p # will set px to 3 and py to 4
and the destructured value can then be used to create a tuple
t := (px, py) # will create tuple<i32,i32> instance
however, tuples are not assignment compatible with general features even
if they would destructure into the same types, i.e.,
u tuple i32 i32 = p # will cause compile time error
q point = (7, 12) # will cause compile time error
The unit tuple '()' can be used as a short-hand to create the empty tuple
'tuple'. The empty tuple can be destructured like any other tuple
using
() := ()
even though this has no effect.
An instance of the single tuple 'tuple A' with sole element 'a' can not
be created using syntactic sugar '(a)', this will produce the plain
value of 'a' instead. However, destructuring of a single tuple is possible:
(a0) := tuple a
which is equivalent to
a0 := a
NYI: A single tuple 'tuple A' is currently not assignment compatible with
type 'A', which would make handling of general tuples easier.
tuples and destructuring can be used to swap two elements or create a
permutation as in
(a, b) := (b, a)
(o, t, a, n) := (n, a, t, o)
A tuple type with no actual generic arguments is isomorphic to 'unit', i.e, it
is a type that has only one single value: '()'.
tuple types provide algebraic product types of all the generic arguments
provided to tuple.
The values within a tuple 'tuple A B C' can be accessed via the tuple's
argument field 'values' followed by a selector referring to the generic
argument's position: 'values.0', 'values.1' and 'values.2', respectively.
Syntactic sugar of the Fuzion language permits an alternative notation
to create values of tuple types as follows
t := (a, b, c, ... )
is equivalent to
t := tuple a b c ...
The actual generic types are inferred from the static types of the values
'a', 'b', 'c', ... the tuple is created from.
Similarly, syntactic sugar for the destructuring of tuples can be used
to access the values as in
(a, b, c, ...) := t
In destructurings, we can denote values we are not interested in using
'_' as in
(_, b) := ("first", "second")
which will set 'b' to '"second"' and drop the first element of the tuple.
As an example, say we want to identify a person by its name and its age,
so we can define
a := ("Alice" , 11)
b := ("Bob" , 22)
c := ("Claire", 33)
Then, we could extract Bob's age using
(_, age) := b
or Claire's name using
(name, _) := c
Destructuring also works for general features, e.g.
point (x,y i32) is {}
p := point 3, 4
(px, py) := p # will set px to 3 and py to 4
and the destructured value can then be used to create a tuple
t := (px, py) # will create tuple<i32,i32> instance
however, tuples are not assignment compatible with general features even
if they would destructure into the same types, i.e.,
u tuple i32 i32 = p # will cause compile time error
q point = (7, 12) # will cause compile time error
The unit tuple '()' can be used as a short-hand to create the empty tuple
'tuple'. The empty tuple can be destructured like any other tuple
using
() := ()
even though this has no effect.
An instance of the single tuple 'tuple A' with sole element 'a' can not
be created using syntactic sugar '(a)', this will produce the plain
value of 'a' instead. However, destructuring of a single tuple is possible:
(a0) := tuple a
which is equivalent to
a0 := a
NYI: A single tuple 'tuple A' is currently not assignment compatible with
type 'A', which would make handling of general tuples easier.
tuples and destructuring can be used to swap two elements or create a
permutation as in
(a, b) := (b, a)
(o, t, a, n) := (n, a, t, o)
A tuple type with no actual generic arguments is isomorphic to 'unit', i.e, it
is a type that has only one single value: '()'.
u128 -- 128-bit unsigned integer values
u16 -- 16-bit unsigned integer values
u32 -- 32-bit unsigned integer values
u64 -- 64-bit unsigned integer values
u8 -- 8-bit unsigned integer values
unsigned integer of arbitrary size, including zero
represented by its bit sequence
represented by its bit sequence
unit -- value to be used as result of features that do not return a result
NOTE: unit corresponds to type void in C, Java, etc.
unit is the preferred result type for features that return without producing
a result value. These are features that typically have an outside effect
such as
println(String s) unit => ...
or features that change the state of an instance such as
increment(delta i64) unit =>
The Fuzion language implementation automatically inserts code that returns the
unit value as a result of these features, there is no need for an explicit unit
result as in
increment(delta i64) unit =>
but it is allowed to return unit explicitly if desired.
Another application of the unit type are generic features when certain generic
values are not needed and can be ignored. An example could be a generic map
implementation map K V that maps values of type K to values of type V. Using
unit as the actual generic argument for V, e.g., map string unit creates a
map that stores no data for each key, which essentially turns the map into a
set of the map's keys.
The Fuzion library knows several different unit types. Another example is nil,
which is used as the alternative type in an option. This enables the use of
option void, which can store two distinct values, void and nil.
Other unit types in Fuzion are TRUE and FALSE.
The simplest syntax to create a value of unit type is an empty block '{}'. Note
that an empty tuple 'tuple' is a different unit value of a different type and
the syntax '()' is (at least for now) not supported.
Please note the fundamental difference between
red is {}
red => {}
The first declares a feature red that defines a new unit type red, the second
declares a feature red with result type unit, i.e., a synonym for unit as in
red unit => {}
The memory required to store a value of unit type is 0 bits, so you can use
plenty without worrying about space constraints. The Fuzion code generators
typically will not generate any code for returning or assigning a value of unit
type, so these are very efficient as well.
NOTE: unit corresponds to type void in C, Java, etc.
unit is the preferred result type for features that return without producing
a result value. These are features that typically have an outside effect
such as
println(String s) unit => ...
or features that change the state of an instance such as
increment(delta i64) unit =>
The Fuzion language implementation automatically inserts code that returns the
unit value as a result of these features, there is no need for an explicit unit
result as in
increment(delta i64) unit =>
but it is allowed to return unit explicitly if desired.
Another application of the unit type are generic features when certain generic
values are not needed and can be ignored. An example could be a generic map
implementation map K V that maps values of type K to values of type V. Using
unit as the actual generic argument for V, e.g., map string unit creates a
map that stores no data for each key, which essentially turns the map into a
set of the map's keys.
The Fuzion library knows several different unit types. Another example is nil,
which is used as the alternative type in an option. This enables the use of
option void, which can store two distinct values, void and nil.
Other unit types in Fuzion are TRUE and FALSE.
The simplest syntax to create a value of unit type is an empty block '{}'. Note
that an empty tuple 'tuple' is a different unit value of a different type and
the syntax '()' is (at least for now) not supported.
Please note the fundamental difference between
red is {}
red => {}
The first declares a feature red that defines a new unit type red, the second
declares a feature red with result type unit, i.e., a synonym for unit as in
red unit => {}
The memory required to store a value of unit type is 0 bits, so you can use
plenty without worrying about space constraints. The Fuzion code generators
typically will not generate any code for returning or assigning a value of unit
type, so these are very efficient as well.
void -- the default empty type
NOTE: For a counterpart to void in C, Java, etc., see unit.fz
void is the bottom type in Fuzion, the default empty type that is a subtype of all
other types.
It is impossible to create any values of this type, consequently, it is impossible
to assign anything to a field of void type.
If used as the type of an argument field for a feature, the feature can never be
called since no value assignable to that argument could ever be produced. This
produces an absurd feature.
If used as the result type of a routine, the routine can never return.
void is the result type of the endless loop
do { <loop body> }
If used as the result type of a field, the field can never be assigned a value,
since no such value can be produced, and the field can never be read since it
remains not initialized forever.
Type void is assignable to all other types, e.g, we can assign void to a value
of type i32:
i i32 := exit 1
Since no value of type void can ever be produced, the assignment is dead code that
will be removed by the fuzion implementation.
Type void may be used as an actual type argument for a type parameter. If this
is done, it will turn all features that have arguments of that type into absurd
features. Also, this will ensure that any feature that produces a result of that
type to never return a result (typically to not be callable in the first place as
well). An example could be a stack of capacity zero: stack void 0 with an
absurd
stack.push(void)
and a pop function with a precondition that is always false
pop void
The memory required to store a value of void type is not defined since these
values do not exist. The Fuzion code generators typically will not generate
any code for features receiving arguments of void type or for code following
a feature call that returns void.
NOTE: For a counterpart to void in C, Java, etc., see unit.fz
void is the bottom type in Fuzion, the default empty type that is a subtype of all
other types.
It is impossible to create any values of this type, consequently, it is impossible
to assign anything to a field of void type.
If used as the type of an argument field for a feature, the feature can never be
called since no value assignable to that argument could ever be produced. This
produces an absurd feature.
If used as the result type of a routine, the routine can never return.
void is the result type of the endless loop
do { <loop body> }
If used as the result type of a field, the field can never be assigned a value,
since no such value can be produced, and the field can never be read since it
remains not initialized forever.
Type void is assignable to all other types, e.g, we can assign void to a value
of type i32:
i i32 := exit 1
Since no value of type void can ever be produced, the assignment is dead code that
will be removed by the fuzion implementation.
Type void may be used as an actual type argument for a type parameter. If this
is done, it will turn all features that have arguments of that type into absurd
features. Also, this will ensure that any feature that produces a result of that
type to never return a result (typically to not be callable in the first place as
well). An example could be a stack of capacity zero: stack void 0 with an
absurd
stack.push(void)
and a pop function with a precondition that is always false
pop void
The memory required to store a value of void type is not defined since these
values do not exist. The Fuzion code generators typically will not generate
any code for features receiving arguments of void type or for code following
a feature call that returns void.
As such it is the outermost feature.
Universe can not be called but you can use it
in a call as part of a full qualifier, e.g.:
`universe.this.say "hello"`