Re: Need Advice: Union or Variant?

2022-11-18 Thread jwatson-CO-edu via Digitalmars-d-learn
On Saturday, 19 November 2022 at 03:38:26 UTC, jwatson-CO-edu 
wrote:
Thank you, something similar to what you suggested reduced the 
atom size from 72 bytes to 40.


Oh, based on another forum post I added constructors in addition 
to reducing the atom size 44%.


```d
struct Atom{
F_Type  kind; // What kind of atom this is
union{
double  num; // NMBR: Number value
string  str; // STRN: String value, D-string
boolbul; // BOOL: Boolean value
struct{ //  CONS: pair
Atom* car; // Left  `Atom` Pointer
Atom* cdr; // Right `Atom` Pointer
}
struct{ //  EROR: Code + Message
F_Error err; // Error code
string  msg; // Detailed desc
}
}
// https://forum.dlang.org/post/omsbr8$7do$1...@digitalmars.com
this( double n ){ kind = F_Type.NMBR; num = n; } // make 
number
this( string s ){ kind = F_Type.STRN; str = s; } // make 
string

this( bool   b ){ kind = F_Type.BOOL; bul = b; } // make bool
this( Atom* a, Atom* d ){ kind = F_Type.CONS; car = a; cdr = 
d; } // make cons
this( F_Error e, string m ){ kind = F_Type.EROR; err = e; msg 
= m; } // make error

}
```




Re: Need Advice: Union or Variant?

2022-11-18 Thread jwatson-CO-edu via Digitalmars-d-learn

On Thursday, 17 November 2022 at 22:49:37 UTC, H. S. Teoh wrote:

Just create a nested anonymous struct, like this:

struct Atom {
F_Type kind;
union { // anonymous union
struct {
Atom*   car; // - Left  `Atom` 
Pointer
Atom*   cdr; // - Right `Atom` 
Pointer
}
struct {
double  num; // - Number value
string  str; // - String value, D-string 
underlies

}
boolbul; // - Boolean value
}
F_Error err = F_Error.NOVALUE; // Error code
}


T
Thank you, something similar to what you suggested reduced the 
atom size from 72 bytes to 40.


Re: Need Advice: Union or Variant?

2022-11-17 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Nov 17, 2022 at 10:16:04PM +, jwatson-CO-edu via 
Digitalmars-d-learn wrote:
> On Thursday, 17 November 2022 at 21:05:43 UTC, H. S. Teoh wrote:
[...]
> > struct Atom {
> > F_Type kind;
> > union { // anonymous union
> > Atom*   car; // - Left  `Atom` Pointer
> > Atom*   cdr; // - Right `Atom` Pointer
> > double  num; // - Number value
> > string  str; // - String value, 
> > D-string underlies
> > boolbul; // - Boolean value
> > F_Error err = F_Error.NOVALUE; // Error code
> > }
> > }
[...]
> Thank you!  This seems nice except there are a few fields that need to
> coexist.
> I need {`car`, `cdr`} -or- {`num`} -or- {`str`} -or- {`bul`}.
> `err` will be outside the union as well because I have decided that
> any type can have an error code attached.  As in an error number
> (other than NaN) can be returned instead of reserving certain numbers
> to represent errors.  Imagine if there was NaN for every datatype.
[...]

Just create a nested anonymous struct, like this:

struct Atom {
F_Type kind;
union { // anonymous union
struct {
Atom*   car; // - Left  `Atom` 
Pointer
Atom*   cdr; // - Right `Atom` 
Pointer
}
struct {
double  num; // - Number value
string  str; // - String value, 
D-string underlies
}
boolbul; // - Boolean value
}
F_Error err = F_Error.NOVALUE; // Error code
}


T

-- 
Meat: euphemism for dead animal. -- Flora


Re: Need Advice: Union or Variant?

