Re: Scope of temporaries as function arguments
On Fri, 28 Jun 2013 07:11:05 +0200 Maxim Fomin ma...@maxim-fomin.ru wrote: On Friday, 28 June 2013 at 04:54:56 UTC, Nick Sabalausky wrote: Probably a silly question, but I wanted to double-check... If you have this: struct Foo {...} bar(Foo()); Then regardless of optimizations (aside from any optimizer bugs, of course) the Foo temporary can't go out of scope or have its dtor called until bar finishes executing, right? Struct dtor is always called in the end of the caller (bar in example). This will be OK, but in general case no. Currently object is copied in caller side but destroyed in callee side, and if one of the arguments next to struct is passed by invoking function which throws, callee and respectively dtor will never be called. Interesting. BTW, for anyone else reading, I just searched bugzilla and it looks like the relevant issue is #9704. Kinda ugly as it means refcounted RAII structs can leek under this condition: func(refCountedStruct, thisThrows()); Ouch. Or I guess more accurately, is there any guarantee that the assert in func() below should always pass?: class Foo { int i = 1; //...etc... } struct Bar { Foo foo; ~this() { foo.i = 2; } //...etc... } void func(Bar bar) { //...anything here that *doesn't* change bar.foo.i... assert(bar.foo.i == 1); // Guaranteed to pass? } void main() { Foo f = new Foo(); func(Bar(f)); } Here yes, but in general case if there are other arguments, and one if them passed by lambda invocation which touches f and modifies, then no. Cool, thanks.
Re: Scope of temporaries as function arguments
On Friday, 28 June 2013 at 06:15:26 UTC, Nick Sabalausky wrote: On Fri, 28 Jun 2013 07:11:05 +0200 Maxim Fomin ma...@maxim-fomin.ru wrote: On Friday, 28 June 2013 at 04:54:56 UTC, Nick Sabalausky wrote: Probably a silly question, but I wanted to double-check... If you have this: struct Foo {...} bar(Foo()); Then regardless of optimizations (aside from any optimizer bugs, of course) the Foo temporary can't go out of scope or have its dtor called until bar finishes executing, right? Struct dtor is always called in the end of the caller (bar in example). This will be OK, but in general case no. Currently object is copied in caller side but destroyed in callee side, and if one of the arguments next to struct is passed by invoking function which throws, callee and respectively dtor will never be called. Interesting. BTW, for anyone else reading, I just searched bugzilla and it looks like the relevant issue is #9704. Kinda ugly as it means refcounted RAII structs can leek under this condition: func(refCountedStruct, thisThrows()); Ouch. Just in case it wasn't clear from the original explanation, this is a bug, it *should* be perfectly safe to pass as many temps as you want, and expect the right amount of destructor called in case of a throw.
Re: Opaque structs
On Friday, 28 June 2013 at 02:17:06 UTC, Brad Anderson wrote: On Friday, 28 June 2013 at 01:40:44 UTC, Andrej Mitrovic wrote: Note that if we implement Issue 8728[1], we could even create a better error message via: - struct S { @disable(S is an opaque C type and must only be used as a pointer) this(); @disable(S is an opaque C type and must only be used as a pointer) this(this); } void main() { S* s1; // ok S s2; // user error } - [1] : http://d.puremagic.com/issues/show_bug.cgi?id=8728 +1. Anything that makes error messages clearer is a win in my book and there is precedents for it in @deprecate(msg) which was a clear win. +1 also. I was going to say deprecated does it that way, so should disable, but that's already in the ticket ^^
Get body of a function as string
Is there any way of getting the body of a function as a string? (Obviously only when the source code is available to the compiler)
Re: Scope of temporaries as function arguments
Am Fri, 28 Jun 2013 02:15:19 -0400 schrieb Nick Sabalausky seewebsitetocontac...@semitwist.com: BTW, for anyone else reading, I just searched bugzilla and it looks like the relevant issue is #9704. Reminds me of an issue I reported later: http://d.puremagic.com/issues/show_bug.cgi?id=10409 -- Marco
zip vs. lockstep -- problem when setting values
Consider the following equivalent code using zip and lockstep respectively to iterate over the entries in an array and set their values: auto arr1 = new double[10]; foreach(i, ref x; zip(iota(10), arr1)) { x = i; } writeln(arr1); auto arr2 = new double[10]; foreach(i, ref x; lockstep(iota(10), arr2)) { x = i; } writeln(arr2); The first array will still be full of nan's when it is output, while the second will have values set correctly. Can anyone offer a reasonable explanation why this should be so? It looks like a bug to me, or at best an unreasonable difference in functionality. :-(
Re: Get body of a function as string
John Colvin: Is there any way of getting the body of a function as a string? (Obviously only when the source code is available to the compiler) I think that currently there isn't a simple way to do it. What is your use case? Bye, bearophile
Re: Get body of a function as string
On Friday, 28 June 2013 at 13:18:39 UTC, bearophile wrote: John Colvin: Is there any way of getting the body of a function as a string? (Obviously only when the source code is available to the compiler) I think that currently there isn't a simple way to do it. What is your use case? Bye, bearophile I want to create a function with an identical body but different parameters: e.g. given a function int foo(int a){ return a+1; } automatically create a new function int foo(int a)(){ return a+1; } I'm trying to implement a sort of automatic compile-time currying.
Re: Get body of a function as string
And why don't you call the function from your clone function? Maybe this could help you: http://dpaste.1azy.net/fork/597affd2 I used it to generate my own rvalue functions because of the lack of rvalue references.
sort error
Hello there, Ive got the following code http://dpaste.dzfl.pl/e391a268 This code throws me a Range Exception in Algorithm.d. If I use a lower number of random vectors, like 100, the code terminates. Also, if I delete the template instruction like this : sort(individuals); I also don't get an exception. Does anybody know, why this is the case?
Re: Scope of temporaries as function arguments
On Friday, 28 June 2013 at 08:08:17 UTC, monarch_dodra wrote: Just in case it wasn't clear from the original explanation, this is a bug, it *should* be perfectly safe to pass as many temps as you want, and expect the right amount of destructor called in case of a throw. Original explanation lacks the word bug deliberately because this is not a bug (in a sense that dmd generates wrong code), but a language design problem. How could you do this: struct S { int i = 1; } void foo(S s) { s.i = 2; } void main() { S s; foo(s); } Currently there are two dtors, one which gets S(2) at the end of foo and second at the end of main, which gets S(1). If you move dtor from callee to caller, it would get S(1) object (struct is passed by value), but it doesn't make sense to destruct S(1) where you have S(2). One possible solution is to pass by pointer in low level, which would probably increase magnitude of problems.
Re: Scope of temporaries as function arguments
On Friday, 28 June 2013 at 14:26:04 UTC, Maxim Fomin wrote: On Friday, 28 June 2013 at 08:08:17 UTC, monarch_dodra wrote: Just in case it wasn't clear from the original explanation, this is a bug, it *should* be perfectly safe to pass as many temps as you want, and expect the right amount of destructor called in case of a throw. Original explanation lacks the word bug deliberately because this is not a bug (in a sense that dmd generates wrong code), but a language design problem. How could you do this: struct S { int i = 1; } void foo(S s) { s.i = 2; } void main() { S s; foo(s); } Currently there are two dtors, one which gets S(2) at the end of foo and second at the end of main, which gets S(1). If you move dtor from callee to caller, it would get S(1) object (struct is passed by value), but it doesn't make sense to destruct S(1) where you have S(2). One possible solution is to pass by pointer in low level, which would probably increase magnitude of problems. I don't understand the problem... There *should* be two destroyers... main.s is postblitted into foo.s, and then foo destroys foo.s at the end of its scope... Where is the problem here?
Re: sort error
snow: http://dpaste.dzfl.pl/e391a268 This code throws me a Range Exception in Algorithm.d. If I use a lower number of random vectors, like 100, the code terminates. Also, if I delete the template instruction like this : sort(individuals); I also don't get an exception. Does anybody know, why this is the case? If I replace your vector with a tuple (that defines automatically a lexicographic opCmp) the problem seems to disappear: import std.stdio, std.random, std.array, std.algorithm, std.range, std.typecons; alias Vector3D = Tuple!(double,x, double,y, double,z); alias Individual = Vector3D[]; Vector3D getFitness(in ref Individual individual) pure nothrow { return individual[0]; } bool myComp(in Individual x, in Individual y) { return x.getFitness y.getFitness; } Vector3D[] initializeRandomVectors(in uint count) { Vector3D[] result; foreach (immutable i; 0 .. count) result ~= Vector3D(uniform(0.0, 11.0), uniform(0.0, 11.0), uniform(0.0, 11.0)); return result; } Individual[] initializeRandomIndividuals() { return 1000.iota.map!(_ = 10.initializeRandomVectors).array; } void main() { auto individuals = initializeRandomIndividuals; individuals.sort!(myComp, SwapStrategy.stable); finished.writeln; } Bye, bearophile
Re: Scope of temporaries as function arguments
On Friday, 28 June 2013 at 15:17:12 UTC, monarch_dodra wrote: Should I have expected a different behavior? import std.stdio; int callme() { throw new Exception(); } struct S { int i = 0; this(int i){this.i = i; writeln(constructing: , i);} this(this){writeln(postbliting: , i);} ~this(){writeln(destroying: , i);} } void foo(S s, int i) { s.i = 2; } void main() { S s = S(1); foo(s, callme()); } Destructor for copied object is not called because it is placed in foo(). Before calling foo(), dmd makes a copy of main.s, calls postblit, then puts code to invoke callme() and code to invoke foo(). Since callme() throws, foo() is not called and destructor placed in foo() is also not called. A struct copy escapes destructor. Now, if you try fix this by putting dtor for copy not in foo(), but in main immediately after foo() invocation, you will have a problem because destructor would get S(1) object while it should destroy S(2). Any modification made in foo() is lost. This can be possible fixed by passing copy by reference which would probably create new ABI problems.
counting words
I'm currently making a few tests with std.algorithm, std.range, etc I have a arry of words. Is it possible to count how often each word is contained in the array and then sort the array by the count of the individual words by chaining ranges? (e.g. without using a foreach loop + hashmap)? -- Kind Regards Benjamin Thaut
Re: Scope of temporaries as function arguments
On Friday, 28 June 2013 at 15:33:40 UTC, Maxim Fomin wrote: On Friday, 28 June 2013 at 15:17:12 UTC, monarch_dodra wrote: Should I have expected a different behavior? import std.stdio; int callme() { throw new Exception(); } struct S { int i = 0; this(int i){this.i = i; writeln(constructing: , i);} this(this){writeln(postbliting: , i);} ~this(){writeln(destroying: , i);} } void foo(S s, int i) { s.i = 2; } void main() { S s = S(1); foo(s, callme()); } Destructor for copied object is not called because it is placed in foo(). Before calling foo(), dmd makes a copy of main.s, calls postblit, then puts code to invoke callme() and code to invoke foo(). Since callme() throws, foo() is not called and destructor placed in foo() is also not called. A struct copy escapes destructor. Now, if you try fix this by putting dtor for copy not in foo(), but in main immediately after foo() invocation, you will have a problem because destructor would get S(1) object while it should destroy S(2). Any modification made in foo() is lost. This can be possible fixed by passing copy by reference which would probably create new ABI problems. I thought that was where you were getting to. Couldn't this simply be solved by having the *caller*, destroy the object that was postblitted into foo? Since foo ends up not being called (because of the exception), then I see no problem having the caller destroy the to-be-passed-but-ends-up-not object? Basically, it would mean creating a argument scope into which each arg is constructed. If something throws, then the up to now built args are deconstruted just like with standard scope. If you reach the end of the scope, then call is made, but passing the resposability of destruction to foo. EG, pseudo code: memcpy_all_args; try { foreach arg in args: arg.postblit; exit(failure) arg.destroy; } call_foo; Isn't that how C++ does it? In terms of passing args by value, I see no difference between CC and postblit... And I'm 99% sure C++ doesn't have this problem...
Re: counting words
On Friday, 28 June 2013 at 16:04:35 UTC, Benjamin Thaut wrote: I'm currently making a few tests with std.algorithm, std.range, etc I have a arry of words. Is it possible to count how often each word is contained in the array and then sort the array by the count of the individual words by chaining ranges? (e.g. without using a foreach loop + hashmap)? If you don't mind sorting twice: words.sort() .group() .array() .sort!((a, b)= a[1] b[1]) .map!(a = a[0]) .copy(words); You could also do it with a hashmap to keep the count.
Re: counting words
On Friday, 28 June 2013 at 16:25:25 UTC, Brad Anderson wrote: On Friday, 28 June 2013 at 16:04:35 UTC, Benjamin Thaut wrote: I'm currently making a few tests with std.algorithm, std.range, etc I have a arry of words. Is it possible to count how often each word is contained in the array and then sort the array by the count of the individual words by chaining ranges? (e.g. without using a foreach loop + hashmap)? If you don't mind sorting twice: words.sort() .group() .array() .sort!((a, b)= a[1] b[1]) .map!(a = a[0]) .copy(words); You could also do it with a hashmap to keep the count. Like so: size_t[string] dic; words.map!((w) { ++dic[w.idup]; return w; }) .array // eager (so dic is filled first), sortable .sort!((a, b) { bool less = dic[a] dic[b]; return less || less a b; }) .uniq .copy(words); It's a bit ugly and abuses side effects with the hash map. The order will differ from the other program when words have identical counts.
Re: Scope of temporaries as function arguments
On 06/28/2013 09:01 AM, monarch_dodra wrote: And I'm 99% sure C++ doesn't have this problem... +1%. :) I just finished checking. No, C++ does not have this problem. But there is the following related issue, which every real C++ programmer should know. ;) http://www.boost.org/doc/libs/1_53_0/libs/smart_ptr/shared_ptr.htm#BestPractices Ali P.S. The C++ program that I have just used for testing: #include iostream #include stdexcept using namespace std; int callme() { throw runtime_error(); return 0; } struct S { int i_; S(int i) : i_(i) { cout constructing: i_ at this '\n'; } S(const S that) { cout copying: that.i_ to this '\n'; i_ = that.i_; } ~S() { cout destroying: i_ at this '\n'; } }; void foo(int i, S s) { s.i_ = 2; } int main() { S s = S(1); try { foo(callme(), s); } catch (...) { cout caught\n; } }
Re: counting words
Am 28.06.2013 18:42, schrieb Brad Anderson: On Friday, 28 June 2013 at 16:25:25 UTC, Brad Anderson wrote: On Friday, 28 June 2013 at 16:04:35 UTC, Benjamin Thaut wrote: I'm currently making a few tests with std.algorithm, std.range, etc I have a arry of words. Is it possible to count how often each word is contained in the array and then sort the array by the count of the individual words by chaining ranges? (e.g. without using a foreach loop + hashmap)? If you don't mind sorting twice: words.sort() .group() .array() .sort!((a, b)= a[1] b[1]) .map!(a = a[0]) .copy(words); You could also do it with a hashmap to keep the count. Like so: size_t[string] dic; words.map!((w) { ++dic[w.idup]; return w; }) .array // eager (so dic is filled first), sortable .sort!((a, b) { bool less = dic[a] dic[b]; return less || less a b; }) .uniq .copy(words); It's a bit ugly and abuses side effects with the hash map. The order will differ from the other program when words have identical counts. I figured something like this by now too. Thank you. But I don't quite understand what the copy is for at the end? -- Kind Regards Benjamin Thaut
Re: counting words
On Friday, 28 June 2013 at 16:25:25 UTC, Brad Anderson wrote: On Friday, 28 June 2013 at 16:04:35 UTC, Benjamin Thaut wrote: I'm currently making a few tests with std.algorithm, std.range, etc I have a arry of words. Is it possible to count how often each word is contained in the array and then sort the array by the count of the individual words by chaining ranges? (e.g. without using a foreach loop + hashmap)? If you don't mind sorting twice: words.sort() .group() .array() .sort!((a, b)= a[1] b[1]) .map!(a = a[0]) .copy(words); You could also do it with a hashmap to keep the count. It's just missing the construction scheme for words. I had this: text .splitter(); .reduce!((words, w)=++words[w], words)(int[string]); But alas... reduce's signature is not ctfe-able :( Well, I've had a PR open for this for about 8 months now...
Re: Scope of temporaries as function arguments
On Friday, 28 June 2013 at 16:50:07 UTC, Maxim Fomin wrote: On Friday, 28 June 2013 at 16:01:05 UTC, monarch_dodra wrote: I thought that was where you were getting to. Couldn't this simply be solved by having the *caller*, destroy the object that was postblitted into foo? Since foo ends up not being called (because of the exception), then I see no problem having the caller destroy the to-be-passed-but-ends-up-not object? In case when there is no exception, struct argument is passed and is modified in callee, destructor in caller would have unchanged version (because structs are passed by value). I'm saying the callee destroys whatever is passed to it, all the time, but that means callee needs to actually be called. If caller constructs objects, but then fails to actually call callee, then caller *has* to be responsible for destroying the objects it has built, but not passed to anyone. But this is only if an exception is thrown: No exception: Caller constructs objects into foo. foo is called, foo becomes owner of objects. foo finishes. foo destroys object. Exception: Caller starts construction. Exception is thrown. Caller destroys objects as exception is propagating. All objects are destroyed, exception goes up.
Re: counting words
On Friday, 28 June 2013 at 16:48:08 UTC, Benjamin Thaut wrote: Am 28.06.2013 18:42, schrieb Brad Anderson: On Friday, 28 June 2013 at 16:25:25 UTC, Brad Anderson wrote: On Friday, 28 June 2013 at 16:04:35 UTC, Benjamin Thaut wrote: I'm currently making a few tests with std.algorithm, std.range, etc I have a arry of words. Is it possible to count how often each word is contained in the array and then sort the array by the count of the individual words by chaining ranges? (e.g. without using a foreach loop + hashmap)? If you don't mind sorting twice: words.sort() .group() .array() .sort!((a, b)= a[1] b[1]) .map!(a = a[0]) .copy(words); You could also do it with a hashmap to keep the count. Like so: size_t[string] dic; words.map!((w) { ++dic[w.idup]; return w; }) .array // eager (so dic is filled first), sortable .sort!((a, b) { bool less = dic[a] dic[b]; return less || less a b; }) .uniq .copy(words); It's a bit ugly and abuses side effects with the hash map. The order will differ from the other program when words have identical counts. I figured something like this by now too. Thank you. But I don't quite understand what the copy is for at the end? Just replacing your original word list with the sorted list (which I just realized is wrong because it will leave a bunch of words on the end, oops). You could .array it instead to get a new array or just store the range with auto and consume that where needed with no extra array allocation.
Re: Scope of temporaries as function arguments
On Friday, 28 June 2013 at 16:01:05 UTC, monarch_dodra wrote: I thought that was where you were getting to. Couldn't this simply be solved by having the *caller*, destroy the object that was postblitted into foo? Since foo ends up not being called (because of the exception), then I see no problem having the caller destroy the to-be-passed-but-ends-up-not object? In case when there is no exception, struct argument is passed and is modified in callee, destructor in caller would have unchanged version (because structs are passed by value). Basically, it would mean creating a argument scope into which each arg is constructed. If something throws, then the up to now built args are deconstruted just like with standard scope. If you reach the end of the scope, then call is made, but passing the resposability of destruction to foo. This is another option but suffers from the same problem (in posted examples exception is always thrown, but in reality it need not to).
Re: sort error
On 06/28/2013 07:00 AM, snow wrote: Hello there, Ive got the following code http://dpaste.dzfl.pl/e391a268 This code throws me a Range Exception in Algorithm.d. If I use a lower number of random vectors, like 100, the code terminates. Also, if I delete the template instruction like this : sort(individuals); I also don't get an exception. Yes, what is thrown is an Error. (Error and Exception are different hierarchies under Throwable.) Does anybody know, why this is the case? Your opCmp does not provide a complete ordering of objects: int opCmp(ref const Vector3D vec) { if (this.x vec.x this.y vec.y this.z vec.z) return 1; if (this.x vec.x this.y vec.y this.z vec.z) return -1; return 0; } According to that function, the following two values are neither less than nor greater than the other: // passes: assert(!(Vector3D(1, 2, 3) Vector3D(2, 1, 3)) !(Vector3D(1, 2, 3) Vector3D(2, 1, 3))); Ali
Re: Scope of temporaries as function arguments
On Fri, 28 Jun 2013 12:44:02 -0400, Ali Çehreli acehr...@yahoo.com wrote: I just finished checking. No, C++ does not have this problem. But there is the following related issue, which every real C++ programmer should know. ;) http://www.boost.org/doc/libs/1_53_0/libs/smart_ptr/shared_ptr.htm#BestPractices Thank you, I didn't know this. I can consider myself a real C++ programmer now :) -Steve
Re: Scope of temporaries as function arguments
On Friday, 28 June 2013 at 16:44:03 UTC, Ali Çehreli wrote: Ali P.S. The C++ program that I have just used for testing: Are you sure that the code is exact translation of demonstrated D problem? I see difference in argument passing order and your version uses try-catch block. This code #include iostream #include stdexcept using namespace std; int callme() { throw runtime_error(); return 0; } struct S { int i_; S(int i) : i_(i) { cout constructing: i_ at this '\n'; } S(const S that) { cout copying: that.i_ to this '\n'; i_ = that.i_; } ~S() { cout destroying: i_ at this '\n'; } }; void foo(S s, int i) { s.i_ = 2; } int main() { S s = S(1); foo(s, callme()); } prints for me: constructing: 1 at 0x7fffb93078d0 terminate called after throwing an instance of 'std::runtime_error' what(): Aborted
Re: counting words
Am 28.06.2013 19:01, schrieb Brad Anderson: On Friday, 28 June 2013 at 16:48:08 UTC, Benjamin Thaut wrote: Am 28.06.2013 18:42, schrieb Brad Anderson: On Friday, 28 June 2013 at 16:25:25 UTC, Brad Anderson wrote: On Friday, 28 June 2013 at 16:04:35 UTC, Benjamin Thaut wrote: I'm currently making a few tests with std.algorithm, std.range, etc I have a arry of words. Is it possible to count how often each word is contained in the array and then sort the array by the count of the individual words by chaining ranges? (e.g. without using a foreach loop + hashmap)? If you don't mind sorting twice: words.sort() .group() .array() .sort!((a, b)= a[1] b[1]) .map!(a = a[0]) .copy(words); You could also do it with a hashmap to keep the count. Like so: size_t[string] dic; words.map!((w) { ++dic[w.idup]; return w; }) .array // eager (so dic is filled first), sortable .sort!((a, b) { bool less = dic[a] dic[b]; return less || less a b; }) .uniq .copy(words); It's a bit ugly and abuses side effects with the hash map. The order will differ from the other program when words have identical counts. I figured something like this by now too. Thank you. But I don't quite understand what the copy is for at the end? Just replacing your original word list with the sorted list (which I just realized is wrong because it will leave a bunch of words on the end, oops). You could .array it instead to get a new array or just store the range with auto and consume that where needed with no extra array allocation. Ok, thank you very much -- Kind Regards Benjamin Thaut
Re: Scope of temporaries as function arguments
On 06/28/2013 10:11 AM, Steven Schveighoffer wrote: On Fri, 28 Jun 2013 12:44:02 -0400, Ali Çehreli acehr...@yahoo.com wrote: http://www.boost.org/doc/libs/1_53_0/libs/smart_ptr/shared_ptr.htm#BestPractices Thank you, I didn't know this. Even though this issue is covered in Herb Sutter's Exceptional C++ book, which I had read with great interest, I re-learned it last year when a colleague showed that link to me. I have always considered C++ a language where mere-mortals like myself must read lots and lots of books to advance (or to write any decent code). This thread makes me think that D is following in C++'s steps. I am too normal to figure out these corner cases myself. :-/ Ali
Re: Scope of temporaries as function arguments
On 06/28/2013 10:17 AM, Maxim Fomin wrote: Are you sure that the code is exact translation of demonstrated D problem? Sorry. I omitted two points. I see difference in argument passing order and your version uses try-catch block. 1) C++ does not specify whether the stack gets unwound when the program terminates with an uncaught exception. That's why I caught to ensure that the stack objects would be destroyed. 2) C++ does not specify in what order function arguments are evaluated. I swapped the parameters because I used gcc under Linux, where the parameters are executed from right-to-left. Ali
Re: Scope of temporaries as function arguments
On Friday, 28 June 2013 at 16:57:29 UTC, monarch_dodra wrote: On Friday, 28 June 2013 at 16:50:07 UTC, Maxim Fomin wrote: On Friday, 28 June 2013 at 16:01:05 UTC, monarch_dodra wrote: I thought that was where you were getting to. Couldn't this simply be solved by having the *caller*, destroy the object that was postblitted into foo? Since foo ends up not being called (because of the exception), then I see no problem having the caller destroy the to-be-passed-but-ends-up-not object? In case when there is no exception, struct argument is passed and is modified in callee, destructor in caller would have unchanged version (because structs are passed by value). I'm saying the callee destroys whatever is passed to it, all the time, but that means callee needs to actually be called. If caller constructs objects, but then fails to actually call callee, then caller *has* to be responsible for destroying the objects it has built, but not passed to anyone. But this is only if an exception is thrown: No exception: Caller constructs objects into foo. foo is called, foo becomes owner of objects. foo finishes. foo destroys object. Exception: Caller starts construction. Exception is thrown. Caller destroys objects as exception is propagating. All objects are destroyed, exception goes up. In this scenario caller should distinguish between two situations: exception was thrown during arguments evaluation or was thrown somewhere in foo, when callee can call destructor for passed argument. Otherwise (for example, using current scope(failure) mechanism to tackle the problem), destructor would be called twice on same struct - first time inside callee as usual, second time - in caller which would think that exception was thrown during argument evaluation. I think some tweak required here, but this sound like a good solution.
Re: Scope of temporaries as function arguments
On Friday, 28 June 2013 at 17:30:58 UTC, Ali Çehreli wrote: On 06/28/2013 10:17 AM, Maxim Fomin wrote: Are you sure that the code is exact translation of demonstrated D problem? Sorry. I omitted two points. I see difference in argument passing order and your version uses try-catch block. 1) C++ does not specify whether the stack gets unwound when the program terminates with an uncaught exception. That's why I caught to ensure that the stack objects would be destroyed. Doesn't it? The stack needs to be unwound for the exception to even escape. It's merely the globals that may not be destroyed. (AFAIK) 2) C++ does not specify in what order function arguments are evaluated. I swapped the parameters because I used gcc under Linux, where the parameters are executed from right-to-left. Ali
Re: counting words
monarch_dodra: Well, I've had a PR open for this for about 8 months now... Do you have Phobos commit rights? If the answer is positive then perhaps you can review and commit some Phobos code written by Andrei and he can do the same with yours. Today it seems the major development bottleneck is the review queue and not having enough writing of patches :-) Bye, bearophile
Re: Scope of temporaries as function arguments
On 06/28/2013 10:53 AM, monarch_dodra wrote: On Friday, 28 June 2013 at 17:30:58 UTC, Ali Çehreli wrote: 1) C++ does not specify whether the stack gets unwound when the program terminates with an uncaught exception. That's why I caught to ensure that the stack objects would be destroyed. Doesn't it? The stack needs to be unwound for the exception to even escape. It's merely the globals that may not be destroyed. (AFAIK) The standard does not specify it. On Linux, abort() gets called causing a core dump, which may be more useful than executing the destructors. Ali
[Question] Could a function return a list of arguments to call another function?
Hi, I would like to know if it's possible to pass the return of a function as argument to another function as below: import std.stdio; auto foo(int x, int y){ writeln(x, y); return 3, 4; } void main(){ foo(foo(1,2)); } I would like to print: 1 2 3 4 PS: I tried return a tuple but it doesn't works. Thanks, Matheus.
Re: Opaque structs
On 6/28/13, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: Unfortunately this tends to spawn unreadable error messages: It looks like there's also a blocking bug: http://d.puremagic.com/issues/show_bug.cgi?id=10497 So I'll have to use my new technique instead anyway. :p
Re: counting words
On Friday, 28 June 2013 at 17:59:58 UTC, bearophile wrote: monarch_dodra: Well, I've had a PR open for this for about 8 months now... Do you have Phobos commit rights? If the answer is positive then perhaps you can review and commit some Phobos code written by Andrei and he can do the same with yours. Today it seems the major development bottleneck is the review queue and not having enough writing of patches :-) Bye, bearophile The answer is negative though :(
Re: counting words
On Friday, 28 June 2013 at 18:53:44 UTC, monarch_dodra wrote: On Friday, 28 June 2013 at 17:59:58 UTC, bearophile wrote: monarch_dodra: Well, I've had a PR open for this for about 8 months now... Do you have Phobos commit rights? If the answer is positive then perhaps you can review and commit some Phobos code written by Andrei and he can do the same with yours. Today it seems the major development bottleneck is the review queue and not having enough writing of patches :-) Bye, bearophile The answer is negative though :( 95 merged phobos pull requests (109 total). Long overdue, I'd say. I don't know if there is really a formal process to getting write privileges but if any of the people who decide are reading this I nominate monarch_dodra.
Re: counting words
On Friday, 28 June 2013 at 19:13:28 UTC, Brad Anderson wrote: On Friday, 28 June 2013 at 18:53:44 UTC, monarch_dodra wrote: On Friday, 28 June 2013 at 17:59:58 UTC, bearophile wrote: monarch_dodra: Well, I've had a PR open for this for about 8 months now... Do you have Phobos commit rights? If the answer is positive then perhaps you can review and commit some Phobos code written by Andrei and he can do the same with yours. Today it seems the major development bottleneck is the review queue and not having enough writing of patches :-) Bye, bearophile The answer is negative though :( 95 merged phobos pull requests (109 total). Long overdue, I'd say. I don't know if there is really a formal process to getting write privileges but if any of the people who decide are reading this I nominate monarch_dodra. How did you come to that number? Total amount of pulls *submitted* ? I count 95 *closed* pull requests, but I think only about 50% of them ever made it through? I'm not sure how to check though (apart from counting 1 by 1...) I'm unsure I'd be totally comfortable pulling inside phobos, but it *is* true that the queue is just getting longer and longer. There are some pulls just sitting there, submitted by trusted people (with pull rights), that are validated and reviewed, but are just waiting for a puller to do the deed. There needs to be a few more reviewers, the ones we have are doing a great job, but are overworked. But I wouldn't want to hijack this thread, nor is learn really the place to talk about that.
Re: [Question] Could a function return a list of arguments to call another function?
On 06/28/2013 11:07 AM, MattCoder wrote: Hi, I would like to know if it's possible to pass the return of a function as argument to another function as below: import std.stdio; auto foo(int x, int y){ writeln(x, y); return 3, 4; } void main(){ foo(foo(1,2)); } I would like to print: 1 2 3 4 PS: I tried return a tuple but it doesn't works. Thanks, Matheus. No, functions cannot return tuples. However, they can return std.typecons.Tuple, so you could do this: auto foo(int i, int j) { writeln(i, , j); return tuple(3,4); } void main() { foo(foo(1,2).field); }
Re: [Question] Could a function return a list of arguments to call another function?
On Fri, 28 Jun 2013 20:07:23 +0200, MattCoder mattco...@hotmail.com wrote: Hi, I would like to know if it's possible to pass the return of a function as argument to another function as below: import std.stdio; auto foo(int x, int y){ writeln(x, y); return 3, 4; } void main(){ foo(foo(1,2)); } I would like to print: 1 2 3 4 PS: I tried return a tuple but it doesn't works. Thanks, Matheus. Not directly, no. But this should work: import std.stdio; import std.typecons : tuple; auto foo(int x, int y){ writeln(x, y); return tuple(3, 4); } void main(){ foo(foo(1,2).tupleof); } -- Simen
Re: counting words
On Friday, 28 June 2013 at 19:31:22 UTC, monarch_dodra wrote: On Friday, 28 June 2013 at 19:13:28 UTC, Brad Anderson wrote: 95 merged phobos pull requests (109 total). Long overdue, I'd say. I don't know if there is really a formal process to getting write privileges but if any of the people who decide are reading this I nominate monarch_dodra. How did you come to that number? Total amount of pulls *submitted* ? I count 95 *closed* pull requests, but I think only about 50% of them ever made it through? I'm not sure how to check though (apart from counting 1 by 1...) I'm unsure I'd be totally comfortable pulling inside phobos, but it *is* true that the queue is just getting longer and longer. There are some pulls just sitting there, submitted by trusted people (with pull rights), that are validated and reviewed, but are just waiting for a puller to do the deed. There needs to be a few more reviewers, the ones we have are doing a great job, but are overworked. But I wouldn't want to hijack this thread, nor is learn really the place to talk about that. I counted closed (I assumed most were merged). Github makes it hard to glean data from pull requests. Allow me to share Exhibit B though: https://github.com/D-Programming-Language/phobos/graphs/contributors?from=2012-06-21to=2013-06-21type=c Second most prolific contributor by commits to phobos over the last year. I am nominating you to do extra bureaucratic work though so I'm kind of being an asshole when you think about it. :P
Local templates and alias parameters
void main() { template A(alias a) { enum A = a.stringof; } int b; string s = A!b; // Error: template instance A!(b) cannot use local 'b' as parameter to non-global template A(alias a) } Bug or feature?
Re: [Question] Could a function return a list of arguments to call another function?
On Friday, 28 June 2013 at 19:39:41 UTC, Ellery Newcomer wrote: However, they can return std.typecons.Tuple, so you could do this: auto foo(int i, int j) { writeln(i, , j); return tuple(3,4); } void main() { foo(foo(1,2).field); } Hi Ellery, Thanks for your help, it works nicely.
Re: [Question] Could a function return a list of arguments to call another function?
On Friday, 28 June 2013 at 19:43:37 UTC, Simen Kjaeraas wrote: import std.stdio; import std.typecons : tuple; auto foo(int x, int y){ writeln(x, y); return tuple(3, 4); } void main(){ foo(foo(1,2).tupleof); } Hi Simen, Thanks for your help too, it worked!
Re: Opaque structs
Am Fri, 28 Jun 2013 03:40:31 +0200 schrieb Andrej Mitrovic andrej.mitrov...@gmail.com: struct S { @disable(S is an opaque C type and must only be used as a pointer) this(); @disable(S is an opaque C type and must only be used as a pointer) this(this); } A naive question: Why isn't struct S {} enough? This should be a struct with size 0 so why do we need to disable the constructor and postblit explicitly?
Re: Opaque structs
On 6/28/13, Johannes Pfau nos...@example.com wrote: A naive question: Why isn't struct S {} enough? This should be a struct with size 0 so why do we need to disable the constructor and postblit explicitly? Because the user should never be able to use such a struct by value, in other words a user might mistakenly write code such as: - struct S { } extern(C) S* get(); extern(C) void call(S*); void main() { S* s = getS(); S s2 = *s; // copies 1 byte call(s2); // no telling what will happen on the C side, usually memory corruption + crash } -
Re: Get body of a function as string
On Friday, 28 June 2013 at 13:55:54 UTC, Namespace wrote: And why don't you call the function from your clone function? Because the body of the new function needs to see the parameters as known at compile-time. Maybe this could help you: http://dpaste.1azy.net/fork/597affd2 I used it to generate my own rvalue functions because of the lack of rvalue references. Thanks, that was helpful for a few hints, but it doesn't fix this particular problem.
Re: Get body of a function as string
John Colvin: Because the body of the new function needs to see the parameters as known at compile-time. I think to curry a function all you need to know is its signature. And in std.traits probably there is all the functionality to see all kinds of function arguments, their names, tags, etc. Bye, bearophile
Re: [Question] Could a function return a list of arguments to call another function?
However, they can return std.typecons.Tuple, so you could do this: auto foo(int i, int j) { writeln(i, , j); return tuple(3,4); } void main() { foo(foo(1,2).field); } field is deprecated in favor of expand
Re: Get body of a function as string
On Friday, 28 June 2013 at 20:50:55 UTC, John Colvin wrote: On Friday, 28 June 2013 at 13:55:54 UTC, Namespace wrote: And why don't you call the function from your clone function? Because the body of the new function needs to see the parameters as known at compile-time. Maybe this could help you: http://dpaste.1azy.net/fork/597affd2 I used it to generate my own rvalue functions because of the lack of rvalue references. Thanks, that was helpful for a few hints, but it doesn't fix this particular problem. Oh, hey! I remember participating in writing some of that :) Yeah, with traits, you can get enough info to extract all the information you want about the function to redeclare it any way you want. The only thing you *can't* get is... the body! If you have access to the source code of the function, you could redeclare it as a token string? eg: before: int foo(int a) { return a+1; } after: enum fooString = q{ return a+1; }; int foo(int a){mixin(fooString);} int foo()(int a){mixin(fooString);} Yeah... not a great solution. The only way I could see it happen would be with a compile __trait ? Does the compiler even have the info, or is it completely obliterated after the lex phase? The compiler *should* have the info, since it can pinpoint the coordinates of compilation errors. But I wouldn't know too much.
Re: Local templates and alias parameters
On 06/28/2013 01:04 PM, John Colvin wrote: void main() { template A(alias a) { enum A = a.stringof; } int b; string s = A!b; // Error: template instance A!(b) cannot use local 'b' as parameter to non-global template A(alias a) } Bug or feature? Popular limitation: :) http://d.puremagic.com/issues/show_bug.cgi?id=5710 Ali
Re: Local templates and alias parameters
On Friday, 28 June 2013 at 23:57:30 UTC, Ali Çehreli wrote: On 06/28/2013 01:04 PM, John Colvin wrote: void main() { template A(alias a) { enum A = a.stringof; } int b; string s = A!b; // Error: template instance A!(b) cannot use local 'b' as parameter to non-global template A(alias a) } Bug or feature? Popular limitation: :) http://d.puremagic.com/issues/show_bug.cgi?id=5710 Ali I get that it's a problem when they are in entirely non-overlapping scopes, but when they are in the same local scope it really shouldn't be an error as there's no need for the double context pointer. Indeed, in this case there's no need for any context pointer at all, it's a purely compile-time manipulation. I'm tempted to create a separate bug report for this as it's not quite the same problem.