Skip to content

Commit b5d9474

Browse files
authored
Merge pull request #9007 from pbackus/improve-sumtype-examples
Improve std.sumtype examples
2 parents 4686927 + ed91e50 commit b5d9474

File tree

4 files changed

+59
-43
lines changed

4 files changed

+59
-43
lines changed

.dscanner.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ redundant_attributes_check="-std.concurrency,-std.digest.md,-std.digest.ripemd,-
404404
style_check="+disabled"
405405
;style_check="-etc.c.curl,-etc.c.odbc.sqlext,-etc.c.odbc.sqltypes,-etc.c.odbc.sqlucode,-etc.c.sqlite3,-etc.c.zlib,-std.algorithm.comparison,-std.algorithm.internal,-std.algorithm.iteration,-std.algorithm.mutation,-std.algorithm.sorting,-std.array,-std.base64,-std.bitmanip,-std.c.linux.linux,-std.compiler,-std.container.array,-std.conv,-std.datetime.date,-std.datetime.interval,-std.datetime.systime,-std.digest,-std.digest.murmurhash,-std.digest.sha,-std.encoding,-std.exception,-std.experimental.allocator,-std.experimental.allocator.building_blocks.affix_allocator,-std.experimental.allocator.building_blocks.allocator_list,-std.experimental.allocator.building_blocks.bucketizer,-std.experimental.allocator.building_blocks.fallback_allocator,-std.experimental.allocator.building_blocks.free_list,-std.experimental.allocator.building_blocks.free_tree,-std.experimental.allocator.building_blocks.null_allocator,-std.experimental.allocator.building_blocks.region,-std.experimental.allocator.building_blocks.segregator,-std.experimental.allocator.common,-std.experimental.allocator.gc_allocator,-std.experimental.allocator.mallocator,-std.experimental.allocator.mmap_allocator,-std.experimental.checkedint,-std.format,-std.functional,-std.getopt,-std.internal.digest.sha_SSSE3,-std.internal.math.errorfunction,-std.internal.math.gammafunction,-std.internal.test.dummyrange,-std.internal.unicode_tables,-std.json,-std.math,-std.meta,-std.numeric,-std.parallelism,-std.path,-std.process,-std.random,-std.range,-std.range.primitives,-std.regex,-std.regex.internal.ir,-std.regex.internal.kickstart,-std.signals,-std.socket,-std.stdio,-std.string,-std.uni,-std.uri,-std.utf,-std.uuid,-std.variant,-std.zlib"
406406
; Checks for undocumented public declarations
407-
undocumented_declaration_check="-etc.c.curl,-etc.c.odbc.sql,-etc.c.odbc.sqlext,-etc.c.odbc.sqltypes,-etc.c.odbc.sqlucode,-etc.c.sqlite3,-etc.c.zlib,-std.algorithm.sorting,-std.array,-std.ascii,-std.base64,-std.bitmanip,-std.c.linux.linux,-std.c.linux.socket,-std.c.osx.socket,-std.c.process,-std.compiler,-std.complex,-std.concurrency,-std.container,-std.container.array,-std.container.binaryheap,-std.container.dlist,-std.container.rbtree,-std.container.slist,-std.conv,-std.csv,-std.datetime,-std.datetime.date,-std.digest,-std.digest.hmac,-std.digest.md,-std.digest.murmurhash,-std.digest.ripemd,-std.digest.sha,-std.encoding,-std.exception,-std.experimental.allocator,-std.experimental.allocator.building_blocks.affix_allocator,-std.experimental.allocator.building_blocks.allocator_list,-std.experimental.allocator.building_blocks.bitmapped_block,-std.experimental.allocator.building_blocks.fallback_allocator,-std.experimental.allocator.building_blocks.free_list,-std.experimental.allocator.building_blocks.free_tree,-std.experimental.allocator.building_blocks.kernighan_ritchie,-std.experimental.allocator.building_blocks.quantizer,-std.experimental.allocator.building_blocks.region,-std.experimental.allocator.building_blocks.segregator,-std.experimental.allocator.building_blocks.stats_collector,-std.experimental.allocator.gc_allocator,-std.experimental.allocator.mallocator,-std.experimental.checkedint,-std.logger.core,-std.file,-std.format,-std.functional,-std.internal.digest.sha_SSSE3,-std.internal.math.biguintcore,-std.internal.math.biguintnoasm,-std.internal.math.biguintx86,-std.internal.math.errorfunction,-std.internal.math.gammafunction,-std.internal.test.dummyrange,-std.internal.test.uda,-std.internal.windows.advapi32,-std.json,-std.math,-std.mmfile,-std.numeric,-std.outbuffer,-std.parallelism,-std.path,-std.process,-std.regex,-std.regex.internal.parser,-std.signals,-std.socket,-std.stdio,-std.string,-std.system,-std.traits,-std.uni,-std.utf,-std.variant,-std.windows.charset,-std.windows.registry,-std.windows.syserror,-std.zip,-std.zlib,-std.int128"
407+
undocumented_declaration_check="-etc.c.curl,-etc.c.odbc.sql,-etc.c.odbc.sqlext,-etc.c.odbc.sqltypes,-etc.c.odbc.sqlucode,-etc.c.sqlite3,-etc.c.zlib,-std.algorithm.sorting,-std.array,-std.ascii,-std.base64,-std.bitmanip,-std.c.linux.linux,-std.c.linux.socket,-std.c.osx.socket,-std.c.process,-std.compiler,-std.complex,-std.concurrency,-std.container,-std.container.array,-std.container.binaryheap,-std.container.dlist,-std.container.rbtree,-std.container.slist,-std.conv,-std.csv,-std.datetime,-std.datetime.date,-std.digest,-std.digest.hmac,-std.digest.md,-std.digest.murmurhash,-std.digest.ripemd,-std.digest.sha,-std.encoding,-std.exception,-std.experimental.allocator,-std.experimental.allocator.building_blocks.affix_allocator,-std.experimental.allocator.building_blocks.allocator_list,-std.experimental.allocator.building_blocks.bitmapped_block,-std.experimental.allocator.building_blocks.fallback_allocator,-std.experimental.allocator.building_blocks.free_list,-std.experimental.allocator.building_blocks.free_tree,-std.experimental.allocator.building_blocks.kernighan_ritchie,-std.experimental.allocator.building_blocks.quantizer,-std.experimental.allocator.building_blocks.region,-std.experimental.allocator.building_blocks.segregator,-std.experimental.allocator.building_blocks.stats_collector,-std.experimental.allocator.gc_allocator,-std.experimental.allocator.mallocator,-std.experimental.checkedint,-std.logger.core,-std.file,-std.format,-std.functional,-std.internal.digest.sha_SSSE3,-std.internal.math.biguintcore,-std.internal.math.biguintnoasm,-std.internal.math.biguintx86,-std.internal.math.errorfunction,-std.internal.math.gammafunction,-std.internal.test.dummyrange,-std.internal.test.sumtype_example_overloads,-std.internal.test.uda,-std.internal.windows.advapi32,-std.json,-std.math,-std.mmfile,-std.numeric,-std.outbuffer,-std.parallelism,-std.path,-std.process,-std.regex,-std.regex.internal.parser,-std.signals,-std.socket,-std.stdio,-std.string,-std.system,-std.traits,-std.uni,-std.utf,-std.variant,-std.windows.charset,-std.windows.registry,-std.windows.syserror,-std.zip,-std.zlib,-std.int128"
408408
; Checks for unused labels
409409
unused_label_check="-std.conv,-std.internal.math.biguintx86,-std.regex.internal.thompson,-std.signals,-std.uni"
410410
; Checks for unused function parameters

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ EXTRA_MODULES_INTERNAL := $(addprefix std/, \
273273
$(addprefix math/, biguintcore biguintnoasm biguintx86 \
274274
errorfunction gammafunction ) \
275275
scopebuffer test/dummyrange test/range \
276+
test/sumtype_example_overloads \
276277
$(addprefix unicode_, comp decomp grapheme norm tables) \
277278
windows/advapi32 \
278279
) \
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/++
2+
For testing only.
3+
4+
Overload set used in std.sumtype example. Needs its own internal module so that
5+
it can be available for `make publictests` without polluting the public API.
6+
+/
7+
module std.internal.test.sumtype_example_overloads;
8+
9+
import std.sumtype;
10+
11+
@safe
12+
{
13+
string handle(int) { return "got an int"; }
14+
string handle(string) { return "got a string"; }
15+
string handle(double) { return "got a double"; }
16+
alias handle = match!handle;
17+
}

