Re: how to define infix function
On Saturday, 2 June 2018 at 22:09:49 UTC, Neia Neutuladh wrote: On Saturday, 2 June 2018 at 21:44:39 UTC, greatsam4sure wrote: Sorry for the typo is it possible to define infix function in D 3.min(5)// 3: where min is a function, works in D 3 min 5 // does not work. thanks in advance This is a horrible abuse of D's operator overloading discovered by FeepingCreature in the distant past. You have to delimit your custom infix operator with slashes; you can't make `3 min 5` work, but you can make `3 /min/ 5` work. Observe: struct Min { MinIntermediate!T opBinaryRight(string op, T)(T value) if (op == "/") { return MinIntermediate!T(value); } } struct MinIntermediate(T) { T value; T opBinary(string op, T)(T value2) if (op == "/") { if (value < value2) return value; return value2; } } Min min; void main() { writeln(1 /min/ 2); } And of course, this can be generalized: struct Operator(alias fn, string operator = "/") { static auto opBinaryRight(string op : operator, T...)(T value1) { struct Result { auto opBinary(string op : operator, U...)(U value2) if (__traits(compiles, fn(value1, value2))) { return fn(value1, value2); } } Result result; return result; } } unittest { import std.algorithm.comparison; alias min = Operator!(std.algorithm.comparison.min); assert(1 /min/ 3 == 1); } Note also the use of static opBinaryRight, allowing one to eschew the 'min' variable. All of this said, I would suggest not using this in prod - it's a neat trick that shows off some of D's power, but I don't see a case where this would be easier to understand than a straightforward function call. -- Simen
Re: how to define infix function
On Saturday, 2 June 2018 at 22:01:02 UTC, Ali Çehreli wrote: On 06/02/2018 02:44 PM, greatsam4sure wrote: > is it possible to define infix function in D > > 3.min(5)// 3: where min is a function, works in D > 3 min 5 // does not work. This is called universal function call syntax (UFCS) in D. The idea is simple: You can pull the first argument out as if the function is a member function of that argument. So, in your case it already works because there is already a min() function that works with two (actually, many) parameters: import std.algorithm; void main() { assert(min(3, 5) == 3); assert(3.min(5) == 3); } However, many people don't like overusing it; it works well only in cases where the first parameter is arguably the "main character" in the operation. For example, min doesn't look good because all parameters have equal roles in that function. Ali Thanks for your reply to my question. Your book: programming in D is real a great help learning D. I will appreciate it if your can expand the book to advance use of D. That is, dealing with D advance use Case. I discover that the D language is very advance but I am lock in the elementary yet don't know the way out. This is because D is the most Higher programming language that I ever use. Better still you can direct me to more materials about D. I am already familiar will all D books. thanks
Re: New programming paradigm
On Thursday, 7 September 2017 at 22:53:31 UTC, Biotronic wrote: On Thursday, 7 September 2017 at 16:55:02 UTC, EntangledQuanta wrote: Sorry, I think you missed the point completely... or I didn't explain things very well. I don't think I did - your new explanation didn't change my understanding at least. This indicates I'm the one who's bad at explaining. Ah well. The point of my post was mostly to rewrite the code you'd posted in a form that I (and, I hope, others) found easier to understand. I see no where in your code where you have a variant like type. True. I've now rewritten it to use std.variant.Algebraic with these semantics: auto foo(T1, T2)(T1 a, T2 b, int n) { import std.conv; return T1.stringof~": "~to!string(a)~" - "~T2.stringof~": "~to!string(b); } unittest { import std.variant; Algebraic!(float, int) a = 4f; Algebraic!(double, byte) b = 1.23; auto res = varCall!foo(a, b, 3); assert(res == "float: 4 - double: 1.23"); } template varCall(alias fn) { import std.variant; auto varCall(int n = 0, Args...)(Args args) { static if (n == Args.length) { return fn(args); } else { auto arg = args[n]; static if (is(typeof(arg) == VariantN!U, U...)) { foreach (T; arg.AllowedTypes) { if (arg.type == typeid(T)) return varCall!(n+1)(args[0..n], arg.get!T, args[n+1..$]); } assert(false); } else { return varCall!(n+1)(args); } } } } Sadly, by using std.variant, I've given up on the elegant switch/case in exchange for a linear search by typeid. This can be fixed, but requires changes in std.variant. Of course, it would be possible to hide all this behind compiler magic. Is that desirable? I frankly do not think so. We should be wary of adding too much magic to the compiler - it complicates the language and its implementation. This is little more than an optimization, and while a compiler solution would be less intrusive and perhaps more elegant, I do not feel it provides enough added value to warrant its inclusion. Next, I'm curious about this code: void bar(var t) { writeln("\tbar: Type = ", t.type, ", Value = ", t); } void main() { bar(3); // calls bar as if bar was `void bar(int)` bar(3.4f); // calls bar as if bar was `void bar(float)` bar("sad"); // calls bar as if bar was `void bar(string)` } What does 'var' add here, that regular templates do not? (serious question, I'm not trying to shoot down your idea, only to better understand it) One possible problem with var here (if I understand it correctly) would be separate compilation - a generated switch would need to know about types in other source files that may not be available at the time it is compiled. Next: var foo(var x) { if (x == 3) return x; return "error!"; } This looks like a sort of reverse alias this, which I've argued for on many occasions. Currently, it is impossible to implement a type var as in that function - the conversion from string to var would fail. A means of implementing this has been discussed since at least 2007, and I wrote a DIP[1] about it way back in 2013. It would make working with variants and many other types much more pleasant. [1]: https://wiki.dlang.org/DIP52 I use something similar where I use structs behaving like enums. Each field in the struct is an "enum value" which an attribute, this is because I have not had luck with using attributes on enum values directly and that structs allow enums with a bit more power. When a runtime value depends on these structs one can build a mapping between the values and functional aspects of program. Since D has a nice type system, one can provide one templated function that represents code for all the enum values. E.g., enum TypeID // actually done with a struct { @("int") i, @("float") f } struct someType { TypeID id; } someType.id is runtime dependent. But we want to map behavior for each type. if (s.id == TypeID.i) fooInt(); if (s.id == TypeID.f) fooFloat(); For lots of values this is tedius and requires N functions. Turning foo in to a template and autogenerating the mapping using mixins we can get something like mixin(MapEnum!(TypeID, "foo")(s.id)) which generates the following code: switch(s.id) { case TypeID.i: foo!int(); break; case TypeID.f: foo!float(); break; } and of course we must create foo: void foo(T)() { } but rather than one for each enum member, we just have to have one. For certain types of code, this works wonders. We can treat runtime dependent values as if they were compile time values without too much work. MapEnum maps runtime to compile time behavior allowing us to use use templates to handle runtime variables. T in foo is actually acting in a runtime fashion depending on the value of id.
Re: how to define infix function
On Saturday, 2 June 2018 at 21:44:39 UTC, greatsam4sure wrote: Sorry for the typo is it possible to define infix function in D 3.min(5)// 3: where min is a function, works in D 3 min 5 // does not work. thanks in advance This is a horrible abuse of D's operator overloading discovered by FeepingCreature in the distant past. You have to delimit your custom infix operator with slashes; you can't make `3 min 5` work, but you can make `3 /min/ 5` work. Observe: struct Min { MinIntermediate!T opBinaryRight(string op, T)(T value) if (op == "/") { return MinIntermediate!T(value); } } struct MinIntermediate(T) { T value; T opBinary(string op, T)(T value2) if (op == "/") { if (value < value2) return value; return value2; } } Min min; void main() { writeln(1 /min/ 2); }
Re: how to define infix function
On 06/02/2018 02:44 PM, greatsam4sure wrote: > is it possible to define infix function in D > > 3.min(5)// 3: where min is a function, works in D > 3 min 5 // does not work. This is called universal function call syntax (UFCS) in D. The idea is simple: You can pull the first argument out as if the function is a member function of that argument. So, in your case it already works because there is already a min() function that works with two (actually, many) parameters: import std.algorithm; void main() { assert(min(3, 5) == 3); assert(3.min(5) == 3); } However, many people don't like overusing it; it works well only in cases where the first parameter is arguably the "main character" in the operation. For example, min doesn't look good because all parameters have equal roles in that function. Ali
how to define infix function
Sorry for the typo is it possible to define infix function in D 3.min(5)// 3: where min is a function, works in D 3 min 5 // does not work. thanks in advance
how to definte infinix function
is it possible to definite infix function in D 3.min(5)// 3 where min is a function works in D 3 min 5 // does not work. thanks in advance
Re: GDC on Travis-CI
On Saturday, 2 June 2018 at 19:48:36 UTC, Matthias Klumpp wrote: @crimaniak: If you really want to build with all compilers, there is a workaround for this issue that does not involve you supporting ancient D versions, and that is to actually use Debian's GDC on Travis. I use this excessively for my own projects, mostly though because I need newer system libraries and because I explicitly want to build with the packaged compilers as well. You can use a similar approach and limit it to GDC only, I created a PR for that: https://github.com/crimaniak/json-patch/pull/1 As you can see on https://travis-ci.org/crimaniak/json-patch/jobs/387197216 , your code builds fine with the latest GDC. Wow! It works! Thanks! So, if you want that workaround, please take it, if not it may serve as a reference for others facing the same problem. Yes, pull request is approved. This is exactly what I was hoping to find. I also recommend this to others who have this problem. It takes some time to install required packages so build was much longer than dmd and lcd builds but I think it's not a problem for most cases. Thanks to everyone who answered!
Re: Orange serializer/deserializer
On 2018-06-02 03:30, IntegratedDimensions wrote: How can I modify the pre serialization and post serialization values? I need to transform some variables that are stored but I would like to do this easily "inline"(would be cool to be able to provide a delegate to do the transformations at the site of definition of the fields). Use the "onSerializing" and "onSerialized" UDAs on a method. "onSerializing" will be called before serializing and "onSerialized" after serializing. Have a look at the unit tests [1]. Also, how does orange handle properties? Seems it just deals with fields and ignores all functions(does not use getter and setter of properties). This is valid, of course, just want to make sure. I still need to be able to transform values pre and post though. That is correct, it only (de)serializes fields. If you want to (de)serialize proprieties, implement the "toData" and "fromData". See the example in the wiki [2]. Note, by implementing these methods none of the standard serialization will occur. If you want to serialize the fields as well, you need to do that as well when implementing "toData" and "fromData". It's also possible to implement these "methods" in a non-intrusive way, i.e. for customizing serialization of third party type [3]. [1] https://github.com/jacob-carlborg/orange/blob/master/tests/Events.d#L39-L54 [2] https://github.com/jacob-carlborg/orange/wiki/Custom-Serialization [3] https://github.com/jacob-carlborg/orange/blob/master/tests/NonIntrusive.d -- /Jacob Carlborg
Re: GDC on Travis-CI
On Saturday, 2 June 2018 at 16:27:38 UTC, Seb wrote: On Saturday, 2 June 2018 at 16:04:09 UTC, Matthias Klumpp wrote: On Saturday, 2 June 2018 at 03:15:56 UTC, crimaniak wrote: I started to work with Travis-CI, building packages using all three main compilers, and noticed that I have problems with gdc every time and need to tweak code because of many things missing. For example: https://travis-ci.org/crimaniak/json-patch/jobs/386963340 Why this situation with gdc and how best to deal with it? The build log seems to indicate it uses gdc 4.8, while the current version of GDC is 8.1 which is based on the 2.076 frontend. Maybe just updating GDC on Travis will fix this. Sadly that's not so easy as 1) the GDC download path changed and we are still waiting on feedback from Ian on this (since more than, see https://github.com/dlang/installer/pull/251) 2) AFAICT there are no public binaries that use anything later than 2.068.2 could be used (see https://gdcproject.org/downloads) That's unfortunate. I hope Iain comments on this soon, because it means GDC will receive much less testing by other projects. For getting up-to-date binaries, in theory those could be extracted from GDC's Debian packages, which are usually very up-to-date (even Git snapshots are occasionally packaged) - problem there is that I am not sure whether they will work standalone and with the older GLibc on Travis. @crimaniak: If you really want to build with all compilers, there is a workaround for this issue that does not involve you supporting ancient D versions, and that is to actually use Debian's GDC on Travis. I use this excessively for my own projects, mostly though because I need newer system libraries and because I explicitly want to build with the packaged compilers as well. You can use a similar approach and limit it to GDC only, I created a PR for that: https://github.com/crimaniak/json-patch/pull/1 As you can see on https://travis-ci.org/crimaniak/json-patch/jobs/387197216 , your code builds fine with the latest GDC. So, if you want that workaround, please take it, if not it may serve as a reference for others facing the same problem.
Re: determining if array element is null
On 06/02/2018 08:35 PM, Neia Neutuladh wrote: 2. `int[4] a = null` treats the initialization as a copy from an array whose value is null. If you run just that line of code, it will produce an error at runtime: "object.Error@(0): Array lengths don't match for copy: 0 != 4" If you want to initialize every member of an array with a value, you write it as: int[4] a; a[] = 5; `int[4] a = 5;` is fine, too.
Re: determining if array element is null
On Saturday, 2 June 2018 at 18:10:38 UTC, eastanon wrote: Does D array implementation support an array of null values? int a[4] = null; But I ran into a type error while checking if a[i] is null foreach(i; 0..3){ if(i == null){ writeln("it is null"); } } } How do you set fixed size array of null values and check if they are null? There are several problems with your code. 1. `int a[4]` should be `int[4] a`. You probably see a warning about using the C-style array syntax. 2. `int[4] a = null` treats the initialization as a copy from an array whose value is null. If you run just that line of code, it will produce an error at runtime: "object.Error@(0): Array lengths don't match for copy: 0 != 4" If you want to initialize every member of an array with a value, you write it as: int[4] a; a[] = 5; 3. `foreach (i; 0..3)` will iterate through a range of integers: 0, 1, and 2. You haven't touched your array. 4. `i == null` is trying to compare an integer, which can never be null, to null. You either want to use std.typecons.Nullable (if you just want integers-that-might-be-null) or an array of pointers to integers (if you want reference semantics). 5. Usually, you want to use `i is null` instead of `i == null`.
Connecting two web sockets at the same time with vibe.d
I am blocked in my project because of an issue while using websockets. I can simplify my problem like : auto ws_url = URL("wss://stream.binance.com:9443/ws/ethbtc@aggTrade"); auto ws = connectWebSocket(ws_url); if ( !ws.connected ) return; sleep(2.seconds); ws_url = URL("wss://stream.binance.com:9443/ws/iotabtc@depth"); auto ws2 = connectWebSocket(ws_url); if ( !ws2.connected ) return; If I don't close the first socket before opening the second one I am getting two different exceptions which can be seen in my question which I already ask in vibe.d's forum : https://forum.rejectedsoftware.com/groups/rejectedsoftware.vibed/thread/52273/ Since I am blocked I am open to any suggestions. Or if some one knows an alternative socket implementation I may have to switch to another library. So do you guys have any suggestions or an alternative library for socket handling? Erdem
determining if array element is null
Does D array implementation support an array of null values? int a[4] = null; But I ran into a type error while checking if a[i] is null foreach(i; 0..3){ if(i == null){ writeln("it is null"); } } } How do you set fixed size array of null values and check if they are null?
Re: GDC on Travis-CI
On Saturday, 2 June 2018 at 16:04:09 UTC, Matthias Klumpp wrote: On Saturday, 2 June 2018 at 03:15:56 UTC, crimaniak wrote: I started to work with Travis-CI, building packages using all three main compilers, and noticed that I have problems with gdc every time and need to tweak code because of many things missing. For example: https://travis-ci.org/crimaniak/json-patch/jobs/386963340 Why this situation with gdc and how best to deal with it? The build log seems to indicate it uses gdc 4.8, while the current version of GDC is 8.1 which is based on the 2.076 frontend. Maybe just updating GDC on Travis will fix this. Sadly that's not so easy as 1) the GDC download path changed and we are still waiting on feedback from Ian on this (since more than, see https://github.com/dlang/installer/pull/251) 2) AFAICT there are no public binaries that use anything later than 2.068.2 could be used (see https://gdcproject.org/downloads)
Re: GDC on Travis-CI
On Saturday, 2 June 2018 at 03:15:56 UTC, crimaniak wrote: I started to work with Travis-CI, building packages using all three main compilers, and noticed that I have problems with gdc every time and need to tweak code because of many things missing. For example: https://travis-ci.org/crimaniak/json-patch/jobs/386963340 Why this situation with gdc and how best to deal with it? The build log seems to indicate it uses gdc 4.8, while the current version of GDC is 8.1 which is based on the 2.076 frontend. Maybe just updating GDC on Travis will fix this.
Re: How are switches optimized
On Friday, 1 June 2018 at 21:18:25 UTC, IntegratedDimensions wrote: If one has a switch of N case then the last cost surely does not cost N times the cost of the first, approximately? It depends on the compiler and optimization level. In general, no optimization or just a handful of cases means it's as if you wrote a bunch of if-then-else statements. When there are many cases, a jump table is the go-to way to optimize it. But the compiler may do more clever transformations: ``` void smallCase(); void largeCase(); void defaultCase(); int switchfunc(int i) { switch(i) { case 8: .. case 64: smallCase(); return 1; case 256: .. case 512: largeCase(); return 2; default: defaultCase(); return 3; } } ``` Even though the front end expands the ranged cases to individual case statements, LDC with -O1 or higher will actually output code akin to this: ``` int switchfunc(int i) { if (cast(uint) (i - 256) >= 257) { if (cast(uint) (i - 8) > 56) { smallCase(); return 1; } defaultCase(); return 3; } largeCase(); return 2; } ``` Notice how even though I put the 256-512 range second, LDC chose to check it first because it's a larger range than 8-64. Also notice the use of unsigned integer underflow to check whether an integer is in a certain range. Something I like to do for text reading functions is this: ``` bool isOneOf(string str)(char chr) { switch (chr) { static foreach(c; str) { case c: return true; } default: return false; } } alias isHexadecimalDigit = isOneOf!"abcdefABCDEF0123456789"; ``` This will efficiently check if a character is in a compile-time known character set using compile-time optimizations. While DMD makes a jumptable for this, LDC actually transforms it into this: ``` bool isHexadecimalDigit(char chr) { ubyte x = cast(ubyte) (chr - 48); if (x > 54) return false; return (0b11001100011 >> x) & 1; } ``` The cases can be encoded in a binary number that is shifted by the value of the character, so that the correct boolean return value (1 or 0) ends up as the least significant bit. DMD uses the same trick if you write it in this way: ``` return (chr == 'a' || chr == 'b' || chr == 'c' || ...); ``` So the most common optimization is indexing in (jump) tables, but smart transformations are done too sometimes. By the way, a chain of if-then-else statements may also be optimized as if it was written in a switch statement. If you want to see how the compiler optimizes your switch statement, check out run.dlang.io (DMD and LDC, press ASM button) or d.godbolt.org (DMD, LDC and GDC).
Re: GDC on Travis-CI
On Saturday, 2 June 2018 at 10:49:30 UTC, rjframe wrote: There is documentation for older Phobos versions online, but I don't remember the link and haven't found it by searching. https://docarchives.dlang.io/
Re: Generate documentation for mixin'd function?
On Fri, 01 Jun 2018 22:48:41 -0600, Jonathan M Davis wrote: > > It's currently possible to put ddoc on template mixins but not string > mixins: > > https://issues.dlang.org/show_bug.cgi?id=2420 > > It was fix for template mixins with > > https://issues.dlang.org/show_bug.cgi?id=648 > > but has yet to be fixed for string mixins. > > - Jonathan M Davis Thank you. --Ryan
Re: GDC on Travis-CI
On Sat, 02 Jun 2018 03:15:56 +, crimaniak wrote: > I started to work with Travis-CI, building packages using all three main > compilers, and noticed that I have problems with gdc every time and need > to tweak code because of many things missing. > For example: https://travis-ci.org/crimaniak/json-patch/jobs/386963340 > Why this situation with gdc and how best to deal with it? GDC is on the 2.068 frontend, so you can't use any symbols introduced since then. There is documentation for older Phobos versions online, but I don't remember the link and haven't found it by searching.
Re: Debugging silent exit of threads in Phobos calls (bugzilla issue submitted)
On Saturday, 2 June 2018 at 09:52:59 UTC, Russel Winder wrote: I get ldc2 from the Debian/Fedora repositories and dmd from d-apt (no Fedora equivalent) I really want to avoid fiddling with files that are installed via packaging. Though I guess any changes can be fixed by a reinstallation of the package. Editing in place would be the easiest and shouldn't be a problem, but at least ldc is relocatable: import folder is specified in config, so you can have it anywhere.
Re: Debugging silent exit of threads in Phobos calls
On Fri, 2018-06-01 at 16:19 -0400, Steven Schveighoffer via Digitalmars-d-learn wrote: > On 6/1/18 1:41 PM, Russel Winder wrote: > > struct Datum { > > public const int a; > > public const int b; > > } > > > > struct Message { > > Datum datum; > > } > > I found the bug. Basically, the Variant static if is failing because > the > assignment it is checking (assigning a Message to a Message) would > overwrite const data. But it's not really overwriting existing data, > it's emplacing into new data (always). So this check is not correct. I think then my bug report 18934 is slightly wrong and it isn't the struct within struct that is the problem, it is the const fields in a struct that is? > Much simpler test case: > > struct S > { > const int x; > } > > void main() > { > import std.variant; > import std.stdio; > Variant v = S(1); > writeln(v.get!S); // same failure > } > Aha, much nicer since it is far more localised to the issue. I was still focused on the receive and the struct within struct, which seems to be the wrong issue: it is the const fields that are the problem. Feel free to ignore my example and stack trace on https://issues.dlang.org/show_bug.cgi?id=18934 and replace it with the above! > If I replace the check in std.variant: > > static if (is(typeof(*cast(T*) target = *src)) || > > with: > > static if (is(typeof(delegate T() {return *src;})) > || > > Then it works (both your code, and the simple example). > > Note that in all cases, variant is returning a COPY of the data, not > a > reference, so it shouldn't be possible to violate const. Excellently done. Thanks for attacking this problem and finding a solution. I will not now even contemplate hacking up my code. Actually I would have put const in and still got a problem it seems, as I had the wrong reason for the problem. > Please, file a bug. I will see if I can submit a PR to fix. > Bug report is 18934. If there can be a fast release of this via 2.080.1 with subsequence fast releases via d-apt and Debian and Fedora packaging, I would be a very happy bunny. In the meantime onward with ACCU 2019 organisation. ACCU needs more D content. Yes it is 50% C++, but that is exactly why it needs D content. It also needs Go content. in 2018 we had Rust content and it went down well. -- Russel. === Dr Russel Winder t: +44 20 7585 2200 41 Buckmaster Roadm: +44 7770 465 077 London SW11 1EN, UK w: www.russel.org.uk signature.asc Description: This is a digitally signed message part
Re: Debugging silent exit of threads in Phobos calls (bugzilla issue submitted)
On Fri, 2018-06-01 at 14:02 -0400, Steven Schveighoffer via Digitalmars-d-learn wrote: > […] > Perfect, put this into a bugzilla entry. Most definitely it's a bug > in > phobos, it's clear from the assert(false, ...) which is NEVER meant > to > happen. Bug report submitted. https://issues.dlang.org/show_bug.cgi?id=18934 Hopefully it is easy to fix and 2.081 can be released quickly as my only way forward is to hack the code to avoid the problem which then essentially destroys the abstractions. OK so it would be a retrievable hack, but one has to draw the line somewhere. Also I have to stop having fun with Me-TV_D and get back on to organising ACCU 2019. It is time D people submitted sessions to ACCU: ACCU 2018 had lots of Rust sessions to counterbalance the C++ stuff and it went down well. > BTW, yes I was saying edit the global phobos sources :) I do this > all > the time to try and debug something. You just have to remember to put > it > back the way it was. In this case, you would just be printing > something > before crashing, so it actually could stay there. > > One "nice" aspect of pretty much everything being a template. I get ldc2 from the Debian/Fedora repositories and dmd from d-apt (no Fedora equivalent) I really want to avoid fiddling with files that are installed via packaging. Though I guess any changes can be fixed by a reinstallation of the package. -- Russel. === Dr Russel Winder t: +44 20 7585 2200 41 Buckmaster Roadm: +44 7770 465 077 London SW11 1EN, UK w: www.russel.org.uk signature.asc Description: This is a digitally signed message part
Re: How are switches optimized
On Friday, 1 June 2018 at 21:18:25 UTC, IntegratedDimensions wrote: What is the best optimizations that a compiler does to switches in general and in the D compilers? The best possible depends a lot on the specific case at hand. Best possible is to fully elide the switch, which does happen. You can use d.godbolt.org to investigate what happens for different pieces of code. Sometimes a jumptable is used, sometimes an if-chain. LLVM's (LDC) and GCC's (GDC) optimizers are strong and the optimized code will often do extra calculations before indexing in the table or before doing the comparisons in the if-chain. Different compilers will make different optimizations. https://godbolt.org/g/pHptff https://godbolt.org/g/AwZ69o A switch can be seen as if statements, or safer, nested if elses. but surely the cost per case does not grow with depth in the switch? If one has a switch of N case then the last cost surely does not cost N times the cost of the first, approximately? Depends on the code, but it's not O(N). This is the cost when implementing a switch as nested ifs. Not true. Nested if's are optimized as well. Sometimes switch is faster, sometimes if-chain, sometimes it's the same. Tables can be used to give O(1) cost, are these used in D's compilers? Yes (LDC and GDC). How are they generally implemented? Hash tables? If the switch is on an enum of small values is it optimized for a simple calculating offset table? Table stored in the instruction stream. Simple offset table with calculation on the index value (I guess you could say it is a simplified hash table). Note that with performance, the rest of the program and the execution flow also matters... cheers, Johan