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

Any.fz


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


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

# Any -- parent feature of all features that do not have an explicit parent
#
public Any ref is


  # create a String from this instance.  Unless redefined, `a.as_string` will
  # create `"instance[T]"` where `T` is the dynamic type of `a`
  #
  public as_string String => "instance[{Any.this.dynamic_type.name}]"


  # convenience prefix operator to create a string from a value.
  #
  # This permits usage of `$` as a prefix operator in a similar way both
  # inside and outside of constant strings: $x and "$x" will produce the
  # same string.
  #
  public prefix $ String => Any.this.as_string


  # Get the dynamic type of this instance.  For value instances `x`, this is
  # equal to `type_of x`, but for `x` with a `ref` type `x.dynamic_type` gives
  # the actual runtime type, while `type_of x` results in the static
  # compile-time type.
  #
  # There is no dynamic type of a type instance since this would result in an
  # endless hierarchy of types.  So for Type values, dynamic_type is redefined
  # to just return Type.type.
  #
  public dynamic_type Type => Any.this.type


  # Get a type as a value.
  #
  # This is a feature with the effect equivalent to Fuzion's `expr.type` call tail.
  # It is recommended to use `expr.type` and not `expr.type_value`.
  #
  # `type_value` is here to show how this can be implemented and to illustrate the
  # difference to `dynamic_type`.
  #
  public type.type_value Type => Any.this.type


  # dynamic_apply -- apply `f.call` to `Any.this`'s dynamic type and value
  #
  # This can be used to perform operation on values depending on their dynamic
  # type.
  #
  # Here is an example that takes a `Sequence Any` that may contain boxed values
  # of types `i32` and `f64`.  We can now write a feature `get_f64` that extracts
  # these values converted to `f64` and build a function `sum` that sums them up
  # as follows:
  #
  #     sum(values Sequence Any)
  #     =>
  #       get_f64 : Typed_Function f64 is
  #         public redef call(T type, v T) f64
  #         =>
  #           if      T : i32 then v.as_f64
  #           else if T : f64 then v.val
  #                           else compile_time_panic
  #
  #       values.map (.dynamic_apply get_f64)
  #             .foldf 0.0 (+)
  #
  #     say <| sum [3.14, 32, 16.0, 8]
  #
  # NYI: ENHANCEMENT: #5892: If this is fixed, we could write
  #
  #     sum(values Sequence Any)
  #     =>
  #       values.map .dynamic_apply T,v->
  #                     if      T : i32 then v.as_f64
  #                     else if T : f64 then v.val
  #                                     else compile_time_panic
  #             .foldf 0.0 (+)
  #
  #     say <| sum [3.14, 32, 16.0, 8]
  #
  public dynamic_apply(R type,
                       F type : Typed_Function R,
                       f F
                       ) R
  =>
    # NYI: BUG: #5894 if fixed, we should be able to write
    #
    #   f.call Any.this Any.this
    #
    # for now, using type inference for `T` works:
    f.call Any.this

last changed: 2026-03-12