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

container/Set.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 Set
#
#  Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------

# Set -- an abstract set of values
#
public Set(public E type : property.equatable) ref : Sequence E is


  # is this sequence known to be finite?  For infinite sequences, features like
  # count diverge.
  #
  public redef finite trit => if size_option?? then trit.yes else trit.unknown


  # number of entries in this set.  May be undefined, i.e., a range of
  # floating point numbers or an infinite set.
  #
  public size_option option i32 => nil


  # does this set contain the given value?
  #
  public redef contains (e E) bool => abstract


  # list representation of values in this set
  #
  public redef as_list list E => abstract


  # create a new Set from a sequence of elements
  #
  public type.new (s Sequence E) container.Set E => abstract


  # create a union of these two Sets
  #
  public union(other container.Set E) container.Set E =>
    Set.this.new (Set.this ++ other)


  # infix variant for Set.union
  #
  public infix ∪ (other container.Set E) =>
    Set.this.union other


  # create an intersection of these two Sets
  #
  public intersection(other container.Set E) container.Set E =>
    Set.this.new (Set.this ++ other).filter(el -> Set.this.contains el && other.contains el)


  # infix variant for Set.intersection
  #
  public infix ∩ (other container.Set E) =>
    Set.this.intersection other


  # this Set without all elements in other
  #
  public difference(other container.Set E) container.Set E =>
    Set.this.new filter(el -> !other.contains el)


  # infix variant for Set.difference
  # Note: the operator is NOT a backslash, but the unicode character U+2216 (SET MINUS)
  #
  public infix ∖ (other container.Set E) =>
    Set.this.difference other



  # is this Set a subset of other?
  # true, iff other contains all
  # elements that this Set contains.
  #
  public is_subset_of(other container.Set E) =>
    Set.this ∀ other.contains


  # is this Set a superset of other?
  # true, iff this Set contains all
  # elements that other contains.
  #
  public is_superset_of(other container.Set E) =>
    other ∀ contains



  # add new element k to this set.
  #
  public add (k E) Set E =>
    panic "*** NYI: REMOVE Set.add, we need some support for mutable Sets ***"


  public redef as_string =>
    if is_empty
      "∅"
    else
      ("\{"
       + (as_list.map x->x.as_string).fold(String.concat ";")
       + "}")


  # equality
  #
  # NYI: remove this, since we inherit from Sequence?
  #
  public fixed redef type.equality(a, b container.Set E)
  # NYI: BUG: #3888
  # pre else
  #     debug: a.finite
  #     debug: b.finite
  =>
    # NYI: a bit expensive
    (a ∪ b).size_option.val = a.size_option.val


  # monoid of Set with infix ∪ operation.
  #
  public type.union =>
    ref : Monoid (container.Set E)
      redef infix ∙ (a, b container.Set E) => a ∪ b
      redef e => (container.Set E).new []
last changed: 2025-01-30