This attempts to introduce one of the most important core features of Taurus lib. Enumify will be used to generate new Algebraic types in an easier way and allow for type repetition within the new type. It will have as dependency SumType, the new version of Algebraic, which is going to be added to Phobos in the next version 2.098.0.
Rationale
A more dynamic algebraic type
Right now the new SumType algebraic generator cannot take duplicated types. This is due to the fact that it cannot match two identical types. A workaround for this is to use type wrappers, such as a struct with an alias this.
struct TypeA { int i; alias i this; }
struct TypeB { int i; alias i this; }
alias MyType = SumType!(TypeA, TypeB);
This is an ok procedure, however, this is not the way if we want TypeA and TypeB to be part of MyType. Resorting to this solution makes those types independent, but there might be some case in which we want those types to be part of another type.
Some examples are Option from Scala and Rust, or Result from Rust. The Some type is an algebraic type defined by two variants, Some and None. These two variants are part of Option and not some independent types. Scala achieves this with classes, making Option abstract, and Rust can achieve this with their implementation of enum. Using classes is an option but not in this case. The use of classes makes GC usage a must and is not compatible with D_BetterC. The other alternative is to use SumType which is a robust algebraic type generator. However, to achieve this behavior, Option must become a sort of algebraic itself with lots of boilerplate code. Because we want to have the ability to have algebraic types with repeated types we must create wrappers inside the new type. Let's take an example at Result. How could we achieve this Result!(int, int)? Ok contains an int and Err as well.
struct Result(T, U) {
public struct ok { T handle; }
public struct err { U handle; }
public immutable SumType!(ok, err) handle;
private this(ok payload) { handle = payload; }
private this(err payload) { handle = payload; }
public static Ok ()(T t) { return Result!(T, U)( ok (t) ); }
public static Err()(U u) { return Result!(T, U)( err(y) ); }
}
This is a solution to our problem. Not so bad, but what if we want an algebraic with lots of variants? Taking as an example, this enum from Rust:
These types can quickly become tedious to write, and let us be honest, all variants of algebraic type should be a part of the type itself and not an independent type.
Description
Enumify is a tool to be used inside a struct. The struct will be defined as the new algebraic type. Variants are defined using the @MemberUDA that takes as the first argument a name, used to define the static function given as the example above, and the rest will define the types and names in a Tuple expression faction.
static function will be named after the original name
structs will be named with after the lower case of the original name
the first argument of @Member must be a string literal
other arguments follow the same expression used to define a valid Tuple
structs will have only a member named handle and an alias this of it
structs of @Member with no types will be empty
structs handle of @Member with one type only will be defined as itself
structs handle of @Member with one type and name (or more), will be defined as a Tuple
structs will have a toString method (not available in D_BetterC) for better formatting
an immutable SumType handle will be used to create the algebraic type and have an alias this
an optional toString can be generated for better formatting
Enumify - a tool to generate better Algebraic types
Abstract
This attempts to introduce one of the most important core features of
Taurus
lib. Enumify will be used to generate newAlgebraic
types in an easier way and allow for type repetition within the new type. It will have as dependencySumType
, the new version ofAlgebraic
, which is going to be added toPhobos
in the next version2.098.0
.Rationale
A more dynamic algebraic type
Right now the new
SumType
algebraic generator cannot take duplicated types. This is due to the fact that it cannot match two identical types. A workaround for this is to use type wrappers, such as a struct with analias this
.This is an ok procedure, however, this is not the way if we want
TypeA
andTypeB
to be part ofMyType
. Resorting to this solution makes those types independent, but there might be some case in which we want those types to be part of another type.Some examples are
Option
fromScala
andRust
, orResult
fromRust
. TheSome
type is an algebraic type defined by two variants,Some
andNone
. These two variants are part ofOption
and not some independent types.Scala
achieves this with classes, makingOption
abstract, andRust
can achieve this with their implementation ofenum
. Using classes is an option but not in this case. The use of classes makes GC usage a must and is not compatible withD_BetterC
. The other alternative is to useSumType
which is a robust algebraic type generator. However, to achieve this behavior,Option
must become a sort of algebraic itself with lots of boilerplate code. Because we want to have the ability to have algebraic types with repeated types we must create wrappers inside the new type. Let's take an example atResult
. How could we achieve thisResult!(int, int)
?Ok
contains anint
andErr
as well.This is a solution to our problem. Not so bad, but what if we want an algebraic with lots of variants? Taking as an example, this enum from Rust:
These types can quickly become tedious to write, and let us be honest, all variants of algebraic type should be a part of the type itself and not an independent type.
Description
Enumify
is a tool to be used inside astruct
. Thestruct
will be defined as the new algebraic type. Variants are defined using the@Member
UDA
that takes as the first argument a name, used to define the static function given as the example above, and the rest will define the types and names in aTuple
expression faction.original
nameoriginal
name@Member
must be a string literalTuple
handle
and analias this
of it@Member
with no types will be empty@Member
with one type only will be defined as itself@Member
with one type and name (or more), will be defined as aTuple
toString
method (not available in D_BetterC) for better formattingimmutable SumType handle
will be used to create the algebraic type and have analias this
toString
can be generated for better formattingUsage
Option
Result
Message