2022-11-17 Thread jwatson-CO-edu via Digitalmars-d-learn
On Thursday, 17 November 2022 at 21:19:56 UTC, Petar Kirov 
[ZombineDev] wrote:
On Thursday, 17 November 2022 at 20:54:46 UTC, jwatson-CO-edu 
wrote:
I have an implementation of the "[Little 
Scheme](https://mitpress.mit.edu/9780262560993/the-little-schemer/)" educational programming language written in D, [here](https://github.com/jwatson-CO-edu/SPARROW)".


It has many problems, but the one I want to solve first is the 
size of the "atoms" (units of data).


`Atom` is a struct that has fields for every possible type of 
data that the language supports. This means that a bool `Atom` 
unnecessarily takes up space in memory with fields for number, 
string, structure, etc.


[...]
Do I use unions or variants?**


In general, I recommend 
[`std.sumtype`](https://dlang.org/phobos/std_sumtype), as it is 
one of the best D libraries for this purpose. It is implemented 
as a struct containing two fields: the `kind` and a `union` of 
all the possible types.
That said, one difficulty you are likely to face is with 
refactoring your code to use the 
[`match`](https://dlang.org/phobos/std_sumtype#.match) and 
[`tryMatch`](https://dlang.org/phobos/std_sumtype#.tryMatch) 
functions, as `std.sumtype.SumType` does not expose the 
underlying kind field.


Other notable alternatives are:
* [`mir-core`](https://code.dlang.org/packages/mir-core)'s 
`mir.algebraic`: http://mir-core.libmir.org/mir_algebraic.html
* 
[`taggedalgebraic`](https://code.dlang.org/packages/taggedalgebraic): https://vibed.org/api/taggedalgebraic.taggedalgebraic/


Thank you!  This is intriguing.
The different flavors of `Atom` I need will have either {`car`, 
`cdr`} -or- {`num`} -or- {`str`} -or- {`bul`}.  Does SumType 
allow me to store the multiple fields {`car`, `cdr`} in one of 
the types, while the other types have only one field?


Since this is a dynamically-typed language, I need the atoms to 
both be interchangeable and to serve different purposes at the 
same time.


Re: Need Advice: Union or Variant?

2022-11-17 Thread jwatson-CO-edu via Digitalmars-d-learn

On Thursday, 17 November 2022 at 21:05:43 UTC, H. S. Teoh wrote:

Question:
**Where do I begin my consolidation of space within `Atom`?  
Do I use

unions or variants?**


In this case, since you're already keeping track of what type 
of data is being stored in an Atom, use a union:


struct Atom {
F_Type kind;
union { // anonymous union
Atom*   car; // - Left  `Atom` Pointer
Atom*   cdr; // - Right `Atom` Pointer
double  num; // - Number value
			string  str; // - String value, D-string 
underlies

boolbul; // - Boolean value
F_Error err = F_Error.NOVALUE; // Error code
}
}

Use Variant if you don't want to keep track of the type 
yourself.

T


Thank you!  This seems nice except there are a few fields that 
need to coexist.

I need {`car`, `cdr`} -or- {`num`} -or- {`str`} -or- {`bul`}.
`err` will be outside the union as well because I have decided 
that any type can have an error code attached.  As in an error 
number (other than NaN) can be returned instead of reserving 
certain numbers to represent errors.  Imagine if there was NaN 
for every datatype.





Re: Need Advice: Union or Variant?

2022-11-17 Thread Petar via Digitalmars-d-learn
On Thursday, 17 November 2022 at 20:54:46 UTC, jwatson-CO-edu 
wrote:
I have an implementation of the "[Little 
Scheme](https://mitpress.mit.edu/9780262560993/the-little-schemer/)" educational programming language written in D, [here](https://github.com/jwatson-CO-edu/SPARROW)".


It has many problems, but the one I want to solve first is the 
size of the "atoms" (units of data).


`Atom` is a struct that has fields for every possible type of 
data that the language supports. This means that a bool `Atom` 
unnecessarily takes up space in memory with fields for number, 
string, structure, etc.


Here is the 
[definition](https://github.com/jwatson-CO-edu/SPARROW/blob/main/lil_schemer.d#L55):


```d
enum F_Type{
CONS, // Cons pair
STRN, // String/Symbol
NMBR, // Number
EROR, // Error object
BOOL, // Boolean value
FUNC, // Function
}

struct Atom{
F_Type  kind; //  What kind of atom this is
Atom*   car; // - Left  `Atom` Pointer
Atom*   cdr; // - Right `Atom` Pointer
double  num; // - Number value
string  str; // - String value, D-string 
underlies

boolbul; // - Boolean value
F_Error err = F_Error.NOVALUE; // Error code
}

```
Question:
**Where do I begin my consolidation of space within `Atom`?  Do 
I use unions or variants?**


In general, I recommend 
[`std.sumtype`](https://dlang.org/phobos/std_sumtype), as it is 
one of the best D libraries for this purpose. It is implemented 
as a struct containing two fields: the `kind` and a `union` of 
all the possible types.
That said, one difficulty you are likely to face is with 
refactoring your code to use the 
[`match`](https://dlang.org/phobos/std_sumtype#.match) and 
[`tryMatch`](https://dlang.org/phobos/std_sumtype#.tryMatch) 
functions, as `std.sumtype.SumType` does not expose the 
underlying kind field.


Other notable alternatives are:
* [`mir-core`](https://code.dlang.org/packages/mir-core)'s 
`mir.algebraic`: http://mir-core.libmir.org/mir_algebraic.html
* 
[`taggedalgebraic`](https://code.dlang.org/packages/taggedalgebraic): https://vibed.org/api/taggedalgebraic.taggedalgebraic/


Re: Need Advice: Union or Variant?

2022-11-17 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Nov 17, 2022 at 08:54:46PM +, jwatson-CO-edu via 
Digitalmars-d-learn wrote:
[...]
> ```d
> enum F_Type{
> CONS, // Cons pair
> STRN, // String/Symbol
> NMBR, // Number
> EROR, // Error object
> BOOL, // Boolean value
> FUNC, // Function
> }
> 
> struct Atom{
> F_Type  kind; //  What kind of atom this is
> Atom*   car; // - Left  `Atom` Pointer
> Atom*   cdr; // - Right `Atom` Pointer
> double  num; // - Number value
> string  str; // - String value, D-string underlies
> boolbul; // - Boolean value
> F_Error err = F_Error.NOVALUE; // Error code
> }
> 
> ```
> Question:
> **Where do I begin my consolidation of space within `Atom`?  Do I use
> unions or variants?**

In this case, since you're already keeping track of what type of data is
being stored in an Atom, use a union:

struct Atom {
F_Type kind;
union { // anonymous union
Atom*   car; // - Left  `Atom` Pointer
Atom*   cdr; // - Right `Atom` Pointer
double  num; // - Number value
string  str; // - String value, 
D-string underlies
boolbul; // - Boolean value
F_Error err = F_Error.NOVALUE; // Error code
}
}

Use Variant if you don't want to keep track of the type yourself.


T

-- 
An elephant: A mouse built to government specifications. -- Robert Heinlein


Need Advice: Union or Variant?

2022-11-17 Thread jwatson-CO-edu via Digitalmars-d-learn
I have an implementation of the "[Little 
Scheme](https://mitpress.mit.edu/9780262560993/the-little-schemer/)" educational programming language written in D, [here](https://github.com/jwatson-CO-edu/SPARROW)".


It has many problems, but the one I want to solve first is the 
size of the "atoms" (units of data).


`Atom` is a struct that has fields for every possible type of 
data that the language supports. This means that a bool `Atom` 
unnecessarily takes up space in memory with fields for number, 
string, structure, etc.


Here is the 
[definition](https://github.com/jwatson-CO-edu/SPARROW/blob/main/lil_schemer.d#L55):


```d
enum F_Type{
CONS, // Cons pair
STRN, // String/Symbol
NMBR, // Number
EROR, // Error object
BOOL, // Boolean value
FUNC, // Function
}

struct Atom{
F_Type  kind; //  What kind of atom this is
Atom*   car; // - Left  `Atom` Pointer
Atom*   cdr; // - Right `Atom` Pointer
double  num; // - Number value
string  str; // - String value, D-string 
underlies

boolbul; // - Boolean value
F_Error err = F_Error.NOVALUE; // Error code
}

```
Question:
**Where do I begin my consolidation of space within `Atom`?  Do I 
use unions or variants?**