mirror of
https://github.com/dlang/phobos.git
synced 2025-04-27 05:30:33 +03:00
sumtype: add overload-set matching example
This is a useful technique, and non-obvious enough that other D community members were surprised when I showed it to them. The unusual formatting and code layout used here achieves the following goals: 1. Have this example appear below "Basic usage". 2. Have the overload set appear as it would at module level. 3. Have as much of the example code unit-tested as possible. Goal (2), in particular, rules out the use of a "wrapper" struct to create an overload set of static methods, which is the technique that's normally used to include an overload set in a unittest block.
This commit is contained in:
parent
e13bd7dec6
commit
d1dfd094f4
4 changed files with 54 additions and 1 deletions
|
@ -404,7 +404,7 @@ redundant_attributes_check="-std.concurrency,-std.digest.md,-std.digest.ripemd,-
|
|||
style_check="+disabled"
|
||||
;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"
|
||||
; Checks for undocumented public declarations
|
||||
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"
|
||||
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"
|
||||
; Checks for unused labels
|
||||
unused_label_check="-std.conv,-std.internal.math.biguintx86,-std.regex.internal.thompson,-std.signals,-std.uni"
|
||||
; Checks for unused function parameters
|
||||
|
|
1
Makefile
1
Makefile
|
@ -272,6 +272,7 @@ EXTRA_MODULES_INTERNAL := $(addprefix std/, \
|
|||
$(addprefix math/, biguintcore biguintnoasm biguintx86 \
|
||||
errorfunction gammafunction ) \
|
||||
scopebuffer test/dummyrange test/range \
|
||||
test/sumtype_example_overloads \
|
||||
$(addprefix unicode_, comp decomp grapheme norm tables) \
|
||||
windows/advapi32 \
|
||||
) \
|
||||
|
|
17
std/internal/test/sumtype_example_overloads.d
Normal file
17
std/internal/test/sumtype_example_overloads.d
Normal file
|
@ -0,0 +1,17 @@
|
|||
/++
|
||||
For testing only.
|
||||
|
||||
Overload set used in std.sumtype example. Needs its own internal module so that
|
||||
it can be available for `make publictests` without polluting the public API.
|
||||
+/
|
||||
module std.internal.test.sumtype_example_overloads;
|
||||
|
||||
import std.sumtype;
|
||||
|
||||
@safe
|
||||
{
|
||||
string handle(int) { return "got an int"; }
|
||||
string handle(string) { return "got a string"; }
|
||||
string handle(double) { return "got a double"; }
|
||||
alias handle = match!handle;
|
||||
}
|
|
@ -77,6 +77,37 @@ version (D_BetterC) {} else
|
|||
assert(!isFahrenheit(t3));
|
||||
}
|
||||
|
||||
/** $(DIVID matching-with-an-overload-set, $(H3 Matching with an overload set))
|
||||
*
|
||||
* Instead of writing `match` handlers inline as lambdas, you can write them as
|
||||
* overloads of a function. An `alias` can be used to create an additional
|
||||
* overload for the `SumType` itself.
|
||||
*
|
||||
* For example, with this overload set:
|
||||
*
|
||||
* ---
|
||||
* string handle(int n) { return "got an int"; }
|
||||
* string handle(string s) { return "got a string"; }
|
||||
* string handle(double d) { return "got a double"; }
|
||||
* alias handle = match!handle;
|
||||
* ---
|
||||
*
|
||||
* Usage would look like this:
|
||||
*/
|
||||
version (D_BetterC) {} else
|
||||
@safe unittest
|
||||
{
|
||||
alias ExampleSumType = SumType!(int, string, double);
|
||||
|
||||
ExampleSumType a = 123;
|
||||
ExampleSumType b = "hello";
|
||||
ExampleSumType c = 3.14;
|
||||
|
||||
assert(a.handle == "got an int");
|
||||
assert(b.handle == "got a string");
|
||||
assert(c.handle == "got a double");
|
||||
}
|
||||
|
||||
/** $(DIVID arithmetic-expression-evaluator, $(H3 Arithmetic expression evaluator))
|
||||
*
|
||||
* This example makes use of the special placeholder type `This` to define a
|
||||
|
@ -182,6 +213,10 @@ version (D_BetterC) {} else
|
|||
assert(pprint(*myExpr) == "(a + (2 * b))");
|
||||
}
|
||||
|
||||
// For the "Matching with an overload set" example above
|
||||
// Needs public import to work with `make publictests`
|
||||
version (unittest) public import std.internal.test.sumtype_example_overloads;
|
||||
|
||||
import std.format.spec : FormatSpec, singleSpec;
|
||||
import std.meta : AliasSeq, Filter, IndexOf = staticIndexOf, Map = staticMap;
|
||||
import std.meta : NoDuplicates;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue