Minimum PR size
I am interested in contributing to D on GitHub, and was wondering if there is a minimum or preferabe minimum size of a pull request; e.g. I woukd like to work on increasing code coverage, and am wondering if a pull request with one additional line of code, e.g. one assert () in a unittest block, would be considered not worth the time to consider as a PR?
Re: Yield from function?
On Tuesday, 31 January 2017 at 06:32:02 UTC, Ali Çehreli wrote: On 01/30/2017 08:12 PM, Profile Anaysis wrote: [...] That's because the fiber is not in a callable state. (You can check with search.state.) Here is one where the fiber function lives (too) long: import std.stdio, std.concurrency, core.thread; class Search : Fiber { this() { super(&start); } int res = 0; void start() { while (true) { Fiber.yield(); ++res; } } } void main() { auto search = new Search(); foreach (i; 0 .. 5) { search.call(); writeln(search.res); } } Ali Thanks.
Re: Minimum PR size
On 31/01/2017 11:36 PM, Jason Schroeder wrote: I am interested in contributing to D on GitHub, and was wondering if there is a minimum or preferabe minimum size of a pull request; e.g. I woukd like to work on increasing code coverage, and am wondering if a pull request with one additional line of code, e.g. one assert () in a unittest block, would be considered not worth the time to consider as a PR? Don't worry about size, just do what adds value.
Syntax of isExpression
Hey guys, could you help me understand the syntax of the isExpression? I have an example, leaned on documentation https://dlang.org/spec/expression.html#IsExpression case 7. // Code starts here // import std.stdio, std.typecons; alias Tup = Tuple!(int, string, bool); enum myType {a, b, c} struct E(T, myType ET, bool P) { T parts; } void main() { auto r = E!(int, myType.a, true)(); fun(Tup.init); writeln("-"); fun(r); } void fun(T)(T t) { static if (is(T : TX!TL, alias TX, TL...)) { writeln(is(TL[0] == int)); writeln(typeid(TL[1])); writeln(typeid(TL[2])); writeln(is(TL[2] == bool)); } } // Code ends here // The question is: why during testing with Tup the last line gives "true" and with the struct it is false? Especially, while the line before is the same for both cases.
Re: Yield from function?
On Tuesday, 31 January 2017 at 06:32:02 UTC, Ali Çehreli wrote: On 01/30/2017 08:12 PM, Profile Anaysis wrote: import std.stdio, std.concurrency, core.thread; class Search : Fiber { this() { super(&start); } int res = 0; void start() { Fiber.yield(); res = 1; } } void main() { auto search = new Search(); search.call(); writeln(search.res); search.call(); writeln(search.res); search.call(); writeln(search.res); // crashes after 3rd call(first two work fine) } That's because the fiber is not in a callable state. (You can check with search.state.) Here is one where the fiber function lives (too) long: import std.stdio, std.concurrency, core.thread; class Search : Fiber { this() { super(&start); } int res = 0; void start() { while (true) { Fiber.yield(); ++res; } } } void main() { auto search = new Search(); foreach (i; 0 .. 5) { search.call(); writeln(search.res); } } Ali Just curious, how can I use start() recursively? I would like to iterate over a recursive structure and yield for each "solution". I could use a stack to store the values but the whole point of the fiber was to avoid that. void start() { while (true) { Fiber.yield(); ++res; } } Seems I can't create start with a parameter and non-void return type. This seems to make it about useless to use a fiber recursively because no pushing and popping on the stack occur. class Search : Fiber { this() { super(&start); } bool End = false; int res = 0; void start() { while (!End) { int Foo(int x) { Fiber.yield(); if (x < 10) { res = Foo(x++); return res; } else return x; } } } void main() { auto search = new Search(); foreach (i; 0 .. 5) { search.call(); writeln(search.res); } search.End = true; } My goal is simple, to yield a solution at each step in the recursive process. Maybe I can use another fiber using the lambda syntax?
Re: Minimum PR size
On Tuesday, 31 January 2017 at 10:42:41 UTC, rikki cattermole wrote: On 31/01/2017 11:36 PM, Jason Schroeder wrote: I am interested in contributing to D on GitHub, and was wondering if there is a minimum or preferabe minimum size of a pull request; e.g. I woukd like to work on increasing code coverage, and am wondering if a pull request with one additional line of code, e.g. one assert () in a unittest block, would be considered not worth the time to consider as a PR? Don't worry about size, just do what adds value. Thanks for the response, will do.
Re: Yield from function?
On 01/31/2017 03:00 AM, Profile Anaysis wrote: > Just curious, how can I use start() recursively? [...] > Seems I can't create start with a parameter and non-void return type. Options: - The class can maintain state - You can start the fiber with a delegate; int local; double state; () => foo(local, state) Other than the entry point, there is no requirement in what you can do. The following code yields inside a recursive function: import std.stdio, std.concurrency, core.thread; class Search : Fiber { int state; this(int state) { this.state = state; super(&start); } int res = 0; void start() { recursive(state); } void recursive(int s) { if (s == 0) { return; } res = s; Fiber.yield(); recursive(s - 1); } } void main() { auto search = new Search(42); foreach (i; 0 .. 5) { search.call(); writeln(search.res); } } Ali
Re: Syntax of isExpression
On 01/31/2017 02:49 AM, Alex wrote: > auto r = E!(int, myType.a, true)(); > static if (is(T : TX!TL, alias TX, TL...)) > { > writeln(is(TL[0] == int)); > writeln(typeid(TL[1])); > writeln(typeid(TL[2])); > writeln(is(TL[2] == bool)); > } That's because 'true' is not the type 'bool' but a value of bool. You can ask whether the type of a value is bool: writeln(is(typeof(TL[2]) == bool)); But then it fails for the Tuple case because typeof(bool) is not bool in that case. You need to cover all cases if both 'bool' and 'true' mean the same thing for you. Ali
Re: Syntax of isExpression
On Tuesday, 31 January 2017 at 11:40:06 UTC, Ali Çehreli wrote: On 01/31/2017 02:49 AM, Alex wrote: > auto r = E!(int, myType.a, true)(); > static if (is(T : TX!TL, alias TX, TL...)) > { > writeln(is(TL[0] == int)); > writeln(typeid(TL[1])); > writeln(typeid(TL[2])); > writeln(is(TL[2] == bool)); > } That's because 'true' is not the type 'bool' but a value of bool. You can ask whether the type of a value is bool: writeln(is(typeof(TL[2]) == bool)); But then it fails for the Tuple case because typeof(bool) is not bool in that case. You need to cover all cases if both 'bool' and 'true' mean the same thing for you. Ali Ah... Thanks!
Re: Yield from function?
On Tuesday, 31 January 2017 at 11:31:28 UTC, Ali Çehreli wrote: On 01/31/2017 03:00 AM, Profile Anaysis wrote: > [...] [...] > [...] return type. Options: [...] Thanks again!
Re: D package for optimizing/compressing images
On Friday, 27 January 2017 at 11:03:15 UTC, aberba wrote: Are there any dub package for compressing images uploaded through web forms? Cropping/resizing may also come in handy. I want one for a vibe.d project. dlib-webp[1] is almost what I've been looking for. In fact, webp is a complete replacement for jpg, png, gif with an added advantage of smaller file size. [1]http://code.dlang.org/packages/dlib-webp
Re: Yield from function?
On Monday, 30 January 2017 at 11:03:52 UTC, Profile Anaysis wrote: I need to yield from a complex recursive function too allow visualizing what it is doing. e.g., if it is a tree searching algorithm, I'd like to yield for each node so that the current state can be shown visually. I realize that there are several ways to do this but D a yield version without additional threads would be optimal. I don't need concurrency or speed, just simple. Sounds like opApply (external iteration) may well be the way to go. It is a great tool to separate (possibly complex) iteration logic from (possibly complex) instance processing logic. Here is a random recipe: https://www.sociomantic.com/blog/2010/06/opapply-recipe An example: - import std.stdio; class Node { int value; Node left, right; this (int value_) {value = value_;} } struct InOrderViewer { Node root; int opApply (int delegate (Node) process) { void recur (Node cur) { if (cur is null) return; recur (cur.left); process (cur); // use return value here to allow break in foreach recur (cur.right); } recur (root); return 0; } } void main () { auto v1 = new Node (1); auto v2 = new Node (2); auto v3 = new Node (3); auto v4 = new Node (4); auto v5 = new Node (5); v2.left = v1; v2.right = v5; v5.left = v3; v3.right = v4; foreach (node; InOrderViewer (v2)) { writeln (node.value ^^ 2); // 1 4 9 16 25 } } - Ivan Kazmenko.
Associative array literal: length wrong when duplicate keys found
Hi. I wanted to check whether a few variables of the same type are all distinct, in a quick and dirty way. I tried to do it similar to Python's "len(set(value_list)) == len(value_list)" idiom by using an associative array (AA). At this point, I found out that when initializing the AA with a literal, the length is the number of keys given, regardless of whether some of them were the same. A minimized example: - import std.stdio; void main () { auto aa = [1 : 2, 1 : 3]; writeln (aa.length, " ", aa); // 2 [1:3, ] } - See, the length is 2, but iteration over aa yields only one key:value pair. Also, note the comma which is a sign of internal confusion as well. My question is, what's the state of this? Is this a bug? Or should it be forbidden to have such an initializer? Or maybe it is a feature with some actual merit? Ivan Kazmenko.
Re: Partial arrays reclaimed?
On Friday, 27 January 2017 at 23:22:17 UTC, Nick Sabalausky wrote: Suppose an array is being used like a FIFO: --- T[] slice; // Add: slice ~= T(); // Remove: slice = slice[1..$]; --- Assuming of course there's no other references to the memory, as this gets used, does the any of the memory from the removed elements ever get GC'd? As I see it, the line slice = slice[1..$]; effectively ends slice's in-place appending capabilities. So each append after remove will likely reallocate. You have to use assumeSafeAppend to re-enable appending in place. Here [1] is an old thread about the caveats of using built-in arrays as queues and stacks. If not in a hurry, the better option is perhaps to just write the respective wrapper structs which explicitly store indices, instead of using built-in slices and assumeSafeAppend all over the place. Ivan Kazmenko. [1] http://forum.dlang.org/post/yrxspdrpusrrijmfy...@forum.dlang.org
Re: Associative array literal: length wrong when duplicate keys found
On Tuesday, 31 January 2017 at 14:15:58 UTC, Ivan Kazmenko wrote: Hi. I wanted to check whether a few variables of the same type are all distinct, in a quick and dirty way. I tried to do it similar to Python's "len(set(value_list)) == len(value_list)" idiom by using an associative array (AA). At this point, I found out that when initializing the AA with a literal, the length is the number of keys given, regardless of whether some of them were the same. A minimized example: - import std.stdio; void main () { auto aa = [1 : 2, 1 : 3]; writeln (aa.length, " ", aa); // 2 [1:3, ] } - See, the length is 2, but iteration over aa yields only one key:value pair. Also, note the comma which is a sign of internal confusion as well. My question is, what's the state of this? Is this a bug? Or should it be forbidden to have such an initializer? Or maybe it is a feature with some actual merit? Ivan Kazmenko. It's a bug, please report it. The initializer should be statically disallowed. Adding a .dup works around the problem. By the way, you can do sets like this, avoiding storing any dummy values, only keys: struct Set(T) { void[0][T] data; void insert(T x) { data[x] = (void[0]).init; } void remove(T x) { data.remove(x); } bool opBinaryRight(string op : "in")(T e) { return !!(e in data); } // other things like length, etc. } unittest { Set!int s; s.insert(4); assert(4 in s); s.remove(4); assert(4 !in s); }
Re: Associative array literal: length wrong when duplicate keys found
On Tuesday, 31 January 2017 at 17:20:00 UTC, John Colvin wrote: It's a bug, please report it. The initializer should be statically disallowed. Adding a .dup works around the problem. OK. Hmm, but the real use case was a bit more complicated, more like: - int n = 10; foreach (i; 0..n) foreach (j; 0..n) foreach (k; 0..n) ... and maybe a couple more ... if ([i: true, j: true, k: true].length == 3) {...} // i, j, k is a set of distinct values - Here, we don't know i, j and k statically, yet the problem is the same. Anyway, I'll file a bug report. By the way, you can do sets like this, avoiding storing any dummy values, only keys: struct Set(T) { void[0][T] data; void insert(T x) { data[x] = (void[0]).init; } void remove(T x) { data.remove(x); } bool opBinaryRight(string op : "in")(T e) { return !!(e in data); } // other things like length, etc. } unittest { Set!int s; s.insert(4); assert(4 in s); s.remove(4); assert(4 !in s); } Yeah, thanks for the recipe! I usually do bool [key] since it does not add much overhead, but would definitely like the real set (void[0] or otherwise) when performance matters. Ivan Kazmenko.
struct: default construction or lazy initialization.
Unless I'm missing something, it seems that neither of these are actually possible. Consider an object which needs internal state to function. The obvious answer is to create it in the constructor: struct Foo(T) { T* payload; this() { payload = cast(T*)malloc(T.sizeof); } ~this() { free(payload); } void foo() { // do something with payload that fails if not initialized } } But this is not possible in D, because structs can't have default constructors. So one may think, I can use lazy initialization instead: struct Foo(T) { T* _payload; ~this() { if(_payload) free(_payload); } @property T* payload() const { if(!_payload) (cast(Foo!T*)&this).payload = cast(T*)malloc(T.sizeof); return _payload; } void foo() { T* p = payload(); // do something with payload that fails if not initialized } void bar() const { T* p = payload(); // do something with payload that fails if not initialized } } So in C++, the above would be fine. Since payload can never be perceived by the caller as uninitialized, the fact that it "breaks" const is irrelevant. But you can't do this in D. If the object is defined at module scope as shared static immutable, the compiler may put it in a readonly section of the executable which would cause an access violation upon trying to initialize it, and there is no way to prevent this from happening. I'm hoping someone will tell me I'm wrong here, because the only alternative to the above approaches is to add boilerplate to _every_ _single_ _function_ that uses the payload in order to deal with separate cases where it's uninitialized. Is there really no solution for this?
Re: struct: default construction or lazy initialization.
On 01/31/2017 03:15 PM, bitwise wrote: > If the object is defined at module scope as shared static immutable Yes, the situation is different from C++ but it's always possible to call a function (which constructor is one) to make the object. It is indeed possible to initialize immutable objects by pure functions as done inside shared static this() below: import core.stdc.stdlib; struct Foo(T) { T* payload; ~this() { free(payload); } void foo() { // do something with payload that fails if not initialized } } auto makeFoo(T)() { // This could be a static member function, even opCall(). auto p = cast(T*)malloc(T.sizeof); *p = 42; return immutable(Foo!T)(cast(immutable(T)*)p); } shared static immutable(Foo!int) foo; shared static this() { foo = makeFoo!int(); } void main() { assert(*(foo.payload) == 42); } Ali
Re: struct: default construction or lazy initialization.
On Tuesday, 31 January 2017 at 23:52:31 UTC, Ali Çehreli wrote: On 01/31/2017 03:15 PM, bitwise wrote: [...] Thanks for the response, but this doesn't really solve the problem. > If the object is defined at module scope as shared static > immutable It is indeed possible to initialize immutable objects by pure functions as done inside shared static this() below: I didn't mean that I wanted my object shared-static-immutable, but only that a solution would have to account for that possibility. Yes, the situation is different from C++ but it's always possible to call a function (which constructor is one) to make the object. I'm saying that a caller should not have to explicitly initialize an object before use, but that a programmer should not have to add boilerplate to deal with zombie objects all over the place either. A container for example: struct Container(T) { void pushBack(T); // ok: mutable method, can lazily initialize payload. // not ok: container may be immutable Range!(const T) opSlice() const; Iterator!(const T) find(T) const; bool empty() const; size_t count() const; } Container!int c; // = Container!int() -> can't do this. if(c.empty) // can't initialize here either.. c.pushBack(1); Such innocent looking code will fail without boilerplate inserted everywhere. -I can't lazily initialize the container in "empty()". -I can't pre-emptively initialize it in a default constructor. This problem causes the propagation of null checks all over the place. Objects returned from the container will have to have a "zombie" state as well, and check validity at each use. I wouldn't classify this as "a difference", but as a hole. Although I don't remember where, I recently saw a discussion about how "mutable" may possibly be implemented. IIRC, there was no solution stated in that discussion. The only solution that comes to mind would be to somehow relax the constraints of const, and make it possible to prevent a struct from being declared immutable, so that lazy initialization could be done. Recent discussions seem to indicate structs having default ctors is not an option.
Re: struct: default construction or lazy initialization.
C#'s "Dispose" pattern comes to mind here. You don't leak memory, you just leak file handles and graphics resources instead when you forget to explicitly call Dispose().
capture stdout or stderr
is it possible to intercept the STDOUT or STDERR and capture the output into a variable ? some pseudocode to explain what I mean string[] output_buffer; stdout.capture_to(output_buffer); writeln("test 1"); # not printed writeln("test 2"); # not printed stdout.release(output_buffer); writeln("test 3"); # printed writeln(output_buffer); # prints '["test 1","test 2"]'
Re: struct: default construction or lazy initialization.
On Wednesday, 1 February 2017 at 00:43:39 UTC, bitwise wrote: Container!int c; // = Container!int() -> can't do this. Can you live with Container!int c = Container!int.create(); because D supports that and can force the issue with `@disable this();` which causes compilation to fail any place where it isn't explicitly initialized.
GC question
Hi all, I was looking at D as the next language to use in my hobby projects, but the "conservative GC" part in the language spec (http://dlang.org/spec/garbage.html) looks a bit concerning. I'm wondering what are the implications of the fact that current GC is a Boehm-style conservative GC rather than a precise one, I've never worked with a conservative GC before. Are there any disallowed memory operations? Can I break things by not following some unchecked rules etc. ? How often does it leak? Do I need to be careful with some operations to avoid leaks? Is a precise GC in the roadmap? any kind of comments on the GC would be really appreciated. Thanks
Re: Minimum PR size
On 2017-01-31 11:36, Jason Schroeder wrote: I am interested in contributing to D on GitHub, and was wondering if there is a minimum or preferabe minimum size of a pull request; e.g. I woukd like to work on increasing code coverage, and am wondering if a pull request with one additional line of code, e.g. one assert () in a unittest block, would be considered not worth the time to consider as a PR? The smaller PR the better :). There's more of an issue if the PR is too big. But adding one assert to one unit test block in ten different PR's might not be appropriate. -- /Jacob Carlborg