Re: Return the complete number
On Wednesday, 24 July 2019 at 16:16:15 UTC, Greatsam4sure wrote: On Wednesday, 24 July 2019 at 15:57:06 UTC, a11e99z wrote: On Wednesday, 24 July 2019 at 15:56:13 UTC, a11e99z wrote: On Wednesday, 24 July 2019 at 15:45:08 UTC, Greatsam4sure wrote: int main(){ double mum = 0; Write("enter a number: ") readf(" %s\n",&num); Writeln(num); } How do I return the complete number the user enter since I don't since the user can enter numbers of various length with dmd approximating it. I will appreciate any help readf!" %s\n"( num ); or num.readf!" %s\n"; or num = readln.strip.to!double; writeln(num) The result is always to six significant figure. I want the whole number to be diaplay So, there are several possible issues here. First, floating-point numbers have limited precision - a double can not correctly represent all integers above 2^52, for instance. That's 4.5 quadrillion though, so rarely an issue. In your case, as others have commented, writefln with a correctly chosen format string[1] will do the trick. However, what is the correctly chosen format string? This is a very hard question to answer, as it depends on what number was typed, and what you mean by 'the complete number the user enter'. While drug's suggestion of "%.16f" will return an accurate representation of the floating-point number, it will include a lot of trailing zeroes that were presumably not present in the input string. It will also expose floating-point's limitations when presented with huge numbers, like 1e23 will print 1603000.. The best option might be "%.16g", which will choose the shortest of the scientific notation and the regular notation, as well as strip trailing zeroes. Depending on the criteria though, this might still not be the optimal solution. -- Simen 1: https://dlang.org/phobos/std_format.html#format-string
Re: Function called twice
On Friday, 2 August 2019 at 21:44:28 UTC, Jordan Wilson wrote: Hello, I don't quite understand why isEven is called twice in the 2nd example? auto isEven(int n) { n.writeln; return (n % 2) == 0; } void main() { auto z = [1,2,3]; // outputs 1 2 3 z.map!(a => tuple!("number")(a)) .filter!(a => a.number.isEven) .array; // outputs 1 2 2 3 z.map!(a => tuple!("number","iseven")(a, a.isEven)) .filter!(a => a.iseven) .array; return; } map doesn't memoize its front value (https://github.com/dlang/phobos/blob/master/std/algorithm/iteration.d#L604), so every time someone looks at it the mapping function needs to be called again. So in the second case, for each item first filter calls map.front which calls isEven, then if it matches the filter (so only the 2), array calls filter.front, which calls map.front, which calls isEven. You can avoid this by eagerly iterating to an array: z.map!(a => tuple!("number","iseven")(a, a.isEven)) .array // new! .filter!(a => a.iseven) .array; I was also gonna suggest using std.functional.memoize to memoize the function in map, but apparently it doesn't like lambdas (https://issues.dlang.org/show_bug.cgi?id=20099). -- Simen
Re: Abstract classes vs interfaces, casting from void*
On Friday, 9 August 2019 at 12:26:59 UTC, John Colvin wrote: import std.stdio; interface I { void foo(); } class C : I { override void foo() { writeln("hi"); } } abstract class AC { void foo(); } class D : AC { override void foo() { writeln("hi"); } } void main() { auto c = new C(); writeln(0); (cast(I)cast(void*)c).foo(); writeln(1); (cast(C)cast(void*)c).foo(); writeln(2); (cast(I)cast(C)cast(void*)c).foo(); auto d = new D(); writeln(3); (cast(AC)cast(void*)d).foo(); writeln(4); (cast(D)cast(void*)d).foo(); writeln(5); (cast(AC)cast(D)cast(void*)d).foo(); } This produces the output: 0 1 hi 2 hi 3 hi 4 hi 5 hi Why is there no "hi" between 0 and 1? We're getting into somewhat advanced topics now. This is described in the Application Binary Interface page of the documentation[0]. In short: classes and interfaces both use a vtable[1] that holds pointers to each of their methods. When we cast a class instance to an interface, the pointer is adjusted, such that the interface's vtable is the first member. Casting via `void*` bypasses this adjustment. Using `__traits(classInstanceSize)`, we can see that `C` has a size of 12 bytes, while `D` only is 8 bytes (24 and 16 on 64-bit). This corresponds to the extra interface vtable as described above. When we first cast to `void*`, no adjustment happens, because we're not casting to an interface. When we later cast the `void*` to an interface, again no adjustment happens - in this case because the compiler doesn't know what we're casting from. If we use `__traits(allMembers, C)`, we can figure out which methods it actually has, and implement those with some extra debug facilities (printf): class C : I { override void foo() { writeln("hi"); } override string toString() { writeln("toString"); return ""; } override hash_t toHash() { debug printf("toHash"); return 0; } override int opCmp(Object o) { writeln("opCmp"); return 0; } override bool opEquals(Object o) { writeln("opEquals"); return false; } } If we substitute the above in your program, we see that the `toString` method is the one being called. This is simply because it's at the same location in the vtable as `foo` is in `I`'s vtable. When casting from a class to a superclass, no pointer adjustment is needed, as the vtable location is the same for both. We can look closer at the vtable, and see that for a new subclass, additional entries are simply appended at the end: class C { void foo() {} } class D : C { void bar() {} } unittest { import std.stdio; C c = new C(); D d = new D(); writeln("Pointer to foo(): ", (&c.foo).funcptr); writeln("Pointer to bar(): ", (&d.bar).funcptr); writeln("Pointer to foo() in C's vtable: ", c.__vptr[5]); writeln("Pointer to foo() in D's vtable: ", d.__vptr[5]); writeln("Pointer to bar() in D's vtable: ", d.__vptr[6]); } As we see, `foo()` has the position in the vtable for both `c` and `d`, while `D`'s new `bar()` method is added as the next entry. -- Simen [0]: https://dlang.org/spec/abi.html [1]: https://en.wikipedia.org/wiki/Virtual_method_table
Re: CT filtering of class members
On Sunday, 11 August 2019 at 15:27:54 UTC, Sjoerd Nijboer wrote: The following snippet doesn't compile I am trying to reflect on a class and only do an operation with all member functions of a class. But I can't seem to use a filter to only get the member functions out of a type T. I understand that there are two errors in my snippet. 1) It cannot mixin a `name` because it is a variable from the lambda that `filter()` is using. 2) members.filter!(name => !ctorAndDtor.canFind(name)) does not filter on symbols defined in ctorAndDtor How can I fix these problems and return all member functions whitout ctor and dtor of a type T? This is classic D mix of compile-time and compile-time (no typo). I suggest reading H.S. Teoh's text on the topic: https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time Now, as for what can actually be done: you should probably use std.meta.Filter (https://dlang.org/library/std/meta/filter.html) to filter the members list. This will require you to define a template to operate on each element. Something like this: import std.meta : Filter; import std.traits : isFunction; import std.algorithm.searching : canFind; enum isNonspecialMemberFunction(string name) = !ctorAndDtor.canFind(name) && isFunction!(__traits(getMember, T, name)); enum memberFunctions = Filter!(isNonspecialMemberFunction, __traits(derivedMembers, T)); Filter operates on AliasSeqs, not arrays. That's why I restated the __traits(derivedMembers, T) part, but this could just as easily be done by changing this line: enum members = [__traits(derivedMembers, T)]; to: alias members = __traits(derivedMembers, T); -- Simen
Re: filtering a row of a jagged array
On Sunday, 11 August 2019 at 16:11:15 UTC, DanielG wrote: int[][] whatever = [ [0], [0, 1, 2], [5, 6, 7, 8, 9, 10] ]; writeln(whatever[2]);// [5, 6, 7, 8, 9, 10] writeln(typeid(whatever[2]));// int[] auto x = whatever[2].filter(x => x > 7); // error Error: template std.algorithm.iteration.filter cannot deduce function from argument types !()(int[], void), candidates are: ... Online example: https://run.dlang.io/is/LUXFuF ... I'm guessing I need to give the compiler some help understanding that this is an array of ints, but 1) how, and 2) why? [if typeid() seems to understand just fine?] You're missing an exclamation mark after filter - it takes the predicate as a template argument. This compiles just fine: auto x = whatever[2].filter!(x => x > 7); -- Simen
Re: Local static class fields
On Tuesday, 13 August 2019 at 04:43:29 UTC, Paul Backus wrote: On Monday, 12 August 2019 at 22:48:43 UTC, Bert wrote: Making a field static is effectively a global variable to the class. I have a recursive class structure(think of a graph or tree) and I need to keep a global state for it, but this state actually needs to be different for each tree object. The reason for this is that structurally it will not change per tree and if it it is not static then it wastes space unnecessarily. [...] Is there any way to do this more naturally in D? It seems to me like the obvious solution is to use two different classes, one to store the global state, and one to store the individual objects in your structure. For example: class Tree { State state; Node root; } class Node { Node[] children; } So I have a Node. How do I find the Tree it belongs to? -- Simen
Re: Local static class fields
On Monday, 12 August 2019 at 22:48:43 UTC, Bert wrote: Making a field static is effectively a global variable to the class. I have a recursive class structure(think of a graph or tree) and I need to keep a global state for it, but this state actually needs to be different for each tree object. The reason for this is that structurally it will not change per tree and if it it is not static then it wastes space unnecessarily. class X { X[] x; static State s; } making s non-static has the problem that every X will allocate storage for s wasting space since for any instance chain of X's they will all have the same s. Making it static though then makes it the same for all instance chain's of X, of which it should be local to each. One way around this is to use an dictionary that associates each state to each instance chain. That is there is a initial X that is the parent of the chain and we can then associate a state to it's address, any other chain will have a different initial X and so we can get a new state. class X { X[] x; static State[X] s; } This is not a huge difficulty to do but does require finding the initial X to use, which is not difficult but wastes cycles for large chains. There will, of course, be a constructor that constructs a chain and creates a new state for it and updates s. Is there any way to do this more naturally in D? First: Are you low on memory? Is traversing the tree actually slow? Since you don't know which of these issues to prioritize, in all likelihood the answer to both questions is no, and you should use the solution that's easier to read. Of course, that's not the answer you want to hear. Let's consider the alternatives: 1) Embed it in each node. Costs 1 pointer's worth of memory per node. Very fast. Very easy to understand. 2) Use a dictionary with entries for each node. Costs more than 1 pointer's worth of memory per node. Fast, but not quite as fast as 1). 1) is almost definitely a better option. 3) Use a dictionary with entries for each root node. Costs more than 1 pointer's worth of memory, but per tree instead of per node. Requires traversal of the tree to find the root, so slower than both 1) and 2), especially for deep hierarchies. Complicated code. 4) Use a derived class for the root node (class RootX : X { State s }). Still requires traversing the tree to find the root, likely via a virtual method. Also requires a bit more work setting up the tree. Might be faster than 3), definitely smallest memory footprint. Relatively easy to follow. There may be other options, but from the above I'd go with either 1) or 4). Now, I've noticed that X doesn't have a pointer to its parent, so traversing the tree to find the root is currently impossible. If this is true, and you have no other use for traversing up the tree, then 1) is the way to go, as 2) is almost never a better option, and 3) and 4) requires adding a parent pointer so you'll pay the memory price anyway. -- Simen
Re: Local static class fields
On Tuesday, 13 August 2019 at 08:41:02 UTC, Bert wrote: On Tuesday, 13 August 2019 at 04:43:29 UTC, Paul Backus wrote: It seems to me like the obvious solution is to use two different classes, one to store the global state, and one to store the individual objects in your structure. For example: class Tree { State state; Node root; } class Node { Node[] children; } Yes, I forgot to mention this as a solution. I was going to go in to more detail. This is not a great solution because it requires a base class simply to hold the "global" state and it requires nodes to have an accessor(they won't know which tree they come from). What you're essentially looking at here is my solution 4): class Node { Node parent; Node[] children; @property State state() { return parent.state; } } class Root : Node { State treeState; override @property State state() { return treeState; } } class State {} What I was thinking though, with D's capabilities, if a constructor could somehow return a "Voldemort" type that makes it all work out. e.g., class Tree { State state; Node root; alias root this; } then the constructor just returns tree which acts as an node. It doesn't have to be a voldemort but it at least hides some of the details... Ultimately it is not too different from using a dictionary though, effectively does the same thing. Something like this may be possible, but it will still need to keep around a pointer to the context (likely the root), costing you the exact same as having a pointer to either the root or the state in each node: class Root { State state; this() { state = new State(); } auto newNode() { class Node { State getState() { return state; } } return new Node(); } } class State { } unittest { auto root1 = new Root(); auto node = root1.newNode(); assert(node.getState() == root1.state); // Note that Node keeps track of its context, thus taking up more space: assert(__traits(classInstanceSize, typeof(node)) > __traits(classInstanceSize, State)); } There may be no way around such a problem in that these might be "optimal". Your's, which added parent in node, might be better since a dictionary doesn't have to be directly maintained. Also, if space is a concern, the dictionary is actually worse than adding a pointer to the state in each node, as the internal book-keeping of the dictionary is more than one pointer's worth per entry (at the very least it needs to keep both the hash of the Node and the pointer to the state). I'd like to get away from actually having a different "root" type though. Mainly because it reduces uniformity and complicates the design I already have. If I could hide all these things and it is not too complicated then it would work better for me. The solution of having a Root class that derives from Node causes complications in three situations: When you create a new tree, when you move a subtree to become a new tree, and when you move a tree to become a subtree. The last two may or may not actually occur in your code, but without knowing more, I have no idea if that's the case. I'm fairly certain you will at some point be creating new trees, though. If the creation of new trees is confined to one or two functions while the creation of new nodes is widespread, this special-casing of roots should be easily manageable. However, since you specifically mention in this post that Paul 'added parent in node', you should definitely go with a pointer to the state in the Node, as per my earlier post. It's faster, you pay the memory cost anyway, and it's easy for maintainers (that's you in 6 months cursing your young-and-careless self) to understand what's going on. Actually, there's one complication with having a pointer to the state in each node that we haven't mentioned: is the state often replaced wholesale? That is, not just its contents changed, but can the state of a tree suddenly point to a wholly different instance of the same class? If each node holds a pointer to it, then this operation is costly. However, this is generally easy to fix/avoid by a) favor mutation over reassignment, or b) another layer of indirection. -- Simen
Re: Input/Output multiple values from function
On Wednesday, 28 August 2019 at 05:17:28 UTC, Jabari Zakiya wrote: Inside func2 I create an input value for func1 and then assign func1's 4 outputs to named variable. That's where the problems arise. func1 does some math based on the input and generates 4 outputs. I can't do (a, b, c,d) = func1(i) directly. What do I do to assign the output of func1 to the individual variables? import std.meta : AliasSeq; import std.typecons : tuple; auto fun() { return tuple(1, "test"); } unittest { int a; string b; AliasSeq!(a, b) = fun; assert(a == 1); assert(b == "test"); } -- Simen
Re: Input/Output multiple values from function
On Wednesday, 28 August 2019 at 13:11:46 UTC, Jabari Zakiya wrote: When I do this: uint a; uint b; uint[] c; uint[] d; AliasSeq!(a, b, c, d) = genPGparameters(pg); modpg= a; res_0= b; restwins = c; resinvrs = d; the compiler (ldc2 1.17) says: D Projects ~/D/bin/ldc2 --release -O3 twinprimes_ssoznew1.d twinprimes_ssoznew1.d(170): Error: cannot implicitly convert expression c of type uint[] to shared(uint[]) twinprimes_ssoznew1.d(171): Error: cannot implicitly convert expression d of type uint[] to shared(uint[]) where modpg, res_0; restwins, resinvrs are shared (global) variables. Reduced example: unittest { int[] a; // cannot implicitly convert expression a of type int[] to shared(int[]) shared int[] b = a; } This is because an int[] is mutable and thread-local, while shared(int[]) is mutable and shared. Shared mutable data must be guarded closely, preferably behind a mutex or similar. Assigning the value of `a` to `b` above would leave a mutable reference to the shared data on a thread, and could easily lead to race conditions. In order to fix this issue, consider several things: Do modpg and friends really need to be shared? Removing shared() from them will still make them available to other parts of your code, but they will be thread-local instead. If you're not doing threaded work, that should be perfectly fine. Can they be immutable? If they're initialized once and never changed, this could be a good solution. If they need to be shared and mutable, have you protected them enough from race conditions? Are there possible situations where other threads may be accessing them while one thread is writing to them? Multi-threaded programming is hard, and requires a lot more knowledge than we have about your project from the code you've posted, so only you can answer these questions. If you're unsure, you can probably just remove shared() from modpg and friends. -- Simen
Re: Input/Output multiple values from function
On Thursday, 29 August 2019 at 10:39:44 UTC, Jabari Zakiya wrote: The values modpg, res_0, restwins, and resinvrs are constant (immutable) values that are generated at run time. They are global/shared and used inside threads. So this process is initializing them at the start of the program, based on the input values to it. Great - then you can use shared(immutable(uint)[]). You should be able to convert from immutable(uint[]) to that without issue. There's a utility function in std.exception called assumeUnique that can be used for conversion to immutable that may be more informative than cast(immutable): shared(uint) modpg; shared(uint) res_0; shared(immutable(uint)[]) restwins; shared(immutable(uint)[]) resinvrs; auto genPGparameters(int i) { import std.typecons; import std.exception; // Showing both cast and assumeUnique: return tuple(1u, 2u, cast(immutable)[3u], [4u].assumeUnique); } unittest { import std.meta : AliasSeq; int pg; // No need for temporaries: AliasSeq!(modpg, res_0, restwins, resinvrs) = genPGparameters(pg); } The compiler only has a problem, it seems, with the arrays and not the single values. Correct - since there are no indirections in a uint, you can assign directly to a shared(uint) - nobody else will have a non-shared pointer to that uint, so it's somewhat safe. If you do the same with uint[], you'll still have a pointer to the same values, and changing a value that says it's thread-local (no shared) will change values that is shared with the rest of the program. There are some issues with the current shared design, but this is what it's intended to do. -- Simen
Re: Test the return type of 'unaryFun' and 'binaryFun'.
On Thursday, 29 August 2019 at 08:58:18 UTC, Mek101 wrote: As the title says, is there a way to test the return type of the 'unaryFun' and 'binaryFun' templates from 'std.functional'? I have the following code, and I want to to be sure that 'predicate' returns a boolean, but neither 'is(typeof(predicate) == bool)' or 'is(ReturnType!predicate == bool)' seem to work. private alias NullSized = Nullable!(size_t, size_t.max); public NullSized indexOf(alias pred = "a == b", Range, V)(Range array, V value) if((isRandomAccessRange!Range || isStaticArray!Range)) { alias predicate = binaryFun!pred; for(size_t i = 0; i < array.length; i++) if(predicate(array[i], value)) return NullSized(i); return NullSized.init; } You'll need to test calling the predicate with the actual types it will be processing - something like is(typeof(predicate(array[0], value)) == bool). You could (and quite possibly should) do this in the template constraint. The reason is binaryFun actually returns a generic function - a template that needs to know its actual argument types. For fun, you could actually test is(typeof(predicate!(ElementType!Range, V)) == bool). -- Simen
Re: getting rid of immutable (or const)
On Thursday, 5 September 2019 at 09:07:30 UTC, berni wrote: import std.algorithm: reverse; writeln(q.reverse); How to get this working? (I hope I don't annoy you by asking that much questions, but I've got the feeling, that I've got only two choices: To shy away from using immutable (like I did in the last three years) or ask a lot of questions in the hope of understanding what's going on... https://dlang.org/library/std/range/retro.html Difference is, retro lazily iterates in reverse order, while reverse eagerly reverses in-place. Don't worry about asking questions - it's a good way to learn, and we like helping. :) Immutable is not very well supported everywhere in the library, sadly. It seems an important building block would be something like Reassignable!T, which would hold a struct with immutable members, and still be reassignable with different values. -- Simen
Re: default values depending on type of template variable
On Wednesday, 11 September 2019 at 08:35:02 UTC, berni wrote: I'd like to write a template, that takes a different default value depending on the type of a variable. I tried this, but it doesn't work: void main() { double a = 1e-8; double b = 1e-10; float c = 1e-4; float d = 1e-6; assert(!test(a)); assert(test(b)); assert(!test(c)); assert(test(d)); } auto test(T, U)(T value, U limit=1e-9) { return value Although being called with a double in the first two tests, the second overload is always used and therefore the first test fails. And without this overload, the last test obviously doesn't pass. Is there a way, to provide default values for template parameters depending on the type of an other parameter? unittest { double a = 1e-8; double b = 1e-10; float c = 1e-4; float d = 1e-6; assert(!test(a)); assert(test(b)); assert(!test(c)); assert(test(d)); } auto test(T, U)(T value, U limit = limit!T) { return value < limit; } // Solution 1: template limit(T) { static if (is(T == float)) { enum limit = 1e-5; } else { enum limit = 1e-9; } } // Solution 2: enum limit(T : float) = 1e-5; enum limit(T : double) = 1e-9; With some tricks this can also be inlined: enum If(bool b, T...) = T[b ? 0 : 1]; auto test(T, U)(T value, U limit = If!(is(T == float), 1e-5, 1e-9)) { return value < limit; } -- Simen
Re: Problem with using std.math: abs and std.complex: abs at the same time
On Wednesday, 18 September 2019 at 12:03:28 UTC, berni wrote: The following code doesn't compile: import std.stdio; void main() { import std.complex: abs, complex; import std.math: abs; auto a = complex(1.0,1.0); auto b = 1.0; writeln(abs(a)); writeln(abs(b)); } The error message depends on the order of the two import statements. Seems like the second import is actually ignored. import std.complex: abs, complex; Is treated by the compiler as if you'd written something somewhat like this: static import std.complex; alias abs = std.complex.abs; alias complex = std.complex.complex; When you add import std.math: abs; It's treated like: static import std.math; alias abs = std.math.abs; In other words, we have two aliases with the same name inside a function scope, and the compiler can't do that (try doing it explicitly, as in the 'treated like' sections above - you'll get a compilation error). This is related to why you can't have overloaded nested functions: unittest { void fun() {} void fun(int i) {} // declaration fun is already defined } How to resolve this, though? The simplest solution is to not use selective imports: import std.math; import std.complex; writeln(abs(complex(1.0,1.0))); writeln(abs(1.0)); If you absolutely can't contaminate the scope with all the unused symbols in std.math and std.complex, you *can* do this: import std.stdio; unittest { import std.complex : complex; static import std.math; alias abs = MergeOverloads!(std.complex.abs, std.math.abs); auto a = complex(1.0,1.0); auto b = 1.0; writeln(abs(a)); writeln(abs(b)); } template MergeOverloads(T...) { alias MergeOverloads = T[0]; static if (T.length > 1) { alias MergeOverloads = MergeOverloads!(T[1..$]); } } I would however label that a horrible hack. FWIW, I've filed this issue: https://issues.dlang.org/show_bug.cgi?id=20226 -- Simen
Re: Problem with using std.math: abs and std.complex: abs at the same time
On Wednesday, 18 September 2019 at 13:24:05 UTC, berni wrote: On Wednesday, 18 September 2019 at 12:37:28 UTC, Simen Kjærås wrote: How to resolve this, though? The simplest solution is to not use selective imports: import std.math; import std.complex; writeln(abs(complex(1.0,1.0))); writeln(abs(1.0)); That works. But: I'm trying to write some code for math.d and when I put this code inside math.d it doesn't work anymore. Also removing "import std.math" or moving it after the other import, did not help. So what you have is basically this? import std.stdio; float abs(float f) { return f >= 0 ? f : -f; } unittest { import std.complex : complex, abs; auto a = complex(1.0,1.0); auto b = 1.0f; writeln(abs(a)); writeln(abs(b)); } That does indeed fail to compile, and there's no easy way to introduce the module-level abs() function to the scope. Again though, MergeOverloads to the rescue: float abs(float f) { return f < 0 ? -f : f; } unittest { import std.complex : complex, cabs = abs; alias abs = MergeOverloads!(cabs, .abs); abs(1); abs(complex(1,1)); } template MergeOverloads(T...) { static foreach (E; T) alias MergeOverloads = E; } -- Simen
Re: Problem with using std.math: abs and std.complex: abs at the same time
On Thursday, 19 September 2019 at 10:25:01 UTC, berni wrote: On Thursday, 19 September 2019 at 07:26:17 UTC, Simen Kjærås wrote: That does indeed fail to compile, and there's no easy way to introduce the module-level abs() function to the scope. Again though, MergeOverloads to the rescue: I'm not sure, if MergeOverloads will be accepted into std/math.d. Meanwhile I've created a pull request (#7187), that does not handle complex numbers although the algorithm would be identical. Maybe handling complex numbers in math.d can be added later (or maybe it's better to put this in std/complex.d anyway, but then code duplication would be necessary). You could perfectly well place MergeOverloads inside whatever function you make, thus not polluting std.math: float abs(float f) { return f < 0 ? -f : f; } unittest { import std.complex : complex, cabs = abs; template MergeOverloads(T...) { static foreach (E; T) alias MergeOverloads = E; } alias abs = MergeOverloads!(cabs, .abs); abs(1); abs(complex(1,1)); } (you can also use this to create ridiculous overload sets, since MergeOverloads doesn't care if one function is called abs and the other dropBackExactly. Please don't do this) If you want to introduce MergeOverloads to Phobos officially, std.math is definitely *not* the place though. :) I'd probably say std.functional, but I'm not really sure where it'd belong. Let's put it in std.exception, since it's an exception from D's usual overload rules in functions. :p I don't think anything in std.math explicitly deals with std.complex at this point (some things may handle it generically), so it seems std.complex would be the logical place for anything that does. Might I ask what specifically you're working on? -- Simen
Re: A proper WAT moment
On Tuesday, 15 October 2019 at 07:06:35 UTC, John Colvin wrote: On Monday, 14 October 2019 at 19:45:11 UTC, Paul Backus wrote: On Monday, 14 October 2019 at 17:00:56 UTC, John Colvin wrote: Different ability to access a property depending if I'm inside something else when I look? [snip] You're attempting to call one of S's member functions without an instance of S to call it on. [snip] The real issue here is that the first `__traits(compiles)` check succeeds, even though the actual expression fails. And all the other ones in my example that access members without an instance that also compile? There's something pretty strange about the rules here. Yeah, Paul's wrong here - the struct is what messes things up here, though I don't understand why. Just putting the first function inside a struct cause the exact same issue: struct S { int a; int e() @property { return a; } } pragma(msg, __LINE__, " ", __traits(compiles,__traits(getMember, S, "e"))); void fun() { pragma(msg, __LINE__, " ", __traits(compiles,__traits(getMember, S, "e"))); } struct S2 { void fun() { pragma(msg, __LINE__, " ", __traits(compiles,__traits(getMember, S, "e"))); } } Interestingly, the code does of course actually compile: struct S3 { void fun() { alias a = __traits(getMember, S, "e"); } }
Re: The compiler can't "see" an inner class
On Sunday, 27 October 2019 at 17:52:51 UTC, Emmanuelle wrote: Hello! See snippet: --- interface AST { static interface Expr : AST { final static class Name : Expr { override void accept(AST.Visitor v) { v.visitName(this); } } } final static class Visitor { void visitName(AST.Expr.Name name); } void accept(AST.Visitor v); } --- If you try to compile that, dmd v2.088.0 complains: --- Error: no property Name for type onlineapp.AST.Expr --- How come? It's defined right there. I would really like some pointers on this, thanks! It's a bug: interface A { interface B : A { class C : B { } } // Fails: no property 'C' for type 'foo.A.B' void inside(A.B.C c) { } } // Works void outside(A.B.C c) { } https://issues.dlang.org/show_bug.cgi?id=20329 -- Simen
Re: Read Once then reset/init value?
On Tuesday, 29 October 2019 at 22:24:20 UTC, Robert M. Münch wrote: I quite often have the pattern where a value should be read just once and after this reset itself. The idea is to avoid that others read the value by accident and get an older state, instead they get an "invalid/reset" value. Is there a library function that can mimic such a behaviour? Something like this? T readOnce(T)(ref T value) { auto tmp = value; value = T.init; return tmp; } unittest { int i = 3; assert(i.readOnce == 3); assert(i == 0); } If so, no, there is no library function for it, but feel free to use the above. You may very well have to change T.init to something more fitting for your use case, of course. If this is not what you need, feel free to explain further, as I'm not sure I understood you correctly. :) -- Simen
Re: Read Once then reset/init value?
On Wednesday, 30 October 2019 at 11:53:42 UTC, Jacob Carlborg wrote: On 2019-10-30 00:28, Simen Kjærås wrote: Something like this? T readOnce(T)(ref T value) { auto tmp = value; value = T.init; return tmp; } unittest { int i = 3; assert(i.readOnce == 3); assert(i == 0); } Perhaps better to encapsulate it in a struct to avoid someone accessing the value directly. Quite possibly, but the post was somewhat low on details, and encapsulating it like that does put certain limits on how it can be used, so it's not necessarily the best idea. FWIW, here's one possible way to do it with a struct: struct Readonce(T, T defaultValue = T.init) { private T value; alias get this; T get() { auto tmp = value; value = defaultValue; return tmp; } void get(T newValue) { value = newValue; } this(T newValue) { value = newValue; } } unittest { Readonce!(int, -1) a = 3; assert(a == 3); assert(a == -1); a = 3; assert(a == 3); assert(a == -1); } -- Simen
Re: Bug or Feature: `this` necessary to call function with template this parameter
On Wednesday, 30 October 2019 at 20:22:25 UTC, Q. Schroll wrote: struct Example { private void helper(int i, this X)() { } void funcTempl(T, this X)(T value) { this.helper!0(); // ^ Why do I need this? } } void main() { auto ex = Example(); ex.funcTempl(1); } The question is in the comment in the code. Is that intentional or a bug? It's a bug - filed as https://issues.dlang.org/show_bug.cgi?id=20341. However, note that typeof(this) inside funcTempl() is different from X, so that inside helper(), X will not be the same as in funcTempl(). To fix this, you will need to pass X on to helper as helper!(0, X). When you do this, you no longer need 'this.' in front of the instantiation. -- Simen
Re: How decode encoded Base64 to string text?
On Friday, 8 November 2019 at 11:46:44 UTC, Marcone wrote: I can encode "Helo World!" to Base64 and get "TWFyY29uZQ==", but if I try to decode "TWFyY29uZQ==" I can not recovery "Helo World!" but [77, 97, 114, 99, 111, 110, 101]. How can I recover "Helo World!" when decode? Thank you. import std; void main(){ string text = "Helo World!"; auto encoded = Base64.encode(text.representation); auto decoded = Base64URL.decode("TWFyY29uZQ=="); writeln(encoded); // prints: "TWFyY29uZQ==" writeln(to!string(decoded)); // prints: [77, 97, 114, 99, 111, 110, 101] but I want to print: "Helo World!" } What Aldo said - Base64 operates on ubyte[], which a string is not (it's immutable(char)[]). There's also assumeUTF (https://dlang.org/library/std/string/assume_utf.html) which may document your code a bit better than a simple cast, but it does the same thing inside. The reason Base64 operates on ubyte[] is to be able to encode arbitrary data, while the reason to!string doesn't convert your ubyte[] to a readable string is that not all ubyte[] are valid strings, and displaying arbitrary data as if it were a string is sure to cause problems. -- Simen
Re: Should I stop being interested in D language if I don't like to see template instantiation in my code?
On Thursday, 14 November 2019 at 09:30:23 UTC, user9876 wrote: A good thing is that in many cases the template instance parameters can be deduced from the arguments used: --- import std; void main() { assert(max(0,1) == 1); // same as assert(max!(int,int)(0,1) == 1); } --- This feature is known as "IFTI" see §6, https://dlang.org/spec/template.html#function-templates. You're not forced to use the D templates but you'll have to write many code by yourself because the standard library use them everywhere. IFTI is nifty. (sorry, I had to) -- Simen
Re: @disable("reason")
On Wednesday, 8 January 2020 at 08:26:51 UTC, user1234 wrote: class Example { @disable this() { pragma(msg, "not allowed..."); } } void main() { new Example(); } outputs: not allowed... /tmp/temp_7F8C65489550.d(12,5): Error: constructor `runnable.Example.this` cannot be used because it is annotated with `@disable` However, it will print that message even if the constructor is never called. If you make the constructor a template instead, you will only get the message when someone attempts to use the default constructor: class Example { @disable this()() { pragma(msg, "not allowed..."); } } void main() { new Example(); } Sadly, this does not work for structs, as they don't really have a default constructor, as Jonathan pointed out. -- Simen
Re: @disable("reason")
On Wednesday, 8 January 2020 at 07:03:26 UTC, Jonathan M Davis wrote: you could just document that no one should ever use its init value explicitly, and that they will have bugs if they do You also create a static init member marked @disable: struct S { @disable this(); @disable static S init(); } This will give sensible error messages anywhere .init is being used. Now, Phobos and other libraries might expect that .init is always working, so this could potentially be a problem.
Re: Custom separator in array format
On Tuesday, 28 January 2020 at 07:36:25 UTC, Malte wrote: I want to format an array using the %(...%) syntax. How can I change the separator? I tried to use ? and add it as additional parameter, but that doesn't seem to work on arrays: import std; void main() { writeln("This works:"); writefln("%,2?d", '_', 2000); // 20_00 auto vec = [1000, 2000, 3000]; writeln("This should fail (separator character expected) but the ? is just ignored:"); writefln("%(%,2?d\t%)", vec); // 10,0020,00 30,00 writeln("This throws:"); writefln("%(%,2?d\t%)", '_', vec); // std.format.FormatException@/dlang/dmd/linux/bin64/../../src/phobos/std/format.d(2271): incompatible format character for integral argument: %( } I think I see why it's not working. Essentially, for each element of vec, format is called with only that element as an argument. Essentially, rather than: foreach (e; vec) writef("%,2?d\t", '_', e); writeln(); You get: foreach (e; vec) writef("%,2?d\t", e); writeln(); For whatever reason, it doesn't throw when missing an argument for the separator - I'd say this is a bug (https://issues.dlang.org/show_bug.cgi?id=20541). For now, you can work around the issue this way: import std.stdio : writefln; import std.format : format; import std.algorithm : map; auto vec = [1000, 2000, 3000]; writefln("%-(%s\t%)", vec.map!(e => format!"%,2?d"('_', e))); -- Simen
Re: Global version/debug statements in file?
On Wednesday, 12 February 2020 at 08:44:24 UTC, cc wrote: Is there some way to globally declare version= or debug= statements in a file and have them apply to the entire project being compiled? As the documentation says these only apply to the module scope they exist in, and need to be added to the command line otherwise. It would be a bit easier for me to maintain a separate .d source file when I want to add/comment out statements for testing than to keep updating the build command line. https://dlang.org/dmd-windows.html#switches specifies that DMD may be passed a file on the command line that contains compiler arguments and switches. This may be freely combined with regular command line arguments if you so wish. So, you could have a file called 'versions' containing this: # Setting 'Compress' version -version=Compress # Optionally set other versions #-version=Foo #-version=Bar and feed it to dmd like so: dmd -w -wi -g @versions -main foo.d -- Simen
Re: From [Tuple!(A,B), ...] to Tuple!(A[], B[])
On Monday, 17 February 2020 at 11:07:33 UTC, foozzer wrote: Hi all, There's something in Phobos for that? Thank you import std.meta : staticMap; import std.typecons : Tuple; // Turn types into arrays alias ToArray(T) = T[]; // Leave everything else the same alias ToArray(T...) = T; // Now apply the above to each element of the Tuple template args: alias ToArrayTuple(T : Tuple!U, U...) = Tuple!(staticMap!(ToArray, U)); unittest { alias A = Tuple!(int, string); assert(is(ToArrayTuple!A == Tuple!(int[], string[]))); alias B = Tuple!(int, "a", string, "b"); assert(is(ToArrayTuple!B == Tuple!(int[], "a", string[], "b"))); } -- Simen
Re: From [Tuple!(A,B), ...] to Tuple!(A[], B[])
On Monday, 17 February 2020 at 11:51:52 UTC, FeepingCreature wrote: On Monday, 17 February 2020 at 11:07:33 UTC, foozzer wrote: Hi all, There's something in Phobos for that? Thank you Here you go: import std; // extract the types that make up the tuple auto transposeTuple(T : Tuple!Types[], Types...)(T tuples) { // templated function that extracts the ith field of an array of tuples as an array auto extractArray(int i)() { return tuples.map!(a => a[i]).array; } // return tuple of calls to extractArray, one for each tuple index return tuple(staticMap!(extractArray, aliasSeqOf!(Types.length.iota))); } void main() { Tuple!(int, double)[] array; array ~= tuple(1, 2.0); array ~= tuple(3, 4.0); Tuple!(int[], double[]) tuple = array.transposeTuple; assert(tuple[0] == [1, 3]); assert(tuple[1] == [2.0, 4.0]); } ^^ Do what he said - I misread the title. :) -- Simen
Re: From [Tuple!(A,B), ...] to Tuple!(A[], B[])
On Monday, 17 February 2020 at 11:51:52 UTC, FeepingCreature wrote: Here you go: import std; // extract the types that make up the tuple auto transposeTuple(T : Tuple!Types[], Types...)(T tuples) { // templated function that extracts the ith field of an array of tuples as an array auto extractArray(int i)() { return tuples.map!(a => a[i]).array; } // return tuple of calls to extractArray, one for each tuple index return tuple(staticMap!(extractArray, aliasSeqOf!(Types.length.iota))); } void main() { Tuple!(int, double)[] array; array ~= tuple(1, 2.0); array ~= tuple(3, 4.0); Tuple!(int[], double[]) tuple = array.transposeTuple; assert(tuple[0] == [1, 3]); assert(tuple[1] == [2.0, 4.0]); } One tiny thing: the above fails for tuples with named fields, like Tuple!(int, "a", string "b"). This code handles that case, and preserves field names: import std.meta : staticMap, aliasSeqOf; import std.typecons : Tuple; import std.range : array, iota; import std.algorithm : map; alias ToArray(T) = T[]; alias ToArray(T...) = T; alias ToArrayTuple(T : Tuple!U, U...) = Tuple!(staticMap!(ToArray, U)); auto transpose(T : Tuple!U, U...)(T[] arr) { auto extract(int i)() { return arr.map!(a => a[i]).array; } return ToArrayTuple!T(staticMap!(extract, aliasSeqOf!(T.Types.length.iota))); } unittest { alias T = Tuple!(int, "a", string, "b"); auto a = [T(1, "a"), T(2, "b")]; assert(a.transpose.a == [1, 2]); assert(a.transpose.b == ["a", "b"]); } -- Simen
Re: operator overload for sh-like scripting ?
On Monday, 17 February 2020 at 13:03:38 UTC, Basile B. wrote: eg Sh(echo) < "meh"; struct Sh { // you see the idea we have op overload for < here } You can't overload < separately - all the comparison operators (<, <=, >, >=) are handled via opCmp. Even if you choose to go down that route, there are other issues - opCmp needs to return something that may be compared to 0, since (a < b) is rewritten as (a.opCmp(b) < 0), and the compiler checks if you are simply discarding the return value of a comparison, so all in all, you shouldn't do that in D (and the hoops you have to jump through to make it work makes the code a lot less readable): struct Sh { int opCmp(string s) { import std.stdio : writeln; writeln(s); return 0; } } unittest { Sh sh; auto _ = sh < "baz"; } This is also not chainable, so something like (sh < "foo" < "bar") won't work, even with parentheses. There's also the issue of (a < b) having a defined meaning in D (a less than b), and such overloading leads to code that may be less readable. This is a point with differing opinions, and I'm not firmly on either side of that argument, but it's worth pointing out. Now, if you absolutely want something that's somewhat similar in regular D code, there's <<: struct Sh { Sh opBinary(string op : "<<")(string s) { import std.stdio : writeln; writeln(s); return this; } } unittest { Sh sh; sh << "foo" << "bar"; } While this works, it's a design choice that C++ has gotten a lot of flak for, including one of my favorite C++ quotes: "I saw 'cout' being shifted 'Hello world' times to the left and stopped right there." There are cases where it's not at obvious to the reader of the code what's happening, so such operator overloading should be used with caution. A better choice, perhaps, if using < is important, would be to use a DSL and have it obvious in the code that normal D rules aren't at play: void fun() { Sh sh; mixin dsl!` sh < "foo"; `; } At this point though, you're looking at a considerable chunk of code just for a bit of syntactic sugar. -- Simen
Re: Why can't I pass a const array to a function that takes scope const arrays?
On Monday, 17 February 2020 at 14:04:34 UTC, Adnan wrote: cdsa ~master: building configuration "cdsa-test-library"... source/strassens_matmul.d(22,16): Error: cannot implicitly convert expression &mat[row][column] of type const(uint)* to uint* source/strassens_matmul.d(37,36): Error: template instance strassens_matmul.getPointPtr!uint error instantiating source/strassens_matmul.d(48,29): I'd just finished writing a long post explaining the stuff you've apparently figured out. Ah well. :p In this case, getPointPtr return T*, but takes scope const ref T[][]. Since getPointPtr always takes a mutable array, you could just get rid of const on its parameters. Alternatively, if you want to be able to use it on arrays of different constness, you could use inout: inout(T)* getPointPtr(T)(inout T[][] mat, size_t row, size_t column) { This will return a pointer to a mutable T if that's what the array holds when you call the function, const(T) if it's a const array, immutable(T) if it's immutable, and so on. The same can be done with the other functions you have. You are also somewhat overusing const, scope and ref, I'd say - you should not take an array by ref unless you plan on modifying it, which you are not doing in getPointPtr or any other of your functions. scope may be worth it, as it guarantees you won't be sending the data elsewhere. None of these are necessary on your ulongs, which are passed by value and never attempted modified. If you really like the extra guarantee that you don't accidentally modify them, feel free to keep 'const', but 'scope' on a ulong does nothing, and it's been argued it should be a compiler error. Lastly, you're using ulongs a lot, and this is mostly correct when compiling for 64-bit, but makes code fail to compile for 32-bit. Using size_t instead makes for code that works for both. All in all, I end up with this code: module strassens_matmul; debug { static import std; } package { size_t getRowSize(T)(const T[][] mat) { return mat[0].length; } size_t getColumnSize(T)(const T[][] mat) { return mat.length; } T[][] createMatrix(T)(size_t rowSize, size_t columnSize) { return new T[][](rowSize, columnSize); } /// row and column are 0 index-based inout(T)* getPointPtr(T)(inout T[][] mat, size_t row, size_t column) { return &mat[row][column]; } T getPointCopy(T)(const T[][] mat, size_t row, size_t column) { return mat[row][column]; } T[][] mulIterative(T)(const T[][] mat1, const T[][] mat2) { auto result = createMatrix!T(getRowSize!T(mat1), getColumnSize!T(mat2)); foreach (row; 0 .. mat1.getRowSize()) { foreach (column; 0 .. mat2.getColumnSize()) { T value; foreach (i; 0 .. mat1.getRowSize()) { value += mat1.getPointCopy(row, i) * mat2.getPointCopy(i, column); } *result.getPointPtr(row, column) = value; } } return result; } } unittest { const uint[][] matA = [[10, 20, 10], [4, 5, 6], [2, 3, 5]]; const uint[][] matB = [[3, 2, 4], [3, 3, 9], [4, 4, 2]]; const uint[][] matC = [[130, 120, 240], [51, 47, 73], [35, 33, 45]]; assert(matA.mulIterative(matB) == matC); } -- Simen
Re: How to declare a virtual member (not a function) in a class
On Tuesday, 18 February 2020 at 12:37:45 UTC, Adnan wrote: I have a base class that has a couple of constant member variables. These variables are abstract, they will only get defined when the derived class gets constructed. class Person { const string name; const int id; } class Male : Person { this(string name = "Unnamed Male") { static int nextID = 0; this.id = nextID++; this.name = name; } } The compiler restricts me from assigning those two functions. How can I get around this? const members can only be set in the constructor of the type that defines them. To set them in a subclass, forward the values to the superclass' constructor: class Person { const string name; const int id; protected this(string _name, int _id) { id = _id; name = _name; } } class Male : Person { this(string name = "Unnamed Male") { static int nextID = 0; super(name, nextID++); } } -- Simen
Re: Alternative to friend functions?
On Tuesday, 18 February 2020 at 12:43:22 UTC, Adnan wrote: class Wife(uint N) : Female { FemaleID engagedTo = -1; const MaleID[N] preferences; this(MaleID[N] preferences) { this.preferences = preferences; } } void engage(N)(ref Wife!N, wife, ref Husband!N husband) { // Here, I want to access both husband and wife's engaged_to } Petar's answer covers your question, so I won't elaborate on that, but I'd like to point out that as Wife and Husband are classes, you probably don't intend to take them by ref - classes are always by ref in D, so you're effectively passing a reference to a reference to a class in `engage`. Basically: class Foo { int n; } void fun(Foo f) { f.n = 3; // Local copy of the reference - does not modify other references. f = null; } void gun(ref Foo f) { f = null; } unittest { Foo f = new Foo(); Foo g = f; f.n = 17; // f and g point to the same object: assert(f.n == 17); assert(g.n == 17); fun(f); // fun() changed the object that both f and g point to: assert(f.n == 3); assert(g.n == 3); gun(f); // gun() changed f to no longer point at the same object, but left g untouched: assert(f is null); assert(g !is null); assert(g.n == 3); } -- Simen
Re: String switch is odd using betterC
On Wednesday, 26 February 2020 at 08:32:50 UTC, Abby wrote: On Wednesday, 26 February 2020 at 08:25:00 UTC, Abby wrote: Any idea why? Ok so this is enough to produce the same result, it seems that there is a problem in string switch when there is more the 6 cases. extern(C) void main() { auto s = "F"; final switch(s) { case "A": break; case "B": break; case "C": break; case "D": break; case "E": break; case "F": break; case "G": break; } } The explanation can be found in druntime/import/core/internal/switch_.d: the __switch template does a simple binary search for less than 7 cases, but calls .idup on each case label for >= 7 cases. There's a comment there about why it's being done, but it seems to be a far more complicated fix than necessary - static immutable cases = [caseLabels]; works just as well, it seems. Anyway, the current code was added in this commit: https://github.com/dlang/druntime/commit/fa665f6618af7dbc09ed5ba1333f385017b7ece8. Anyways, reported here: https://issues.dlang.org/show_bug.cgi?id=20613 -- Simen
Re: How to copy const object?
On Thursday, 27 February 2020 at 11:28:11 UTC, Mitacha wrote: I've a const struct object and I'd like to make a mutable copy of it. Struct definition contains string and an array of structs. ``` struct A { string a; B[] b; } struct B { string a; string b; } ``` As far as I can tell copy constructor isn't generated for struct `A` because it contains an array. Correct? Is there an idiomatic way to create copy of a const object? As long as the copy is also const, you can just assign it to a new variable of the same type: const A a = A("foo",[B("bar", "baz")]); const A b = a; If, however, you require a mutable copy, things get a little more hair. In D, const is transitive, so that A.b[0] is a const(B). This will thus not work: A c = a; // Error: cannot implicitly convert expression a of type const(A) to A For built-in arrays, the .dup function does this: const int[] arr1 = [1]; int[] arr2 = arr1; // Fails to compile int[] arr3 = arr1.dup; // Works For symmetry, we can add a similar function to A: struct A { string a; B[] b; A dup() const { return A(a, b.dup); } } This lets us easily create a copy: A d = a.dup; Now, the reason you can't just assign from const(A) to A, while this works with const(B) to B, e.g., is that A contains mutable indirections. That is, you can change the contents of A.b. Since copies are generally shallow copies in D, allowing this behavior would have unfortunate consequences: const(A) a1 = A("foo", [B("bar", "baz")]); A a2 = a1; // Assume this worked assert(a1.b[0].a == "bar"); a1.b[0].a = "qux"; // Can't change b[0] through a1, since it's const a2.b[0].a = "qux"; // But we can change it through a2! assert(a1.b[0].a != "bar"); // And suddenly the const value in a1.b has changed. -- Simen
Re: Call method if declared only
On Friday, 28 February 2020 at 08:08:59 UTC, Виталий Фадеев wrote: On Friday, 28 February 2020 at 06:12:37 UTC, Виталий Фадеев wrote: Searching solution for idea ! Goal is to get System message, dispatch/route to method ! If method implemented only ! I dream on in future write clean code of a derived widgets like this : class Base { // dispatch void On( message ... ) { // call On() // example: call OnKeyUp() - if method OnKeyUp() is exists only } } May be other than derived ? May be templating ? How to implement ? Now I go in ths way: [snip] Searching for beauty readable code... Here's an attempt. It looks up all subclasses of Base in the same module, and calls the named method if it exists. However, it will fail for any subclass of Base that is defined in a different module. import core.sys.windows.windows; import std.stdio; class Base { LRESULT On(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_KEYDOWN: return tryCall!"OnWM_KEYDOWN"(wParam, lParam); default: } return 0; } auto tryCall(string name, Args...)(Args args) { import std.meta; alias This = typeof(this); alias module_ = __traits(parent, This); enum isSubclass(T...) = is(T[0] : This); alias getModuleMember(string name) = __traits(getMember, module_, name); enum hasMethod(T) = __traits(hasMember, T, name); // Get every member in this module enum memberNames = __traits(allMembers, module_); alias members = staticMap!(getModuleMember, memberNames); // Filter away anything that isn't derived from Base alias subclasses = Filter!(isSubclass, members); // Get rid of anything that doesn't have a method with the correct name alias subclassesWithMethod = Filter!(hasMethod, subclasses); // Sort them so you get the most derived types first alias Types = DerivedToFront!subclassesWithMethod; // Check for each type if the `this` is an instance of that specific one static foreach (T; Types) { if (cast(T)this !is null) { // And look up that method and call it. return __traits(getMember, cast(T)this, name)(args); } } // If `this` is not one of the types with that method, return some default value return 0; } } class Button : Base { LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam) { writeln("WM_KEYDOWN"); return 0; } } unittest { Base b1 = new Base(); Base b2 = new Button(); writeln("Base:"); b1.On(WM_KEYDOWN, 0, 0); writeln("Button:"); b2.On(WM_KEYDOWN, 0, 0); } -- Simen
Re: Call method if declared only
On Friday, 28 February 2020 at 06:12:37 UTC, Виталий Фадеев wrote: Searching solution for idea ! For whatever reason, it seems my attempts at answering this earlier has disappeared into the void. Here: import core.sys.windows.windows; import std.stdio; class Base { LRESULT On(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_KEYDOWN: return tryCall!"OnWM_KEYDOWN"(wParam, lParam); default: } return 0; } auto tryCall(string name, Args...)(Args args) { import std.meta; alias This = typeof(this); alias module_ = __traits(parent, This); enum isSubclass(T...) = is(T[0] : This); alias getModuleMember(string name) = __traits(getMember, module_, name); enum hasMethod(T) = __traits(hasMember, T, name); // Get every member in this module enum memberNames = __traits(allMembers, module_); alias members = staticMap!(getModuleMember, memberNames); // Filter away anything that isn't derived from Base alias subclasses = Filter!(isSubclass, members); // Get rid of anything that doesn't have a method with the correct name alias subclassesWithMethod = Filter!(hasMethod, subclasses); // Sort them so you get the most derived types first alias Types = DerivedToFront!subclassesWithMethod; // Check for each type if the `this` is an instance of that specific one static foreach (T; Types) { if (cast(T)this !is null) { // And look up that method and call it. return __traits(getMember, cast(T)this, name)(args); } } // If `this` is not one of the types with that method, return some default value return 0; } } class Button : Base { LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam) { writeln("WM_KEYDOWN"); return 0; } } unittest { Base b1 = new Base(); Base b2 = new Button(); writeln("Base:"); b1.On(WM_KEYDOWN, 0, 0); writeln("Button:"); b2.On(WM_KEYDOWN, 0, 0); } Now, this only works for subclasses defined in the same module. A possibly better solution would be interfaces: import core.sys.windows.windows; import std.stdio; class Base { LRESULT On(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_KEYDOWN: if (cast(IKeyDown)this) { return (cast(IKeyDown)this).OnWM_KEYDOWN(wParam, lParam); } default: } return 0; } } interface IKeyDown { LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam); } class Button : Base, IKeyDown { LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam) { writeln("WM_KEYDOWN"); return 0; } } unittest { Base b1 = new Base(); Base b2 = new Button(); writeln("Base:"); b1.On(WM_KEYDOWN, 0, 0); writeln("Button:"); b2.On(WM_KEYDOWN, 0, 0); } -- Simen
Re: Call method if declared only
On Friday, 28 February 2020 at 09:25:58 UTC, Виталий Фадеев wrote: Yes. Thank ! I read it. Problem is - OS has many messages + user messages... It mean what interfaces like IKeyDown must me declared. All. Dream on write less code... So let's create a template for that: interface IMessageHandler(alias msg) { mixin("LRESULT On"~__traits(identifier, msg)~"(WPARAM wParam, LPARAM lParam);"); } And use it: import core.sys.windows.windows; import std.stdio; class Base { LRESULT On(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_KEYDOWN: if (auto that = cast(IMessageHandler!WM_KEYDOWN)this) { return that.OnWM_KEYDOWN(wParam, lParam); } break; default: } return 0; } } class Button : Base, IMessageHandler!WM_KEYDOWN { LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam) { writeln("WM_KEYDOWN"); return 0; } } unittest { Base b1 = new Base(); Base b2 = new Button(); writeln("Base:"); b1.On(WM_KEYDOWN, 0, 0); writeln("Button:"); b2.On(WM_KEYDOWN, 0, 0); } You'll still have to specify for each derived class which messages they handle, but no need to define hundreds of interfaces separately. -- Simen
Re: Call method if declared only
On Friday, 28 February 2020 at 10:33:11 UTC, Виталий Фадеев wrote: Thanks all ! I happy ! Check this one: void On( T, M )( T o, M message ) { [snip] void main() { auto a = new A(); a.Send( a, WM_KEYUP ); a.Send( a, WM_KEYDOWN ); } That does mostly work, but fails for this code: void main() { Base a = new A(); a.send( a, WM_KEYUP ); } Basically, whenever you assign a derived to a base, this solution doesn't work, because T will be Base, not A. I enjoyed with the previous code, so I wrote the code necessary to handle any WM_ message: import core.sys.windows.windows; import std.stdio; import std.meta; template startsWith(string prefix) { enum startsWith(string s) = s.length >= prefix.length && s[0..prefix.length] == prefix; } enum getMessageValue(string s) = __traits(getMember, core.sys.windows.winuser, s); // Get the all the WM_ messages alias messageNames = Filter!(startsWith!"WM_", __traits(allMembers, core.sys.windows.winuser)); alias messageValues = NoDuplicates!(staticMap!(getMessageValue, messageNames)); class Base { LRESULT On(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { foreach (msg; messageValues) { case msg: if (auto that = cast(IMessageHandler!msg)this) { return that.handle(wParam, lParam); } break; } default: } return 0; } } interface IMessageHandler(alias msg) { mixin("LRESULT On"~__traits(identifier, msg)~"(WPARAM wParam, LPARAM lParam);"); alias handle = mixin("On"~__traits(identifier, msg)); } class Button : Base, IMessageHandler!WM_KEYDOWN, IMessageHandler!WM_SETTINGCHANGE { LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam) { writeln("WM_KEYDOWN"); return 0; } LRESULT OnWM_SETTINGCHANGE(WPARAM wParam, LPARAM lParam) { writeln("WM_SETTINGCHANGE"); return 0; } } unittest { Base b1 = new Base(); Base b2 = new Button(); writeln("Base:"); // None of these will print anything, as Base doesn't handle them b1.On(WM_KEYDOWN, 0, 0); b1.On(WM_SETTINGCHANGE, 0, 0); b1.On(WM_DRAWITEM, 0, 0); writeln("Button:"); b2.On(WM_KEYDOWN, 0, 0); b2.On(WM_SETTINGCHANGE, 0, 0); // This will print nothing, as Button doesn't handle that message. b2.On(WM_DRAWITEM, 0, 0); } -- Simen
Re: What does assigning void mean?
On Thursday, 5 March 2020 at 08:35:52 UTC, drug wrote: On 3/5/20 10:47 AM, mark wrote: In Adam Ruppe's D Cookbook there're these lines in a ref counting example: RefCountedObject o = void; // What does this mean/do? o.data = new Implementation(); o.data.refcount = 1; I don't understand the first line; could someone explain please? In D all vars are initialized by default. If you use assigning void then the var won't be initialized. To expand a bit on this: You probably don't want to initialize things with = void - it can lead to hard-to-track bugs and unexpected behavior. The reasons it's there is almost entirely as an optimization - if you know the variable will be initialized elsewhere void initialization ensure things won't be initialized twice when once is enough, and this can be faster. The other use case is when for whatever reason there is no valid default value, but you still want an instance. Probably in order to fill it with data from somewhere else. This would apply e.g. to structs with @disabled parameterless constructors whose contents you are reading from disk. In short, when you know you need to void initialize something, that's when you're ready to use it. Kinda like goto. -- Simen
Re: Idiomatic way to express errors without resorting to exceptions
On Saturday, 7 March 2020 at 15:44:38 UTC, Arine wrote: The case when there isn't a value should be handled explicitly, not implicitly. Propogating a None value isn't useful Except when it is useful, and shouldn't be handled explicitly. I have code in D, C and C++ that looks like this: ReturnValue result = someInitialValue; auto foo = getFoo(); if (!foo) return result; auto bar = foo.fun(); if (!bar) return result; return bar.gun(); In C#, this would be: return getFoo()?.fun().gun() ?? someInitialValue; And with implicit handling in Optional!T, it looks like this: return getFoo().oc.fun().gun().or(someInitialValue); Clearly the latter two are more readable, and I'm not gonna care that it's a little slower in the 99% of cases where speed is not important. -- Simen
Re: @property with opCall
On Monday, 9 March 2020 at 09:25:31 UTC, Calvin P wrote: Is this a bugs ? == struct A { ref auto opCall(string tmp) scope return { return this; } } struct B { A _a; @property ref auto a() scope return { return _a; } } extern(C) int main(){ A a; a("a")("b"); B b; b.a("a")("b"); // Error: function test_opCall.B.a() is not callable using argument types (string) return 0; } == I has to use b.a()("a")("b") to avoid the compiler error. I think it should work to avoid the unnecessary () Should I submit a bugs ? As written on https://dlang.org/spec/function.html#property-functions: WARNING: The definition and usefulness of property functions is being reviewed, and the implementation is currently incomplete. Using property functions is not recommended until the definition is more certain and implementation more mature. So no, I don't think it's necessary to file a bug - we're aware they're somewhat wonky, and until a resolution has been agreed on, I don't think filing bugs on what's undecided behavior is worth it. -- Simen
Re: Aliases to mutable thread-local data not allowed
On Tuesday, 10 March 2020 at 08:13:19 UTC, mark wrote: I have this struct: struct Deb { string name; ... Unit[string] tags; // set of tags Deb dup() const { Deb deb; deb.name = name; ... foreach (key; tags.byKey) deb.tags[key] = unit; return deb; } } void readPackageFile(Tid parentTid, string filename) { // (some code elided) try { Deb deb; auto file = File(filename); foreach(lino, line; file.byLine.enumerate(1)) readPackageLine(parentTid, filename, lino, line, deb); // readPackageLine also calls send with same code as AAA below if (deb.valid) send(parentTid, deb.dup); // AAA /home/mark/opt/ldc2-1.20.0-linux-x86_64/bin/../import/std/concurrency.d(625,5): Error: static assert: "Aliases to mutable thread-local data not allowed." Is there any nice solution to this? Surely it is a common pattern to read multiple files and create lots of data items to be merged into a collection? As the error message hints at, the problem is Deb may hold references to data that is shared with other objects on the thread from which it originates. Since you know this is not the case, even if the compiler can't prove it, you can safely cast your Deb to immutable: if (deb.valid) send(parentTid, cast(immutable)deb.dup); In fact, even the .dup is unnecessary here, since no data is shared with other objects, so you can simply write send(parentTid, cast(immutable)deb);. (Note on this point: since you have not included all your code, it could be other parts create shared mutable state, in which case .dup is necessary, and if badly written may not be sufficient. -- Simen
Re: Aliases to mutable thread-local data not allowed [testable source code]
On Tuesday, 10 March 2020 at 20:03:21 UTC, mark wrote: I've managed to make a cut-down version that's < 170 LOC. It needs to be run on Debian or a Debian-based Linux (e.g., Ubuntu). Hopefully this will help someone understand and be able to help! This took some time figuring out. Turns out, std.concurrency.spawn won't take a delegate as its callable argument. There are sensible reasons for this - delegates have a context that is not guaranteed to be immutable, so allowing delegate callables could lead to mutable aliasing. I've filed an issue to improve documentation and error messages: https://issues.dlang.org/show_bug.cgi?id=20665 However, knowing that some things are impossible do not necessarily help us figure out what we can do to fix the problem, and the good news is, the problems can be fixed. Since the problem is we're giving a delegate where the API expects a function, we can simply turn it into a function. In the code you've given, that means making readPackageFile and readPackageLine static. This make spawn() run as it should. In addition, there's a problem with this line in receive(): (DoneMessage) { jobs--; } That looks sensible, but since DoneMessage doesn't have a name, it is parsed as a templated function taking one argument of unspecified type and called DoneMessage. For some reason, templates passed as function arguments show up in compiler output as 'void', giving this weird error message: template std.concurrency.receive cannot deduce function from argument types !()(void delegate(Deb deb) pure nothrow @safe, void) The solution here is to simply give DoneMessage a name: (DoneMessage d) { jobs--; } With those changes, things at least compile. Now it's up to you to ensure the semantics are correct. :) One last thing: you're passing parentTid around, and that's not actually necessary - std.concurrency.ownerTid does the exact same thing, and is available even if not explicitly passed anywhere. -- Simen
Re: Aliases to mutable thread-local data not allowed [testable source code]
On Wednesday, 11 March 2020 at 09:29:54 UTC, mark wrote: Hi Simen, I think you must have done something else but didn't mention to get it to compile. I did the exact changes you said and it wouldn't compile. Here's what I get with changes mentioned below (with new full source): Fascinating. It works just fine when compiling for 32-bit targets with DMD on Windows, but not for 64-bit targets, nor when compiling with LDC. Apparently, this difference is due to DMD supporting 80-bit reals, and thus giving a different size to Variant (VariantN!20 on DMD on Windows, VariantN!16 or VariantN!32 elsewhere). There's a bug in VariantN that then causes the compilation to fail (https://issues.dlang.org/show_bug.cgi?id=20666). The issue at hand then, is that Deb is too big until that issue if fixed. The simple solution to this is to allocate Deb on the heap with new and pass pointers instead of instances directly. Since you are already calling .dup whenever you pass a Deb somewhere, you can simply modify .dup to return a Deb* and the receive function to receive a Deb*, and I think you should be good to go. -- Simen
Re: Aliases to mutable thread-local data not allowed [testable source code]
On Wednesday, 11 March 2020 at 12:43:28 UTC, mark wrote: On Wednesday, 11 March 2020 at 12:22:21 UTC, Simen Kjærås wrote: On Wednesday, 11 March 2020 at 09:29:54 UTC, mark wrote: [snip] Fascinating. It works just fine when compiling for 32-bit targets with DMD on Windows, but not for 64-bit targets, nor when compiling with LDC. Apparently, this difference is due to DMD supporting 80-bit reals, and thus giving a different size to Variant (VariantN!20 on DMD on Windows, VariantN!16 or VariantN!32 elsewhere). There's a bug in VariantN that then causes the compilation to fail (https://issues.dlang.org/show_bug.cgi?id=20666). The issue at hand then, is that Deb is too big until that issue if fixed. The simple solution to this is to allocate Deb on the heap with new and pass pointers instead of instances directly. Since you are already calling .dup whenever you pass a Deb somewhere, you can simply modify .dup to return a Deb* and the receive function to receive a Deb*, and I think you should be good to go. I did that and it compiles & runs, but no Debs get added to the collection. See https://github.com/mark-summerfield/d-debtest-experiment -- the 'mto' version is the one with your fixes. Yeah, I forgot we cast to immutable to be able to send, so receive has to receive immutable(Deb)*, after which you can call deb.dup to get a mutable copy: receive( (immutable(Deb)* deb) { debForName[deb.name] = deb.dup; }, (DoneMessage m) { jobs--; } ); -- Simen
Re: A set type implemented as an AA wrapper
On Thursday, 12 March 2020 at 08:51:24 UTC, mark wrote: I use sets a lot and since I believe that D's rbtree is O(lg n) for add/remove/in and that D's AA is O(1) for these, I want to implement a set in terms of an AA. Below is the code I've got so far. It allows for add and remove. However, it has three problems (that I know of): XXX: I need to use an if on the struct to restrict T to be a type that supports toHash and opEquals (i.e., to be a valid AA key) I'd suggest simply testing if an AA with that key type is valid: struct AAset(T) if (is(int[T])) YYY: The range() method is clearly not good D style but I don't know how to support foreach (item; aaset) ... As Ferhat points out, you could use opApply for this. There's also the option of implenting the range primitives front, popFront() and empty. However, the easiest solution is the one you've already chosen, combined with alias this: struct AAset(T) if (is(int[T])) { // stuffs... auto range() { return set.byKey; } alias range this; } ZZZ: I can't figure out how to support the in operator. 'in' for AAs returns a pointer to the value it finds, or null if no item is found. This pointer does not implicitly convert to bool when returned from a function, so you need to compare it to null: bool opBinaryRight(string op)(T lhs) { static if (op == "in") return (lhs in set) != null; else static assert(0, "operator " ~ op ~ " not supported"); } I would also suggest using a template specialization instead of static if and static assert: bool opBinaryRight(string op : "in")(T lhs) { return (lhs in set) != null; } -- Simen
Re: Get symbols (and/or UDAs) of subclass from superclass
On Sunday, 15 March 2020 at 20:18:03 UTC, James Blachly wrote: I would like to programmatically retrieve members of a subclass to create a self-documenting interface. I am afraid that my approach is not possible due to need for compile time __traits / std.traits, and runtime typeinfo. My proposed approach is as follows: class Base { string whatever; string toString() { // loop over __traits(allMembers, typeof(this)) or getSymbolsByUDA, etc. } } /// There may be a dozen Derived classes class Derived1 : Base { @Config("a name", "a description") float probability; } class Derived2 : Base { @Config("another", "more description") int replicates; } ... There's no built-in way to do this - toString() doesn't know what derived classes exist, and more could be added from other modules and even dynamically loaded libraries. Now, there are ways to do something somewhat like it. I would suggest creating an abstract method in the base class, that derived class would have to override, and use a template this argument to get the correct type for __traits(allMembers) to operate on: class Base { override string toString() { return toStringImpl(); } abstract string toStringImpl(); string toStringBase(this That)() { // foreach (e; __traits(allMembers, That) {...} } } class Derived : Base { override string toStringImpl() { return this.toStringBase(); } } Since toStringImpl will always call toStringBase, this could perhaps better be modeled with a template mixin: mixin template DerivedToString() { override string toStringImpl() { return this.toStringBase(); } } class Derived2 : Base { mixin DerivedToString!(); } This way, you can have all the logic of toString in the base class, and the only thing a subclass will have to include is one line for the mixin. In addition, since toStringImpl is abstract, the implementer of a subclass will get a compile-time error if he or she forgets to do either the mixin or override toStringImpl themselves. -- Simen
Re: Find the heir.
On Sunday, 29 March 2020 at 14:04:53 UTC, TodNaz wrote: Hello! class A { ... } class B : A { ... } class C : A { ... } A example1; B example2 = new B(...); A = example2; auto heir = A.whoheir(); /// The question in this code is: is it possible to track the class inheritor? Or is it beyond D? Sorry if the question is fool ... The question is a bit unclear - what is whoheir expected to return? This is one way that may or may not fulfill your requirements: module foo; class A { string whoheir() { return typeid(this).name; } } class B : A {} class C : A {} unittest { A a = new B(); assert(a.whoheir == "foo.B"); a = new C(); assert(a.whoheir == "foo.C"); } -- Simen
Re: Checked!({short, ushort, byte, ubyte}, Throw): compilation fails
On Friday, 17 April 2020 at 08:59:19 UTC, kdevel wrote: On Friday, 17 April 2020 at 04:29:06 UTC, Meta wrote: Unlike C/C++, char is not a numeric type in D; It's a UTF-8 code point: Thanks, it's a code /unit/. main reads now: void main () { bar!ubyte; bar!byte; bar!ushort; bar!short; bar!uint; bar!int; bar!ulong; bar!long; } and dmd complains: The problem is, short/short gives an int answer: unittest { import std.experimental.checkedint; Checked!(short, Throw) a; pragma(msg, typeof(a/a)); } So, in your code you get this situation: unittest { import std.experimental.checkedint; Checked!(int, Throw) a; Checked!(short, Throw) b = a; } And assigning from an int to a short may discard data, so it's statically disallowed by Checked. This is a deliberate design choice, and the appropriate way to handle it is with a cast: unittest { import std.experimental.checkedint; Checked!(int, Throw) a = 65535; Checked!(short, Throw) b = cast(short)a; } The above code will throw when casting (before the assignment), because 65535 can't fit in a short. You also get a deprecation message, about an integral promotion not being performed. I believe the result is correct and the warning can be ignored. -- Simen
Re: Extracting user defined attributes on function parameters
On Friday, 17 April 2020 at 16:54:42 UTC, Adam D. Ruppe wrote: This part seems fine... pragma(msg, ParameterDefaults!f.stringof); It is this, specifically, that causes the problem. Replace it with: void main() { import std.stdio; writeln(ParameterDefaults!f.stringof); } and it is fine. So pragma(msg) is doing something really weird, the bug doesn't appear to be in Phobos per se, I think it is the compiler doing the wrong thing, it seems to me it works inside a function scope but not at module scope.. It's even more fascinating - the issue doesn't occur if ParameterDefaults is defined in the same module that it's used in, and it works if there's a type with the same name as the UDA. Reducing the code as much as I can, I get this: struct S {} void f(@S int = 3); pragma(msg, ParameterDefaults!f.stringof); template ParameterDefaults(func...) { import std.traits : FunctionTypeOf; static if (is(FunctionTypeOf!(func[0]) PT == __parameters)) { enum ParameterDefaults = (PT[0..1] args) @trusted { return *&(args[0]); }(); } } The above code works, and prints "3". If you move ParameterDefaults to a different module, something like this: - import bar; struct S {} void f(@S int = 3); pragma(msg, ParameterDefaults!f.stringof); - module bar; template ParameterDefaults(func...) { static if (is(typeof(func[0]) PT == __parameters)) { enum ParameterDefaults = (PT[0..1] args) @trusted { return *&(args[0]); }(); } } - Then you get an error message about 'undefined identifier S'. Add some kind of S to bar, and you get an error message about S not being readable at compile-time or things just work if it is readable. It seems the UDA is being looked up in the wrong context. -- Simen
Re: Extracting user defined attributes on function parameters
On Wednesday, Friday, 17 Apr 2020 17:45:47 UTC, H. S. Teoh wrote: I wonder if the ultimate cause of the above case is ultimately caused by the change to import semantics that hid private symbols from outside the module. Perhaps something, somewhere, is triggering an illegal access of a private symbol, which percolates up the call/instantiation stack and causing what appears to be a strange compiler discrepancy. Not unlikely. Importing the module defining S in the module defining ParameterDefaults does indeed make things compile. Hiding S by making it private makes the error return. (for whatever reason your message isn't visible in the web interface) -- Simen
Re: Extracting user defined attributes on function parameters
On Saturday, 18 April 2020 at 09:19:48 UTC, Simen Kjærås wrote: On Wednesday, Friday, 17 Apr 2020 17:45:47 UTC, H. S. Teoh wrote: I wonder if the ultimate cause of the above case is ultimately caused by the change to import semantics that hid private symbols from outside the module. Perhaps something, somewhere, is triggering an illegal access of a private symbol, which percolates up the call/instantiation stack and causing what appears to be a strange compiler discrepancy. Not unlikely. Importing the module defining S in the module defining ParameterDefaults does indeed make things compile. Hiding S by making it private makes the error return. It's not about private. Or even if it is, there's other issues. Proof: struct A { struct S {} void f(@S int = 3); pragma(msg, Issue20744!f); } template Issue20744(func...) { static if (is(typeof(func[0]) PT == __parameters)) { alias Issue20744 = (PT args) {}; } } -- Simen
Re: How convert String to Hex?
On Saturday, 18 April 2020 at 15:47:38 UTC, Marcone wrote: How convert String to Hex? Example: string text = "Hello World"; // Converted to Hex = 48656c6c6f20576f726c64 import std.format : format; string hex = format("%(%2x%)", "Hello World"); import std.stdio : writeln; writeln(hex); A bit of explanation: %( %) is a range formatting specifier, and basically means "format each element of the range with the format specifier between these two symbols". In other words, it's the equivalent of "Hello World".map!(c => format("%2x", c)).joiner. -- Simen
Re: Can’t use UFCS to create InputRange?
On Wednesday, 29 April 2020 at 08:34:53 UTC, Ogi wrote: struct R {} int front(R r) { return 42; } void popFront(R r) {} bool empty(R r) { return false; } void main() { import std.range.primitives : isInputRange; static assert(isInputRange!R); } Error: static assert: `isInputRange!(R)` is false What’s going on here? The template IsInputRange is in the std.range.primitives module, and thus can't see the front, popFront and empty definitions in your module. -- Simen
Re: Can’t use UFCS to create InputRange?
On Wednesday, 29 April 2020 at 09:16:58 UTC, user1234 wrote: The static checker doesn't see your free funcs because to do so it would have to import the whole module. (is it possible to do that ? no idea.) Of course it's possible! :) We can find the context of R (in this case, the module) with __traits(parent), and import that: mixin("import "~__traits(parent, R).stringof["module ".length..$]~";"); However, doing that in isInputRange doesn't help much. First, all other range functions would have to do it, and second, just importing into function scope doesn't enable UFCS lookup. Also your signature for the primitives are quite unusual (i.e not idiomatic). Usually they dont take param. Usually we pass a type that contains the member funcs matching to IsIntputRange. You can see a good counterexample to this in https://dlang.org/library/std/range/primitives/pop_front.html, which defines popFront for regular arrays. However, that is the one and only counterexample I know of. Of course, nothing stops us from defining our own front, popFront and friends that combine the two approaches above: template front(R) { auto front(R r) { return __traits(getMember, __traits(parent, R), "front")(r); } } template popFront(R) { auto popFront(R r) { return __traits(getMember, __traits(parent, R), "popFront")(r); } } template empty(R) { auto empty(R r) { return __traits(getMember, __traits(parent, R), "empty")(r); } } We could conceivably add these to std.range.primitives (probably adding some constraints first), and suddenly UFCS ranges are possible! (I am as of yet not convinced that we should, though) -- Simen
Re: Can't recreate a range?
On Wednesday, 29 April 2020 at 20:43:20 UTC, Casey wrote: void popFront() { } I mean, it might be you messed up in posting this, but having an empty popFront and expecting it to do something is a tad optimistic. Apart from that, it seems like the code should do what you want it to. What's the value of count when the code asserts? I'm afeared we'll need some code that actually compiles and shows off the issue to give any more answers. -- Simen
Re: Can't recreate a range?
On Thursday, 30 April 2020 at 13:23:25 UTC, Paul Backus wrote: On Thursday, 30 April 2020 at 13:04:47 UTC, Casey wrote: Here's a minimal code example that duplicates the issue: import std.array, std.range, std.stdio, std.traits, std.string; auto readStream(Range)(auto ref Range r) if (isInputRange!(Unqual!Range)) { struct StreamRange(Range) { alias R = Unqual!Range; R _input; auto buff = appender!string; Using a default value like this means that it will be shared among all instances of the struct. Instead, you should set `buff = appender!string` in the constructor, so that each struct will have its own appender. Yup, that's the one. No need to assign it at all, in fact - the line can be replaced with Appender!string buff; And things just work. -- Simen
Re: Aliasing current function template instance
On Friday, 1 May 2020 at 20:28:58 UTC, Jean-Louis Leroy wrote: Is it possible, inside a function template, to create an alias to the instantiated function? IOW the equivalent of __FUNCTION__, but yielding an alias? The closest I came is: import std.string; import std.traits; void foo(T)(lazy T) { mixin( "alias thisFunction = ", __FUNCTION__[0..__FUNCTION__.lastIndexOf('.')], ";"); pragma(msg, Parameters!thisFunction); } void main() { foo(0); foo(""); } dmd -c aliasthisfunction.d (lazy int) (lazy string) ...but (unsurprisingly) this fails in presence of overloads. I.e. if I throw in: void foo(T)(int, T); ...then I get: aliasthisfunction.d(6): Error: template `aliasthisfunction.foo` matches more than one template declaration: aliasthisfunction.d(4): `foo(T)(lazy T)` and aliasthisfunction.d(20): `foo(T)(int, T)` ... Something I have overlooked? Any ideas? This should work: alias context(alias a) = __traits(parent, a); void fun() { alias ctx = context!({})(); } {} becomes a lambda inside fun(), so it's parent is fun(). The same could be done by introducing a symbol explicitly, but that pollutes the namespace. This template works inside functions, methods, lambdas, modules, structs, classes and interfaces. -- Simen
Re: Bug?
On Tuesday, 5 May 2020 at 04:02:06 UTC, RazvanN wrote: truct K { ~this() nothrow {} } void main() { static class C { this(K, int) {} } static int foo(bool flag) { if (flag) throw new Exception("hello"); return 1; } try { new C(K(), foo(true)); } catch(Exception) { } } Result: object.Exception@test.d(18): hello If the destructor of K is not marked nothrow the code does not throw an exception. Is this a bug or am I missing something? Surely the above code, which silently discards the exception, does not print "hello"? Regardless, I ran your code with writeln inside the catch(), and without the try-catch entirely, with and without nothrow on K's destructor. I am unable to replicate the issue on my computer with DMD 2.091.0, as well as on run.dlang.io. Is something missing in your code here? -- Simen
Re: variant visit not pure?
On Thursday, 7 May 2020 at 09:22:28 UTC, learner wrote: Good morning, Is there a reason why std.variant.visit is not inferring pure? ``` void test() pure { Algebraic!(int, string) alg; visit!( (string) => 0, (int) => 0)(alg); } Error: pure function test cannot call impure function test.visit!(VariantN!(16LU, int, string)).visit ``` std.variant.Algebraic is essentially a std.variant.Variant in different clothes. Variant is very flexible, and this comes at a cost (and isn't used in Algebraic, meaning you pay for things you don't use). Like Dukc said, you might be better off with Taggedalgebraic or SumType (https://code.dlang.org/packages/sumtype). Variant uses runtime type information to hold *any* type. Since Algebraic specifically only holds a few types, all the framework that's in place for Variant is wasted on Algebraic, and makes it less useful and less performant. -- Simen
Re: Is there a way to benchmark/profile portably?
On Thursday, 7 May 2020 at 10:21:07 UTC, Dukc wrote: Is there some way to measure the performance of a function so that the results will be same in different computers (all x86, but otherwise different processors)? I'm thinking of making a test suite that could find performance regressions automatically. I figured out Bochs[1] could be used for that, but it seems an overkill for me to install a whole virtual operating system just to benchmark functions. Does anybody know more lightweight way? [1] http://bochs.sourceforge.net/ If I understand correctly, you want to measure how many cycles pass, rather than clock time? If so, it seems perf can do that: https://perf.wiki.kernel.org/index.php/Tutorial -- Simen
Re: XMM Intrinsics
On Friday, 8 May 2020 at 12:38:51 UTC, Marcio Martins wrote: Hi, I am building a CRC32C implementation using SSE for D, because I couldn't find any readily available :[ However, I am unable to find any documentation regarding which SSE instructions are available and how I could use them in D. I can see core.simd can't seem to make any use of it. How would I go about calling _mm_* functions in D in a way that is portable between D compilers? You would use core.simd: https://dlang.org/library/core/simd.html Sadly, the supported instructions are not documented on that page, and you'll need to look at the source to get at them: https://github.com/dlang/druntime/blob/master/src/core/simd.d#L85-L384 (I'll file a bug on this) There's a bit more info on D SIMD instructions here: https://dlang.org/spec/simd.html -- Siomen
Re: XMM Intrinsics
On Friday, 8 May 2020 at 13:09:49 UTC, kinke wrote: On Friday, 8 May 2020 at 12:49:00 UTC, Simen Kjærås wrote: How would I go about calling _mm_* functions in D in a way that is portable between D compilers? You would use core.simd: Nope one wouldn't, because that horrible interface isn't supported by LDC, and I guess GDC neither. The intel-intrinsics dub package aims to provide a compiler-independent layer: https://code.dlang.org/packages/intel-intrinsics TIL, thanks! :) -- Simen
Re: How does a free list work?
On Saturday, 9 May 2020 at 19:54:44 UTC, Pavel Shkadzko wrote: I have been reading about memory management in D on https://wiki.dlang.org/Memory_Management and found an example of a free list (pattern?): "Free lists are a great way to accelerate access to a frequently allocated and discarded type.". Here is the example of free list: --- class Foo { static Foo freelist; // start of free list Foo next; // for use by FooFreeList static Foo allocate() { Foo f; if (freelist) { f = freelist; freelist = f.next; } else f = new Foo(); return f; } static void deallocate(Foo f) { f.next = freelist; freelist = f; } } --- Do I understand correctly that by switching between static and non-static Foo we keep the object from being garbage collected by the GC? So in a situation when I need to create an object and then discard it, I can implement this pattern to use memory more efficiently. Also, it's a little strange that since both f and freelist are null we are basically doing null = null in first if condition. The GC keeps a list of roots - that is, objects that are known to be active and should not be collected. The static freelist is one of those - since it's static it should of course never be collected. From these roots, the GC scans all referenced objects recursively, and finally releases all memory that has not been scanned (and that thus have no path of pointers leading from a root to that memory). Since any call to new will check if memory is available, and potentially trigger a GC collection, it can be expensive, so if you can avoid allocating and deallocating objects a lot, it's an easy optimization. To more clearly show this, here's some code that prints what it does: import std.stdio : writeln; class Foo { static Foo freelist; Foo next; string name; this(string name) { this.name = name; } ~this() { writeln("GC collecting ", name); } static Foo allocate(string name) { if (freelist) { auto f = freelist; freelist = f.next; writeln("Fetching ", f.name, " from freelist, changing name to ", name); f.name = name; return f; } writeln("Nothing in freelist, allocating new ", name); return new Foo(name); } static void deallocate(Foo f) { writeln("Adding ", f.name, " to freelist, freelist.next points to ", freelist ? freelist.name : "(null)"); f.next = freelist; freelist = f; } } unittest { Foo a = Foo.allocate("A"); Foo b = Foo.allocate("B"); Foo c = Foo.allocate("C"); Foo.deallocate(a); Foo.deallocate(b); a = null; b = null; c = null; import core.memory; GC.collect(); // For some reason I need to call this twice for C to be collected? GC.collect(); Foo d = Foo.allocate("D"); Foo e = Foo.allocate("E"); Foo f = Foo.allocate("F"); } The above code creates this output: Nothing in freelist, allocating new A Nothing in freelist, allocating new B Nothing in freelist, allocating new C Adding A to freelist, freelist.next points to (null) Adding B to freelist, freelist.next points to A GC collecting C Fetching B from freelist, changing name to D Fetching A from freelist, changing name to E Nothing in freelist, allocating new F 1 unittests passed GC collecting E GC collecting D GC collecting F Here's what it does in more words: For the first call to allocate(), the freelist is null, and a new Foo is created in the 'else' path, before being returned. Nothing is assigned to freelist or next. The second and third call does the exact same thing, since nothing has been assigned to the freelist. We then deallocate a, which assigns it to the freelist. Next we deallocate b, which sets b's 'next' field to point at a, and sets freelist to point at b. We then set a, b, and c to null, so those references will no longer keep the Foos alive. Then we call GC.collect, which finds that the Foo previously stored in b is now in freelist, and thus will be kept. The Foo that was in a is referenced by freelist.next, and will also live. The foo in c, however, is no longer referenced anywhere, and will be collected. This shows the main point of the freelist - to ensure the objects aren't collected by the GC - but what happens afterwards? When we allocate d, freelist points at the Foo that used to be stored in b, so it is returned from allocate(), and the freelist is changed to point to the Foo that used to be in a. Allocating e there's still something in freelist, so it is returned. At this point the freelist is empty, and allocating f creates a new Foo, just like when we allocated a, b, and c. -- Si
Re: What could this be?
On Monday, 11 May 2020 at 11:20:51 UTC, Joel wrote: I'm gotten stuck with this error - "..is not visible from module.." Without some code it's hard to say exactly, but this generally means you're referencing a private symbol in a different module: module foo; private struct S {} module bar; import foo; foo.S s; // foo.S is not visible from module bar -- Simen
Re: Bug?
On Monday, 11 May 2020 at 12:44:45 UTC, Jack Applegame wrote: On Monday, 11 May 2020 at 12:30:22 UTC, Adam D. Ruppe wrote: UFCS is only defined to work with global scope functions. A restricted import (module : symbol, symbols) puts things in local scope so ufcs doesn't apply. But in this case the error should be displayed for lines 4 and 5, not 11. Line 11 contains a call to a member function, not UFCS. In addition, if you add the parentheses, then it works: assert(rng.front() == '1'); You're right, and it absolutely seems the call on lines 4 and 5 work correctly. Instead, the compiler is confused by the presence of two different overloads for front in Range!T, and doesn't attempt to call the one it can call. We get the exact same behavior here: struct S { int gun()(int i) { return 0; } alias fun = gun; int fun() { return 1; } } static assert(S().fun == 1); Filed here: https://issues.dlang.org/show_bug.cgi?id=20821 -- Simen
Re: Assignment of tuples
On Wednesday, 20 May 2020 at 13:51:05 UTC, Steven Schveighoffer wrote: Please file an issue. https://issues.dlang.org/show_bug.cgi?id=20850 -- Simen
Re: opEquals @safe is ignored
On Sunday, 24 May 2020 at 08:57:28 UTC, Luis wrote: dmd ignores @trusted or @safe on opEquals, throwing this error : onlineapp.d(27): Error: @safe function onlineapp.__unittest_L24_C7 cannot call @system function object.opEquals An override @system or @trusted function can't be @safe, or I it a bug ? Also, how will this be affected by DIP1028 ? Looking at the output, it's actually druntime's opEquals that can't be called. That's the global function that ensure opEquals is called on both sides of the comparison, and it's not @safe. This makes classes even worse to use in D than, and I'm not sure how to properly handle this. If we make it @trusted, suddenly I can call @system opEquals from @safe functions without issue. Root cause is, classes in D all inherit from Object, which has some defaults that aren't always what you want. It seems DIP1028 will make your code automatically compile, along with this: class C { override bool opEquals(Object o) @system { *cast(int*)123456 = 3; return true; } } @safe void mySafeFunction() { assert(new C() == new C()); } -- Simen
Re: Unable to access a variable declared inside an if statement (Error: is shadowing variable)
On Wednesday, 27 May 2020 at 11:03:51 UTC, BoQsc wrote: I'm lacking knowledge on how to achieve what I want and getting an error. What is the correct way to do what I tried to achieve in this code? Everything was intuitive until I started to add notice variable to the writeln. Rdmd says variable `notice` is shadowing variable. if (driveLetter.exists){ auto directory = "/Backup"; if ((driveLetter ~ directory).exists){ auto notice = "Backup directory exists."; } writeln(driveLetter, notice); } Variables only live in a specified scope, starting from where they are declared, and ending when they reach the '}' indicating the end of said scope. In you case, 'notice' only lives inside the if ((driveLetter ~ directory).exists) scope, and doesn't exist outside. In order to fix this, you will need to declare it outside: if (driveLetter.exists) { auto directory = "/Backup"; auto notice = "Backup directory does not exist."; if ((driveLetter ~ directory).exists) { notice = "Backup directory exists."; } writeln(driveLetter, notice); } This also makes it clearer what value 'notice' will have when the backup directory doesn't exist - in your case you haven't assigned it any value in that case. -- Simen
Re: Fastest way to check using if identifier has already been defined, using static if or similar?
On Wednesday, 3 June 2020 at 09:39:34 UTC, Basile B. wrote: You can use this template: enum Exists(alias T) = is(typeof(T)); I don't know if there's a faster way bu this technic is used, notatbly in phobos, to workaroud issues of double declaration in `static foreach` enum Exists(alias T) = is(typeof(T)); static assert(!Exists!bar); // undefined identifier bar -- Simen
Re: Fastest way to check using if identifier has already been defined, using static if or similar?
On Wednesday, 3 June 2020 at 15:25:51 UTC, Paul Backus wrote: On Wednesday, 3 June 2020 at 13:24:17 UTC, Basile B. wrote: This is because the template parameter must be resolved to a valid symbol or type. This version other version bypass the problem: --- enum Exists(string s) = is(typeof(mixin(s))); void main() { static if (!Exists!"foo") int foo; foo = 42; } --- Fails if the symbol in question is the name of a type. struct Foo {} enum Exists(string s) = is(typeof(mixin(s))); static assert(Exists!"Foo"); // false What you actually want is something like this: enum Exists(string s) = __traits(compiles, { mixin("alias _ = ", s, ";"); }); And they both fail if the thing you refer to isn't available in the scope where Exists is defined. I believe this covers most cases, but there may very well be corner cases I haven't considered: string exists(string s) { return "__traits(compiles, { mixin(\"alias _ = "~s~";\"); })"; } // Handles values: int global; unittest { int local; { int outOfScope; } static assert(mixin("local".exists)); static assert(mixin("global".exists)); static assert(!mixin("outOfScope".exists)); } // And types: struct Global {} unittest { struct Local {} { struct OutOfScope; } static assert(mixin("Global".exists)); static assert(mixin("Local".exists)); static assert(!mixin("OutOfScope".exists)); } // But not expressions: static assert(!mixin("1+2".exists)); // Correctly fails for missing declarations: static assert(!mixin("nowhere".exists)); Like Stefan said though, we're quite a bit off from the original request - the above certainly shouldn't be faster than drathier's original code. The only advantage I see is that it might read a little clearer. -- Simen
Re: how to append (ref) int[] to int[][]?
On Monday, 8 June 2020 at 06:13:36 UTC, mw wrote: Hi, I have this program: import std.stdio; void f(ref int[] arr) { arr ~= 3; } void main() { int[][] arrs; int[] arr; foreach (i; 0 .. 3) { arr = new int[0]; arrs ~= arr; //(a) [[], [], []] f(arr); // arrs ~= arr; //(b) [[3], [3], [3]] } writeln(arrs); } This program will print out [[], [], []]. If I comment out (a), and use (b), it will print out [[3], [3], [3]] So based on this behavior, looks like "~=" will append a copy of `arr`; but what I really want in (a) is append `ref arr` and output [[3], [3], [3]], i.e. the real `arr` be appended instead of its copy. I have to say this semantics surprised me. I tried to change arrs' decl to: (ref (int[]))[] arrs; // the intended semantics I want But I got compiler error out: "found ( when expecting function literal following ref". 1) I'm wondering how to achieve what I want? and 2) why "~=" here will append a copy rather than the real `arr` itself to arrs? Arrays (technically, slices) in D are essentially this struct: struct Array(T) { T* ptr; size_t length; // operator overloads } So when you have int[][], each element of the outer array is an Array!int. These, as simple structs, are copied about, so that changing one does not change another. The simple solution here is to call f not on arr, but on arrs[$-1] (the last element of arrs). If that is not possible you will need arrs to be an int[]*[]. -- Simen
Re: `this` template params for struct not expressing constness.
On Monday, 8 June 2020 at 07:35:12 UTC, adnan338 wrote: Self* searchTree(this Self)(auto in ref T item) const { if (&this is null) return null; if (this.item == item) return &this; return (this.item < item) ? this.right.searchTree(item) : this.right.searchTree(item); } This method is const, which means 'this' is const, while Self is not. What you're looking for here is inout (https://dlang.org/spec/function.html#inout-functions): auto searchTree()(auto in ref T item) inout { if (&this is null) return null; if (this.item == item) return &this; return (this.item < item) ? this.right.searchTree(item) : this.right.searchTree(item); } -- Simen
Re: `this` template params for struct not expressing constness.
On Monday, 8 June 2020 at 09:08:40 UTC, adnan338 wrote: On Monday, 8 June 2020 at 08:10:19 UTC, Simen Kjærås wrote: On Monday, 8 June 2020 at 07:35:12 UTC, adnan338 wrote: Self* searchTree(this Self)(auto in ref T item) const { if (&this is null) return null; if (this.item == item) return &this; return (this.item < item) ? this.right.searchTree(item) : this.right.searchTree(item); } This method is const, which means 'this' is const, while Self is not. What you're looking for here is inout (https://dlang.org/spec/function.html#inout-functions): auto searchTree()(auto in ref T item) inout { if (&this is null) return null; if (this.item == item) return &this; return (this.item < item) ? this.right.searchTree(item) : this.right.searchTree(item); } -- Simen Thank you. Few followup questions, if you don't mind. 1. What does that blank template parameter mean? Just forces the function to be a template. The only reason for this is it's required for auto ref to work, which you may or may not need on that function. 2. Since `inout` acts as a wildcard for immutable/const/non-const qualifiers, what should I do to have the compiler ensure that my method does not mutate a non-const tree inside the body? Inside inout functions, `this` is treated as const - any attempt to modify it should give a compile error. Since D const is transitive, anything reachable from `this` is also treated as const. If you're able to mutate a non-const tree inside the body, there's a bug in the compiler. -- Simen
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? The heuristic I use is 'do I need polymorphism?' If no, it's a struct. Another thing that may be worth considering is reference semantics. The latter is easy to do with a struct, while polymorphism is generally a class-only thing (but check out Tardy, which Atila Neves recently posted in the Announce group). I would say I basically never use classes in D - pointers and arrays give me all the reference semantics I need, and polymorphism I almost never need. -- Simen
Re: Parallel array append using std.parallelism?
On Thursday, 18 June 2020 at 14:43:54 UTC, H. S. Teoh wrote: I have an array of input data that I'm looping over, and, based on some condition, generate new items that are appended onto a target array (which may already contain data). Since the creation of new items is quite expensive, I'm thinking to parallelize it with parallel foreach. To avoid data races, my thought is for each generated item to be appended to thread-specific temporary arrays, that after the parallel foreach get sequentially appended to the target array. Something like this: Item[] targetArray = ...; // already contains data Item[][nThreads] tmp; foreach (elem; input.parallel) { if (condition(elem)) { auto output = expensiveComputation(elem); tmp[threadId] ~= output; } } foreach (a; tmp) targetArray ~= a; Is there an easy way to achieve this with std.parallelism? I looked over the API but there doesn't seem to be any obvious way for a task to know which thread it's running in, in order to know which tmp array it should append to. If possible I'd like to avoid having to manually assign tasks to threads. There's an example of exactly this in std.parallelism: https://dlang.org/phobos/std_parallelism.html#.TaskPool.workerIndex In short: Item[] targetArray = ...; // already contains data // Get thread count from taskPool Item[][] tmp = new Item[][taskPool.size+1]; foreach (elem; input.parallel) { if (condition(elem)) { auto output = expensiveComputation(elem); // Use workerIndex as index tmp[taskPool.workerIndex] ~= output; } } foreach (a; tmp) targetArray ~= a; -- Simen
Re: Flagging special conditions on return from a function call
On Tuesday, 23 June 2020 at 04:01:45 UTC, Denis wrote: (1) Assign an unused value for the flag (e.g. -1 when the function returns an int), and return the combined value/flag. This happens in some Phobos algorithms, and might be the most common on this list. (2) Return a tuple with the value and the flag (3) Return a struct or tuple with named value and flag members Would certainly work, but I don't think it's common in D. (4) Set the function return value normally, and put the flag in an "out" variable passed as an argument to the function (5) Return the flag, and put the value in an "out" variable passed to the function (i.e. the reverse of #4) Both of these happen. I don't know which is more common. In C# these are probably the most common way (except for exceptions) to signal these cases. (6) Use two separate functions, one that returns the value, and another that can be called afterwards to check the flag (like eof(), for example) (7) Use a side effect and set a designated global variable Global variables are frowned upon, so probably not this. :p One thing I feel is missing here (perhaps because std.variant.Algebraic is egregious): (8) Return a Maybe!T or Algebraic!(T, ErrorCode) It's what I personally would prefer, but I have only rarely seen it in D code. Given a properly written Maybe, this could enforce proper handling of the error case, either by throwing on trying to get at Maybe!T.getValue when it's holding None, or by presenting an interface that only compiles when both cases are covered, like fun().match((T t) => t, () => Error()). -- Simen
Re: Unused template arguments; what type to use?
On Friday, 26 June 2020 at 13:21:25 UTC, drathier wrote: How can I tell the compiler that I will never create a value of type X, while still being able to write code that uses it? Using void as a template parameter is where I started, but I still need to be able to declare variables inside this unreachable function, like `T foo;` even when `T == void`. Can I get any closer to what I want than an empty struct? Depends on what you care about, I guess. A final abstract class has been my go-to on a few occasions. I'd argue the empty struct is better in most cases, and a forward-declared struct with no implementation might work in some cases. -- Simen
Re: How to implement Canceleable spawn() from parent
On Tuesday, 30 June 2020 at 08:15:54 UTC, aberba wrote: On Tuesday, 30 June 2020 at 00:33:41 UTC, Ali Çehreli wrote: On 6/29/20 4:34 PM, aberba wrote: > So with this, without the Thread.sleep() to block main from exiting, the > spawned thread will terminate immediately. You can call core.thread.thread_joinAll at the end of main. So I tried that initially but my (){ writeln(...) } wasn't printing anything in console. Could that be related to stdout buffering? The program kept running though. Seems weird. This works great on my machine: import core.time : Duration, msecs; import core.thread : Thread, thread_joinAll; import std.concurrency : spawn, Tid, send, receiveTimeout; import std.stdio : writeln; private struct IntervalStop {} Tid setInterval(Duration dur, void function() fn) { return spawn((Duration d, void function() f){ while (!receiveTimeout(d, (IntervalStop s){})) { f(); } }, dur, fn); } void stopInterval(Tid tid) { tid.send(IntervalStop()); } void main() { auto a = setInterval(1000.msecs, (){ writeln("Hello from spawned thread A"); }); // Stop it before it happens stopInterval(a); Thread.sleep(2000.msecs); auto b = setInterval(1000.msecs, (){ writeln("Hello from spawned thread B"); }); // Let this one run a little Thread.sleep(2500.msecs); stopInterval(b); auto c = setInterval(1000.msecs, (){ writeln("Hello from spawned thread C"); }); // Sending the wrong message doesn't make it happen or stop prematurely c.send("Stop this at once!"); Thread.sleep(2500.msecs); stopInterval(c); thread_joinAll(); } So I guess the error is elsewhere, but I'm not sure where and how. -- Simen
Re: How to implement Canceleable spawn() from parent
On Tuesday, 30 June 2020 at 13:44:38 UTC, aberba wrote: On Tuesday, 30 June 2020 at 12:48:32 UTC, Simen Kjærås wrote: On Tuesday, 30 June 2020 at 08:15:54 UTC, aberba wrote: On Tuesday, 30 June 2020 at 00:33:41 UTC, Ali Çehreli wrote: On 6/29/20 4:34 PM, aberba wrote: > So with this, without the Thread.sleep() to block main from exiting, the > spawned thread will terminate immediately. You can call core.thread.thread_joinAll at the end of main. So I tried that initially but my (){ writeln(...) } wasn't printing anything in console. Could that be related to stdout buffering? The program kept running though. So I guess the error is elsewhere, but I'm not sure where and how. Yeah, you're right. I changed receiveTimeout() to receive() to try something and forgot to change it back. Jeez, I hate myself. Thanks. So how can I now hide the core.thread.thread_joinAll so the library user doesn't have to type it themselves in main() ? I don't see how that can be done. __gshared Tid mainTid; static this() { if (mainTid.tupleof[0] is null) { mainTid = thisTid; } } static ~this() { if (thisTid == mainTid) { thread_joinAll(); } } The above code does the trick. So, what does it do? __gshared means 'this variable is accessible to all threads'. static this() runs upon creation of any thread including the main thread. Since the main thread will run first*, it gets to store its Tid in mainTid, and every other thread will see a populated mainTid and leave it alone. In the module destructor, which runs after main(), we call thread_joinAll() iff we're the main thread. Now, why should you not do this? Well first, instead of getting a tidy crash you get a process that doesn't end. Second, there's the race conditions described below. Third, there's the principle of least astonishment. D programmers expect that when main() returns, the program will exit shortly(ish), while this zombie could continue running indefinitely. -- Simen *I'm pretty sure this is possibly wrong, if a module constructor spawns a new thread. There's also a possible race condition where newly spawned modules may conceivably not see a properly initialized mainTid.
Re: scope guard question
On Tuesday, 30 June 2020 at 12:18:14 UTC, Steven Schveighoffer wrote: I can see where it would be confusing, and it could probably contain an example and clarification. https://issues.dlang.org/show_bug.cgi?id=20997
Re: Generating struct members from c structs
On Wednesday, 1 July 2020 at 07:26:44 UTC, Anthony wrote: When doing interop with a c library, is there a way to automatically generate the fields that are needed for a struct? [snip] Is there an easier way though? Dstep is probably what you're looking for: https://github.com/jacob-carlborg/dstep It eats C header files and creates appropriate D files from them. -- Simen
Re: Progress printing with threads?
On Wednesday, 1 July 2020 at 07:52:28 UTC, AB wrote: Hello. I am unsure how to proceed about printing progress in my program. Suppose the program is processing a very big file and is iterating the file's bytes using a for loop. The processing takes several minutes and I want a progress percentage be printed every 2 seconds in this manner: Progress: 0.40% Progress: 3.20% Progress: 5.73% Is it a good idea to std.concurrency.spawn a new thread and pass to it cast(float)i * 100 / fileSize somehow? If not, what's a better way to do this? This example code shows my situation: MmFile input = new MmFile(/* ... */); ulong fileSize= input.length; for (ulong i = 0; i < fileSize; ++i) { // ... } Thanks in advance. If doing the update in the same thread that does the processing is somehow not an option, this works for me: import std.concurrency; import std.stdio; import core.thread; import core.time; void main() { ulong filesize = 1234; ulong i = 0; Tid progress = spawn((shared const(ulong)* p, ulong f){ while (!receiveTimeout(2000.msecs, (int i){ })) { writeln(*p, "/", f, ": ", *p*100.0/f, "%"); } }, cast(shared)&i, filesize); for (; i < filesize; ++i) { // Process } progress.send(0); // Stop } There's a cast to shared there which may be suboptimal, but since the progress thread is only reading it, I would say it's ok. -- Simen
Re: What's the point of static arrays ?
On Thursday, 9 July 2020 at 12:12:06 UTC, wjoe wrote: I'm not considering supposed performance benefits/penalties because these need to be profiled. Considering the many downsides why would I ever want to choose a static over a dynamic array ? Simply put: static arrays are not dynamic arrays, and if you try to use one as the other you're going to be disappointed. Usually, you use static arrays when you interface with something else that does it - generally a file format or a C library. For the most part you're right, you should probably use a dynamic array instead. Now, as for your points: - Can neither grow nor shrink them - Can't append elements - Can't remove elements These are the same as the first point. - Can't slice them - Can't range them Sure you can: unittest { import std.stdio; import std.algorithm; int[10] a = [1,2,3,4,5,6,7,8,9,10]; // Note I'm slicing the static array to use in range algorithms: writeln(a[].map!(b => b+2)); // Slicing works: auto b = a[3..6]; b[] = 7; writeln(a); } - Assignment copies the whole array, as in int[5] a; auto b = a; This is often a factor in choosing a static array. It's not better or worse, just different. And sometimes it's different in exactly the way you need. - Size is limited by stack - Stack overflow issues So allocate your static array on the heap if this is a problem? Some of the cons could be considered a feature. Also GC but it's possible to make a dynamic array implementation which avoids the GC. Basically none of the drawbacks you refer to are actual drawbacks, but instead part of what makes static arrays useful. Static arrays are not a poor man's dynamic arrays, they're a different beast, doing different things. -- Simen
Re: What's the point of static arrays ?
On Friday, 10 July 2020 at 10:13:23 UTC, wjoe wrote: However stack memory needs to be allocated at program start. I don't see a huge benefit in allocation speed vs. heap pre-allocation, or is there? I mean 1 allocation vs 2 isn't going to noticeably improve overall performance. You seem to still be thinking of static arrays as the same kind of "thing" as a dynamic array. They're (usually) more like ints or structs than containers: they're generally small, they're often parts of other structures or classes, and they're fairly often the element type of a larger dynamic array. For instance, a bitmap image could be a byte[4][][], with dynamic dimensions 3840x2160. If instead of byte[4] we used byte[], not only would things grind to a halt immediately, we'd also be using massively more memory. When you're using a static array on the stack, it's usually just because it's more convenient to say `int[16] buffer;` than `auto buffer = new int[16];`. The fact it may be faster is mostly a side benefit. Also, even if you did preallocate such a buffer, there's the overhead of remembering how to get to it, the work of setting it up, probably a function call on use, etc. The alternative is terser, built-in, more obvious to maintainers, pretty unlikely to overflow the stack, and very unlikely to be slower. Allocating a multi-MiB static array on the stack is a sign that you're using your screwdriver as a hammer, and there are probably better ways to do what you're trying to do. a[] What happens here exactly ? It creates a dynamic array that points to the data in the static array. It's just shorthand for a[0..$]: unittest { int[4] a = [1,2,3,4]; auto b = a[]; assert(b.length == 4); assert(b.ptr == &a[0]); auto c = a[0..$]; assert(b is c); } -- Simen
Re: miscellaneous array questions...
On Tuesday, 21 July 2020 at 13:42:15 UTC, Steven Schveighoffer wrote: On 7/21/20 8:34 AM, Adam D. Ruppe wrote: The others aren't wrong about stack size limits playing some role, but the primary reason is that it is a weird hack for @safe, believe it or not. ... I don't recall exactly when this was discussed but it came up in the earlier days of @safe, I'm pretty sure it worked before then. I think this was discussed, but was not the reason for the limitation. The limitation exists even in D1, which is before @safe: https://digitalmars.com/d/1.0/arrays.html#static-arrays I have stressed before that any access of a pointer to a large object in @safe code should also check that the base of the object is not within the null page (this is not currently done). This is the only way to ensure safety. It seems the limitation was introduced in DMD 0.123, in May 2005: https://forum.dlang.org/post/d61jpa$1m0l$1...@digitaldaemon.com Walter gives some justification in the post immediately following: 1) Gigantic static arrays are often either the result of a typo or are a newbie mistake. 2) Such require a lot of memory for the compiler to handle. Before the OS officially runs out of memory, it goes to greater and greater lengths to scavenge memory for the compiler, often bringing the computer to its knees in desperation. 3) D needs to be a portable language, and by capping the array size a program is more likely to be portable. 4) Giant arrays are reflected in a corresponding giant size for the exe file. 5) There simply isn't a need I can think of for such arrays. There shouldn't be a problem with allocating them dynamically. I admit I thought it was an old optlink limitation, but it seems it's basically arbitrary. -- Simen
Re: can't access an alias created inside an if statement
On Wednesday, 5 August 2020 at 09:05:36 UTC, Flade wrote: I have used an if-else statement to create an alias to avoid code duplication but it doesn't let me access it outside the if statement. Is there a way to solve this? You're probably looking for static if: static if (useAlias) { alias myAlias = getAlias!(); } myAlias foo = getFoo(); What happens is a regular if statement introduces a scope, so anything declared inside it is unavailable outside. static if does not introduce a new scope, and so its contents can be accessed. static if only works with compile-time constant conditions, but aliases are also compile-time constructs, so this should not pose a problem. -- Simen
Re: can't access an alias created inside an if statement
On Wednesday, 5 August 2020 at 09:32:58 UTC, Flade wrote: Thanks! You see it should work but the thing is. I'm using it inside a function. I'm checking for one of the function's parameter (if parameter == false) and it says that "the variable `parameter` cannot be read at compile time. Do you know if there is a way to fix this? As the error message says, the value must be known at compile time. Most likely, you can simply pass it as a template parameter: void fun(bool parameter)(int arg1, string arg2) { static if (parameter) { } } void main() { fun!true(1, "foo"); fun!false(19, "bar"); } -- Simen
Re: Cannot call @system funciton (stdout)
On Saturday, 15 August 2020 at 23:59:36 UTC, Joel wrote: ../../JMiscLib/source/jmisc/base.d(176,2): Error: @safe function jmisc.base.upDateStatus!string.upDateStatus cannot call @system function std.stdio.makeGlobal!"core.stdc.stdio.stdout".makeGlobal /Library/D/dmd/src/phobos/std/stdio.d(4837,20): std.stdio.makeGlobal!"core.stdc.stdio.stdout".makeGlobal is declared here I got around it by avoiding 'stdout'. First, what's wrong with using writeln and friends instead of directly mucking about with stdout? :p stdout is __gshared, so it's available on any thread at any time. That's not @safe, so it's @system. If you know you're not using stdout from multiple threads, or don't care (it might be perfectly safe even though it's possible to misuse), you can use this code: @property File trustedStdout() @trusted { return stdout; } That's a @trusted wrapper that you can call from @safe code. It's not actually safe though, as multiple threads could be using trustedStdout at the same time. In many use cases, this is unlikely to matter, but it's wroth keeping in mind. -- Simen
Re: Template: get function name
On Monday, 17 August 2020 at 08:07:32 UTC, novice3 wrote: Hello. I have wrapping Windows API functions, wich return 0 on success and erroro code on failure. I copy wenforce template as: ``` private T denforce(T, S)(T value, lazy S msg = null, string file = __FILE__, size_t line = __LINE__) { import core.sys.windows.winerror: NO_ERROR; import std.conv: to; if (value != NO_ERROR) throw new WindowsException(value, to!string(msg), file, line); return value; } ``` and use it: ``` DhcpEnumServers(0, null, servers, null, null).denforce("DhcpEnumServers"); Then windows api - extern (Windows)DhcpEnumServers - return error, then Windows exception throwed with name of failed api "DhcpEnumServers". Can we change template to avoid api name dublicate? Can denforce template obtain "DhcpEnumServers" function name to format message "DhcpEnumServers api failed"? Thanks. Take the function as an alias parameter and wrap the entire call: auto denforce(alias fn, string file = __FILE__, size_t line = __LINE__, Args...)(Args args) { import core.sys.windows.winerror: NO_ERROR; auto value = fn(args); if (value != NO_ERROR) { throw new WindowsException(value, __traits(identifier, fn)~" api call failed.", file, line); } return value; } unittest { denforce!DhcpEnumServers(0, null, servers, null, null); } For bonus points, you could also get the error message for the returned error code: string convertErrorCode(uint code) { import core.sys.windows.winbase : FormatMessage, LoadLibrary, FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_IGNORE_INSERTS, FORMAT_MESSAGE_FROM_HMODULE; wchar[512] buf; auto written = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, null, code, 0, buf.ptr, buf.length, null); if (!written) { auto inst = LoadLibrary("Ntdsbmsg.dll"); if (inst) { written = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, inst, code, 0, buf.ptr, buf.length, null); } } if (written) { import std.conv : to; return buf.ptr.to!string; } else { import std.format : format; return format("An unknown error occured: %x", code); } } unittest { import core.sys.windows.winerror : ERROR_INVALID_FUNCTION; import std.stdio; writeln(convertErrorCode(ERROR_INVALID_FUNCTION)); writeln(convertErrorCode(1234567891)); } -- Simen
Re: Can a call to pragma(msg, __FILE__, ...) be mixin templatized?
On Monday, 17 August 2020 at 21:18:41 UTC, Per Nordlöw wrote: I'm using pragma(msg, __FILE__, "(", __LINE__, ",1): Debug: ", "A useful debug message"); to print compile-time information formatted as standard compiler diagnostics. These are picked up by Emacs Flycheck and overlayed in the editor and listen in the *Flycheck errors* buffer. Very convenient. When I want to get the type of something at compile-time. In order to not having to repeat oneself I'm now looking for a way to extract this into a `mixin template`. Is this possible somehow and still preserve the instantiation site values of `__FILE__` and `__LINE__`? mixin template ctLog(string msg, string file = __FILE__, size_t line = __LINE__) { pragma(msg, file, "(", line, "): ", msg); } mixin ctLog!"Module scope"; unittest { mixin ctLog!"function scope"; } struct S { mixin ctLog!"Struct scope"; } This works for me. -- Simen
Re: Can a call to pragma(msg, __FILE__, ...) be mixin templatized?
On Tuesday, 18 August 2020 at 08:05:20 UTC, Per Nordlöw wrote: On Tuesday, 18 August 2020 at 08:03:04 UTC, Per Nordlöw wrote: Forgot to mention that I want to support variadic arguments to `ctLog` similar to what is done with And these arguments should be of any template argument kind, not only a compile-time string. I'm not a fan of string mixins (ask Adam how they're the scourge of good programming, a wart on D's behind, and so on :p), but I found no good way to do this without them: string ctLog(Args...)(string file = __FILE__, size_t line = __LINE__) { import std.conv : to; string result = `pragma(msg, "`~file~`(", `~line.to!string~`, "): "`; static foreach (e; Args) { result ~= `, `~e.stringof; } return result~`);`; } mixin(ctLog!("This ", "is ", "module ", "scope.")); unittest { mixin(ctLog!"function scope"); } struct S { mixin(ctLog!"Struct scope"); } -- Simen
Re: Wrong selection of opEquals for objects.
On Friday, 28 August 2020 at 08:16:01 UTC, Alexandru Ermicioi wrote: Hi everyone, there is https://issues.dlang.org/show_bug.cgi?id=21180 bug, anyone knows how to avoid it? Test case: - import std; class Silly { bool opEquals(const Silly silly) const @safe { return silly is this; } alias opEquals = Object.opEquals; } bool comp(T)() @safe { return new T() == new T(); } void main() { comp!Silly.writeln; comp!(const Silly).writeln; comp!(immutable Silly).writeln; } - It always tries to call Object.opEquals, when narrower overload should've been selected. - Alex. Essentially, this boils down to the issues described in https://issues.dlang.org/show_bug.cgi?id=1824, and a host of other bugzilla issues. When you do a == b with a and b being class objects, it's lowered to object.opEquals(a, b)[0], which casts both a and b to Object before doing the comparison. So, you'll need to override Object.opEquals to have the right function called: class Silly { int field; this(int f) { field = f; } override bool opEquals(Object o) { auto silly = cast(Silly)o; // If cast returns null, it's not a Silly instance if (!silly) return false; // Compare Silly objects return field == silly.field; } } unittest { Silly a = new Silly(1); assert(a == new Silly(1)); assert(a != new Silly(2)); } That takes care of choosing the correct overload, but as you may have noticed, there's another issue: your @safe function comp() can't call the @system function object.opEquals. Since object.opEquals operates on Object instances, not your specific subclass, it has to assume the worst, and is @system. There's no real good solution to that in the language as of now, and some of us have been pulling our hair for years because of it. What you'll need to do is mark every function that does compare two class objects with == as @trusted or @system. -- Simen [0]: https://github.com/dlang/druntime/blob/master/src/object.d#L166
Re: Wrong selection of opEquals for objects.
On Friday, 28 August 2020 at 10:42:09 UTC, Alexandru Ermicioi wrote: No that is not a solution at all, in template code that requires safety. You basically will have to sacrifice safety for rest of types, such as structs, unions & enums for the sake of objects being able to compare. Yup. There's a reason I'm saying it's suboptimal. FWIW, you can limit the taint by using @trusted lambdas. One of the reasons this hasn't been fixed is idiomatic D code very rarely uses classes, but that does not mean they're always the wrong tool. Could we just template that opEquals in this manner: --- bool opEquals(T : Object, X : Object)(T lhs, X rhs) { if (lhs is rhs) return true; if (lhs is null || rhs is null) return false; if (!lhs.opEquals(rhs)) return false; if (typeid(lhs) is typeid(rhs) || !__ctfe && typeid(lhs).opEquals(typeid(rhs))) { return true; } return rhs.opEquals(lhs); } --- That would at least allow us to define an overload which is safe and would be picked up by new implementation. I'm wondering why it wasn't done yet, are there any reasons for that? The template solution may look like it solves every problem, but it really doesn't. Consider this code: class A { bool opEquals(A) { return false; } } class B : A { bool opEquals(B) { return true; } } unittest { B b1 = new B(); B b2 = new B(); A a1 = b1; A a2 = b2; assert(b1 == b2); assert(a1 != a2); // WTF? } With the template solution, the function in B would be ignored when stored in a variable with static type A. This solution would sometimes do the right thing, other times it would silently do the wrong thing. Also, why it is limited to just objects? It seems that this function enforces symmetry between two objects. What about rest of the possible types, such as structs, unions? That's an issue. The spec clearly states (https://dlang.org/spec/operatoroverloading.html#equals): 2. [T]he expressions a.opEquals(b) and b.opEquals(a) are tried. If both resolve to the same opEquals function, then the expression is rewritten to be a.opEquals(b). 3. If one is a better match than the other, or one compiles and the other does not, the first is selected. 4. Otherwise, an error results. This is clearly not the case: struct S1 { bool opEquals(S2 a) { return true; } } struct S2 { bool opEquals(S1 a) { return false; } } unittest { S1 a; S2 b; assert((a == b) == (b == a)); // Fails } I didn't find a bugzilla entry on this, but I'm pretty sure there is one. As for why there's no global function like for classes, that's because there's no need - there is no disconnect between the static and dynamic types of non-class variables (or, if there is, it's explicitly programmed in, like in std.variant.Variant). -- Simen
Re: Wrong selection of opEquals for objects.
On Friday, 28 August 2020 at 13:35:43 UTC, Alexandru Ermicioi wrote: On Friday, 28 August 2020 at 12:29:20 UTC, Simen Kjærås wrote: Seems that these methods should be rooted out from Object, and placed in respective interfaces like: - interface Equatable(T) { bool opEquals(T value); } - Then it would be a lot more simple. People who want equality check, will implement interface with right type, for example Equatable!Object. Yup, it's been proposed, but nothing's come of it yet. Here's Andrei's DIP on ProtoObject, which apparently is untouched for over two years now: https://github.com/andralex/DIPs/blob/ProtoObject/DIPs/DIP.md The main problem with solving this issue is doing so will break all code that uses the current system. This is clearly suboptimal. -- Simen
Re: Tuple poilerplate code
On Tuesday, 1 September 2020 at 02:08:54 UTC, JG wrote: Is there anyway to remove the boilerplate code of dealing with tuples: I find myself having to write things like this fairly often auto someRandomName = f(...); //where f returns a tuple with two parts auto firstPart = someRandomName[0]; auto secondPart = someRandomName[1]; Is to possible to write something so that the above is essentially equivalent to: assignTuple!(firstPart,secondPart) = f(...); The closest I can produce is using a template mixin so that I would have to write: mixin AssignTuple!(()=>f(...),"firstPart","secondPart"); When you know the types, this works: import std.typecons : tuple; import std.meta : AliasSeq; int firstPart; string secondPart; AliasSeq!(firstPart, secondPart) = tuple(1, "foo"); assert(firstPart == 1); assert(secondPart == "foo"); I know Timon Gehr worked on a DIP for improved tuples, which I think would include the syntax `auto (firstPart, secondPart) = tuple(1, "foo");`, but I don't know what's happened to that idea lately. I also feel it's worth pointing out that Paul Backus' code looks elegant when used outside a map as well: tuple(1, "foo").unpack!((i, s) { writeln("i (", typeof(i).stringof, "): ", i, ", s (", typeof(s).stringof, "): ", s); }); Will print: i (int): 1, s (string): foo -- Simen
Re: tupleof seems to break encapsulation
On Friday, 4 September 2020 at 10:16:47 UTC, 60rntogo wrote: Consider the following code. foo.d --- module foo; struct Foo { private int i; } --- main.d --- void main() { import std.stdio; import foo; auto x = Foo(); writeln(x); // ++x.i; ++x.tupleof[0]; writeln(x); } --- As expected, the commented line does not compile. If I uncomment it, I get the error "no property i for type foo.Foo". However, the rest of the code compiles just fine and outputs: --- Foo(0) Foo(1) --- This appears to defeat the purpose of declaring i private. What am I missing? It's a known issue: https://issues.dlang.org/show_bug.cgi?id=19326 There are some very good reasons to allow some access to private fields, though it should be more limited than is currently the case. -- Simen