taggedalgebraic 0.11.0 adds TaggedUnion

Sönke Ludwig sludwig+d at outerproduct.org
Sat Feb 23 13:18:15 UTC 2019


Am 23.02.2019 um 09:51 schrieb Jacob Carlborg:
> On 2019-02-22 18:09, Sönke Ludwig wrote:
>> TaggedUnion is the low level tagged union functionality separated out 
>> from TaggedAlgebraic. Because it doesn't support transparent access of 
>> methods and operators of the contained value, it is able to provide a 
>> number of convenience features. On top of that, visit and tryVisit is 
>> now supported for pattern matching, analogous to the version for 
>> std.variant.Algebraic. This is the basic usage:
>>
>>      union U {
>>          string caption;
>>          int height;
>>          int width;
>>      }
>>      alias Value = TaggedUnion!U;
>>
>>      auto val = Value.caption("foo");
>>      assert(val.kind == Value.Kind.caption);
>>      assert(val.value!(Value.Kind.caption) == "foo");
>>
>>      // shorthand syntax:
>>      assert(val.isCaption);
>>      assert(val.captionValue == "foo");
>>
>>      // set a different type/kind
>>      val.setHeight(10);
> 
> Why not using property syntax, i.e. `val.height = 10`?

The main reason is to distinguish the act of setting a new value from 
the one of modifying an existing value. In the former case it is okay if 
the currently stored kind/type differs, but in the latter case that 
would be a programming error.

This would have worked with a setter and an r-value getter, but that 
would have unnecessarily impeded performance for working with complex 
types, at least for the primary access syntax.

Following from the above, the raw name is used instead as a static 
property to enable a short construction syntax for a specific kind (e.g. 
`Value.width(10)`).


>>      val.visit!(
>>          (int i) { assert(i == 10); }
>>          (string s) { assert(false); }
>>      );
> 
> How does this handle the above case when there are two `int`? How do I 
> know if it's the "width" or "height" that has been set?
> 

I'm still thinking about a nice syntax for kind based pattern matching*, 
but for now this will call the same visitor for both, width and height. 
You'd have to query val.isWidth/val.kind to check the specific kind.


* really unfortunate that a template has to be instantiated first to be 
able to query the parameters of the contained function, otherwise 
`(@(Kind.width) i) { ... }` would be possible.


More information about the Digitalmars-d-announce mailing list