std/sumtype.d

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ include:
1111
* No dependency on runtime type information (`TypeInfo`).
1212
* Compatibility with BetterC.
1313
14+
$(H3 List of examples)
15+
16+
* [Basic usage](#basic-usage)
17+
* [Matching with an overload set](#matching-with-an-overload-set)
18+
* [Recursive SumTypes](#recursive-sumtypes)
19+
* [Memory corruption](#memory-corruption) (why assignment can be `@system`)
20+
* [Avoiding unintentional matches](#avoiding-unintentional-matches)
21+
* [Multiple dispatch](#multiple-dispatch)
22+
1423
License: Boost License 1.0
1524
Authors: Paul Backus
1625
Source: $(PHOBOSSRC std/sumtype.d)
@@ -77,52 +86,38 @@ version (D_BetterC) {} else
7786
assert(!isFahrenheit(t3));
7887
}
7988

80-
/** $(DIVID introspection-based-matching, $(H3 Introspection-based matching))
89+
/** $(DIVID matching-with-an-overload-set, $(H3 Matching with an overload set))
90+
*
91+
* Instead of writing `match` handlers inline as lambdas, you can write them as
92+
* overloads of a function. An `alias` can be used to create an additional
93+
* overload for the `SumType` itself.
94+
*
95+
* For example, with this overload set:
8196
*
82-
* In the `length` and `horiz` functions below, the handlers for `match` do not
83-
* specify the types of their arguments. Instead, matching is done based on how
84-
* the argument is used in the body of the handler: any type with `x` and `y`
85-
* properties will be matched by the `rect` handlers, and any type with `r` and
86-
* `theta` properties will be matched by the `polar` handlers.
97+
* ---
98+
* string handle(int n) { return "got an int"; }
99+
* string handle(string s) { return "got a string"; }
100+
* string handle(double d) { return "got a double"; }
101+
* alias handle = match!handle;
102+
* ---
103+
*
104+
* Usage would look like this:
87105
*/
88106
version (D_BetterC) {} else
89107
@safe unittest
90108
{
91-
import std.math.operations : isClose;
92-
import std.math.trigonometry : cos;
93-
import std.math.constants : PI;
94-
import std.math.algebraic : sqrt;
95-
96-
struct Rectangular { double x, y; }
97-
struct Polar { double r, theta; }
98-
alias Vector = SumType!(Rectangular, Polar);
99-
100-
double length(Vector v)
101-
{
102-
return v.match!(
103-
rect => sqrt(rect.x^^2 + rect.y^^2),
104-
polar => polar.r
105-
);
106-
}
107-
108-
double horiz(Vector v)
109-
{
110-
return v.match!(
111-
rect => rect.x,
112-
polar => polar.r * cos(polar.theta)
113-
);
114-
}
109+
alias ExampleSumType = SumType!(int, string, double);
115110

116-
Vector u = Rectangular(1, 1);
117-
Vector v = Polar(1, PI/4);
111+
ExampleSumType a = 123;
112+
ExampleSumType b = "hello";
113+
ExampleSumType c = 3.14;
118114

119-
assert(length(u).isClose(sqrt(2.0)));
120-
assert(length(v).isClose(1));
121-
assert(horiz(u).isClose(1));
122-
assert(horiz(v).isClose(sqrt(0.5)));
115+
assert(a.handle == "got an int");
116+
assert(b.handle == "got a string");
117+
assert(c.handle == "got a double");
123118
}
124119

125-
/** $(DIVID arithmetic-expression-evaluator, $(H3 Arithmetic expression evaluator))
120+
/** $(DIVID recursive-sumtypes, $(H3 Recursive SumTypes))
126121
*
127122
* This example makes use of the special placeholder type `This` to define a
128123
* [recursive data type](https://en.wikipedia.org/wiki/Recursive_data_type): an
@@ -227,6 +222,10 @@ version (D_BetterC) {} else
227222
assert(pprint(*myExpr) == "(a + (2 * b))");
228223
}
229224

225+
// For the "Matching with an overload set" example above
226+
// Needs public import to work with `make publictests`
227+
version (unittest) public import std.internal.test.sumtype_example_overloads;
228+
230229
import std.format.spec : FormatSpec, singleSpec;
231230
import std.meta : AliasSeq, Filter, IndexOf = staticIndexOf, Map = staticMap;
232231
import std.meta : NoDuplicates;
@@ -266,8 +265,7 @@ private enum isInout(T) = is(T == inout);
266265
*
267266
* The special type `This` can be used as a placeholder to create
268267
* self-referential types, just like with `Algebraic`. See the
269-
* ["Arithmetic expression evaluator" example](#arithmetic-expression-evaluator) for
270-
* usage.
268+
* ["Recursive SumTypes" example](#recursive-sumtypes) for usage.
271269
*
272270
* A `SumType` is initialized by default to hold the `.init` value of its
273271
* first member type, just like a regular union. The version identifier
@@ -1619,9 +1617,9 @@ enum bool isSumType(T) = is(T : SumType!Args, Args...);
16191617
* overloads are considered as potential matches.
16201618
*
16211619
* Templated handlers are also accepted, and will match any type for which they
1622-
* can be [implicitly instantiated](https://dlang.org/glossary.html#ifti). See
1623-
* ["Introspection-based matching"](#introspection-based-matching) for an
1624-
* example of templated handler usage.
1620+
* can be [implicitly instantiated](https://dlang.org/glossary.html#ifti).
1621+
* (Remember that a $(DDSUBLINK spec/expression,function_literals, function literal)
1622+
* without an explicit argument type is considered a template.)
16251623
*
16261624
* If multiple [SumType]s are passed to match, their values are passed to the
16271625
* handlers as separate arguments, and matching is done for each possible

0 commit comments

Comments
 (0)