Re: "in" operator gives a pointer result from a test against an Associative Array?
On Friday, 10 May 2024 at 00:18:16 UTC, Andy Valencia wrote: tst7.d(6): Error: cannot implicitly convert expression `e in this.members` of type `bool*` to `bool` tst7.d(15): Error: template instance `tst7.Foo!uint` error instantiating I'm getting this for this bit of source (trimmed from the bigger code). I switched to this.members.get(e, false) and that works fine, but I'm still curious: struct Foo(T) { bool[T] members; bool has(T e) { return (e in this.members); } } void main() { import std.stdio : writeln; auto t = Foo!uint(); writeln(t.has(123)); } Yes. The reason for this is that it avoids having to essentially do the same check twice. If `in` returned a bool instead of a pointer, after checking for whether the element exists (which requires searching for the element in the associative array), you'd then have to actually *get* it from the array, which would require searching again. Returning a pointer to the element if it exists (or `null` if it doesn't) cuts this down to 1 operation.
Re: A look inside "filter" function defintion
On Monday, 1 August 2022 at 23:35:13 UTC, pascal111 wrote: This is the definition of "filter" function, and I think it called itself within its definition. I'm guessing how it works? '''D template filter(alias predicate) if (is(typeof(unaryFun!predicate))) { /** Params: range = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) of elements Returns: A range containing only elements `x` in `range` for which `predicate(x)` returns `true`. */ auto filter(Range)(Range range) if (isInputRange!(Unqual!Range)) { return FilterResult!(unaryFun!predicate, Range)(range); } } ''' I think this line needs explanation: '''D return FilterResult!(unaryFun!predicate, Range)(range); ''' To give a vastly simplified answer, the term "eponymous template" essentially means that if you have an item declared inside a template that has a same name as the template: ```D template SomeTemplate(T) { alias SomeTemplate = T; } ``` It is not a compile error. Instead, when you use the template: ```D SomeTemplate!int n; ``` The compiler rewrites your code like to: ```D SomeTemplate!int.SomeTemplate n; ``` Because normally when you instantiate a template, you have to refer to the declarations inside it by name: ```D template SomeOtherTemplate(T) { alias SomeAlias = T; } //SomeOtherTemplate!int n; Error: `SomeOtherTemplate!int` is used as a type SomeOtherTemplate!int.SomeAlias n; //Ok ``` Except in the special case I outlined above. It's essentially a hack that was brought over from C++. It makes using templates more ergonomic.
Re: Fix template parameter
On Monday, 8 August 2022 at 12:02:02 UTC, Dom Disc wrote: Hello. I found in the documentation functions declared like this: ```D pure @nogc @safe BigInt opAssign(T : BigInt)(T x); ``` This is a template function, even if T is constrained to always be BigInt (it may also include anything that is a subtype of BigInt... I've received different answers on what exactly `(T: SomeType)` means in this context). This means that it cannot be virtual, you can't take its address, and as bauss said, it won't show up in the object file if it's not used. As far as I know, there's no advantage to doing this over `opAssign(BigInt x)`, UNLESS `(T: BigInt)` means "BigInt and any subtype of BigInt", in which case the advantage is similar to doing ` void opAssign(T val)` in Java (referring to polymorphism; this won't give you virtual dispatch like it does in Java).
Re: Colors in Raylib
On Tuesday, 1 March 2022 at 15:37:55 UTC, Ali Çehreli wrote: On 3/1/22 07:19, Mike Parker wrote: > On Tuesday, 1 March 2022 at 13:15:09 UTC, meta wrote: > >> >> enum Color >> { GRAY } >> >> void setColor(Color color); >> >> setColor(GRAY); > > Then that defeats the purpose of having named enums. Yes and no. meta is pointing at a difference between the above and the following: writeln(GRAY); In the latter case, the compiler has no clue whether I intended to type GRAM. But in the former case, the type is Color. What remains is whether the compiler should be looking deep into Color and have a list of values to lower GRAY to Color.GRAY. We heard this before for the switch statement: When the variable is Color, the case values can be accepted as Color as well (without the qualifier). (Yes, 'with' works as well, but the idea is the same.) It feels the same for even int because we don't write int(42) when passing an int argument: void foo(int) {} foo(int(42)); // works foo(42); // works as well So the lack of this compiler help does not bother me but still, I think the request is meaningful. Ali Yes, that's exactly the point I was trying to make, thanks Ali!
Re: Colors in Raylib
On Tuesday, 1 March 2022 at 12:29:56 UTC, Steven Schveighoffer wrote: On 3/1/22 7:22 AM, meta wrote: If the type is ``Color`` I think the compiler should allow ``GRAY`` if it is a member of ``Color``, isn't how strong statically typed language should work? I wonder what is the rational against it? How hard would it be to allow it? The problem is how the original source works. The only way to define a manifest constant for a struct instance in C is to #define it. So I'm sure that if raylib could put that inside the `Color` type it would, but it can't. What a D binding should do is exactly what Mike said -- provide a complete binding as expected, and then add machine-generated nicer APIs. I actually have an open issue, in case anyone is interested in working on it: https://github.com/schveiguy/raylib-d/issues/8 -Steve Oh I was talking with regard to D's enum, not about the binding, allowing it via D, would make interfacing with C code easier enum Color { GRAY } void setColor(Color color); setColor(GRAY);
Re: Colors in Raylib
If the type is ``Color`` I think the compiler should allow ``GRAY`` if it is a member of ``Color``, isn't how strong statically typed language should work? I wonder what is the rational against it? How hard would it be to allow it?
Re: https://run.dlang.io/ vs All dmd compilers (2.060 - latest)
Is the source of 'run.dlang.io' available somewhere?
Re: split Error - no overload matches
A trick i use often: ```D import std; void main() { import uni = std.uni; writeln("Learning D is fun".split!(uni.isWhite)); } ``` Under-rated way of importing things, you don't bloat your scope anymore
Re: What is the meaning of @future ?
On Friday, 17 September 2021 at 10:31:34 UTC, bauss wrote: On Thursday, 16 September 2021 at 20:53:34 UTC, Elmar wrote: Hello D community. I was browsing the `__traits` keywords and I found `isFuture` whose descriptions says something about `@future`-annotated variables. [link](https://dlang.org/spec/traits.html#isFuture) I didn't find anything about `@future` for the D programming language. I only found that this annotation is used in Apex to denote futures (a.k.a. promises) as programming concept. Is this something which exists, existed, was abandoned early as an idea? I remember I had read that D uses a "fiber" library to provide coroutines and such. Maybe somebody knows an answer for this. It's just another "useless" attribute that the language has added before fixing any of the real problems :) Basically it reserves a symbol for the future. It's similar to creating ex. an empty function that throws an error or something like "Not implemented" While I understand why it was added and what purpose it serves then I fail to see why that was prioritized over actual issues. It's solving an almost non-existing issue. I think the main reason it was added is because Sociomantic asked for it, but they are of course not around anymore.
Re: nothrow and std.exception.ifThrown
On Friday, 30 April 2021 at 13:42:49 UTC, Steven Schveighoffer wrote: On 4/30/21 9:24 AM, Meta wrote: My point is that I think marking the *function* nothrow is not correct, it's the second parameter that dictates the throwing of the result. And you can probably fix the second parameter to be a templated delegate: ```d CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, scope T2 errorHandler) if (is(typeof(errorHandler(E.init ``` And of course, we get into chicken-and-egg problems with this because if you pass in a lambda, there's no types for it to figure this stuff out. Another option is to overload on the delegate, but meh. I'd really like to see a language change that says "infer the attributes of this function based on the fact that it calls the delegate passed in." -Steve Now that you mention it, I don't see why lazy parameters can't have their attributes inferred. What happened to the DIP to replace lazy parameters with automatic conversion of passed values to delegates, anyway? I.e.: ``` CommonType!(T1, T2) ifThrown(E: Throwable = Exception, T1, T2)(scope T1 delegate() expression, scope T2 delegate() errorHandler); //getString() and "some string" automatically converted to `string delegate()` auto s = getString().ifThrown("some string"); ```
Re: nothrow and std.exception.ifThrown
On Thursday, 29 April 2021 at 20:00:23 UTC, novice2 wrote: i dont understand why (templates too dificult for me yet), but if i comment "lazy" from T2, then compiler allow add "nothrow" to "ifThrown" ```d CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, /*lazy*/ scope T2 errorHandler) nothrow ``` https://run.dlang.io/is/KTdd3G This is because marking a function parameter as `lazy` is just syntax sugar for the following: ``` CommonType!(T1, T2) ifThrown(E: Throwable = Exception, T1, T2)(scope T1 delegate() expression, scope T2 delegate() errorHandler); string def = "some string"; auto s = format("%d", x).ifThrown({ return def; }); ``` Behind the scenes, a `lazy` parameter is not really a value - it's a function that _returns_ a value. The problem is that this function is not `nothrow`, and can't be marked as such (this is arguably a gap in the language). Removing `lazy` changes `errorHandler` to be a plain old value again - which cannot throw an exception, of course - so `ifThrown` can be marked `nothrow`. However, you lose all the benefits of `errorHandler` being lazily computed.
Re: nothrow and std.exception.ifThrown
On Friday, 30 April 2021 at 13:05:00 UTC, Steven Schveighoffer wrote: On 4/29/21 1:50 PM, Meta wrote: The reason for this, apparently, is in the definition of `ifThrown`: ``` CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, lazy scope T2 errorHandler) nothrow ``` It's not marked as `nothrow` in the function's definition, so even if the delegate passed to ifThrown _is_ nothrow, the compiler can't tell. There's no easy way around this that I can think of OTOH that doesn't involve some effort on your part. Wait, I don't get what you are saying. You mean it should be marked nothrow? It's a template, so it *should* be inferred nothrow if it were actually nothrow. The current definition is not marked nothrow as you alluded, and when I do mark it nothrow, it complains that the lazy parameter used for the exception handler is not nothrow. It seems there's no way to infer the throwing of the lazy parameter, lazy parameters are never nothrow. The higher order function DIP would I think help with this. -Steve Change it to a delegate and it's the same thing. ifThrown being a template is irrelevant in this case because it is accepting the handler as a function argument, not a template argument. You: 1. Need to make it a delegate instead of a lazy argument. 2. Need to mark the delegate as nothrow. For the function to be inferred as nothrow.
Re: nothrow and std.exception.ifThrown
On Thursday, 29 April 2021 at 16:02:20 UTC, novice2 wrote: Hello. I need use std.format.format() in nothrow function. format() can throw. For this case i have special default string. I don't want embrace format into try..catch block, and i found elegant std.exception.ifThrown. But DMD say "ifThrown not nothrow" https://run.dlang.io/is/kXtt5q ```d nothrow string foo(int x, string def) { import std.format: format; import std.exception: ifThrown; return format("%d", x).ifThrown(def); } Error: function std.exception.ifThrown!(Exception, string, string).ifThrown is not nothrow ``` What i can use instead of ifThrown, or how it can be changed to nothrow? Thanks. The reason for this, apparently, is in the definition of `ifThrown`: ``` CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, lazy scope T2 errorHandler) nothrow ``` It's not marked as `nothrow` in the function's definition, so even if the delegate passed to ifThrown _is_ nothrow, the compiler can't tell. There's no easy way around this that I can think of OTOH that doesn't involve some effort on your part. One thing you can do is wrap ifThrown with `std.exception.assumeWontThrow`: ``` import std.exception: ifThrown, assumeWontThrow; import std.functional: pipe; alias ifThrown = pipe!(std.exception.ifThrown, assumeWontThrow); nothrow string foo(int x, string def) nothrow { import std.format: format; return format("%d", x).ifThrown(def); } ```
Re: Is there a more elegant way to do this in D?
On Thursday, 8 April 2021 at 18:01:56 UTC, Meta wrote: On Thursday, 8 April 2021 at 12:19:29 UTC, WebFreak001 wrote: ```d string to01String(int[] x) @safe { auto conv = x.to!(ubyte[]); // allocates new array, so later cast to string is OK conv[] += '0'; // assume all numbers are 0-9, then this gives the correct result return (() @trusted => cast(string)conv)(); } ``` The @trusted lambda can also be replaced with [std.exception.assumeUnique](https://dlang.org/library/std/exception/assume_unique.html). Never mind me, assumeUnique is @system (or at least it's inferred as @system), and anyway, you can't implicitly convert `immutable(ubyte)[]` to `immutable(char)[]`.
Re: Is there a more elegant way to do this in D?
On Thursday, 8 April 2021 at 12:19:29 UTC, WebFreak001 wrote: ```d string to01String(int[] x) @safe { auto conv = x.to!(ubyte[]); // allocates new array, so later cast to string is OK conv[] += '0'; // assume all numbers are 0-9, then this gives the correct result return (() @trusted => cast(string)conv)(); } ``` The @trusted lambda can also be replaced with [std.exception.assumeUnique](https://dlang.org/library/std/exception/assume_unique.html).
Re: Is this bug ? format %(%)
On Wednesday, 7 April 2021 at 17:31:09 UTC, Paul Backus wrote: On Wednesday, 7 April 2021 at 17:04:56 UTC, novice2 wrote: On Wednesday, 7 April 2021 at 13:43:18 UTC, Paul Backus wrote: So, you should change your code to writefln("%-(%s, %)", s); sorry i dont read docs so carefully thanks It's not your fault--this is a pretty obscure feature, and it's not documented very well. Even after you've found the correct page in the documentation (the page for `formattedWrite` [1]), you have to scroll down past multiple examples to find the text that explains it. [1] https://dlang.org/phobos/std_format.html#formattedWrite I have created a pull request that will hopefully make this more prominent on the doc page: https://github.com/dlang/phobos/pull/7944
Re: Immutable
On Saturday, 27 March 2021 at 20:44:12 UTC, Brad wrote: I was looking through lots of sample code on Rosetta Code. D has a lot of solutions out there. That is really nice but it has me wondering - coming from other languages that do not support the concept of immutability - do real world programmers and/or hobbyists really use it as much as I see it on Rosetta Code? I know it adds a layer of security to your code, but I am still thinking "why?". Thanks for entertaining a newbie question. FYI, most of those examples were written by someone who goes by "Bearophile", and their style of writing D uses immutable/const/pure/nothrow/etc. wherever possible. It's not necessarily the style that all D programmers use, though there are a number of people that do. As for advantages, when it comes to the basic value types (int, float, bool, etc.), it's not all that useful. Where immutable can become very useful, though, is with types that have indirections (i.e. pointers). D's `string` type, for example, is actually a simple alias in Druntime: alias string = immutable(char)[]; Meaning "a mutable array of immutable chars". This means that you can modify the array itself, such as changing its length, appending to it, etc., but you cannot its individual elements. E.g., the following will work: string s1 = "this is a string"; s1 ~= '.'; assert(s1 == "this is a string."); But this will NOT work: string s2 = "this is a string "; s2[$ - 1] = '.'; Error: cannot modify immutable expression s2[__dollar - 1LU] This is just a simple example, but it allows the compiler to do some major optimizations on string handling code. Something that is usually very slow in C/C++ is such code, because strings are mutable arrays of mutable characters. Thus, they have to be copied around everywhere, which is slow and uses a lot of memory unnecessarily. Not so in D; because strings are mutable arrays of immutable characters, you can freely pass out references to the whole string, or a subrange of it. This would be very dangerous in C/C++, but in D you don't have to worry about the string changing out from under you by some code somewhere else in the program that you gave a reference to. Thus, string handling code is far faster in D than in C/C++. That is just one example, but you can see how immutable makes possible a lot of optimizations that would simply be impossible in languages without it.
Re: Very confusing error message when calling a class method from an invariant
On Wednesday, 10 March 2021 at 04:57:19 UTC, Paul Backus wrote: On Wednesday, 10 March 2021 at 03:39:15 UTC, Meta wrote: class Human { static immutable MAX_AGE = 122; bool alive = true; int age = 0; //Error: mutable method onlineapp.Human.checkAge is not callable using a const object invariant(checkAge()); [...] What the hell does this even mean, and where does it come from? Adding `inout` to `checkAge` actually does cause it to compile and run too. WTF? From the language spec [1]: The invariant is in the form of a const member function. So, inside the invariant, the object is treated as const, which means you can't modify it and can only call const methods. [1] https://dlang.org/spec/class.html#invariants Now that you mention it, I'm pretty sure I've run into this before; I must've forgotten about it. I understand the rationale behind this, but it doesn't really make sense IMO that only invariants treat the object as const, and not pre/post conditions as well. Ah well. Thanks for quick answer.
Very confusing error message when calling a class method from an invariant
class Human { static immutable MAX_AGE = 122; bool alive = true; int age = 0; //Error: mutable method onlineapp.Human.checkAge is not callable using a const object invariant(checkAge()); void growOlder() in(alive) out(; checkAge()) { age++; if (age > MAX_AGE) die(); } void die() in(alive) out(; !alive) { alive = false; } bool checkAge() { return age >= 0 && age <= MAX_AGE || !alive; } } void main() { Human h = new Human(); h.growOlder(); } What the hell does this even mean, and where does it come from? Adding `inout` to `checkAge` actually does cause it to compile and run too. WTF?
Re: opBinary : Static ifs or specialization?
On Tuesday, 23 June 2020 at 23:53:36 UTC, claptrap wrote: So you have opBinary and half a dozen operators to implement. Do you use a separate method for each operator or do you have one method and a big static if else if to select code path? I assume they are functionally equivalent? So its just about style? An idiomatic example: import std.algorithm: among; struct Test { int payload; Test opBinary(string op)(Test other) if (op.among!("+", "-", "*", "/")) //Limit supported ops { mixin("return Test(payload " ~ op ~ "other.val);"); } int opBinary(string op)(int n) //No constraint; support the full range of integer operations { mixin("return payload " ~ op ~ "n;"); } }
Re: Should a parser type be a struct or class?
On Wednesday, 17 June 2020 at 11:50:27 UTC, Per Nordlöw wrote: Should a range-compliant aggregate type realizing a parser be encoded as a struct or class? In dmd `Lexer` and `Parser` are both classes. In general how should I reason about whether an aggregate type should be encoded as a struct or class? IMO it doesn't need to be. However, it's worth saying that range semantics aren't a great fit for parsers - at least that's been my experience. Parsers need to be able to "synchronize" to recover from syntax errors, which does not fit into the range API very well. You can probably fit it in somewhere in popFront or front or empty, as your implementation permits, but I find it's just easier to forego the range interface and implement whatever primitives you need; *then* you can add a range interface over top that models the output of the parser as a range of expressions, or whatever you want.
Re: Retrieve the return type of the current function
On Tuesday, 5 May 2020 at 18:19:00 UTC, Meta wrote: mixin template magic() { alias CallerRet = typeof(return); CallerRet magic() { return CallerRet.init; } } Small edit: you can remove the "CallerRet" alias by doing the following: mixin template magic() { typeof(return) magic() { return typeof(return).init; } } Though I wouldn't really recommend it as it's very confusing, IMO. This works because "typeof(return)" in the return position here refers to the caller's scope, while "typeof(return)" inside the function refer's to the function's scope.
Re: Retrieve the return type of the current function
On Tuesday, 5 May 2020 at 17:11:53 UTC, learner wrote: On Tuesday, 5 May 2020 at 16:41:06 UTC, Adam D. Ruppe wrote: typeof(return) Thank you, that was indeed easy! Is it possible to retrieve also the caller return type? Something like: ``` int foo() { return magic(); } auto magic(maybesomedefaulttemplateargs = ??)() { alias R = __traits(???); // --> int! } ``` Mixin templates maybe? You *can* use mixin templates to access the caller's scope, which means typeof(return) will refer to the caller's return type, instead of the callee's. However, there's no way to both mixin and call the mixin template in a single line, so it's not DRY: int foo() { mixin magic; return magic(); } mixin template magic() { alias CallerRet = typeof(return); CallerRet magic() { return CallerRet.init; } } void main() { foo(); } Maybe somebody else knows a way to get around having to first mixin magic.
Re: Checked!({short, ushort, byte, char}, Throw): compilation fails
Unlike C/C++, char is not a numeric type in D; It's a UTF-8 code point: import std.traits; void main() { pragma(msg, isNumeric!char); //Prints false }
Re: Discord bot written in D
On Monday, 6 April 2020 at 21:23:22 UTC, Quantium wrote: Are there any libraries to creade a simple discord bot using D? And if you know these libraries, could you day me their pros and cons? I've used https://github.com/b1naryth1ef/dscord to build a Discord bot, a little over a year ago. However, it didn't even seem that actively maintained back then; I had to patch over at least one bug. Other than that, though, it worked smoothly and was easy to get started with.
Re: `in` parameters optimization
On Wednesday, 25 December 2019 at 01:24:52 UTC, Adnan wrote: Does the compiler automatically pass values by reference if possible with `in` parameters in higher level of optimization flags? I would normally use `in ref` but sometimes it's not compatible with different types. No. "in" is short for "const scope" (https://dlang.org/spec/function.html#param-storage). The only mechanism D has for expressing "pass this argument by ref if possible, and by value otherwise" is "auto ref" (https://dlang.org/spec/function.html#auto-ref-functions), which requires your function to be templated.
Re: Using map result type
On Wednesday, 11 December 2019 at 20:08:37 UTC, Meta wrote: import std.algorithm; import std.range; void mapAccepter(E)(InputRange!E r) { import std.array: array; import std.stdio: writeln; auto collected = r.array; writeln(collected); } void main() { int[] nums = [1, 2, 3]; auto evenness = inputRangeObject(map!(n => n % 2 == 0)(nums)); mapAccepter(evenness); } I guess I should mention, that if you are expecting a range of booleans, you can of course write mapAccepter as a non-templated function: void mapAccepter(InputRange!bool r); But if you want to support any type of input range, the function needs to at least be templated on the element type of the range.
Re: Using map result type
On Sunday, 8 December 2019 at 01:10:21 UTC, AA wrote: I'd like to accept the return type of map. From some previous questions that I should accept a template? So for something like: ``` void mapAccepter(Range)(Range r) { import std.array : array; import std.stdio : writeln; auto collected = r.array; writeln(collected); } void main() { import std.algorithm.iteration : map; int[] nums = [1, 2, 3]; auto evenness = map!(n => n % 2 == 0)(nums); mapAccepter(evenness); } ``` 1) Is there any way I can make `mapAccepter` not a templated function? Yes (mostly, anyway), using the interfaces in std.range.interfaces: https://dlang.org/phobos/std_range_interfaces.html import std.algorithm; import std.range; void mapAccepter(E)(InputRange!E r) { import std.array: array; import std.stdio: writeln; auto collected = r.array; writeln(collected); } void main() { int[] nums = [1, 2, 3]; auto evenness = inputRangeObject(map!(n => n % 2 == 0)(nums)); mapAccepter(evenness); } `mapAccepter` still needs to be templated on the element type of the range, but there are ways to avoid that as well, if desired. I wouldn't recommend it, however, as it wouldn't be that useful in this case. 2) Is there any way if I need to make `mapAccepter` templated to constrain Range to be a range of booleans. Yup, there are two ways that you you primarily do that. Either constraining E in the template declaration, or adding a constraint on the template. Generally option 2 is the more idiomatic D way. Option 1: constrain E to be of type bool: void mapAccepter(E: bool)(InputRange!E r); OR void mapAccepter(E)(InputRange!E r) if (is(E == bool)); There's not much difference between these two, but the latter is probably preferred. Option 2: use std.traits and a template constraint: void mapAccepter(E)(InputRange!E r) if (is(ElementType!r == bool));
Re: Unexpectedly nice case of auto return type
On Tuesday, 3 December 2019 at 22:11:39 UTC, Meta wrote: On Tuesday, 3 December 2019 at 17:45:27 UTC, H. S. Teoh wrote: The thing is, `void` means "no return type" (or "no type" in some contexts), i.e., void == TBottom in that case. Not *quite* correct. void is not a bottom type; it's a unit type, meaning that it's a type with only 1 value (as is null, interestingly). void does not mean "no return type"; it means "there's only 1 possible value that can be returned". A function returning TBottom means that the function will never return, e.g., it loops forever, or throws an exception, etc. Whoops, skimmed over the post already mentioning this.
Re: Unexpectedly nice case of auto return type
On Tuesday, 3 December 2019 at 17:45:27 UTC, H. S. Teoh wrote: The thing is, `void` means "no return type" (or "no type" in some contexts), i.e., void == TBottom in that case. Not *quite* correct. void is not a bottom type; it's a unit type, meaning that it's a type with only 1 value (as is null, interestingly). void does not mean "no return type"; it means "there's only 1 possible value that can be returned". A function returning TBottom means that the function will never return, e.g., it loops forever, or throws an exception, etc. I agree with the OP that it's silly not to give typeof(null) a name. As null is a unit type, we could easily have `null` stand in for typeof(null) as well. A type that contains only one value can be synonymous with that value (see also, Rust's unit type (), which has one value, ()).
Re: Alternative to C++ macro in D
On Sunday, 3 November 2019 at 16:55:36 UTC, Vinod K Chandran wrote: Hi all, I can do this in C++. #include using namespace std ; #define end }; #define log(x) cout << x << endl #define wait std::cin.get() int main() { log("Trying to avoid the visual clutter aused by closing curly braces") ; string myStr = "Now, code looks more elegant" ; log(myStr) ; mixin template cToD(string code) `log` and `wait` are straightforward. Just write a function: import std.stdio; void log(T)(T x) { writeln(x); } void wait() { readln(); } However, you can't do things like `#define end }`. The D language intentionally disallows doing stuff like this. If you *really* want to do this, you can sort of emulate it with mixins: mixin template cToD(string code) { import std.array: replace; mixin(code.replace("end", "}")); } mixin cToD!` int main() { log("Trying to avoid the visual clutter aused by closing curly braces") ; string myStr = "Now, code looks more elegant" ; log(myStr) ; wait ; return 0; end `; But I would strongly recommend against it.
Re: Elegant way to test if members of array A are present in array B?
On Tuesday, 11 June 2019 at 17:12:17 UTC, Robert M. Münch wrote: Is there a simple and elegant way to do this? Or is just using a foreach(...) with canFind() the best way? There are two versions of find that can find a range within another: https://dlang.org/phobos/std_algorithm_searching.html#.find https://dlang.org/phobos/std_algorithm_searching.html#.find.3
Re: How to debug long-lived D program memory usage?
On Wednesday, 17 April 2019 at 22:37:38 UTC, Adam D. Ruppe wrote: On Wednesday, 17 April 2019 at 19:07:46 UTC, Jacob Carlborg wrote: Perhaps try some of these flags [1] and [2]. oooh, those are very interesting too. What I was kinda hoping is it would have stats for which file and line of code was responsible for most allocations; a detailed profile. But even so, this is an interesting gem. Not at all what you want, but it may be useful for figuring out where the leaks are. Have you tried compiling with -vgc? https://dlang.org/dmd-windows.html#switch-vgc
Re: Block statements and memory management
On Saturday, 16 March 2019 at 03:47:43 UTC, Murilo wrote: Does anyone know if when I create a variable inside a scope as in {int a = 10;} it disappears complete from the memory when the scope finishes? Or does it remain in some part of the memory? I am thinking of using scopes to make optimized programs that consume less memory. I'd recommend against these sorts of micro-optimizations. Compilers are every good at doing this kind of thing manually so you don't have to worry about it and can concentrate on the actual logic of your program.
Re: Query for -dip1000
On Sunday, 10 February 2019 at 20:04:29 UTC, Per Nordlöw wrote: Is there a way to query if the -dip1000 flag has been passed to the compiler? I need it for enabling certain DIP-1000 escape analysis tests only when -dip1000 has been passed. For instance static assert(!__traits(compiles, { char[] f() { char[2] x; return x[].splitterASCII!(_ => _ == ' ').front; } })); at https://github.com/nordlow/phobos-next/blob/bd2fe42978aab2313977042c858d77c5766538e8/src/splitter_ex.d#L110 Or do I have to write a trait myself? https://issues.dlang.org/show_bug.cgi?id=19669
Re: Implement Interface Using Super
On Wednesday, 30 January 2019 at 01:02:37 UTC, Jonathan M Davis wrote: Yeah. It would be like trying to do something like alias x = this.x; As it stands, I believe that super is always either used as a function call to the constructor or to mean the this pointer for the base class. I don't think that it ever means the type of the base class - just like this never means the type of the current class or struct. And their usage is pretty much identical. They're both either used for calling a constructor or for accessing the pointer/reference of the object. It's just that one of them is for the current class or struct, whereas the other is for a base class of the current class. The only difference in syntax that I can think of between them at the moment is that this is also used to name constructors when they're declared, whereas super is not used in that sort of way (since any constructor that would be referenced by super would be declared with this, not super). - Jonathan M Davis Current, you *can* use `super` to mean the type of the base class, but it's been deprecated in a recent release (IIRC): class Super { } class Sub { super test() { return new Super(); } } void main() { (new Sub()).test(); } From DPaste: Up to 2.080.1: Success and no output Since 2.081.2: Success with output: onlineapp.d(7): Deprecation: Using `super` as a type is deprecated. Use `typeof(super)` instead
Re: Implement Interface Using Super
On Monday, 28 January 2019 at 22:17:56 UTC, Steven Schveighoffer wrote: On 1/28/19 3:28 PM, Jonathan Levi wrote: On Sunday, 27 January 2019 at 09:31:46 UTC, bauss wrote: On Sunday, 27 January 2019 at 05:37:57 UTC, Jonathan Levi wrote: This works in LDC *but not* DMD? . . . Is this a bug in DMD *or* in LDC? There is no bug here. So... LDC is the one that is bugged? Yeah, that's odd. It should be the same result, as they both have the same semantics for the front end. I'll defer to an LDC developer to answer that, but in truth, it really should be the way LDC implements it, even if that's not how the language spec is. I think it would have been nice to have a way of explicitly use the super method to implement an interface without having to rewrite the whole signature. I thought I remember seeing a way once, but I must have been dreaming. I agree. BTW, the typeof(super) requirement is super-annoying. alias x = super.x; is clear, I don't see why we need to specify typeof(super) in this context at least. -Steev It's because aliases do not support context pointers, I'm pretty sure.
Re: Why tuples are not ranges?
On Thursday, 28 June 2018 at 17:00:37 UTC, Mr.Bingo wrote: I mean, if you think about it, the memory layout of a tuple is sequential types: T1 T2 ... So, to popFront a tuple is just changing the starting offset. You're right; it can definitely be done. struct TupleRange(T...) { size_t index; Tuple!T store; @property length() { assert(index <= store.length); return store.length - index; } Algebraic!T front() { assert(length > 0); return typeof(return)(store[index]); } void popFront() { assert(length > 0); index++; } }
Re: foreach DFS/BFS for tree data-structure?
On Thursday, 14 June 2018 at 11:31:50 UTC, Robert M. Münch wrote: I have a simple tree C data-structure that looks like this: node { node parent: vector[node] children; } I would like to create two foreach algorthims, one follwing the breadth first search pattern and one the depth first search pattern. Is this possible? I read about Inputranges, took a look at the RBTree code etc. but don't relly know/understand where to start. While it's possible to do with input ranges, it's not pretty and I'm not sure that it's as performant as the traditional method. I would recommend going with one of the other suggestions in this thread.
Re: What is the point of nothrow?
On Monday, 11 June 2018 at 04:11:38 UTC, Bauss wrote: On Monday, 11 June 2018 at 00:47:27 UTC, Jonathan M Davis wrote: On Sunday, June 10, 2018 23:59:17 Bauss via Digitalmars-d-learn wrote: What is the point of nothrow if it can only detect when Exception is thrown and not when Error is thrown? It seems like the attribute is useless because you can't really use it as protection to write bugless, safe code since the nasty bugs will pass by just fine. I'm aware that it's a feature that nothrow can throw Error, but it makes the attribute completely useless because you basically have no safety to guard against writing code that throws Error. To an extend @safe works, but there are tons of stuff that throws Error which you can only detect and guard against manually. So what is the point of nothrow when it can only detect exceptions you'd catch anyway. To me it would be so much more useful if you could detect code that could possibly throw Error. Why do you care about detecting code that can throw an Error? Errors are supposed to kill the program, not get caught. As such, why does it matter if it can throw an Error? Now, personally, I'm increasingly of the opinion that the fact that we have Errors is kind of dumb given that if it's going to kill the program, and it's not safe to do clean-up at that point, because the program is in an invalid state, then why not just print the message and stack trace right there and then kill the program instead of throwing anything? But unforntunately, that's not what happens, which does put things in the weird state where code can catch an Error even though it shouldn't be doing that. As for the benefits of nothrow, as I understand it, they're twofold: 1. You know that you don't have to worry about any Exceptions being thrown from that code. You don't have to worry about doing any exception handling or having to ensure that anything gets cleaned up because of an Exception being thrown. 2. If the compiler knows that a function can't throw an Exception, then it doesn't have to insert any of the Exception handling mechanism stuff that it normally does when a function is called. It can assume that nothing ever gets thrown. If an Error does get thrown, then none of the proper clean-up will get done (e.g. constructors or scope statements), but because an Error being thrown means that the program is in an invalid state, it's not actually safe to be doing clean-up anyway. So, the fact that a function is nothrow gives you a performance benefit, because none of that extra Exception handling stuff gets inserted. How large a benefit that is in practice, I don't know, but it is a gain that can't be had with a function that isn't nothrow. - Jonathan M Davis Well at least from my point of view I would care about code that can throw Error, because if say nothrow could detect that then you could prevent writing that code that throws jt at all and thus you'd be writing less error prone code. Maybe not necessarily nothrow, but something else that could ensure that your code is "100% safe" to run without any errors happening from ex. Accessing out of bounds, accessing invalid memory, attempting to access the member of an uninitialized class etc. Like you'd have to handle each such cases. Writing code in D today you have to think about each statement you write and whether it could possibly throw Error because you have little to no tools that helps you preventing writing such code. I'm very well aware that Error is not supposed to be caught and that the program is in an invalid state, but ehat I'm trying to get at is that if nothrow or at least a feature similar existed that could detect code that may throw Error, then you could prevent writing code that throws it in the first place. It would be a great tool to writing bugless code. There's nothing unsafe about Error getting thrown in your code. Error makes your program more safe, because it terminates the program immediately instead of letting it do stuff like corrupt memory or crash the system. Error getting thrown denotes a logic error in your program. Some base assumption you've made is not actually true, and thus the program is in an invalid state and must exit immediately. The reason why nothrow cannot help you here is because these are logic errors that are only detectable at runtime. If it was possible to detect these types of errors at compile time, then there would be no need for Error.
Re: how to define infix function
On Saturday, 2 June 2018 at 23:17:48 UTC, Simen Kjærås wrote: 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 That is interesting. I don't know yet whether it's good or bad, but certainly, it's interesting.
Re: try & catch / repeating code - DRY
On Tuesday, 22 May 2018 at 18:20:43 UTC, Robert M. Münch wrote: I see that I'm writing try { ... different code ... } catch (myException e) { ... same handling code ... } over and over again. Of course I can put the exception handling code into a function to not duplicate it. However, I still need to write this construct over and over again. Is there a way to handle it more generic? Like: ??? (... code ...); or ??? { ... code ...}; Where ??? would do the try and re-use the exception handling code everytime? I hope this is understandable. Have you looked at std.exception.ifThrown? You could define a handler function and pass it to ifThrown for each expression that may throw. If it's a statement, I believe you could wrap it in a lambda which is immediately called, then append .ifThrown(handler).
Re: Creating a template mixin for explicit casts.
On Thursday, 17 May 2018 at 15:25:37 UTC, Sjoerd Nijboer wrote: Given the following code `struct Foo(T) if(isNumeric!T) { T t; .. other code } struct Bar(T) if(isNumeric!T) { T t; .. other code } Foo!float foo_float; Foo!double foo_double; Bar!float bar_float; ` I want to make a template mixin that is able to cast one of these generic structs to the other explicitly. I have a bunch of these structs and therefore I thought it would make sense to do it by template mixin. I just don't know what language or library features I need to use and how to apply them. ` fooDouble = cast (Foo!double) foo_float; // case [1] if possible, done by // an implicit cast. Else by //explicit. fooFloat = cast (Foo!float) foo_double; // case [2] barFloat = cast (Bar!float) foo_float; // case [3] ` How would I do this in D? Before you write anything yourself, check whether std.conv.castFrom does what you need: https://dlang.org/phobos/std_conv.html#castFrom
Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait
On Thursday, 10 May 2018 at 12:55:36 UTC, Uknown wrote: On Thursday, 10 May 2018 at 11:06:06 UTC, Per Nordlöw wrote: On Wednesday, 9 May 2018 at 21:09:12 UTC, Meta wrote: It's a context pointer to the enclosing function/object/struct. Mark the struct as static to get rid of it. Ok, but why an extra void* for `S.tupleof` and not for `T.tupleof` which is also scoped inside a unittest? I'm guessing T is a POD, so it doesn't need a context pointer, whereas S is not counted as a POD since a member function was @disabled. Yes, exactly. From my tests, if you add _any_ member method to a struct, it becomes non-POD. When you think about it, this makes perfect sense, as there's no possible way to access anything through a context pointer if there is no executable code within the struct's scope. As far an @disabled postblit: Plain Old Data A struct or union is Plain Old Data (POD) if it meets the following criteria: it is not nested it has no postblits, destructors, or assignment operators it has no ref fields or fields that are themselves non-PO https://docarchives.dlang.io/v2.079.0/spec/struct.html#POD Now if you do this: struct R { @disable this(this); int* _ptr; } unittest { struct S { @disable this(this); int* _ptr; } struct T { int* _ptr; } pragma(msg, "R: ", typeof(R.tupleof)); pragma(msg, __traits(allMembers, R)); pragma(msg, "S: ", typeof(S.tupleof)); pragma(msg, __traits(allMembers, S)); pragma(msg, "T: ", typeof(T.tupleof)); pragma(msg, __traits(allMembers, T)); } It prints: R: (int*) tuple("__postblit", "_ptr", "__xpostblit", "opAssign") S: (int*, void*) tuple("__postblit", "_ptr", "this", "__xpostblit", "opAssign") T: (int*) tuple("_ptr") So it looks like disabling a struct's postblit actually counts as having a __postblit and __xpostblit function (don't ask me why), in addition to a construction and opAssign... no idea why, and maybe this is a bug, but I bet there's a good reason for it. Anyway, as per my first point, this means it'll need a context pointer unless you mark the struct as static.
Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait
On Wednesday, 9 May 2018 at 18:04:40 UTC, Per Nordlöw wrote: On Wednesday, 9 May 2018 at 17:52:48 UTC, Meta wrote: I wasn't able to reproduce it on dmd-nightly: https://run.dlang.io/is/9wT8tH What version of the compiler are you using? Ahh, the struct needs to be in a unittest block for it to happen: struct R { @disable this(this); int* _ptr; } unittest { struct S { @disable this(this); int* _ptr; } struct T { int* _ptr; } pragma(msg, "R: ", typeof(R.tupleof)); pragma(msg, "S: ", typeof(S.tupleof)); pragma(msg, "T: ", typeof(T.tupleof)); } prints R: (int*) S: (int*, void*) T: (int*) Why is that? It's a context pointer to the enclosing function/object/struct. Mark the struct as static to get rid of it.
Re: Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait
On Wednesday, 9 May 2018 at 14:07:37 UTC, Per Nordlöw wrote: Why (on earth) does struct S { @disable this(this); int* _ptr; } pragma(msg, typeof(S.tupleof)); prints (int*, void*) when struct S { int* _ptr; } pragma(msg, typeof(S.tupleof)); prints (int*) ?!!! I wasn't able to reproduce it on dmd-nightly: https://run.dlang.io/is/9wT8tH What version of the compiler are you using?
Re: Ambiguous template parameter names
On Thursday, 3 May 2018 at 02:48:10 UTC, jmh530 wrote: On Thursday, 3 May 2018 at 00:52:58 UTC, Meta wrote: [snip] It's not a big per se. It's a consequence of the declaration expanding to the real template function form (I can't type it all out as I'm on my phone), thus the inner `val` from the function shadows the one from the template. That makes sense. Before creating the example, I would have assumed that when you instantiate it as foo!1, then the `val=1` would flow through to the inner foo function. template foo(int val) { int foo(int val) { return val; } } If you want that, you might be able to do `int val = val` on the inner function, though I'm not sure that'll work.
Re: Ambiguous template parameter names
On Wednesday, 2 May 2018 at 20:32:43 UTC, jmh530 wrote: In the function below, there is a template parameter and a normal parameter both with the same name. However, the function returns the normal parameter. The template parameter is effectively ignored. I was surprised by this behavior. Is this a bug or intentional? I did not see it documented anywhere. ``` int foo(int val)(int val) { return val; } void main() { assert(foo!1(2) == 2); } ``` It's not a big per se. It's a consequence of the declaration expanding to the real template function form (I can't type it all out as I'm on my phone), thus the inner `val` from the function shadows the one from the template.
Re: Create variable for RedBlackTree range
On Wednesday, 2 May 2018 at 10:39:29 UTC, ag0aep6g wrote: On 04/28/2018 06:36 PM, Gerald wrote: What is the appropriate way to create a variable for the range returned by RedBlackTree lowerBound and upperBound. For example, given this code: ``` RedBlackTree!long promptPosition = redBlackTree!long(); long row = to!long(vte.getVadjustment().getValue()); RBRange!(RBNode!long*) range; [...] } ``` The second line where I declare the range variable as RBRange!(RBNode!long*) the compiler complains with the following warning: Deprecation: std.container.rbtree.RBRange(N) is not visible from module terminal Which makes sense since RBRange is a private struct. RedBlackTree also has public range types: Range, ConstRange, ImmutableRange. And `RedBlackTree!long.Range` is an alias for `RBRange!(RBNode!long*)`. So: RedBlackTree!long promptPosition = redBlackTree!long(); RedBlackTree!long.Range range; For completeness' sake, and if you don't want to re-specify the template parameters you passed to RedBlackTree, you can write: promptPosition.Range range;
Re: Add property-like Function to Type ?
On Tuesday, 24 April 2018 at 21:36:19 UTC, Rubn wrote: I was wondering if I could create my own property in a way that can be used the same way as something like "T.sizeof". Right now I have the following to replace length: uint length32(T)(T[] array) { return cast(uint)array.length; } I want something similar to be able to do the following: uint size = T.sizeof32; The closest I can think of is doing: uint size = sizeof32!T That's the best I can do, which is fine but I was wondering if there's any other way around that? If you don't control T and can't add members, then the best thing you can probably do is instead write T.init.sizeof32. Actually, though, you can be sneaky about it and use a local function to shadow Test, but this is probably more trouble than it's worth: import std.stdio; struct Test { } @property sizeof32(Test t) { return 1; } void main() { @property Test() { return .Test.init; } writeln(Test.sizeof32); } This is really annoying, though, because you have to declare the Test function in every function or struct/class definition you use it in. You can create a mixin that does it automatically, but you'd still have to do `mixin(testProperties)` (where testProperties is an enum you've defined that's just the function definition).
Re: Warning on self assignment
On Wednesday, 25 April 2018 at 02:32:32 UTC, Per Nordlöw wrote: On Wednesday, 25 April 2018 at 02:23:04 UTC, Mike Franklin wrote: Are people using self assignment of structs as a way of force-running the postblit? Is there a valid use case for that? Mike If they are, there should be a better way of force-running the postblit. You can call __postblit or __xpostblit (I think the latter is a postblit introduced via a mixin or template mixin).
Re: Better way to append to array than ~= ?
On Tuesday, 3 April 2018 at 20:02:46 UTC, Vladimirs Nordholm wrote: On Tuesday, 3 April 2018 at 19:53:11 UTC, Meta wrote: On Tuesday, 3 April 2018 at 19:02:25 UTC, Vladimirs Nordholm wrote: [...] In this specific case, since you know the length of `Args`, you can pre-allocate an array of that size and loop through it doing your initialization. However, if you want really performant code, you should allocate a static array on the stack outside of the function and pass it in as a buffer. I don't think I know the size of the arguments. If I pass in "123" and MySpecialType('a'), the result should be: assert(foo("123", MySpecialType('a')) == [MySpecialType('1'), MySpecialType('2'), MySpecialType('3'), MySpecialType('a')]); What should the length of the pre-allocated array be? You know the static types of the arguments, so it is not impossible. However, the more flexible you need to be, the more complex your code will have to be, and it probably won't be worth the added complexity. Anyway, sorry for derailing a bit. That's not really your question. Using Appender!MySpecialType might be marginally faster than ~=, but from the looks of it you are already using Appender. I don't know if there's much more you can do to speed up appending without just rolling your own solution or restructuring your code.
Re: Better way to append to array than ~= ?
On Tuesday, 3 April 2018 at 19:02:25 UTC, Vladimirs Nordholm wrote: Hello people. I currently have a function which multiple times per second takes in arguments, and appends the argument as my special type. The following code should explain what I do more properly: struct MySpecialType { char c; } auto foo(Args...)(Args args) { MySpecialType[] bar; foreach(ref arg; args) { static if(is(typeof(arg) == MySpecialType)) { bar ~= arg; } else { foreach(c; to!string(arg)) { bar ~= MySpecialType(c); } } } // do more stuff } Now, from my trace.log, some of the topmost things on the timing list are `std.array.Appender!(immutable(char).stuff>`. I also remember reading some years ago that ~= isn't optimal for speed. So my question is: Is there a better and/or faster way of doing this, or is this the best approach? In this specific case, since you know the length of `Args`, you can pre-allocate an array of that size and loop through it doing your initialization. However, if you want really performant code, you should allocate a static array on the stack outside of the function and pass it in as a buffer.
Re: Issue with traits usability
On Wednesday, 21 March 2018 at 15:36:01 UTC, Márcio Martins wrote: Hi! How do I get past this? static struct X { int x; private enum T = 1; private alias M = string; } foreach (Member; __traits(allMembers, X)) { pragma(msg, __traits(getProtection, __traits(getMember, X, Member))); } Output: public private c.d(1084): Error: argument string has no protection c.d(1084):while evaluating pragma(msg, __traits(getProtection, string)) What I want to achieve essentially is skip all X's aliases and templates, but get everything else, like enums and data members. How would I go about this in a robust way? I actually want to skip aliases, and templates. In addition to Simen's answer, you can you std.traits.FieldNameTuple to get only the fields of your struct (which only includes struct members that are actually part of the struct's memory layout): import std.traits; static struct X { int x; private enum T = 1; private alias M = string; } void main() { foreach (Member; FieldNameTuple!X) { pragma(msg, __traits(getProtection, __traits(getMember, X, Member))); } } This example prints "public" once.
Re: Going from string to identifier
On Wednesday, 21 February 2018 at 22:11:04 UTC, Jean-Louis Leroy wrote: Here's what I am trying to do: mixin template MakeFun(string ID, int X) { int mixin(ID)() { return X; } } mixin MakeFun!("one", 1); // int one() { return 1; } Alas I get: makefunc.d(3): Error: no identifier for declarator `int` makefunc.d(3): Error: found `{` when expecting `;` makefunc.d(3): Error: declaration expected, not `return` makefunc.d(4): Error: unrecognized declaration Is there a shorter way than building the entire function definition as a string mixin? As in: mixin template MakeFun(string ID, int X) { import std.format; mixin(format("int %s() { return %s; }", ID, X)); } mixin MakeFun!("one", 1); Mixins have to be full declarations. You can't mix in bits and pieces... except when you can: import std.stdio; void main() { enum teste = "asdf"; string s = mixin("teste"); writeln(s); //Prints "asdf" } It looks like a grammar error as opposed to a semantic one. D's grammar just doesn't support `mixin` in the function name position. One way you can make it a little more palateable: mixin template MakeFun(string ID, int X) { import std.format; mixin(q{ int %s { return %s; } }.format(ID, X)); } `q{}` denotes a token string that must contain valid tokens (I'm not sure if the available compiler implementations actually enforce this), and I _think_ token strings will be properly syntax-highlighted by most tools. https://dlang.org/spec/lex.html#token_strings
Re: opCast cannot implicitly convert a.opCast of type X to Y
On Thursday, 15 February 2018 at 00:27:40 UTC, Meta wrote: On Wednesday, 14 February 2018 at 23:46:30 UTC, aliak wrote: On Wednesday, 14 February 2018 at 15:14:24 UTC, Meta wrote: Ooh yes, of course! Thank you :) Even better: import std.conv; auto b = a.map!(to!float); Actually, that won't quite work without redefining map a little: Optional!U map(alias f, U = typeof(f(t.init)))() { etc... }
Re: opCast cannot implicitly convert a.opCast of type X to Y
On Wednesday, 14 February 2018 at 23:46:30 UTC, aliak wrote: On Wednesday, 14 February 2018 at 15:14:24 UTC, Meta wrote: I think the best way to do this is to implement `map` for your optional type. Optional!U map(U, alias f)() { return empty? no!U : some!U(f(t)); } Optional!int a = 3; auto b = a.map!(v => cast(float)v); assert(is(typeof(b) == Optional!float)); Ooh yes, of course! Thank you :) Even better: import std.conv; auto b = a.map!(to!float);
Re: opCast cannot implicitly convert a.opCast of type X to Y
On Monday, 12 February 2018 at 02:05:16 UTC, aliak wrote: From spec: Cast expression: "cast ( Type ) UnaryExpression" converts UnaryExpresssion to Type. And https://dlang.org/spec/operatoroverloading.html#cast makes no mention of the return type of opCast. One could think that the return type of opCast would be the return type. But it seems it must be the same as the template parameter of opCast else you get a compile error that seems like it can be much better. --- import std.stdio; struct B(T) { T t; } struct A(T) { T t; auto opCast(U)() { return B!U(cast(U)t); } } void main() { auto a = A!int(3); auto b = cast(float)a; // error } Error: cannot implicitly convert expression a.opCast() of type B!float to float Is this deliberate? The use case I have is making an optional type that you can cast to a different type: auto opCast(U)() const { static if (isOptional!U) { alias V = OptionalTarget!U; return empty ? no!V : some!V(cast(V)front); // it's a range so "front" is the raw value } else { return empty ? no!U : some!U(cast(U)front); } } It would allow for scenarios like: Optional!int a = 3; auto b = cast(float)a; // b == some!float Cheers - Ali I think the best way to do this is to implement `map` for your optional type. Optional!U map(U, alias f)() { return empty? no!U : some!U(f(t)); } Optional!int a = 3; auto b = a.map!(v => cast(float)v); assert(is(typeof(b) == Optional!float));
Re: Error in template instantiation from D-Cookbook example
On Friday, 9 February 2018 at 21:31:29 UTC, ShadoLight wrote: writeln(parse(code)); // to aid with debugging writeln(convertToD(parse(code))); // debugging aid ..to.. writeln(parse(code)[]); // to aid with debugging writeln(convertToD(parse(code))[]); // debugging aid The problem becomes apparent once you uncomment one of these and paste the offending string ("5 5 + 3 - 2 * 1 + 3 /") in. `writeln(convertToD(parse("5 5 + 3 - 2 * 1 + 3 /"))[]);` prints the following: push(5); push(5); push(call!+(pop(), pop())); push(3); push(call!-(pop(), pop())); push(2); push(call!*(pop(), pop())); push(1); push(call!+(pop(), pop())); push(3); push(call!/(pop(), pop())); If you look at the definition of call: int call(string op)(int a, int b) { return mixin("b"~op~"a"); } So it takes a string as its sole template argument. The problem is that the code in convertToD forgot to add the quotes around the operators that are supposed to be passed as strings to call. If you modify line 14 from the example you pasted to add these quotes to the mixin string, it works: code ~= "push(call!"~piece~"(pop(), pop()));\n"; becomes code ~= "push(call!\""~piece~"\"(pop(), pop()));\n"; Running the modified code, it prints: push(5); push(5); push(call!"+"(pop(), pop())); push(3); push(call!"-"(pop(), pop())); push(2); push(call!"*"(pop(), pop())); push(1); push(call!"+"(pop(), pop())); push(3); push(call!"/"(pop(), pop())); And `runDslCode!"5 5 + 3 - 2 * 1 + 3 /"();` prints `[5]`.
Re: Rewriting a c++ template to D (replacing iterator with ranges "properly")
On Friday, 26 January 2018 at 14:16:04 UTC, aliak wrote: 1) I've seen some phobos code checking for assignability like this: is(typeof(range.front = false)) ... is that an advantage of that over hasAssignableElements? Or is that just basically combining constraints 3 and 4 which I have above? Where did you see this? That's got to be some very old code; I can't think of any instance where you would not want to use `hasAssignableElements` instead.
Re: Cannot use local lambda as parameter to non-global template
On Monday, 15 January 2018 at 13:55:57 UTC, Nordlöw wrote: Why do I get errors like template instance remove!((_) => _ == 1) cannot use local '__lambda5' as parameter to non-global template remove()(in K key) for x.remove!(_ => _ == 1); but not for x.remove!"a == 11"; ? How are these two lambdas different? The function `remove` is a templated member of a struct instance `x`. Can you give a bit more context? The following code does not cause a compile error: import std.stdio; import std.algorithm; void main() { auto arr = [1, 2, 3]; arr.remove!(_ => _ == 1); writeln(arr); } Or was that code meant as an example?
Re: structs inheriting from and implementing interfaces
On Friday, 29 December 2017 at 12:03:59 UTC, Mike Franklin wrote: In C#, structs can inherit from and implement interfaces. using System; interface IPrint { void Print(); } struct MyStruct : IPrint { public void Print() { Console.WriteLine(ToString()); } } public class Program { public static void Main() { MyStruct s = new MyStruct(); s.Print(); } } https://dotnetfiddle.net/lpXR1O But in D it doesn't appear possible. import std.stdio; interface IPrint { void print(); } // Error: base classes are not allowed for struct, did you mean ;? struct MyStruct : IPrint // Error: base classes are not allowed for struct, did you mean ;? { void print() { writeln("MyStruct"); } } void main() { MyStruct s; s.Print(); } https://run.dlang.io/is/j4xwla Is that simply because it hasn't been implemented or suggested yet for D, or was there a deliberate design decision? Thanks for your insight, Mike You want wrap: https://dlang.org/phobos/std_typecons.html#wrap
Re: Alias example should supposedly be illegal, but runs fine
On Monday, 18 December 2017 at 23:44:46 UTC, Michael wrote: Hello, I have been looking at the following example found right at the end of the section here: https://dlang.org/spec/declaration.html#alias struct S { static int i; } S s; alias a = s.i; // illegal, s.i is an expression alias b = S.i; // ok b = 4; // sets S.i to 4 and it runs fine to me, including if I add: a = 3; So, to me I don't see why either can't be valid, but either way something needs to be fixed to reflect that this is no longer illegal in DMD v2.077.1. I think the reason that this works is because i is static, meaning that you don't need the `this` reference of S to access it and thus it can be aliased. Declaring a static class or struct variable is pretty much the same as declaring a global variable, just with a tighter scope. If you look at it that way, then this makes a lot more sense. If you declare a global variable i at module scope, of course you can create an alias for it.
Re: Using enum types
On Monday, 4 December 2017 at 22:34:41 UTC, helxi wrote: Why can't enums be used as types in this (simplified) example? enum Positivity { Positive, Negative } struct Wave { public: Positivity slope; } enum Waves { Sin = Wave(Positivity.Positive), Cos = Wave(Positivity.Negative) } int nth_value(T : Waves)(int n); int nth_value(T : Waves.Sin)(int n) { return n % 2 ? 1 : -1; } int nth_value(T : Waves.Cos)(int n) { return n % 2 ? -1 : 1; } We Adam said, Waves.Sin and Waves.Cos are values, while Waves itself is the type. You want to do the following: int nth_value(Waves w: Waves.Sin)(int n) { //Etc. } At least I *think* that's what you want. I'm on mobile and dpaste is down so I have no way to double check the syntax, which I can never remember.
Re: std.algorithm
On Thursday, 30 November 2017 at 20:49:36 UTC, flamencofantasy wrote: Hello, I have the following csv text; auto input = "Start Date,End Date,Subject,All day event,Categories,Show time as 1/1/2018,1/1/2018,New Year's Day,TRUE,Holiday,3 1/15/2018,1/15/2018,\"Martin Luther King, Jr. Day\",TRUE,Holiday,3 2/19/2018,2/19/2018,President's Day,TRUE,Holiday,3 5/28/2018,5/28/2018,Memorial Day,TRUE,Holiday,3 7/4/2018,7/4/2018,Independence Day,TRUE,Holiday,3 9/3/2018,9/3/2018,Labor Day,TRUE,Holiday,3 11/22/2018,11/22/2018,Thanksgiving Day,TRUE,Holiday,3 11/23/2018,11/23/2018,Day after Thanksgiving,TRUE,Holiday,3 12/24/2018,12/24/2018,Christmas Eve,TRUE,Holiday,3 12/25/2018,12/25/2018,Christmas Day,TRUE,Holiday,3"; What is the most clean compact efficient/lazy way to produce a range that removes the first line and then retains the second and third columns of the following lines, basically producing this; "1/1/2018,New Year's Day 1/15/2018,\"Martin Luther King, Jr. Day\" 2/19/2018,President's Day 5/28/2018,Memorial Day 7/4/2018,Independence Day 9/3/2018,Labor Day,TRUE 11/22/2018,Thanksgiving Day 11/23/2018,Day after Thanksgiving 12/24/2018,Christmas Eve 12/25/2018,Christmas Day" Thanks a bunch This *almost* works: import std.algorithm; import std.range; import std.stdio; import std.string; void main() { auto input = "Start Date,End Date,Subject,All day event,Categories,Show time as 1/1/2018,1/1/2018,New Year's Day,TRUE,Holiday,3 1/15/2018,1/15/2018,\"Martin Luther King, Jr. Day\",TRUE,Holiday,3 2/19/2018,2/19/2018,President's Day,TRUE,Holiday,3 5/28/2018,5/28/2018,Memorial Day,TRUE,Holiday,3 7/4/2018,7/4/2018,Independence Day,TRUE,Holiday,3 9/3/2018,9/3/2018,Labor Day,TRUE,Holiday,3 11/22/2018,11/22/2018,Thanksgiving Day,TRUE,Holiday,3 11/23/2018,11/23/2018,Day after Thanksgiving,TRUE,Holiday,3 12/24/2018,12/24/2018,Christmas Eve,TRUE,Holiday,3 12/25/2018,12/25/2018,Christmas Day,TRUE,Holiday,3"; input.lineSplitter() .dropOne() .map!(l => l.splitter(',') .dropOne() .take(2) .joiner(",")) .each!writeln(); } The only problem is the comma in Martin Luther King, Jr. Day, so that line comes out as `1/15/2018,"Martin Luther King`.
Re: Alias on an array element
On Friday, 13 October 2017 at 13:22:42 UTC, Adam D. Ruppe wrote: * Use a @property ref function to return the array element and trust the compiler to inline it. You could also use pragma(inline, true).
Re: Alias on an array element
On Friday, 13 October 2017 at 01:12:38 UTC, solidstate1991 wrote: On Friday, 13 October 2017 at 01:09:56 UTC, solidstate1991 wrote: I'm making a struct for easy color handling Here's a code sample: ublic struct Color{ union{ uint raw; ///Raw representation in integer form, also forces the system to align in INT32. ubyte[4] colors; ///Normal representation, aliases are used for color naming. ubyte alpha, red, green, blue; } version(LittleEndian){ alias alpha = colors[0]; alias red = colors[1]; alias green = colors[2]; alias blue = colors[3]; }else{ alias alpha = colors[3]; alias red = colors[2]; alias green = colors[1]; alias blue = colors[0]; } } All the aliases are fail to compile, have not found anything about it in any of the documentations I checked. Edit: ubyte alpha, red, green, blue; was added so I can continue debugging after the refactoring until I find a solution. You can only create aliases for symbols, not expressions. You could create accessor functions that return the appropriate indices.
Re: How to check if string is available at compile time
On Thursday, 21 September 2017 at 12:30:15 UTC, David Bennett wrote: On Thursday, 21 September 2017 at 11:42:36 UTC, David Bennett wrote: [snip] ``` string[] escapeCTFE(Args...)(){ static foreach (arg; Args){ static if(__traits(compiles, ###WHATDOIPUTHERE###)){ [snip] So far the best I've come up with is : ``` enum isCTstring(alias arg) = (!isAssignable!(typeof(arg)) || __traits(compiles, mixin(` "foo" ~ `~__traits(identifier, arg; string[] escapeCTFE(Args...)(){ static foreach (arg; Args){ static if(isCTstring!(arg)){ pragma(msg, "Do work on string: ", arg); }else{ pragma(msg, __traits(identifier, arg), " can only be read at runtime"); } } return new string[32]; } ``` But this seems quite hackish... any better ideas? Try __traits(compiles, { enum _ = arg; }). Creating an enum necessarily requires that its value is available at compile time.
Re: Choosing between enum arrays or AliasSeqs
On Thursday, 24 August 2017 at 19:41:46 UTC, Nordlöw wrote: Given enum e = ['a', 'b', 'c']; import std.meta : AliasSeq; enum a = AliasSeq!['a', 'b', 'c']; is it somehow possible to convert (at compile-time) `e` to `a`? Is it cheaper CT-performance wise to use AliasSeq instead of enum static arrays? My use case is expressed by the TODOs in the following code snippet import std.algorithm : among; /** English indefinite articles. */ enum englishIndefiniteArticles = [`a`, `an`]; /** English definite articles. */ enum englishDefiniteArticles = [`the`]; /** English definite articles. */ enum englishArticles = englishIndefiniteArticles ~ englishDefiniteArticles; /** Check if $(D c) is a Vowel. */ bool isEnglishIndefiniteArticle(C)(C c) if (isSomeChar!C) { return cast(bool)c.among!(`a`, `an`); // TODO reuse englishIndefiniteArticles } /** Check if $(D c) is a Vowel. */ bool isEnglishDefiniteArticle(C)(C c) if (isSomeChar!C) { return cast(bool)c.among!(`the`); // TODO reuse englishDefiniteArticles } /** Check if $(D c) is a Vowel. */ bool isEnglishArticle(C)(C c) if (isSomeChar!C) { return cast(bool)c.among!(`a`, `an`, `the`); // TODO reuse englishArticles } https://dlang.org/phobos/std_meta.html#aliasSeqOf
Re: Automatic function body writing howto?
It's hard to tell offhand but I would recommend that you extract the inner string into a function that generates that string, allowing you to print out the finished product before mixing it in.
Re: Why does stringof not like functions with arguments?
On Thursday, 10 August 2017 at 15:55:41 UTC, Jason Brady wrote: Wow. That makes perfect sense. I forgot stringof works only with expressions It works with symbols too. See the following: template test(){} pragma(msg, test.stringof);
Re: Why does stringof not like functions with arguments?
On Wednesday, 9 August 2017 at 01:39:07 UTC, Jason Brady wrote: Why does the following code error out with: app.d(12,10): Error: function app.FunctionWithArguments (uint i) is not callable using argument types () Code: import std.stdio; void FunctionWithoutArguments() { } void FunctionWithArguments(uint i) { } void main() { writeln(FunctionWithoutArguments.stringof); writeln(FunctionWithArguments.stringof); } Welcome to optional parentheses hell. Please enjoy your stay. Because function calls in D can optionally omit the parens, `FunctionWithArguments.stringof` is actually attempting to call `FunctionWithArguments` without any arguments, and then call `stringof` on the result. In other words, it's actually trying to do this: writeln(FunctionWithArguments().stringof); And the D compiler is rightly telling you that you can't call the function with no arguments. The easiest solution is to use __traits(identifier) instead: writeln(__traits(identifier, FunctionWithArguments)); You can make a handy template helper to do this for you: enum stringOf(alias symbol) = __traits(identifier, symbol); writeln(stringOf!FunctionWithArguments);
Re: if (auto x = cast(C) x)
On Wednesday, 9 August 2017 at 21:54:46 UTC, Q. Schroll wrote: For a class/interface type `A` and a class `C` inheriting from `A` one can do A a = getA(); if (auto c = cast(C) a) { .. use c .. } to get a `C` view on `a` if it happens to be a `C`-instance. Sometimes one cannot find a good new name for `c` while there is no advantage of accessing `a` when `c` is available. D does not allow to shadow `a` in the if-auto declaration for good reasons. How about relaxing the rule for cases like these, where the rhs is the lhs with a cast to derived? if (auto a = cast(C) a) { .. use a typed as C .. } One can think of `a` being *statically* retyped to `C` as this is a (strictly) better type information. Internally, it would be a shadowing, but it does not matter as the disadvantages don't apply (if I didn't miss something). One option is to use https://dlang.org/library/std/algorithm/comparison/cast_switch.html
Re: Template mixins and selective imports
On Thursday, 3 August 2017 at 19:03:55 UTC, Meta wrote: `mixin vectorize!sin vsin; alias sin = vsin;` and see if it Should be `alias sin = vsin.sin;`
Re: Template mixins and selective imports
On Thursday, 3 August 2017 at 15:29:47 UTC, jmh530 wrote: I am trying to create a vectorize function that mixes in a new version of function with the same name that applies the function (to an ndslice). The code below compiles without error and has the behavior I would expect. However, when I change the function import to a selective import (e.g. from import std.math; to import std.math : sin;), then I get errors implying that the overload is not actually created. Ideally, I would like to get this working with any kind of import. One thing I noticed is that the fullyQualifiedName of sin changes quite a bit depending on whether you use one or the other. This may be related to either of the following: https://issues.dlang.org/show_bug.cgi?id=16287 https://issues.dlang.org/show_bug.cgi?id=16023 --- import std.traits : isFunction; private enum _vectorize(string f) = " import mir.ndslice.slice : SliceKind, Slice; auto " ~ f ~ "(SliceKind kind, size_t[] packs, Iterator) (Slice!(kind, packs, Iterator) slice) { import mir.ndslice.topology : map; return slice.map!(f); } "; mixin template vectorize(alias f) if (isFunction!f) { mixin(_vectorize!(__traits(identifier, f))); } unittest { import std.stdio : writeln; import mir.ndslice.slice : sliced; import mir.ndslice.topology : map; import std.math; //import std.math : sin; auto x = [0.0, 1.0, 2.0, 3.0].sliced; auto y = x.map!(sin); writeln(y); mixin vectorize!(sin); auto z = sin(x); writeln(z); } I'm not 100% certain, but I believe you have to bring the vectorized overload of sin into the overload set, so first try `mixin vectorize!sin vsin; alias sin = vsin;` and see if it works. https://dlang.org/spec/function.html#overload-sets
Re: Is std.xml seriously broken, or is it me?
On Sunday, 30 July 2017 at 02:58:09 UTC, Mike wrote: I'm trying to use std.xml, and I can't get it to work. I tried the simplest program I could think of: import std.xml; import std.stdio; void main() { auto parser = new DocumentParser("encoding=\"utf-8\"?>"); parser.onStartTag["device"] = (ElementParser parser) { writeln("device"); }; parser.parse(); } https://dpaste.dzfl.pl/262597d2fda6 I used it before without any trouble. Is it somehow seriously broken? If not, what am I doing wrong? Thanks, Mike I don't know about your code specifically, but std.xml has been on the chopping block for many years and is pretty much still around because nobody has written a replacement yet. I'd recommend using Adam Ruppe's DOM library instead: https://github.com/adamdruppe/arsd/blob/master/dom.d
Re: Pass range to a function
On Thursday, 27 July 2017 at 21:16:03 UTC, Chris wrote: I'm using regex `matchAll`, and mapping it to get a sequence of strings. I then want to pass that sequence to a function. What is the general "sequence of strings" type declaration I'd need to use? In C#, it'd be `IEnumerable`. I'd rather not do a to-array on the sequence, if possible. (e.g. It'd be nice to just pass the lazy sequence into my categorize function.) What is the value of `???` in the following program: ``` import std.stdio, std.regex, std.string, std.algorithm.iteration; auto regexToStrSeq(RegexMatch!string toks) { return toks.map!(t => t[0].strip()); } void categorize(??? toks) { foreach (t; toks) { writeln(t); } } void main() { auto reg = regex("[\\s,]*(~@|[\\[\\]{\\}()'`~^@]|\"(?:.|[^\"])*\"|;.*|[^\\s\\[\\]{}('\"`,;)]*)"); auto line = "(+ 1 (* 2 32))"; auto baz = matchAll(line, reg); categorize(regexToStrSeq(baz).array); } ``` If for some reason you can't make categorize a template like Ali suggested, or you need runtime polymorphism, you can use std.range.interfaces: import std.range.interfaces; void categorize(InputRange!string toks) { foreach (t; toks) { writeln(t); } } void main() { //etc. categorize(inputRangeObject(regexToStrSeq(baz))); }
Re: Array of Template instantiations
On Thursday, 20 July 2017 at 13:11:56 UTC, Alex wrote: On Thursday, 20 July 2017 at 12:33:43 UTC, Alex wrote: The Problem is, i dont know what type WHAT_TYPE is / i don´t know how to build a loopable something of futures. Ok, i think i understood now. my function `load` returns `KpiResponseEntity` so Future!(KpiResponseEntity)[] futures; seems to work To get the type you can also use `typeof`. alias ResponseType = typeof(async(&load , queryA )); ResponseType[] futures; futures ~= async( &load , queryA ); futures ~= async( &load , queryB ); futures ~= async( &load , queryC );
Re: replacement for squeeze and removechars.
On Tuesday, 18 July 2017 at 15:28:06 UTC, Antonio Corbi wrote: Hi all, I'm trying dmd-2.075.0-rc1 in one of my projects where I use `squeeze` and `removechars`. Both of them are flagged as obsolete and in the docs we are suggested to use functions from std.regex and/or std.algorithm. Does any one kow a one-liner from std.regex or std.algorithm that can take the role of those deprecated functions? Thank's A. Corbi As Seb somewhat undiplomatically put, there are replacements listed in the changelog. Use std.regex.replaceAll to replace std.string.removechars: import std.string; import std.regex; // old "abc".removechars("a-z"); // new "abc".replaceAll(regex("[a-z]"), ""); Use std.algorithm.iteration.uniq to replace std.string.squeeze: import std.algorithm; import std.string; // old "hello".squeeze; // new "hello".uniq; Though it would be nice to have these alternatives listed right there in the deprecation message.
Re: Fiber based UI-Toolkit
On Sunday, 9 July 2017 at 21:12:24 UTC, bauss wrote: On Sunday, 9 July 2017 at 19:43:14 UTC, Christian Köstlin wrote: I wonder if there is any fiber based / fiber compatible UI-Toolkit out for dlang. The second question is, if it would make sense at all to have such a thing? christian It doesn't really make sense to have that, because most (if not all) operating systems only allow rendering from a single thread and I believe OSX (possibly macOS too.) only allows it from the main thread. Which means the only thing you can really operate on other threads are events, but you'll always have to do callbacks to your UI thread in order to render. Aren't all fibers executed from a single thread?
Re: Advice wanted on garbage collection of sockets for c++ programmer using D
On Wednesday, 28 June 2017 at 15:55:41 UTC, John Burton wrote: On Tuesday, 27 June 2017 at 09:54:19 UTC, John Burton wrote: I'm coming from a C++ background so I'm not too used to garbage collection and it's implications. I have a function that creates a std.socket.Socket using new and connects to a tcp server, and writes some stuff to it. I then explicitly close the socket, and the socket object goes out of scope. Am I doing this right? Or is there a better way to do this in D? Thanks. For my use case here, I'm increasingly thinking that just calling the underlying 'C' socket and send calls is better. No need for anything complicated at all for my actual program :) One final piece of advice as this thread seemed to have gone off the rails a bit. You can always put a `scope(exit) socket.close();` after you create the socket. This will ensure that the socket will be closed once the scope is exited no matter what... almost, anyway. If an Error is thrown no stack unwinding is done but at this point your program is in an unrecoverable state anyway and you have a lot more to worry about than a socket that hasn't been closed.
Re: Help me escape optional parens hell
On Saturday, 24 June 2017 at 08:08:33 UTC, ketmar wrote: Meta wrote: So I have no clue what I'm doing wrong. This is driving me insane. h. known $#^#$@^@%. enum SymName = (&symbol).stringof[2..$]; // this, instead of symbol.stringof dirty hack, let's hope that DMD devs won't change `.toString()` output (i.e. first two chars will always be "& "). besides this, i know no other way to stop compiler from calling the function there. It's dirty but I guess I'll have to go with this hack for the time being. Also, I filed a bug: https://issues.dlang.org/show_bug.cgi?id=17546
Help me escape optional parens hell
The code: alias Response = Nullable!(string, "empty response (error)"); Response processMessage(string commandModule)(string message, bool isCommand) { import std.meta; import std.string; import std.traits; import command_uda; mixin("import " ~ commandModule ~ ';'); bool foundCommandMatch = false; foreach(symbol; getSymbolsByUDA!(mixin(commandModule), Command)) { enum commandUDA = getUDAs!(symbol, Command)[0]; auto commandPhrase = commandUDA.phrase == "" ? symbol.stringof : commandUDA.phrase; //Error: function signature> is not callable using argument types () auto commandPhrasePattern = regex(`^%s\s`.format(commandPhrase)); if (message.matchFirst(commandPhrasePattern) && !foundCommandMatch) { version(responseDebug) writeln("Matched command ", symbol.stringof, " with phrase '", commandPhrase, "'\n"); //Same issue return Response(symbol(message.strip())); } } return Response.init; } I've been banging my head against this and cannot figure out why `symbol.stringof` is being called instead of getting a string of the symbol. I tried to create a reduced test case but it works fine: import std.stdio; import std.traits; enum Attr; @Attr string test1() { return __FUNCTION__; } @Attr string test2() { return __FUNCTION__; } void process() { foreach (symbol; getSymbolsByUDA!(mixin(__MODULE__), Attr)) { writeln("The result of calling ", symbol.stringof, " is ", symbol()); } } void main() { process(); } So I have no clue what I'm doing wrong. This is driving me insane.
Re: Builtin array-scalar equality
On Wednesday, 14 June 2017 at 21:15:32 UTC, Nordlöw wrote: Why isn't bool c = a[] == 4; allowed when a[] = b[] + 4; is? given that int[] a, b; That's just how it is. There are a lot of array-wise operations that *could* be implemented in the language but aren't.
Re: Algebra With Types
On Friday, 21 April 2017 at 18:54:38 UTC, David Sanders wrote: Thank-you for your input. With your help, I was able to figure out number whether a type is an instantiation of std.variant.Algebraic. Now, I need help on concatenating Template Sequence Parameters. See the block comments below. Thanks, Dave import std.stdio; import std.variant; alias Zero = void; struct One{}; struct Sum(T, U) { static if (is(T == Zero)) { static if (is(U == Zero)) { alias type = Zero; } else { alias type = U; } } else static if (is(U == Zero)) { alias type = T; } else static if (is(T _ == VariantN!V, V...)) { static if(is(U _ == VariantN!W, W...)) { alias type = Algebraic!/* Concatenate V[1..$] with U[1..$] */ } else { alias type = Algebraic!/* Concatenate V[1..$] with U */ } } else static if(is(U _ == VariantN!V, V...)) { alias type = Algebraic!/* Concatenate T with V[1..$] */ } else { alias type = Algebraic!(T, U); } } void main() { static assert (is(Zero == Sum!(Zero, Zero).type)); static assert (is(One == Sum!(Zero, One).type)); static assert (is(One == Sum!(One, Zero).type)); static assert (is(Algebraic!(One, One) == Sum!(One, One).type)); static assert (is(Algebraic!(One, One, One) == Sum!(Sum!(One, One).type, One).type)); } As an aside, there's a less convoluted way to do type-level arithmetic which is IMO also more concise and looks nicer. You don't have to mess around with Algebraic at all: struct Zero; struct Succ(N); alias One = Succ!Zero; alias Pred(N: Zero)= Zero; alias Pred(N: Succ!Np, Np) = Np; alias Add(N1: Zero, N2: Zero) = Zero; alias Add(N1, N2: Zero) = N1; alias Add(N1: Zero, N2) = N2; alias Add(N1, N2) = Add!(Succ!N1, Pred!N2); void main() { static assert(is(Pred!One == Zero)); static assert(is(Succ!One == Succ!(Succ!Zero))); static assert(is(Add!(Zero, Zero) == Zero)); static assert(is(Add!(Zero, One) == One)); static assert(is(Add!(One, Zero) == One)); static assert(is(Add!(One, One) == Succ!(Succ!(Zero; alias Two = Succ!One; static assert(is(Add!(One, One) == Two)); static assert(is(Add!(One, Two) == Succ!(Succ!(Succ!Zero; static assert(is(Sub!(Zero, Zero) == Zero)); static assert(is(Sub!(One, Zero) == One)); static assert(is(Sub!(Zero, One) == Zero)); static assert(is(Sub!(Two, One) == One)); static assert(is(Sub!(One, Two) == Zero)); } Implementing Mul, Div and the integer set is an exercise left to the reader.
Re: Algebra With Types
On Friday, 21 April 2017 at 16:31:37 UTC, H. S. Teoh wrote: On Fri, Apr 21, 2017 at 04:16:30PM +, David Sanders via Digitalmars-d-learn wrote: I'm trying to do algebra with types ala http://chris-taylor.github.io/blog/2013/02/10/the-algebra-of-algebraic-data-types/ Below you will find my attempts at "adding" types in D. I've outlined the parts I'm having trouble with using block comments. 1) How do I figure out whether a type is an instantiation of std.variant.Algebraic? 2) If the type is Algebraic, how do I capture its AllowedTypes? [...] static if (is(T : Algebraic!(U...), U)) { // U now refers to the argument to Algbraic. } --T There's also a private `isAlgebraic` template[1]. Is there any reason why we couldn't just make this public? 1. https://github.com/dlang/phobos/blob/master/std/variant.d#L2236
Re: How to get return type of current method?
On Wednesday, 19 April 2017 at 00:22:14 UTC, Mike B Johnson wrote: On Tuesday, 18 April 2017 at 23:49:35 UTC, ketmar wrote: Mike B Johnson wrote: How can I get the return type of the current method without specifying the name or any complexity? Similar to typeof(this). typeof(return) Thanks, sweet and simple! One note: if the function has a return type of `auto`, you cannot use `typeof(return)` within the function.
Re: Using template mixin, with or without mixin ?
On Saturday, 8 April 2017 at 22:37:18 UTC, ag0aep6g wrote: On 04/08/2017 11:59 PM, Meta wrote: enum a = 0; template test1() { enum b1 = a; //Okay, a is in scope at the declaration site //enum c = d1; Error: undefined identifier d1 This line works just fine, actually. There's really no difference between a normal template and a mixin template when you use it in a mixin. } mixin template test2() { enum b2 = a; //Okay, a is in scope at the declaration site enum c = d1; //Okay, d1 is in scope at the *instantiation* site //enum e = d2; Error: undefined identifier d2 } void main() { enum d1 = 0; //<--d1 is declared here mixin test1!(); mixin test2!(); //<--so it is in scope here enum d2 = 0; //d2 was not declared before test2 was mixed in //so it is not in scope for test2 } Hmm, you're right, but this is not how it is supposed to behave according to the documentation. https://dlang.org/spec/template-mixin.html
Re: Using template mixin, with or without mixin ?
On Saturday, 8 April 2017 at 09:47:07 UTC, biocyberman wrote: On Friday, 7 April 2017 at 23:53:12 UTC, Ali Çehreli wrote: The difference is that you can't use funcgen as a regular template: funcgen!(void, void); Error: template instance funcgen!(void, void) mixin templates are not regular templates I think it's good practice to use 'mixin template' if it's intended to be so. Ali Thanks for a very concise answer. In addition to Ali's answer, mixin templates do their symbol looking at the instantiation site, while regular templates do it at the declaration site. Example: enum a = 0; template test1() { enum b1 = a; //Okay, a is in scope at the declaration site //enum c = d1; Error: undefined identifier d1 } mixin template test2() { enum b2 = a; //Okay, a is in scope at the declaration site enum c = d1; //Okay, d1 is in scope at the *instantiation* site //enum e = d2; Error: undefined identifier d2 } void main() { enum d1 = 0; //<--d1 is declared here mixin test1!(); mixin test2!(); //<--so it is in scope here enum d2 = 0; //d2 was not declared before test2 was mixed in //so it is not in scope for test2 }
Re: Is DMD breaking BigInt?
On Saturday, 8 April 2017 at 12:14:31 UTC, Russel Winder wrote: On Fri, 2017-04-07 at 22:47 +, Meta via Digitalmars-d-learn wrote: […] Do you have the -dip1000 switch enabled? Not as far as I know. Why would I want to do that? You wouldn't as the std lib doesn't work with it yet.
Re: Is DMD breaking BigInt?
On Friday, 7 April 2017 at 17:06:31 UTC, Russel Winder wrote: Simple Dub build of a Factorial example using Unit-Threaded for testing. Works fine with ldc2 breaks with dmd. This is on Debian Sid fully up to date. |> ldc2 --version LDC - the LLVM D compiler (1.1.1): based on DMD v2.071.2 and LLVM 3.9.1 built with LDC - the LLVM D compiler (1.1.0) Default target: x86_64-pc-linux-gnu Host CPU: broadwell http://dlang.org - http://wiki.dlang.org/LDC |> dmd --version DMD64 D Compiler v2.073.2 |> dub test --compiler=ldc2 Package factorial (configuration "unittest") defines no import paths, use {"importPaths": [...]} or the default package directory structure to fix this. Running custom 'unittest' configuration. Performing "unittest" build using ldc2 for x86_64. unit-threaded 0.7.11: target for configuration "library" is up to date. factorial ~master: building configuration "unittest"... Running pre-build commands... Building package unit-threaded in /home/users/russel/.dub/packages/unit-threaded-0.7.11/unit-threaded/ Performing "$DFLAGS" build using dmd for x86_64. unit-threaded 0.7.11: building configuration "gen_ut_main"... Linking... Running ../../../../.dub/packages/unit-threaded-0.7.11/unit-threaded/gen_ut_main -f ut_main.d To force a rebuild of up-to-date targets, run again with --force. Running ./factorial-test Automatically generated file ut_main.d Running unit tests from dirs ["."] factorial.Check the base case for all algorithms.: factorial.Check the property for all algorithms.: factorial.Traditional example-based testing.: Time taken: 34 ms, 363 μs, and 2 hnsecs 3 test(s) run, 0 failed. OK! |> dub test Package factorial (configuration "unittest") defines no import paths, use {"importPaths": [...]} or the default package directory structure to fix this. Running custom 'unittest' configuration. Performing "unittest" build using dmd for x86_64. unit-threaded 0.7.11: target for configuration "library" is up to date. factorial ~master: building configuration "unittest"... Running pre-build commands... Building package unit-threaded in /home/users/russel/.dub/packages/unit-threaded-0.7.11/unit-threaded/ Performing "$DFLAGS" build using dmd for x86_64. unit-threaded 0.7.11: building configuration "gen_ut_main"... Linking... Running ../../../../.dub/packages/unit-threaded-0.7.11/unit-threaded/gen_ut_main -f ut_main.d factorial.d(71,15): Error: template std.bigint.BigInt.__ctor cannot deduce function from argument types !()(string) immutable, candidates are: /usr/include/dmd/phobos/std/bigint.d(64,5): std.bigint.BigInt.__ctor(Range)(Range s) if (isBidirectionalRange!Range && isSomeChar!(ElementType!Range) && !isInfinite!Range) /usr/include/dmd/phobos/std/bigint.d(146,5): std.bigint.BigInt.__ctor(T)(T x) if (isIntegral!T) /usr/include/dmd/phobos/std/bigint.d(162,5): std.bigint.BigInt.__ctor(T)(T x) if (is(Unqual!T == BigInt)) dmd failed with exit code 1. If anyone has any useful intelligence as to what happening and how I can workaround it, I'd be a grateful bunny. Do you have the -dip1000 switch enabled?
Re: Write file at compile time?
On Sunday, 2 April 2017 at 19:42:52 UTC, Inquie wrote: I would like to write the output of a manifest constant at compile time to a file instead of console using pragma(msg). Is this possible? D does not allow IO at compile time for security reasons.
Re: Template specialisation for range of types
On Sunday, 12 March 2017 at 21:12:13 UTC, data pulverizer wrote: On Sunday, 12 March 2017 at 20:15:43 UTC, Meta wrote: auto max(T: const U, U)(T* x, T* y) <- Changed `ConstOf!U` to `const U` { writeln("Const template"); return *x > *y ? x : y; } How detailed can I be about the template specialisation? From example in the book "C++ the complete guide" we can have: /* pointer const reference */ template inline T* const& max(T* const& a, T* const&b) { return a* < b* ? b : a; } /* const reference const pointer */ template inline T const* const& max(T* const* const& a, T* const* const& b) { ...; } What would be the equivalent in D? Unfortunately this is impossible in D as const is transitive. The best you can do is try to emulate it using wrapper types. I'd start by taking a look at std.experimental.typecons.Final, which implements C++-style head (logical) constness.
Re: Template specialisation for range of types
On Sunday, 12 March 2017 at 20:22:33 UTC, ketmar wrote: Meta wrote: The reason this doesn't work is when you use ConstOf!U, it's not looking for a `const U`, it's looking for the type `ConstOf!U`. I'm not sure if this is a bug or not... no, not a bug. this is the way type deconstruction works: it checks if your type was constructed with a given template. Yeah, it seems to be checking the pattern rather than the type. However, ConstOf!T is just an alias for const(T), but the alias does not seem to be "unwrapped", even though they are supposed to be transparent.
Re: Template specialisation for range of types
On Sunday, 12 March 2017 at 18:49:22 UTC, data pulverizer wrote: Hello all, I am attempting to write templates for differently qualified types using specialisations. Below is an example for const and non-const outlining my approach: `` import std.stdio : writeln; import std.traits : ConstOf; auto max(T)(T x, T y) { writeln("General template"); return x > y ? x : y; } auto max(T: ConstOf!U, U)(T* x, T* y) { writeln("Const template"); return *x > *y ? x : y; } void main(){ const double p = 2.4, q = 3; writeln(max(&p, &q)); } `` I get this output: General template 7FFE5B3759A8 In this case would like to use the ConstOf specialisation instead of the default implementation for the inputs which are const. Thanks for you answers in advance You need to make one little change for this to work: import std.stdio : writeln; import std.traits : ConstOf; auto max(T)(T x, T y) { writeln("General template"); return x > y ? x : y; } auto max(T: const U, U)(T* x, T* y) <- Changed `ConstOf!U` to `const U` { writeln("Const template"); return *x > *y ? x : y; } void main(){ const double p = 2.4, q = 3; writeln(max(&p, &q)); //Prints "Const template" } The reason this doesn't work is when you use ConstOf!U, it's not looking for a `const U`, it's looking for the type `ConstOf!U`. I'm not sure if this is a bug or not... Anyway, this will also work if we change the following: void main(){ ConstOf!double p = 2.4, q = 3; <- Changed `const double` to `ConstOf!double` writeln(max(&p, &q)); //Prints "Const template" }
Re: Comparing Instances of Classes
On Friday, 10 March 2017 at 17:08:42 UTC, Whatsthisnow wrote: I guess i am just too used to the java way of x.equals(object) which at the source is exactly 'return this == object' Java would return false here too, though, if it actually did `this == object` in its default compare method. If I remember correctly, comparing two objects with == in Java compares their addresses, not their contents.
Re: In Expressions
On Saturday, 4 March 2017 at 17:11:46 UTC, Andrey wrote: Hello, is there any way to using in expression like in python, e.g. if 4 in [1, 3, 4]: do something My code in D if (regionAlign in [RegionAlign.top, RegionAlign.bottom]) { ... } throws an error: incompatible types for (((cast(Widget)this).regionAlign()) in ([top, bottom])): 'RegionAlign' and 'RegionAlign[]' The reason this is disallowed for normal arrays is that finding a key in an array is O(n) while finding a key in an associative array is O(1). Rather than let users unknowingly write code that looks the same but is far slower for arrays, D doesn't allow this. You can use std.algorithm.among, however. import std.algorithm; if (regionAlign.among!(RegionAlign.top, RegionAlign.bottom)) { //etc. } http://dlang.org/phobos/std_algorithm_comparison.html#.among
Re: template parameter inference and introspection
On Friday, 24 February 2017 at 11:17:46 UTC, John Colvin wrote: Unfortunately that only works by accident of my example. A counterexample: T foo(Q = float, T = short)(T t) { return t; } alias Typeof(alias v) = typeof(v); template getInstantiation(alias f, T...) { import std.meta; alias getInstantiation = f!(staticMap!(Typeof, T)); } static assert(is(typeof(foo(3)) == int)); // ok static assert(is(typeof(getInstantiation!(foo, 3)(3)) == int)); // fails This looks like VRP is kicking in when it shouldn't, or maybe it's a different bug. 3 should be typed as int by default unless we explicitly ask for something else.
Re: template parameter inference and introspection
On Thursday, 23 February 2017 at 18:21:51 UTC, Meta wrote: On Thursday, 23 February 2017 at 16:01:44 UTC, John Colvin wrote: Is there any way to get a reference/alias to the instantiation of a template function that would be called, given certain parameters? I.e. to get the result of whatever template parameter inference (and overload resolution) has occurred? E.g. for some arbitrarily complex foo: static assert(__traits(compiles, foo(3))); alias fooWithInt = someMagic(foo(3)); so if foo was `void foo(T)(T t) {}` then `fooWithInt` would be `foo!int`, but if it was `void foo(Q = float, T = long)(T t)` then `fooWithInt` would be `foo!(float, int)` I don't believe so, because foo(3) is a value (void), not a type like foo!int would be. You can't get it back after you've called the function. You would have to do something like: alias fooWithInt = someMagic!foo(3); Where someMagic constructs the alias to foo!int based on the type of arguments passed, or something like that. A quick and rough example I threw together. Annoyingly, I can't figure out a way to tell the compiler that I want to printout the symbol of fooWithInt, not call it without parens. The best I can do is print out its type. void foo(T)(T t) {} void foo(Q = float, T = long)(T t) {} alias Typeof(alias v) = typeof(v); template getInstantiation(alias f, T...) { import std.meta; alias getInstantiation = f!(staticMap!(Typeof, T)); } alias fooWithInt = getInstantiation!(foo, 3); alias fooWithLong = getInstantiation!(foo, 3L); void main() { pragma(msg, typeof(fooWithInt)); pragma(msg, typeof(fooWithLong)); }
Re: template parameter inference and introspection
On Thursday, 23 February 2017 at 16:01:44 UTC, John Colvin wrote: Is there any way to get a reference/alias to the instantiation of a template function that would be called, given certain parameters? I.e. to get the result of whatever template parameter inference (and overload resolution) has occurred? E.g. for some arbitrarily complex foo: static assert(__traits(compiles, foo(3))); alias fooWithInt = someMagic(foo(3)); so if foo was `void foo(T)(T t) {}` then `fooWithInt` would be `foo!int`, but if it was `void foo(Q = float, T = long)(T t)` then `fooWithInt` would be `foo!(float, int)` I don't believe so, because foo(3) is a value (void), not a type like foo!int would be. You can't get it back after you've called the function. You would have to do something like: alias fooWithInt = someMagic!foo(3); Where someMagic constructs the alias to foo!int based on the type of arguments passed, or something like that.