Re: How to call function with variable arguments at runtime?
On Tuesday, 10 October 2017 at 02:58:45 UTC, Mr. Jonse wrote: I need to store a hetrogeneous array of delegates. How can I do this but still call the function with the appropriate number of parameters at run time? I have the parameters as Variant[] params and a function/delegate pointer(void* for now). Normally I'd push the parameters on the stack and use a call, but I'm sure D has some ability to do this, like apply(foo, args) would be the same as foo(args[0], ..., args[1]). I'm not concerned about type correctness, it should always be consistent between what I call and what is stored. Thanks. Like so? import std.variant; void foo(int a, string b, float c) { import std.stdio; writefln("a = %s, b = %s, c = %s", a, b, c); } auto apply(alias fn)(Variant[] values) { import std.traits : ParameterTypeTuple; import std.conv : emplace; alias Types = ParameterTypeTuple!fn; assert(values.length == Types.length); Types args = void; foreach(i, ref arg; args) { // using emplace instead of assignment here to be fully correct emplace!(typeof(arg))(, values[i].get!(typeof(arg))); } return fn(args); } void main() { Variant[] values = [Variant(1), Variant("Hello world"), Variant(3.14159f)]; apply!foo(values); }
Re: GC
On Sunday, 30 July 2017 at 09:12:53 UTC, piotrekg2 wrote: I would like to learn more about GC in D. For example can anyone explain why do we need memset(0) here: https://github.com/dlang/phobos/blob/master/std/container/array.d#L356 , doesn't it assume a certain type of GC? What if there is a need to change the GC algorithm in the future? The current GC is a conservative one, which means that it has at best an incomplete knowledge of the types in the memory it scans. Therefore, whenever it sees a value that, when interpreted as a pointer, points to a pool of memory owned by the GC, it needs to assume that it is indeed a pointer, which means it has to keep the referenced object alive. A false pointer is one that only looks like a valid pointer but is in reality some other kind of data, or in this case data in a block of memory that's still allocated, but no longer actually in use. False pointers can keep GC-managed objects alive that could actually be freed, so they're something that should be avoided. The container overwrites the memory with zeroes because a zero value is never a valid pointer. Changing the GC algorithm would do no harm here. The best we could hope for is that the GC at some pointer becomes fully precise (unlikely), so it can distinguish false from real pointers by itself. In this case, the memset would become unnecessary, but it wouldn't lead to wrong behaviour.
Re: Static array * scalar is not working for me
On Sunday, 30 July 2017 at 08:18:07 UTC, Danni Coy wrote: The following code is not working for me float[3] f; f[] = abs(f)[] * -1.0f; where abs is a function that returns a float[3]; it complains that f should be attached to some memory. Is it a bug or am I missing something? I cannot reproduce the error with the code you've given. It's either missing some import, or a definition of `abs()`. The one in std.math doesn't accept arrays at all.
Re: Split Real / Float into Mantissa, Exponent, and Base
On Friday, 3 March 2017 at 18:09:02 UTC, Jonathan M. Wilbur wrote: I have tried to come up with a good way to get the mantissa, exponent, and base from a real number, and I just can't come up with a good cross-platform way of doing it. I know about std.math.frexp(), but that function only gives you another real as the mantissa. I need an integral mantissa, exponent, and base. Is there either (1) a crafty, cross-platform way of doing this or (2) a function in a standard library that does this that I somehow missed? If there is no such function, what are your thoughts on me implementing such a thing and submitting it to Phobos, probably similar to how frexp is implemented (elseifs for each FP format)? See std.bitmanip.FloatRep and std.bitmanip.DoubleRep: https://dlang.org/phobos/std_bitmanip.html#.FloatRep https://dlang.org/phobos/std_bitmanip.html#.DoubleRep
Re: switch to member
You can utilize a little-known `switch` syntax trick in combination with `foreach`. Because a `foreach` over tuples is unrolled at compile time, it works even if your fields don't have exactly the same types: -- struct Foo { int x, y; long a, b, c; short i, j, k; } enum Which { x, y, a, b, c, i, j, k, } void assignValue(ref Foo q, Which member, short e) { import std.traits : EnumMembers; import std.conv : to; final switch(member) { // foreach over a tuple is unrolled at compile time foreach(w; EnumMembers!Which) { case w: // expands to: q.x, q.y, ... mixin("q." ~ w.to!string) = e; break; } } } void main() { import std.stdio : writeln; Foo q; writeln("before: ", q); assignValue(q, Which.a, 42); assignValue(q, Which.x, 1); writeln("after: ", q); }
Re: Complex numbers are harder to use than in C
On Saturday, 19 November 2016 at 20:24:09 UTC, Marduk wrote: On Saturday, 19 November 2016 at 12:55:57 UTC, Marc Schütz wrote: On Saturday, 19 November 2016 at 11:11:36 UTC, Nordlöw wrote: On Saturday, 19 November 2016 at 09:38:38 UTC, Marduk wrote: The difference is that D is more verbose. Am I missing something? Can we have C's behaviour in D? Something like auto I(T)(T im) if (isNumeric!T) { return complex(0, im); } unittest { auto x = 1 + 2.I; } Or simply: enum I = complex(0, 1); auto x = 1 + 2*I; Thanks! That's a clever idea. What I do not understand is why if I declare the array with Complex!double I need to complexify each entry. I would expect that D automatically casts 0.0 to complex(0.0). I agree, this is unfortunate. I don't know of any reason why the following couldn't work in principle: Complex!float[] arr = [1.0, 2.0, 3.0, 4.0]; // or even auto arr = [1+2*I, 2.0, 3.0, 4.0];// compiler finds common type // just like it works for auto arr = [1, 2, 3.0, 4];// typeof(arr) is double[] I believe it was a conscious decision. D doesn't do as many implicit type conversion as C++, because they often make it hard to understand what's going on. In the above examples though, IMO it wouldn't be a problem.
Re: Complex numbers are harder to use than in C
On Saturday, 19 November 2016 at 20:08:42 UTC, Marduk wrote: On Saturday, 19 November 2016 at 11:11:36 UTC, Nordlöw wrote: On Saturday, 19 November 2016 at 09:38:38 UTC, Marduk wrote: The difference is that D is more verbose. Am I missing something? Can we have C's behaviour in D? Something like auto I(T)(T im) if (isNumeric!T) { return complex(0, im); } unittest { auto x = 1 + 2.I; } Nice. But I am unsure of how to use this. I just pasted the definition of I inside the main function of my program followed by auto x = 1 + 2.I; and the compiler complained with Error: no property 'I' for type 'int'. Try placing it outside the function. Method call syntax doesn't work with nested functions, see here: https://dlang.org/spec/function.html#pseudo-member "The reason why local symbols are not considered by UFCS, is to avoid unexpected name conflicts."
Re: Complex numbers are harder to use than in C
On Saturday, 19 November 2016 at 11:11:36 UTC, Nordlöw wrote: On Saturday, 19 November 2016 at 09:38:38 UTC, Marduk wrote: The difference is that D is more verbose. Am I missing something? Can we have C's behaviour in D? Something like auto I(T)(T im) if (isNumeric!T) { return complex(0, im); } unittest { auto x = 1 + 2.I; } Or simply: enum I = complex(0, 1); auto x = 1 + 2*I;
Re: Best approach to handle accented letters
On Friday, 28 October 2016 at 11:24:28 UTC, Alfred Newman wrote: Hello, I'm getting some troubles to replace the accented letters in a given string with their unaccented counterparts. Let's say I have the following input string "très élégant" and I need to create a function to return just "tres elegant". Considering we need to take care about unicode chars, what is the best way to write a D code to handle that ? Cheers import std.stdio; import std.algorithm; import std.uni; import std.conv; void main() { auto str = "très élégant"; immutable accents = unicode.Diacritic; auto removed = str .normalize!NFD .filter!(c => !accents[c]) .to!string; writeln(removed); // prints "tres elegant" } This first decomposes all characters into base and diacritic, and then removes the latter.
Re: weighted round robin
On Tuesday, 18 October 2016 at 16:43:19 UTC, vino wrote: On Wednesday, 12 October 2016 at 13:44:59 UTC, Erikvv wrote: In your first post you mention it should be weighted, but I see no weights anywhere. Hi Marc, I am at the initial stage of implementing the round robin algorithm and still not reached the next part of weighted , if you have the code then please send me at present i am trying to implement this algorithm in my Server socket program and i would require few more days to complete it. Note that I'm not the one you wrote the above comment ;-)
Re: Determining if a class has a template function
On Wednesday, 12 October 2016 at 16:57:50 UTC, Meta wrote: There's also a *very* ugly hack you can do: //A template function's .stringof is of the format name>()() //so match on the number of brackets to determine whether it's a template function or not enum isTemplateFunction = __traits(isTemplate, f) && fstr.balancedParens('(', ')') && (fstr.canFind("if") || fstr.count!(c => cast(bool)c.among!('(', ')')) == 4); This won't work if there are additional parens _inside_ compile/runtime parameters, though, which there is ample opportunity for: T func(T : U!(int, string), U)(const(T) param = defaultValue!(const(T))());
Re: opIndexDispatch?
On Thursday, 13 October 2016 at 01:09:06 UTC, Ali Çehreli wrote: On 10/10/2016 12:01 PM, Yuxuan Shui wrote: Hi, Why is there no opIndexDispatch for overloading a[x].func() ? I could not understand the question fully but would using an element proxy work? I assume a proxy would indeed work, but it's indeed inconsistent. A proxy would work for opIndexAssign() and friends as well, so why do they exist, when opIndexDispatch() doesn't?
Re: isRvalue trait
On Monday, 10 October 2016 at 11:46:01 UTC, Nordlöw wrote: At https://github.com/nordlow/phobos-next/blob/master/src/moval.d I've implemented a helper function for creating r-value out of l-values defined as E movedToRvalue(E)(ref E e) { import std.algorithm.mutation : move; E value; move(e, value); // this can be optimized return value; } Doesn't the second overload of `move()` already do what you want? https://dlang.org/phobos/std_algorithm_mutation.html#.move Note that in your implementation, you needlessly initialize `value`, which then needs to be properly destroyed by `move()`, which the Phobos implementation avoids: https://github.com/dlang/phobos/blob/master/std/algorithm/mutation.d#L1083-L1088 For the case when movedToRvalue is called with an r-value, such as in, static assert(__traits(compiles, { consume(S(14)); })); I would like to overload to an identity op. If the compiler is smart enough to understand what `moveEmplace()` does, it could already do this automatically.
Re: weighted round robin
On Saturday, 8 October 2016 at 22:48:53 UTC, vino wrote: Hi, Can some one guide me on how to implement the weighted round robin, below is what i tried or any other better ways to do it Main Requirement : Incoming socket connection has to be sent to 3 servers in the weighted round robin fashion. Prog:1 import std.stdio; import std.range; import std.range.primitives; void main() { auto a = [1,2,3]; // E.g :Server Array auto b = [1,2,3,4,5]; // E.g: Socket Array auto r = roundRobin(a, b); writeln(r); } OUTPUT : [1, 1, 2, 2, 3, 3, 4, 5] Requirement : [1, 1, 2, 2, 3, 3,1,4,2,5] auto r = roundRobin(a.cycle, b.cycle); Beware though that this yields an infinite range. If you just need one round, you can use: import std.algorithm.comparison : max; writeln(r.take(max(a.length, b.length)));
Re: Explicit casting of enum -- intentional restriction?
On Saturday, 1 October 2016 at 20:52:48 UTC, rcorre wrote: I just tried to compile an old project and the following failed: --- enum Paths : string { bitmapDir = "content/image", fontDir = "content/font", soundDir = "content/sound", ... if (Paths.preferences.exists) ... --- It turns out members of Paths are no longer implicitly converted to string, and I needed to use if ((cast(string)Paths.preferences).exists) Is this an intentional limitation or a regression? I didn't see it in the last few changelogs but I'll admit I didn't check them rigorously. This is the PR that broke it: https://github.com/dlang/phobos/pull/3447
Re: Problem parsing IPv4/IPv6 addresses with std.socket.parseAddress
On Tuesday, 27 September 2016 at 14:57:26 UTC, Dsciple wrote: struct ConfigParams { // ... // Define configuration parameters' static default fields static immutable BindAddresses defaultBindAddresses = BindAddresses([ BindAddress("192.168.2.10") ]); // ... } Yepp, that's definitely the culprit. I don't understand why the unit tests of all individual members of ConfigParams (BindAddresses, BindAddress and so on) would work in isolation using the same kind of initialization, whereas some of them would fail as members of ConfigParams. Because in your unit tests, your BindAddress variables are probably normal, local variables. These are initial at runtime as you would expect. Only in places where a static initialization is required, the compiler will evaluate the initializer at compile time. Examples: // global, but no initializer => ok BindAddress global1; // global with initializer => needs to be evaluated at compile time BindAddress global2 = BindAddress("127.0.0.1"); struct Config { // default value for members => evaluate at compile time BindAddress bindAddress = BindAddress("0.0.0.0"); } void main() { // assignment to globals at runtime works (of course) global1 = BindAddress("192.168.1.2"); // local with initializer => works at runtime BindAddress local1 = BindAddress("10.0.0.1"); // static => same as global, evaluated at compile time static BindAddress static1 = BindAddress("127.0.0.1"); } You could solve the problem as you suggested by moving the initializations into a constructor, but if your default values are only ever IPs (i.e., no hostname resolution necessary), you could also add an additional function that parse them without calling into the C library, e.g. struct BindAddress { // ... static BindAddress fromIP(string addr) { // ... } } struct Config { // ... BindAddress bindAddress = BindAddress.fromIP("127.0.0.1"); } You can try whether InternetAddress.parse() [1] works at compile time, otherwise you would have to implement it by hand. [1] https://dlang.org/phobos/std_socket.html#.InternetAddress.parse
Re: Problem parsing IPv4/IPv6 addresses with std.socket.parseAddress
On Tuesday, 27 September 2016 at 09:04:53 UTC, Dsciple wrote: As said, this works fine when tested in isolation, and the compiler only complains when using BindAddress as a member of ConfigParams. Any idea what the problem may be? Or is there maybe a ready to use, high-level library for parsing parameters from command-line arguments and config files of some kind? I assume your ConfigParams variable is global or static? Can you show how you initialize it, and how it's declared? You're probably using it in a way that requires it to be evaluated at compile time. That's the case for initializers of global/static variables, as well as default values of struct members.
Re: thisExePath purity
On Tuesday, 20 September 2016 at 04:17:21 UTC, crimaniak wrote: Hi and thanks all! On Tuesday, 20 September 2016 at 00:43:10 UTC, Jonathan M Davis wrote: immutable string executablePath; shared static this() { import std.file : thisExePath(); executablePath = thisExePath(); } This code is good for my needs but I start to think about how to call thisExePath only if it is really used and come to this solution: import std.traits: ReturnType, Parameters; string staticMemoize(alias T, Parms = Parameters!T)() pure { struct Holder(alias T) { static shared immutable ReturnType!T value; shared static this(){ value = T(Parms); } } return Holder!T.value; } unittest { import std.file : thisExePath; assert(staticMemoize!thisExePath == thisExePath); } Something like this. Need to refine about input parameters, but I hope, idea is clear. Unlike the function memoize from phobos staticMemoize really pure. And unlike proposed solution with ordinary variable staticMemoize is lazy, because no call - no instantiation. Have a look at `std.concurrency.initOnce`: https://dlang.org/phobos/std_concurrency.html#.initOnce But you will still need to use assumePure() for calling `thisExePath`, and it might do other things that are impure...
Re: Fiber Concurrency Showcase
On Tuesday, 13 September 2016 at 10:02:28 UTC, Andrea Fontana wrote: On Tuesday, 13 September 2016 at 09:46:46 UTC, Nordlöw wrote: I would like to experiment with Fibers/Coroutines in D/vibe.d. I'm missing a code example in std.concurrency that highlights an example of using Fibers for massive concurrency. Could anybody show me such a code example or link to a more descriptive tutorial? Check this: http://ddili.org/ders/d.en/fibers.html Andrea Ha! Should have refreshed the page before replying :-P
Re: Fiber Concurrency Showcase
On Tuesday, 13 September 2016 at 09:46:46 UTC, Nordlöw wrote: I would like to experiment with Fibers/Coroutines in D/vibe.d. I'm missing a code example in std.concurrency that highlights an example of using Fibers for massive concurrency. Could anybody show me such a code example or link to a more descriptive tutorial? Ali has an asynchronous I/O example in the Fibers chapter of his book: http://ddili.org/ders/d.en/fibers.html
Re: How to group similar member functions from different classes?
On Friday, 15 July 2016 at 17:25:23 UTC, cy wrote: On Monday, 20 June 2016 at 16:39:54 UTC, Marc Schütz wrote: Untested: Seems to only work if A and B are both defined in the same file as Foos (defeating the purpose). Putting A and B in a.d and b.d respectively gives me these errors: a.d(2): Error: undefined identifier 'Foos' a.d(2): Error: mixin a.A.Foos!() is not defined b.d(2): Error: undefined identifier 'Foos' b.d(2): Error: mixin b.B.Foos!() is not defined I also tried switching it around, like // b.d import foos Foos; class B { mixin Foos; } but that of course gives the error: foos.d(4): Error: undefined identifier 'A' b.d(3): Error: mixin b.B.Foos!() error instantiating since you can't do a static if(typeof(this) == A) without importing A from a somehow. (you can do else static if(typeof(this) == B) without importing B though, since it does the branch for A first) I think a mixin here is just required, because you can't use an identifier before it's defined, even at compile time. Honestly, I have yet to find a use for mixin templates. It works if you add forward declarations for the classes: import a, b; class A; class B; mixin template Foos() { static if(is(typeof(this) == A)) void foo() { /* implementation for A */ } static if(is(typeof(this) == B)) void foo() { /* implementation for B */ } }
Re: local const functions - bug ?
On Sunday, 10 July 2016 at 07:20:29 UTC, Meta wrote: On Friday, 8 July 2016 at 09:01:10 UTC, Marc Schütz wrote: `foo()` is effectively a delegate, therefore `const` applies to the context. AFAIK const on a function can only ever refer to the `this` pointer, but there is no `this` pointer. To the `this` pointer, or the context, in case of delegates. Here, `foo()` is a nested function that accesses a variable in the outer scope. This qualifies it as a delegate [1]: "When comparing with nested functions, the function form is analogous to static or non-nested functions, and the delegate form is analogous to non-static nested functions. In other words, a delegate literal can access stack variables in its enclosing function, a function literal cannot." [1] https://dlang.org/spec/expression.html#FunctionLiteral
Re: local const functions - bug ?
On Thursday, 7 July 2016 at 15:02:29 UTC, Jonathan M Davis wrote: On Thursday, July 07, 2016 10:33:39 Basile B. via Digitalmars-d-learn wrote: this compiles without error: struct Foo { int i; void bar() { void foo() const { i = 1; } foo; } } In this case "const" seems to be a noop. Do you think it's a bug ? Shouldn't "const" be applied, despite of foo() inaccessibility ? It makes no sense for const to be used on foo. foo is not a member function, so there's nothing for the const to apply to. `foo()` is effectively a delegate, therefore `const` applies to the context.
Re: Initializing static array with contents of (static and dynamic) arrays
auto concat(T : E[n], E, size_t n)(const E[][] args...) @nogc { size_t offset = 0; T result = void; foreach(arr; args) { result[offset .. offset+arr.length] = arr; offset += arr.length; } assert(offset == result.length); return result; } static immutable ubyte[4] sigma0 = [101, 120, 112, 97]; static immutable ubyte[4] sigma1 = [110, 100, 32, 51]; static immutable ubyte[4] sigma2 = [ 50, 45, 98, 121]; static immutable ubyte[4] sigma3 = [116, 101, 32, 107]; void func(in ref ubyte[32] key, in ref ubyte[16] n) @nogc { ubyte[64] buf; buf[0..4] = sigma0; buf[4..20] = key[0..16]; buf[20..24] = sigma1; buf[24..40] = n; buf[40..44] = sigma2; buf[44..60] = key[16..$]; buf[60..64] = sigma3; auto buf2 = concat!(ubyte[64])(sigma0, key[0..16], sigma1, n, sigma2, key[16..$], sigma3); assert(buf == buf2); } void main() { ubyte[32] key = [0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1]; ubyte[16] n = key[0..16]; func(key, n); } Some remarks: * I added `ref` to `func`'s parameters, because the arrays are relatively large, so passing them by value might be costly (you should measure it if you care). * The `void` initialization in `concat` is an optimization that is valid only for POD types. * Returning the array is cheap because of NRVO.
Re: Is there anyway to make opApply @nogc?
On Tuesday, 21 June 2016 at 19:21:01 UTC, Gary Willoughby wrote: Right ok, thanks! It doesn't seem to help though as the compiler complains about it being not @nogc. You probably need to declare the delegate and opApply() itself as @nogc, too: int opApply(scope int delegate(int) @nogc dg) @nogc { }
Re: How to group similar member functions from different classes?
Untested: // foo.d import a, b; mixin template Foos { static if(is(typeof(this) == A)) void foo() { /* implementation for A */ } static if(is(typeof(this) == B)) void foo() { /* implementation for B */ } } // a.d import foo; class A { mixin Foos; } // b.d import foo; class B { mixin Foos; } You must not have static constructors in any of these modules because you'd likely get problems with circular initialization.
Re: Error: castSwitch
On Tuesday, 7 June 2016 at 03:55:03 UTC, none wrote: import std.algorithm.iteration : map; import std.algorithm : castSwitch; import std.format : format; class A { int value; this(int value) { this.value = value; }} interface I { } class B : I { } Object[] arr = [new A(5), new B(), null]; auto results = arr.map!(castSwitch!( (A a) => "class A with a value of %d".format(a.value), (I i) => "derived from I", (B b) => "class B", () => "null reference", ))(); The codes get nonsense error like: /home/bthach/dlang/dmd-2.071.0/linux/bin64/../../src/phobos/std/algorithm/comparison.d(277): Error: no property 'format' for type 'string' Note the location of the error: it is in Phobos, not in your code. It's a bug, it should actually print a valid error message. Filed here: https://issues.dlang.org/show_bug.cgi?id=16135 It has nothing to do with the fact that you're using `format`, that's just coincidence. But when I changed the order: [...] (B b) => "class B", (I i) => "derived from I", Suprisingly, it works. `castSwitch` tries the types you pass it in the order you specify. If you pass `I` first, the `B` case will never be matched because it is "shadowed" by the former (every `B` is also an `I`). `castSwitch` detects this situation and wants to print a message to warn you. However, someone forgot to import `std.format` (which is used for formatting the error message), resulting in the error you observed.
Re: opCall override default constructor?
On Thursday, 2 June 2016 at 08:50:26 UTC, Jacob Carlborg wrote: Is it intentional that a non-static opCall overrides the default constructor of a struct? struct Foo { int a; void opCall(string b) { } } void main() { auto f = Foo(3); // line 14 f("asd"); } The above code gives the following error: main.d(14): Error: function main.Foo.opCall (string b) is not callable using argument types (int) It's this bug: https://issues.dlang.org/show_bug.cgi?id=9078
Re: Why do some T.init evaluate to true while others to false?
On Monday, 30 May 2016 at 19:06:53 UTC, ArturG wrote: does this count? struct Foo { int x; float f; } void main() { Foo foo; if(foo is typeof(foo).init) "A: does'nt work".writeln; foo = Foo(); if(foo is typeof(foo).init) "B: works".writeln; } This one is a bug in DMD. It works correctly with LDC. `Foo()` is supposed to be identical to `Foo.init`. File here: https://issues.dlang.org/show_bug.cgi?id=16105
Re: Operator overloading through UFCS doesn't work
On Sunday, 29 May 2016 at 07:18:10 UTC, Jonathan M Davis wrote: On Friday, May 27, 2016 09:08:20 Marc Schütz via Digitalmars-d-learn wrote: On Thursday, 26 May 2016 at 06:23:17 UTC, Jonathan M Davis wrote: > The difference is that it's impossible to do > 10.opBinary!"+"(15), so if you're forced to do > foo.opBinary!"+"(bar) to get around a symbol conflict, it > won't > work with built-in types. Well, that begs the question: Why don't built-in types define `opBinary`? That's just another arbitrary irregularity, isn't it. It was never intended that any op* function be called by anyone except where the compiler lowers code to use them. They're for declaring overloaded operators on user-defined types so that those types can be used with those operators. If you're calling opBinary in your own code, you're doing it wrong. And it would be downright silly to then add opBinary to the built-in types. If I were to design my own language from scratch, that's actually how I would do it. All operators, even for built-in types, would just be syntax sugar for the method calls. The goal should be to minimize the difference between built-in and user-defined types as much as possible. Turtles all the way down... They don't need operator overloading. They already have the operators. Operators are supposed to be used as operators, not functions, and if there's any need to use them as functions, then there's something seriously wrong. And the fact that allowing free functions to overload operators via UFCS sends us into that territory just highlights the fact that they're a horrible idea. I'd say the fact that it doesn't work, and can't currently work for the reasons you described, points to an inconsistency in the language's design. It means that we have two largely overlapping concepts (builtin types and user defined types), where most language features work the same for both, but some don't. That's not the end of the world, of course, but still...
Re: Why do some T.init evaluate to true while others to false?
On Thursday, 26 May 2016 at 16:45:22 UTC, ArturG wrote: im just playing with this template[1] is there anything else i missed? (if you dont mind) it basically treats any T.init as false and skips the function/delegate and just returns type. [1] https://dpaste.dzfl.pl/d159d83e3167 If you just want to check whether something is equal to its type's .init value, use the `is` operator, which does a bitwise comparison: if(value is typeof(value).init) ...
Re: Testing array ptr for offset 0...
On Thursday, 26 May 2016 at 22:47:02 UTC, Era Scarecrow wrote: On Thursday, 26 May 2016 at 22:15:42 UTC, ag0aep6g wrote: Sorry, I'm still lost. Why can't you do whatever you're doing in opOpAssign directly there, or in a free function? Does the pseudo-array contain any additional data? Would a wrapper around a built-in array not work? Well a few things at work. First the array is originally a static array, so I pass it as a slice; But if you pass it as a slice you get the entire length, and modifying the length requires either changing length or appending, both which may cause allocation (something I want to avoid). By making my own compatible structure I can manage the length and pointer directly and precisely. You can do that with arrays, too, without causing allocations: assert(slice.length < static_array.length); slice = slice.ptr[0 .. slice.length+1]; Of course that's unsafe, but your pointer magic certainly is, too.
Re: Operator overloading through UFCS doesn't work
On Thursday, 26 May 2016 at 06:23:17 UTC, Jonathan M Davis wrote: The difference is that it's impossible to do 10.opBinary!"+"(15), so if you're forced to do foo.opBinary!"+"(bar) to get around a symbol conflict, it won't work with built-in types. Well, that begs the question: Why don't built-in types define `opBinary`? That's just another arbitrary irregularity, isn't it.
Re: full copies on assignment
On Thursday, 26 May 2016 at 10:51:30 UTC, John Nixon wrote: On Wednesday, 25 May 2016 at 15:44:34 UTC, Marc Schütz wrote: On Tuesday, 24 May 2016 at 20:58:11 UTC, John Nixon wrote: On Tuesday, 24 May 2016 at 15:17:37 UTC, Adam D. Ruppe wrote: On Tuesday, 24 May 2016 at 14:29:53 UTC, John Nixon wrote: Or add an explicit constructor: struct CS { // ... this(const CS rhs) { this = rhs; } Unfortunately this results in "Error: cannot implicitly convert expression (rhs) of type const(CS) to CS'. Hmm... this is the full program that works for me: import std.stdio; struct CS { char[] t; this(const CS rhs) { this = rhs; } CS opAssign(const CS rhs) { writeln("CS.opAssign called"); this.t = rhs.t.dup; return this; } }; void test_fun(const ref CS rhs) { auto cs = CS(rhs); writeln("cs = ",cs); } void main() { CS rhs; rhs.t = "string".dup; test_fun(rhs); return; }
Re: full copies on assignment
On Tuesday, 24 May 2016 at 20:58:11 UTC, John Nixon wrote: On Tuesday, 24 May 2016 at 15:17:37 UTC, Adam D. Ruppe wrote: On Tuesday, 24 May 2016 at 14:29:53 UTC, John Nixon wrote: This naively doesn’t seem right because the RHS of an assignment should not be altered by it. It's because the char[] being shallow copied still leads to mutable stuff. What I typically do here is just add a method `dup` to the struct that deep copies. Then you do `CS cs = rhs.dup;` when you want to construct it, like you'd do with a copy of a naked array. Thank you for this suggestion, perhaps a slightly neater workaround. Or add an explicit constructor: struct CS { // ... this(const CS rhs) { this = rhs; } } Then you can write: auto cs = CS(rhs);
Re: mutable keyword
On Sunday, 22 May 2016 at 09:42:54 UTC, Jack Applegame wrote: I agree. But I think we need something that allows *logical* const and immutable. Strict binding constness to physical memory constancy is not always necessary and sometimes even harmful. http://wiki.dlang.org/DIP89
Re: Immutable objects and constructor ?
On Friday, 20 May 2016 at 15:07:53 UTC, chmike wrote: The error message is gone, but I now have another compilation error message I don't understand. This is what I have in fact interface Info { . . . } class MyInfos { . . . protected: class Obj : Info { . . . } public: static immutable Obj one = new immutable Obj(...); static immutable Obj two = new immutable Obj(...); } I get a compiler error in the two assignments to the static Obj member variables: 'this' is only defined in non-static member functions, not MyInfos Is it related to the fact that the Obj class is encapsulated ? Yes, nested classes have an implicit reference to their parent object, which doesn't exist in your case. My goal is to be able to write things like this: void main() { Info x1 = MyInfos.one, x2 = MyInfo.two, x3; assert(x3 is null); x3 = x1; assert(x3 is x1); assert(x3 is MyInfo.one); // Use static immutable instance references as case arg in switch switch(x1) { case MyInfo.one: ...; } } It looks like your don't actually need `Obj` to be a real nested class. Try declaring it as `static Obj : Info { }`. This should work if `Obj`'s methods don't need access to `MyInfo`'s non-static members.
Re: Using shorthand *= leads to unexpected result?
On Sunday, 15 May 2016 at 13:01:45 UTC, Michael wrote: It may be that I'm doing something wrong here, but after updating DMD to the latest version, my simulations started producing some very odd results and I think I've pinpointed it to a sign inversion that I was making. Here is some code from dpaste to demonstrate the behaviour I get vs. the behaviour I expected: https://dpaste.dzfl.pl/9bd7aea75fb2 Any ideas? Am I getting something wrong or is this some sort of regression with the latest DMD? It's a regression introduced here: https://github.com/dlang/dmd/pull/5534 I've filed a bug report: https://issues.dlang.org/show_bug.cgi?id=16027
Re: Compiler silently ignores some method overloads
On Tuesday, 10 May 2016 at 22:17:00 UTC, pineapple wrote: On Tuesday, 10 May 2016 at 09:57:11 UTC, pineapple wrote: On Monday, 9 May 2016 at 18:56:15 UTC, Peter Häggman wrote: No problem here (tested with everything in a single module). I can't help more. Front end version ? Well, this is the full struct that has those malfeasant overrides: http://pastebin.com/9h2s028J I found the problem - It turns out I was importing that glcolor module at both the top of the file and in a version(unittest) block. I'm not sure _why_ that broke things, but removing the redundant unittest import fixed my problem. This looks like a bug. Please report it at https://issues.dlang.org/ , if possible with a minimal example, thanks!
Re: Setting a list of values
On Monday, 2 May 2016 at 08:46:31 UTC, Ali Çehreli wrote: On 05/01/2016 12:54 PM, Xinok wrote: > On Sunday, 1 May 2016 at 05:42:00 UTC, Ali Çehreli wrote: >> On 04/30/2016 10:05 PM, Joel wrote: >> > This has no effect: >> > _bars.each!(a => { a._plots.fillColor = Color(255, 180, 0); >> }); >> >> This is a common issue especially for people who know lambdas from >> other languages. :) >> >> Your lambda does not do any work. Rather, your lambda returns another >> lambda, which is promptly ignored: > > Those are some discrete semantics. I know D pretty well and even I > didn't see the problem initially. Anybody else think it's worth adding a > warning to the compiler for this specific case? A warning would be great but I don't see how it can cover all cases. A special warning for std.algorithm.each might work but this exact issue appeared on the main thread just a few minutes ago: http://forum.dlang.org/post/qsayoktyffczskrnm...@forum.dlang.org alias funType = void function(int x); funType fun = (x) => { assert(x); }; // cannot return non-void from void function Ali Warning (better: disallowing altogether) about `=>` directly followed by `{` should be enough to cover all cases. To express that you really want a lambda returning a lambda, it can be rewritten either as: (x) => () { assert(x); } or as: (x) => ({ assert(x); }) This check can be done purely by looking at the tokens. Should we someday introduce tuples with `{}`, the check needs to be done after the node starting with `{` has been parsed to distinguish between delegate and tuple literals.
Re: Setting a list of values
On Sunday, 1 May 2016 at 05:42:00 UTC, Ali Çehreli wrote: On 04/30/2016 10:05 PM, Joel wrote: > This has no effect: > _bars.each!(a => { a._plots.fillColor = Color(255, 180, 0); }); This is a common issue especially for people who know lambdas from other languages. :) Your lambda does not do any work. Rather, your lambda returns another lambda, which is promptly ignored: import std.stdio; import std.algorithm; void main() { auto arr = [ 1, 2 ]; arr.each!(a => { writeln(a); }); // returns lambda for each a } The lambda that 'each' takes above is "given a, produce this lambda". . To do the intended work, you need to remove the curly braces (and the semicolon): arr.each!(a => writeln(a)); Or, you could insert empty () to call the returned lambda but that would completely be extra work in this case: arr.each!(a => { writeln(a); }()); Or, remove the arrow: arr.each!((a) { writeln(a); });
Re: vibe.d is blocking threads
On Wednesday, 27 April 2016 at 23:30:10 UTC, Nicholas Wilson wrote: On Wednesday, 27 April 2016 at 13:00:29 UTC, RuZzz wrote: Code: import std.concurrency; import core.thread; //import vibe.http.client; // If uncommented this line, the thread "worker" does not start void worker() { foreach (i; 0 .. 5) { Thread.sleep(500.msecs); writeln(i, " (worker)"); } } void main() { spawn(); foreach (i; 0 .. 5) { Thread.sleep(300.msecs); writeln(i, " (main)"); } writeln("main is done."); } How to launch threads with vibe.d? It doesn't work at both compilers. You don't. vibe.d uses fibers (aka green threads). That doesn't matter. Native threads should work just fine, I'm using them without problems in a vibe.d app. Could it be that your main() function is never called at all? Try to insert a writeln() at the beginning. If so, this could be related to the "VibeDefaultMain" setting, see here: http://vibed.org/docs#custom-main
Re: Shallow copy object when type is know
On Wednesday, 20 April 2016 at 19:58:15 UTC, Tofu Ninja wrote: How does D not have shallow copy? Seems like a very basic functionality... You could implement a `dup()` method. `dup` is already used for shallow copying of arrays, why not reuse it for classes (as a convention)?
Re: multithreading profiling
Which platform/OS, dmd version, and command line are you using?
Re: Problem with circular imports of modules with static ctors an immutable variables
On Friday, 15 April 2016 at 05:35:24 UTC, Uranuz wrote: In my program I have error with circular imports of modules with static ctors. So I decided to move ctors in separate file and import it only from the 1st file. But problem is that in the first file I have immutables that should be initialized in shared static ctor. However doing it from another module's ctor gives compilation error: "Error: cannot modify immutable expression". 1. Is it a bug? Not really. The rules are there to avoid cyclic initialization dependencies, but they are a bit coarse at the moment. 2. Could I solve this problem another way? You could put the immutable globals in the the same module as the shared ctors, and publicly import them in the "real" modules they are intended to be in. You might have to play around with `package` protection if you want to make them invisible in the helper module, too.
Re: how to parse a string into a phobos datatype with additional logic
On Thursday, 7 April 2016 at 08:06:03 UTC, Puming wrote: On Thursday, 7 April 2016 at 07:45:06 UTC, yawniek wrote: what is the way one is supposed to parse e.g. a double of unixtime (as delived by nginx logs) into a SysTime? currently i'm creating a wrapper struct around SysTime with alias this as: https://gist.github.com/yannick/6caf5a5184beea0c24f35d9d4a4c7783 really ugly imho. is there a better way to do this? you mean http://dlang.org/phobos/std_datetime.html#.SysTime.fromUnixTime ? That one only accepts `long`, though, so you'd lose sub-second precision.
Re: parsing fastq files with D
On Thursday, 24 March 2016 at 08:24:15 UTC, eastanon wrote: On Thursday, 24 March 2016 at 06:34:51 UTC, rikki cattermole wrote: As a little fun thing to do I implemented it for you. It won't allocate. Making this perfect for you. With a bit of work you could make Result have buffers for result instead of using the input array allow for the source to be an input range itself. I made this up on dpaste and single quotes were not playing nicely there. So you'll see "\r"[0] as a workaround. Thank you very much. I think you have exposed me to a number of new concepts that I will go through and annotate the code with. I read all input from file as follows. string text = cast(string)std.file.read(inputfile); foreach(record;FastQRecord.parse(text)){ writeln(record); } Does this mean that text is allocated to memory? and is there a better way to read and process the inputfile? Yes, it's read into your processes memory. You can use std.mmfile [1] to make things a bit more efficient. It will, too, read the data into memory, but it will do so in a way (memory mapping) that only loads what is actually accessed (everything in your case), and that allows the operating system to efficiently release and reload parts of it if memory runs low. Unfortunately there is no example in the documentation, but it works like this (untested): import std.mmfile; auto file = new MmFile(inputfile); string text = cast(string) file[]; ... [1] http://dlang.org/phobos/std_mmfile.html
Re: Checking if a port is listening
On Wednesday, 23 March 2016 at 21:37:09 UTC, Lucien wrote: When I remove the Thread.sleep, it doesn't find all adresses. Why ? Socket.select() will wait _at most_ 100 msecs. If a socket gets ready before that timeout, it will return immediately. Therefore, you might not get the full TIMES*100 msecs, and some hosts might not have responded in time.
Re: getOverloads, but also include all the imported members
On Wednesday, 23 March 2016 at 20:54:20 UTC, Yuxuan Shui wrote: Say: module one; void func(int a){} / module two; import one; void func(float a){} Is there a way to get both func() in module two? Add in module two: alias func = one.func;
Re: Checking if a port is listening
On Saturday, 19 March 2016 at 09:55:13 UTC, Lucien wrote: const int MAX = 64; Socket[] sockets = new Socket[MAX]; string ipb = "192.168.0."; for (int i = 1; i < MAX; i++) { Here's the reason for your SEGV: You need to start at 0, because otherwise `sockets[0]` is `null`. When you add that to the SocketSet, it will trigger the segfault. I guess you want to skip the 0 because it represents the subnet address; in that case, you simply mustn't add `sockets[0]` to the set. But then there is another problems: You're using `select()` the wrong way. The point of using select() is that you can check things asynchronously. Your code should be structured like this (pseudo code): auto ss = new SocketSet(); for(i; 1 .. MAX) { auto s = new Socket(...); s.blocking = false; s.connect(...); ss.add(s); } while(ss.count > 0) { auto write_ss = ss.dup; auto status = Socket.select(null /* read */, write_ss /* write */, null /* error */, 500.msecs); // for a connect()ing socket, writeability means connected if(status < 0) writeln("interrupted, retrying"); else if(status == 0) writeln("timeout, retrying"); else { writeln(status, " socket(s) changed state"); for(fd; 0 .. write_ss.maxfd+1) { // check whether this socket has changed if(!write_ss.isSet(fd)) continue; // if yes, remove it from the original SocketSet ss.remove(fd); writeln("successfully connected to 192.168.0.", fd+1); } } }
Re: Whitch can replace std::bind/boost::bind ?
On Friday, 18 March 2016 at 10:50:34 UTC, Dsby wrote: foreach (i ; 0..4) { auto th = new Thread(delegate(){listRun(i);});//this is erro _thread[i]= th; th.start(); } void listRun(int i) { writeln("i = ", i); // the value is not(0,1,2,3), it all is 2. } I want to know how to use it like std::bind. This is a bug in the compiler: https://issues.dlang.org/show_bug.cgi?id=2043
Re: Checking if a port is listening
Looking at an strace of nmap, it seems it opens a bunch of sockets, puts them into non-blocking mode, calls connect on them (which will return EINPROGRESS), and then uses select(2) to wait for them (in a loop, until all have either been accepted or rejected). select(2) accepts a timeout value, so you can determine how long you want to wait. Here's an excerpt: ... socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 50 fcntl(50, F_GETFL) = 0x2 (flags O_RDWR) fcntl(50, F_SETFL, O_RDWR|O_NONBLOCK) = 0 setsockopt(50, SOL_SOCKET, SO_LINGER, {onoff=1, linger=0}, 8) = 0 setsockopt(50, SOL_SOCKET, SO_BINDTODEVICE, [0], 4) = -1 EPERM (Operation not permitted) setsockopt(50, SOL_IP, IP_TTL, [-1], 4) = 0 connect(50, {sa_family=AF_INET, sin_port=htons(32778), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress) socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 51 fcntl(51, F_GETFL) = 0x2 (flags O_RDWR) fcntl(51, F_SETFL, O_RDWR|O_NONBLOCK) = 0 setsockopt(51, SOL_SOCKET, SO_LINGER, {onoff=1, linger=0}, 8) = 0 setsockopt(51, SOL_SOCKET, SO_BINDTODEVICE, [0], 4) = -1 EPERM (Operation not permitted) setsockopt(51, SOL_IP, IP_TTL, [-1], 4) = 0 connect(51, {sa_family=AF_INET, sin_port=htons(1029), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress) socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 52 fcntl(52, F_GETFL) = 0x2 (flags O_RDWR) fcntl(52, F_SETFL, O_RDWR|O_NONBLOCK) = 0 setsockopt(52, SOL_SOCKET, SO_LINGER, {onoff=1, linger=0}, 8) = 0 setsockopt(52, SOL_SOCKET, SO_BINDTODEVICE, [0], 4) = -1 EPERM (Operation not permitted) setsockopt(52, SOL_IP, IP_TTL, [-1], 4) = 0 connect(52, {sa_family=AF_INET, sin_port=htons(2013), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress) select(53, [3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52], [3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52], [3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52], {0, 0}) = 100 (in [3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52], out [3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52], left {0, 0}) ... I'm pretty sure the setsockopt() calls aren't essential.
Re: Checking if a port is listening
On Wednesday, 16 March 2016 at 22:22:15 UTC, Anonymouse wrote: import core.thread; // for .seconds Nitpick: `seconds` is defined in `core.time`; `core.thread` just reexports it. s.setOption(SocketOptionLevel.SOCKET, SNDTIMEO, 10.seconds); s.setOption(SocketOptionLevel.SOCKET, RCVTIMEO, 10.seconds);
Re: size_t index=-1;
On Thursday, 17 March 2016 at 17:09:46 UTC, Steven Schveighoffer wrote: On 3/16/16 6:37 PM, Mathias Lang wrote: On Wednesday, 16 March 2016 at 21:49:05 UTC, Steven Schveighoffer wrote: No, please don't. Assigning a signed value to an unsigned (and vice versa) is very useful, and there is no good reason to break this. I'm not talking about removing it completely. The implicit conversion should only happen when it's safe: ``` int s; if (s >= 0) // VRP saves the day { uint u = s; } ``` ``` uint u; if (u > short.max) throw new Exception("Argument out of range"); // Or `assert` short s = u; ``` Converting unsigned to signed or vice versa (of the same size type) is safe. No information is lost. Strictly speaking yes, but typically, an `int` isn't used as a bit-pattern but as an integer (it's in the name). Such behaviour is very undesirable for integers. It's the comparison between the two which confuses the heck out of people. I think we can solve 80% of the problems by just fixing that. That's probably true, anyway.
Re: Gdmd compiling error
On Monday, 14 March 2016 at 14:46:06 UTC, Orkhan wrote: On Monday, 14 March 2016 at 11:11:28 UTC, Ali Çehreli wrote: On 03/14/2016 02:56 AM, Orkhan wrote: > THe output like that : > root@ubuntu:/opt/xcomm# gdmd > Can't exec "/usr/local/bin/gdc": No such file or directory at Ok, now you need to install gdc: http://gdcproject.org/downloads In short, the project that you are trying to build depends on gdmd, which is a dmd-like interface to gdc, which needs to be installed on your system. Ali Dear Ali , Thanks for your answer and time. I have tried to install and the output was like that. I gues it is already installed in my linux. isnt it ? root@ubuntu:/opt/xcomm# sudo apt-get install gdc Reading package lists... Done Building dependency tree Reading state information... Done gdc is already the newest version. 0 upgraded, 0 newly installed, 0 to remove and 180 not upgraded. root@ubuntu:/opt/xcomm# It is very urgent for me to install the project , I hope will do with your help . Thanks. What does `which gdc` print? If it says something like "which: no gdc in ...", there is a problem with the installation of GDC. Otherwise, you can use the following as a quick workaround: sudo ln -s `which gdc` /usr/local/bin/gdc The proper solution is to find out why gdmd insists on using that non-existing path instead of relying on $PATH lookup, and fix it.
Re: In D, lexically, which are the chars that can follow $, exactly ?
On Sunday, 13 March 2016 at 14:07:31 UTC, Basile B. wrote: '$' is only valid in an indexExpression (https://dlang.org/spec/grammar.html#IndexExpression), so it can only be followed by - ' ' - ']' - operators , usually '-' but also '/', '+', '>>' etc Is that right ? I'd like to relax the lexical rule for C.E static macros which currently is - "^\$\w*[a-zA-Z]$", so for example "$a1A" is valid and "$a1" is not. But it looks like for example "$)" or "$}" wouldn't be ambiguous since it's not possible in D. I don't know what C.E is, but `$` is an expansion of `PrimaryExpression`, which means it can (syntactically) appear anywhere a `PrimaryExpression` is allowed. For example, this compiles: void main() { int[] a; a[0 .. ($)] = 0; }
Re: static if else behavior and is type comparison
On Friday, 11 March 2016 at 12:10:53 UTC, Artur Skawina wrote: On 03/11/16 09:21, Ali Çehreli via Digitalmars-d-learn wrote: You've been bitten by a common usability issue. :) On 03/11/2016 12:02 AM, Fynn Schröder wrote: static if (is(U == ubyte)) { } else if (is(U == ushort)) { You mean 'else static if'. (Not your fault: I (and others) wish the compiler warned about this problem.) It can not warn about this "problem" - because it's a perfectly fine and relatively common construct (a RT check guarded by a CT check). It can first deprecate and later disallow static if(...) ... else if(...) ... It's always possible (and IMO preferable) to write the clearer static if(...) { ... } else { if(...) ... } It already does this for similar error-prone cases, e.g. if(...) ; while(...) ; // Error: use '{ }' for an empty statement, not a ';'
Re: Cannot compile program with DMD built from source
On Wednesday, 9 March 2016 at 16:13:38 UTC, Minas Mina wrote: Hello, I have followed the instructions here (http://wiki.dlang.org/Starting_as_a_Contributor#POSIX) to install DMD, druntime and phobos from source. My platform is Ubuntu 15.10 x64. This is the error I get: http://pastebin.com/kWCv0ymn It seems it tries to link against a wrong Phobos version. Try running dmd with the `-v`, it will output how it invokes the linker (usually starting with "cc"). Maybe you have to adjust your dmd.conf, or create one. I like to place a link to dmd in my ~/bin directory (which is in $PATH), and put a dmd.conf next to it, so it's picked up automatically: [Environment] DFLAGS=-I/home/marc/d/phobos -I/home/marc/d/druntime/import -L-L/home/marc/d/phobos/generated/linux/release/64/ -L--no-warn-search-mismatch -L--export-dynamic
Re: constant expression
On Tuesday, 23 February 2016 at 08:00:24 UTC, Nicholas Wilson wrote: Silly question. Why is this necessary? Due to a problem with the implementation, associative arrays currently can't be initialized statically. We hope it will eventually get fixed, but until then, you have to use module constructors as a workaround.
Re: Simple performance question from a newcomer
On Tuesday, 23 February 2016 at 11:10:40 UTC, ixid wrote: We really need to standard algorithms to be fast and perhaps have separate ones for perfect technical accuracy. While I agree with most of what you're saying, I don't think we should prioritize performance over accuracy or correctness. Especially for numerics people, precision is very important, and it can make a just as bad first impression if we don't get this right. We can however make the note in the documentation (which already talks about performance) a bit more prominent: http://dlang.org/phobos/std_algorithm_iteration.html#sum
Re: Enforcing checks for return code
On Thursday, 18 February 2016 at 07:21:05 UTC, Chris Katko wrote: Hello. I'm almost brand-new to the D language and still absorbing things. I'm wondering if it's possible to fire off a compile-time (or worst case, a run-time) warning or error if a function is called, but the return value is not checked. I'm not trying to enforce whether someone actually deciphers the value's meaning correctly. I just want to enforce that somewhere, a variable or expression is receiving the return value of a particular function. Any ideas? As Jonathan said, there's no such built-in feature, and exception are preferred over return codes. However, you can implement such a check at run time: struct ForceCheck(T) { private T payload; private bool checked = false; @disable this(); @disable this(this); this()(auto ref T payload) { this.payload = payload; } ref T get() { this.checked = true; return payload; } alias get this; void ignore() { this.checked = true; } ~this() { assert(this.checked, "you forgot to check the return value"); } } auto forceCheck(T)(auto ref T value) { return ForceCheck!T(value); } auto foo() { return forceCheck(42); } void main() { { auto a = foo(); if(a != 42) { } // stored values } { if(foo() != 42) { } // direct access } { foo().ignore(); // explicitly ignore return value } { auto b = foo(); // this one asserts foo(); // as does this one } } I guess it's reasonably performant; it could be optimized further by only adding the `checked` member if assertions are enabled (using `version(assert)`).
Re: Why is there no combination of popFront and front to pop? (aka Python `next`)
On Wednesday, 17 February 2016 at 01:45:24 UTC, Rikki Cattermole wrote: On 17/02/16 1:19 PM, Seb wrote: In any case such a next method would be very easy to implement (see below) and thus I am wondering why it isn't part of phobos? ``` auto next(Range)(ref Range a){ auto b = a.front; a.popFront(); return b; } Thanks for your input! Oh but there is: http://dlang.org/phobos/std_range_primitives.html#.moveFront `moveFront()` doesn't call `popFront()`.
Re: Confusion regarding struct lifecycle
On Tuesday, 16 February 2016 at 04:00:27 UTC, Mike Parker wrote: On Tuesday, 16 February 2016 at 03:39:00 UTC, Matt Elkins wrote: On Tuesday, 16 February 2016 at 03:31:51 UTC, maik klein wrote: In D you can always call Foo.init even with @disable this(), Foo.init can be called implicitly (not just explicitly)? If so, why even have @disable this(), if it offers no guarantees? IMO, this is a bug. It should have to be explicit, just as it is with a single struct instance. There is likely some bug here. In the example, though, the elements _are_ constructed explicitly (except foos[4]). This is legitimate, as the first assignment of an element in a construct counts as construction.
Re: static array of structs clarification questions
On Friday, 12 February 2016 at 21:56:09 UTC, Steven Schveighoffer wrote: That's odd. I think anonymous probably has the answer (they are context pointers), but I'm also surprised they are null, they shouldn't be. In this example, `void foo()` doesn't access any outer variables, so there's no need for a context to be created.
Re: static array of structs clarification questions
On Saturday, 13 February 2016 at 14:53:39 UTC, ZombineDev wrote: On Saturday, 13 February 2016 at 10:22:36 UTC, Marc Schütz wrote: On Friday, 12 February 2016 at 21:56:09 UTC, Steven Schveighoffer wrote: That's odd. I think anonymous probably has the answer (they are context pointers), but I'm also surprised they are null, they shouldn't be. In this example, `void foo()` doesn't access any outer variables, so there's no need for a context to be created. Yes, but the compiler will create a context regardless of this. See also this issue: https://issues.dlang.org/show_bug.cgi?id=15343 It adds a hidden member, but it doesn't actually allocate a context, therefore the member is null: auto foo() @nogc { int j; struct Foo { int i; void info() { i += 5; } } return Foo(); } Replace `i` by `j`, and it no longer compiles, because then it really allocates a context. As for your bug report: I believe the documentation specifies the current behaviour somewhere, but I cannot find it now. Nested structs always have a context pointer, except if they don't have methods (for layout compatibility with C). I think this is necessary to avoid "paradoxa" like the following: int j; struct Foo { int i; void info() { static if(Foo.sizeof == 4) j += 5; else i += 5; } }
Re: Is this a bug in std.typecons.Tuple.slice?
On Tuesday, 9 February 2016 at 09:05:58 UTC, Ola Fosheim Grøstad wrote: IMO one shouldn't be able to take the reference of a tuple, to ensure that it can be kept in registers. No need to restrict the language here, there's nothing stopping a decent compiler from storing tuples (actually _anything_) in registers, in some cases even if references are taken. I'm pretty sure LLVM can handle this.
Re: Is this a bug in std.typecons.Tuple.slice?
On Tuesday, 9 February 2016 at 11:38:14 UTC, Ola Fosheim Grøstad wrote: On Tuesday, 9 February 2016 at 10:54:42 UTC, Marc Schütz wrote: No need to restrict the language here, there's nothing stopping a decent compiler from storing tuples (actually _anything_) in registers, in some cases even if references are taken. I'm pretty sure LLVM can handle this. If you don't restrict the language people will write code that the optimizer will struggle with. So what? Using that argument, you could just as well forbid taking the address of any variable. What's so special about tuples, in contrast to structs and arrays? LLVM can only handle what goes on within a compilation unit, and not if there are stores, because those are visible in other threads. Tuples should be considered immutable constants (think functional programming), not in-memory storage. Again, why? Tuple's can serve as a good approximation to SIMD registers. What relation does that have to the above?
Re: Is this a bug in std.typecons.Tuple.slice?
On Tuesday, 9 February 2016 at 14:28:35 UTC, Ola Fosheim Grøstad wrote: On Tuesday, 9 February 2016 at 13:43:16 UTC, Marc Schütz wrote: So what? Using that argument, you could just as well forbid taking the address of any variable. What's so special about tuples, in contrast to structs and arrays? Some key common qualities for a tuple: 1. They are primarily used for multiple return values from functions. As you said, primarily. There's no reason not to use them for something else. 2. Tuples use structural typing, not nominal typing. This has no relevance for the question at hand. 3. They are identity-less. If you can take reference and compare, they no longer are identity-less. Like value types in general, nothing special about tuples here. Tuples should be considered immutable constants (think functional programming), not in-memory storage. Again, why? Because that is how a tuple is commonly defined, for performance and semantic reasons. I believe it's more because the concept is more frequently used in functional programming languages, for which immutability is not surprising. Other languages do have mutable tuples, e.g. Swift and C++11 (std::tuple). Tuple's can serve as a good approximation to SIMD registers. What relation does that have to the above? You don't want to spill out SIMD registers to the stack if you can avoid it. You want to do the changes within the CPU pipeline, i.e. using copies (and register renaming). As said above, wanting to avoid spilling is not a reason to disallow spilling. Besides, fixed-size arrays seem more similar to SIMD registers, and they don't have the restrictions you tuples to have.
Re: Bug or intended?
The specification doesn't list (non-static) members a valid template alias parameters: http://dlang.org/spec/template.html#TemplateAliasParameter
Re: Conflicting UDA
On Saturday, 6 February 2016 at 13:36:32 UTC, Márcio Martins wrote: I came across an issue with UDAs and was wondering if there really is no way or if I just missed something... Basically, my library has an @ignore UDA, which conflicts with vibe.d's vibe.data.serialization. If both mine and vibe's module are imported, DMD will fail with a very non-descriptive error message, seen below... The obvious solution would be to prefix my UDAs, but then I suppose every library writer would have to abide by this convention, which in practice won't happen, and would bring us back to the C-style redundant symbol names all over. It's unpleasant to have to disambiguate even when not necessary... I suppose I could also do @mylibattr("ignore") instead, but this is also hideous and overly verbose... I tried @mylib.ignore, which would not be too bad, if necessary only to disambiguate, but it seems like the parser doesn't understand it. `@(mylib.ignore)` should work. You could open an enhancement request to enable the paren-less syntax.
Re: Overloading free functions & run-time dispatch based on parameter types
On Friday, 5 February 2016 at 19:48:45 UTC, Robert M. Münch wrote: I thought about it too, but I need it to work with more then one parameter, so I tried this which doesn't work: Value nativePlus(Value a, Value b){ // @@ not working, runtime exception castSwitch!( (IntV a) { castSwitch!( (IntV b) {return new IntV(a.num + b.num);} )(b); }, (StringV a) {return new StringV("string plus");}, )(a); // to keep compiler happy when using castSwitch (has no return statement) return new UnsetV(); } I don't see why this wouldn't work, if you've in fact covered all combinations. One thing that tripped my up was a null references - these are never castable to anything, not even Object. If not all combinations are valid, you can add a lambda that accept Value (or even Object), which is called as a "default" branch. and ended with this, which works and is straight forward but maybe not that elegant: Value nativePlus(Value a, Value b){ if(cast(IntV) a && cast(IntV) b) return new IntV((cast(IntV)a).num + (cast(IntV)b).num); if(cast(StringV) a && cast(StringV) b) return new StringV((cast(StringV)a).str ~ (cast(StringV)b).str); // if no case was hit (could throw) return new UnsetV(); } Can this be written simpler or more elegant? It's similar to how castSwitch is implemented, though the double casts are inefficient. You could use: if(auto inta = cast(IntV) a) { if(auto intb = cast(IntV) b) { return new IntV(inta.num + intb.num); } } (Again, this can be automated.) I read this here: https://github.com/D-Programming-Language/phobos/pull/1266#issuecomment-53507509 (functional pattern matching) but it seems it won't be implemented... at the end of the day what I simulate are poor-mans-multimethods As I read the discussion, it was just decided to defer the more complex version of castSwitch for later, but it wasn't rejected.
Re: Overloading free functions & run-time dispatch based on parameter types
Does the following help? import std.algorithm.comparison : castSwitch; import std.stdio; class A { } class B : A { } class C : A { } auto foo_impl(B b) { writeln("called foo(B)"); } auto foo_impl(C c) { writeln("called foo(C)"); } auto foo(A a) { return a.castSwitch!( (B b) => foo_impl(b), (C c) => foo_impl(c), ); } void main() { B b = new B(); A a = b; foo(a); // called foo(B) } With a bit of template magic, you can make it DRY, e.g. alias foo = buildSwitch!foo_impl;
Re: print function
On Friday, 5 February 2016 at 07:04:27 UTC, cy wrote: Mind if I elaborate on this a bit? If that is unrolled, I understand it will unroll into several calls to write, as in print("1","2","3") => write("1"," ");write("2"," ");write("3","\n"); Up to here, yes. And presumably, write() unrolls its arguments too. Each string argument to write() unrolls to a put(). And put("abc") unrolls into put("a");put("b");put("c"), each of which that call the C routine fwrite with a length 1. No, (explicit) unrolling with foreach could only happen if there's either a variadic argument list, or if "abc" were a template argument. (In the latter case you'd need more than a simple foreach.) Of course, I don't know whether put() call fwrite() for every single character (these are written with single quotes, btw), but that wouldn't be unrolling strictu sensu.
Re: Proper Use of Assert and Enforce
On Friday, 5 February 2016 at 08:45:00 UTC, Minas Mina wrote: Use assertions when a variable's value should not depend on external factors. For example, let's say you want to write a square root function. The input must be >= 0, and because this depends on external factors (e.g. user input), you must check it with `enforce()`. Or alternatively, you could place the responsibility of ensuring that precondition on the caller, in which case you'd use assert(). The output of the function must should always be >= 0 as well, but this does not depend on any external factor, so use assert for it (a negative square root is a program bug). auto sqrt(float val) { enfore(val >= 0f); float result = ... assert(result >= 0f); return result; } For assert()s about values coming from the caller or returned to it, you can use contracts, to make it clear that you're not only checking an internal invariant of your function: auto sqrt(float val) in { assert(val >= 0); } out(result) { if(val == 0) assert(result == 0); assert(result >= 0); } body { // use assert()s in the body only for implementation // details of your algorithm ... }
Re: std.typecons.Proxy requires a nothrow destructor and toHash?
On Wednesday, 3 February 2016 at 10:16:56 UTC, Saurabh Das wrote: Why doesn't this work? Is it a requirement that a proxied struct must have a nothrow destructor and toHash? It used to work in 2.066.1; bisecting points to this PR: https://github.com/D-Programming-Language/phobos/pull/3043 When bisecting between 2.066 and 2.067, there are other candidates: https://github.com/D-Programming-Language/phobos/pull/3042 https://github.com/D-Programming-Language/dmd/pull/4459 https://github.com/D-Programming-Language/druntime/pull/1188 Unlikely: https://github.com/D-Programming-Language/phobos/pull/3001 https://github.com/D-Programming-Language/phobos/pull/3043 https://github.com/D-Programming-Language/dmd/pull/4452 https://github.com/D-Programming-Language/dmd/pull/4463 Please file a bug report at: https://issues.dlang.org/enter_bug.cgi
Re: Why this code can't take advantage from CTFE?
On Wednesday, 3 February 2016 at 16:07:59 UTC, Messenger wrote: What is a good way to try to force it? Using enum? Then optionally copying the value once to avoid the "manifest constant" copy/paste behaviour, where applicable? template forceCTFE(alias expr) { alias forceCTFE = expr; } auto value = forceCTFE!(some_expression());
Re: Variadic template parameters T... bounding
On Tuesday, 2 February 2016 at 14:55:42 UTC, Daniel Kozak wrote: On Tuesday, 2 February 2016 at 14:47:43 UTC, Marc Schütz wrote: if you mix ints and floats, the common type is deduced correctly: this is a bug for me :). I do not like this. I am ok with (u)byte to int conversion and similar, but mixing float and integral types does not seems to be OK. I see. But it's also consistent with array type deduction elsewhere: auto a = [1, 2.5]; pragma(msg, typeof(a)); // double[] ... and more importantly: class A { } class B : A { } class C : A { } auto a = [new A(), new B()]; pragma(msg, typeof(a)); // A[]
Re: Variadic template parameters T... bounding
On Tuesday, 2 February 2016 at 14:12:54 UTC, Daniel Kozak wrote: On Tuesday, 2 February 2016 at 13:57:54 UTC, Marc Schütz wrote: On Tuesday, 2 February 2016 at 13:52:55 UTC, Marc Schütz wrote: The last call should work IMO, but it doesn't. I believe that's a compiler bug. Filed: https://issues.dlang.org/show_bug.cgi?id=15640 I would say it is not a bug test!A(new B(), new C()); // works which is what I expected The bug is that `T` is not automatically inferred to be `A`. That's not a restriction of type inference in general: if you mix ints and floats, the common type is deduced correctly, just not for classes.
Re: chain(const(array of class)) fails
The constraint that fails is the one with `CommonType`: pragma(msg, CommonType!(const(B), const(C))); // void `CommonType` uses the `?:` operator to derive the common type: writeln(true ? b : c); // Error: incompatible types for ((b) : (c)): 'const(B[])' and 'const(C[])' writeln(true ? b[0] : c[0]); // Error: incompatible types for ((b[0]) : (c[0])): 'const(B)' and 'const(C)' At the moment I can't see a reason why that shouldn't work.
Re: chain(const(array of class)) fails
On Tuesday, 2 February 2016 at 09:51:52 UTC, Marc Schütz wrote: The constraint that fails is the one with `CommonType`: pragma(msg, CommonType!(const(B), const(C))); // void `CommonType` uses the `?:` operator to derive the common type: writeln(true ? b : c); // Error: incompatible types for ((b) : (c)): 'const(B[])' and 'const(C[])' writeln(true ? b[0] : c[0]); // Error: incompatible types for ((b[0]) : (c[0])): 'const(B)' and 'const(C)' At the moment I can't see a reason why that shouldn't work. This change broke it: https://github.com/D-Programming-Language/dmd/pull/125 I filed a bug report: https://issues.dlang.org/show_bug.cgi?id=15638
Re: Variadic template parameters T... bounding
On Tuesday, 2 February 2016 at 13:52:55 UTC, Marc Schütz wrote: The last call should work IMO, but it doesn't. I believe that's a compiler bug. Filed: https://issues.dlang.org/show_bug.cgi?id=15640
Re: Region allocator strage error
On Monday, 1 February 2016 at 12:05:53 UTC, ref2401 wrote: On Sunday, 31 January 2016 at 14:48:34 UTC, ref2401 wrote: I am getting runtime error: core.exception.AssertError@std\experimental\allocator\building_blocks\region.d(235): Assertion failure At least tell me can anyone replicate it? Missing imports for c: import std.experimental.allocator; import std.experimental.allocator.building_blocks; I can't reproduce it on Linux x86_64, neither with latest DMD from git, nor DMD 2.070.0. It's the following assert, maybe it helps finding the cause: https://github.com/D-Programming-Language/phobos/blob/master/std/experimental/allocator/building_blocks/region.d#L235
Re: Digger 2.4 & DMD 2.070.0
On Thursday, 28 January 2016 at 07:45:01 UTC, Robert M. Münch wrote: Just compiled the latest release with digger. Everything works without any problems, but the resulting binary shows the following version: mac-pro:Digger robby$ ./result/bin/dmd --version DMD64 D Compiler v2.069-devel-682687b Copyright (c) 1999-2015 by Digital Mars written by Walter Bright Hmm... I'm about to update the openSUSE package, which builds the archive from [1]. The resulting binary prints a similar version instead of "v2.070.0": DMD64 D Compiler v2.069-devel-605be4c Is the archive wrong, or do I need to do something special to get the right version? By the way, the copyright line still says "2015". [1] https://github.com/D-Programming-Language/dmd/archive/v2.070.0.tar.gz
Re: how to allocate class without gc?
On Tuesday, 26 January 2016 at 13:56:39 UTC, Igor wrote: //ubyte[__traits(classInstanceSize, App)] buffer; auto buffer = core.stdc.stdlib.malloc(__traits(classInstanceSize, App))[0..__traits(classInstanceSize, App)]; works, so it is the ubyte line. Can you please post the full code? From your description, it looks like the stack frame might get invalidated...
Re: alias template parameter
On Friday, 21 June 2013 at 14:08:43 UTC, Sergei Nosov wrote: If I have a function auto apply(alias fun, T...)(T args) { return fun(args); } And then I have int y = 2; apply!(x => y)(1); How in the world does this work? Is the context address known at compile-time? No, but because lambdas are always unique, there will always be a dedicated template instance for every time you do this. The compiler will then hard-wire that instance to make it able to access the context pointer. By the way, you can also pass local variables by alias, in which case the same will happen. I guess it does so by passing the offset of the variable in the current stack frame (unless it's inlined and optimized, of course), but I don't know the details. I guess it's up to the compiler.
Re: First project: questions on how-to, and on language features
On Sunday, 24 January 2016 at 06:07:13 UTC, Alex Vincent wrote: (1) It's not clear how to specify certain parts of a module or library as non-exportable. Is that possible? Is it desirable? (It's not that important, yet, but still...) Yes, definitely. By default symbols in a module are `public`, but you can mark them as `private`. These aren't accesible from other modules: module test; void foo() { }// public, because there's no annotation private bar() { } // private void bar2() { } // public again private: // everything from here on is private void bla() { } void blubb() { } (2) In the unittest code, I have a block that I want to rewrite using assertThrown, but I can't figure out from either the book or the website the correct usage. What's the right way to specify a StringException with a particular message I expect to receive? Here's the relevant documentation: https://dlang.org/phobos/std_exception.html#.assertThrown https://dlang.org/phobos/std_exception.html#.collectExceptionMsg `assertThrown()` doesn't allow to check the message directly, it can only check whether a particular type of exception has been thrown: assertThrown!StringException(throw new StringException("test")); Instead, you can use `collectExceptionMsg()` to check both the message and the exception type: assert( collectExceptionMsg!StringException(throw ...) == "test" ); (4) How should the scope(exit) and scope(failure) guard statements intermix with preconditions and postconditions? Pre- and postconditions are supposed to run before you enter the function, or after you left it, respectively. Therefore, and scope() blocks in the function body would already have completed when the postcondition is entered. OTOH, scope() blocks only run if control flow has passed through them. In a precondition, this hasn't happened yet, and therefore they will not run. If you mean whether you can use scope() blocks in pre- and postconditions, yes, you can. The will then run when you leave the pre- and postcondition. But usually, pre- and postconditions only consist of very little code that's not supposed to do any serious work, so they are less likely to be used there. Or, looking at it from a different angle: A scope() block only runs at the end of the lexical scope / block it appears in. Pre- and postconditions are not part of the function body, or vice versa. Therefore, see above. (5) My append() function has a postcondition that currently depends on debug-only members of the class being set in the precondition. This seems artificial - not the part about setting these variables in the precondition, but having the variables defined on the class to begin with. If they were defined only for the lifetime of the function's execution, starting in the precondition, this would be more natural. Is there a Right Way to define function-only debug variables for use in postconditions? If not, would this be a valid use-case to consider amending the language specification to clarify? I'm not an expert in contract programming, but as I see it, your precondition doesn't actually check anything, you're kinda abusing them as preparation for your postcondition. That's likely not the way it's supposed to be. I see what you're trying to achieve, and I believe it's legitimate to check for... You could either just move the assert()s into the function body just before the end, where you have access to the local variables (but you could easily miss an early return), or put them into a scope(exit) block (but then you could accidentally check it too early). Your best bet here is probably to check it in a unittest, although they are for a slightly different purpose, strictly speaking.
Re: `static` symbol needs to be `immutable` for compile-time access?
On Friday, 22 January 2016 at 10:15:19 UTC, Mike Parker wrote: A static variable is still a runtime variable. It's effectively the same as declaring a variable outside of the function scope at module scope, except that it's visible only in the current scope and the function name gets mangled into the symbol int i; void foo() { static int j; } j is no more a compile-time value than i is. If you want an array of constant values available at compile-time, then you need to declare the array as immutable. To expand on this: As you noted, a `static` local variable is, with regards to its lifetime, effectively global. This means there could be code like the following: int func(string s) { int [] i = [5, 6, 7]; auto result = i[2]; i[2] = 42; return result; } I.e., the array could contain a different value depending on whether the function has already been run before. Functions evaluated at compile time need to be effectively pure, because the order of declarations in D is specified not to matter (modulo bugs). Making the variable immutable, or turning it into a normal local variable (even a mutable one!), guarantees that.
Re: Template specialization
On Friday, 22 January 2016 at 01:33:42 UTC, Darrell Gallion wrote: void foo(A)() if (!is (A == int)) { pragma(msg, "int"); } void foo(A)() if (is (A == int[])) { pragma(msg, "int[]"); } void main() { foo!(int)(); foo!(int[])(); } === source\app.d(15): Error: template app.foo cannot deduce function from argument types !(int)(), candidates are: source\app.d(3):app.foo(A)() if (!is(A == int)) source\app.d(8):app.foo(A)() if (is(A == int[])) source\app.d(16): Error: app.foo called with argument types () matches both: source\app.d(3): app.foo!(int[]).foo() and: source\app.d(8): app.foo!(int[]).foo() Have a look at the first template constraint. It checks whether the template parameter _is not_ `int`, so of course, the first instantiation fails, and the second one is ambiguous.
Re: Template specialization
On Friday, 22 January 2016 at 13:03:52 UTC, Darrell Gallion wrote: On Friday, 22 January 2016 at 11:23:56 UTC, Marc Schütz wrote: On Friday, 22 January 2016 at 01:33:42 UTC, Darrell Gallion wrote: void foo(A)() if (!is (A == int)) { pragma(msg, "int"); } void foo(A)() if (is (A == int[])) { pragma(msg, "int[]"); } void main() { foo!(int)(); foo!(int[])(); } === source\app.d(15): Error: template app.foo cannot deduce function from argument types !(int)(), candidates are: source\app.d(3):app.foo(A)() if (!is(A == int)) source\app.d(8):app.foo(A)() if (is(A == int[])) source\app.d(16): Error: app.foo called with argument types () matches both: source\app.d(3): app.foo!(int[]).foo() and: source\app.d(8): app.foo!(int[]).foo() Have a look at the first template constraint. It checks whether the template parameter _is not_ `int`, so of course, the first instantiation fails, and the second one is ambiguous. I'm aware this doesn't look right or compile. How do I do this? Just remove the `!` in the first template constraint, and it will compile. void foo(int x) { } void foo(int [] x) { } template foo(T)(T x){} void main() { int x; int [] a; foo((x); foo(a); foo("hi"); } You lost me here...
Re: Mixin Template Function Attributes
On Wednesday, 20 January 2016 at 16:37:31 UTC, jmh530 wrote: I'm not sure if this is how the behavior is supposed to be or if it is a bug. I believe, however, that it _is_ a bug that the imported symbols are visible outside the template. Most likely related to the infamous https://issues.dlang.org/show_bug.cgi?id=314
Re: Mixin Template Function Attributes
On Wednesday, 20 January 2016 at 16:37:31 UTC, jmh530 wrote: I'm not sure if this is how the behavior is supposed to be or if it is a bug. It's not a bug. The `@attribute:` syntax applies to all following declarations _inside the current scope_, i.e. until your mixin templates closing `}`.
Re: Static Arrays in Structs/Classes and Dynamic Array Sizes
Here's what I suggest: alias T = int; class VariableLengthClass { private: string someMember; size_t length_; T[0] data_; public: static make(Args...)(size_t length, Args args) { static assert( typeof(this).init.data_.offsetof == __traits(classInstanceSize, typeof(this)), ".data_ must be last member"); import core.memory : GC; import std.conv : emplace; const size = __traits(classInstanceSize, typeof(this)) + length * typeof(this).init.data_[0].sizeof; auto buffer = GC.malloc(size, 0, typeid(typeof(this))); auto result = buffer[0 .. size].emplace!(typeof(this))(args); result.length_ = length; return result; } @property length() const { return length_; } @trusted ref opIndex(size_t index) inout { assert(index < length, "index out of bounds"); return data_.ptr[index]; } size_t opDollar() const { return length_; } @trusted opSlice() inout { return data_.ptr[0 .. length]; } @trusted opSlice(size_t lower, size_t upper) inout { assert(lower >= 0, "negative indices not allowed"); assert(upper >= lower, "upper bound must be >= lower bound"); assert(upper <= length, "upper bound must not be larger than length"); return data_.ptr[lower .. upper]; } } void main() { import std.stdio; auto p = VariableLengthClass.make(20); //p[6 .. $] = 10; // https://issues.dlang.org/show_bug.cgi?id=15582 p[6] = 1; writeln(p[5 .. $]); } Explanation: We can't use the `new` operator, because the classes size is only known at runtime. Instead, we define a static method `make` that takes a length as its first argument, and then the remaining args for the constructor. It allocates memory from the GC and calls `emplace` to construct the object there. The actual data can be accessed using the operator implementations, to provide some encapsulation and memory safety. See the `main()` function for usage examples. Slice assignment (commented out) currently doesn't work due to a compiler bug. Depending on your requirements, other solutions are possible. You could, for example, make the class a template and the array length a template parameter, then have all instances derive from one common base class. Btw, does anyone know whether it's possible to make `emplace` call a private constructor? It would be better to make them private to prevent a user from accidentally using `new`...
Re: How to declare an alias to a function literal type
On Tuesday, 12 January 2016 at 15:41:02 UTC, ParticlePeter wrote: I have a function type and variable and assign a function to it: void function( int i ) myFunc; myFunc = void function( int i ) { myCode; } How would I declare an alias for void function( int i ) such that the case above would work like this: // alias MF = void function( int i ); // not working // alias void function( int i ) MF; // not working MF myFunc; myFunc = MF { myCode }; Please, if possible, also show me where I should have found the answer (D Reference, Alis book, etc. ) This works for me: alias MF = void function(int i); // works fine - what was your error? void main() { import std.stdio; MF myFunc; // you can also use the full `function(int i) { ... }` in the next line myFunc = (i) { writeln("i = ", i); }; myFunc(42); }
Re: How to declare an alias to a function literal type
On Tuesday, 12 January 2016 at 16:55:48 UTC, ParticlePeter wrote: I can rewrite the definition of otherFunc like this: void otherFunc( MF mf ); But I cannot pass an anonymous function to otherFunc like this: otherFunc( MF { myCode; } ); Thats what I want. Any working example? If I understand you correctly (not sure), you would like to write `MF` so that you don't need to specify the parameters in the lambda? That's not possible, because the code inside the lambda needs names for them if it wants to access them, but parameter names are _not_ part of the function type, and therefore the alias doesn't know about them. However, you don't need to specify the full parameter list in the lambda, the names and `ref` are enough: otherFunc( (ref a, ref b, ref c) { /* use a, b, c */ } );
Re: sliced().array compatibility with parallel?
On Sunday, 10 January 2016 at 01:16:43 UTC, Ilya Yaroshenko wrote: On Saturday, 9 January 2016 at 23:20:00 UTC, Jay Norwood wrote: I'm playing around with win32, v2.069.2 dmd and "dip80-ndslice": "~>0.8.8". If I convert the 2D slice with .array(), should that first dimension then be compatible with parallel foreach? [...] Oh... there is no bug. means must be shared =) : shared double[1000] means; I'd say, if `shared` is required, but it compiles without, then it's still a bug.
Re: Strange 'memset' error when using std.range.repeat and std.array.array
On Monday, 4 January 2016 at 12:20:09 UTC, Ur@nuz wrote: On Monday, 4 January 2016 at 12:00:32 UTC, tcak wrote: On Monday, 4 January 2016 at 10:50:17 UTC, Ur@nuz wrote: Sorry, the actual code is: ... lines ~= ' '.repeat.take(newIndentCount).array; ...with character quotes. But it still fails with error described in stack trace in Gcx.bigAlloc() What's your OS? On Linux x64, it works without any error. Yes. It's Ubuntu 14. It works when it's in the separate example, but not working inside my project. The strange thing is that it working in another place inside the same application. So I don't know what to think about it. Maybe this problem occurs only when some amount of memori is being allocated or something.. What is the value of `newIndentCount` when this happens? Could it be it is too big, or negative? If not, you could try reducing your program using dustmite: https://github.com/CyberShadow/DustMite/wiki/Detecting-a-specific-segfault
Re: Size of Compiled Program
On Monday, 4 January 2016 at 13:49:03 UTC, Martin Tschierschke wrote: When I was writing a small speed test - D versus Ruby, calculating the first n prime numbers, I realized, that for small n Ruby may be faster, than compiling and executing with D. But for n = 1,000,000 D outperforms Ruby by app. 10x. Looking at the size of my prime executable, it was around 800 kB with DMD and even with optimization and "gdc -Os" > 1 MB. Why is such a short program resulting in a so big binary? That's probably basic these compilers statically link the runtime (and standard?) libraries by default. Compiling your program with `ldc2 -O3`, I get a binary of 28K, and stripping gets it down to 17K.
Re: immutable promise broken in unions?
On Saturday, 2 January 2016 at 12:08:48 UTC, Meta wrote: On Saturday, 2 January 2016 at 12:07:31 UTC, John Colvin wrote: You are manually breaking immutable by making a union of immutable and mutable data and then writing to the mutable reference. This is roughly equivalent to casting away immutable and then writing to the reference. It's a bug in your code. All references to the same data should be 1) either immutable or const or all the references should be 2) either mutable or const (assuming the data was never immutable). Anything else is dangerous. Surely the compiler should disallow this. It makes it trivial to break the type system otherwise. Right, this is a known bug: https://issues.dlang.org/show_bug.cgi?id=13537
Re: C string to D without memory allocation?
On Monday, 21 December 2015 at 09:46:58 UTC, Shriramana Sharma wrote: Jonathan M Davis via Digitalmars-d-learn wrote: If it isn't, all that means is that the array's capacity will be 0, so it's going to have to reallocate So it's safe to return a string produced by fromStringz without having to worry that the user would append to it? Yes. Then why is it marked @system? Only because one cannot be sure that the input point refers to a valid null-terminated string? Exactly.
Re: Problems with string literals and etc.c.odbc.sql functions
On Saturday, 19 December 2015 at 14:16:36 UTC, anonymous wrote: On 19.12.2015 14:20, Marc Schütz wrote: As this is going to be passed to a C function, it would need to be zero-terminated. `.dup` doesn't do this, he'd have to use `std.string.toStringz` instead. However, that function returns a `immutable(char)*`, which would have to be cast again :-( Ouch, I totally missed that. Looks like we don't have a nice way to do this then? I guess so. Theoretically, we could change `toStringz()` to return `char*`; if its result is unique (we would have to change the implementation to always make a copy), it should then be implicitly convertible to `immutable(char)*`. But that would break code, because it could have been used like `auto s = "xyz".toStringz;`, where `s` would then have a different type. So, there'd need to be an additional function, `toMutableStringz`.