Project

domain

0.0
No commit activity in last 3 years
No release in over 3 years
Domain simply provides base classes and modules for implementing domains very simply.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 10.0
~> 2.12
 Project Readme

Domain - Build data-types the easy way

This gem provides modules (module factories in fact) for creating domains, aka data-types, in a various common ways.

Links

https://github.com/blambeau/domain

Scalar domains

A scalar domain has visible components that define the scalar structure of its values. For example a Point domain might have x and y components.

# Immediately create a Point class, that is, an implementation of the Point domain
# This is similar to `Struct.new(:x, :y)`
Point = Domain.scalar(:x, :y)

# Another way, if you want to define operators for the Point domain
class Point
  extend Domain::Scalar.new(:x, :y)

  def distance
    Math.sqrt(x*x + y*y)
  end
end

# in either case, `==`, `eql?` and `hash` are implemented in a consistent way
Point.new(1, 2) == Point.new(1, 2)

Reuse domains

A domain can also be built by reuse (the current implementation only support reusing a single value) For instance, a List domain could simply be implemented by reusing an Array.

class List
  extend Domain::Reuse.new(Array)

  def head
    # the reused instance is accessible under `reused_instance` (protected)
    reused_instance.first
  end

  # reuse through delegation to `reused_instance`
  delegate :each, :size, :empty?

  # similar to `delegate` but redecorate the resulting value (will yield Lists)
  reuse :map, :reject, :select
end

# The reused instance is expected to be passed at construction time
List.new [1, 2, 3]

# `==`, `eql?` and `hash` are already implemented in a consistent way
List.new([1, 2]) == List.new([1, 2])

Union domains

A union domain is simply a domain whose values are the union of other domains. The missing Boolean domain can simply be defined as follows:

# Factors a Boolean domain immediately
Boolean = Domain.union(TrueClass, FalseClass)

# or use the module factory in your own class
class Boolean
  extend Domain::Union.new(TrueClass, FalseClass)
end

# in either case, `===` is implemented in a consistent way
Boolean === true
Boolean === false

Specialization by constraints

A domain can also be built through specialization by constraint, that is specifying a predicate that will filter the values of a super domain. For instance:

# Factors the set of positive integers
PosInt = Domain.sbyc(Integer){|i| i > 0}

# or use the module factory (you'll have to extend Integer yourself for consistency)
class PosInt < Integer
  extend Domain::SByC.new(Integer){|i| i > 0}
end