digitalmars.D - Custom Blocks
- Chris Williams (69/69) Aug 09 2010 I'm not sure whether the design of D 2.0 has stabilized as yet, but if n...
- Andrei Alexandrescu (13/15) Aug 09 2010 [snip]
- Robert Jacques (3/19) Aug 09 2010 vote++
- dsimcha (17/32) Aug 09 2010 So this would basically allow the creation of custom flow control constr...
- Andrej Mitrovic (4/39) Aug 10 2010 Wow! That looks sweet. I Imagine this could be put to good use inside
- Kagamin (2/12) Aug 09 2010 I don't think, doOnce will work. Though, it's a useful idiom.
- Stanislav Blinov (20/37) Aug 10 2010 Maybe this one would:
- Jacob Carlborg (11/27) Aug 10 2010 This would be awesome. I think Ruby and Scala have one of the best
- Michel Fortin (15/24) Aug 10 2010 But is this ugly hack (as you call it) really better than the "normal wa...
- Mafi (13/29) Aug 10 2010 Hi,
- Robert Jacques (8/44) Aug 10 2010 You're not being impolite, this is exactly what Andrei is looking for an...
- Lutger (4/26) Aug 10 2010 Nevertheless, it would be fantastic!
- Jason House (3/25) Aug 10 2010 vote++
- Chris Williams (15/22) Aug 10 2010 the
- aarti_pl (17/33) Aug 10 2010 I think it will be great to have it in language!
- Chris Williams (44/53) Aug 10 2010 the
- Lutger (10/14) Aug 10 2010 ruby blocks have a special syntax for block parameters and foreach in D ...
- Nick Sabalausky (6/21) Aug 10 2010 That's a very good point.
- Chris Williams (30/36) Aug 11 2010 should be
- cemiller (22/38) Aug 10 2010 I think this way will be better:
- Nick Sabalausky (8/23) Aug 10 2010 I was thinking something like this:
- Robert Jacques (4/29) Aug 10 2010 Mixing function args with delegate args makes me think of foreach:
- Tomek =?UTF-8?B?U293acWEc2tp?= (8/22) Aug 11 2010 All great, but if there's no remedy for the return WTF, I'd leave this (...
- Robert Jacques (5/28) Aug 11 2010 Fun does. This is the same as function/delegate literals today.
- KennyTM~ (19/52) Aug 12 2010 This is an unacceptable buggy edge case. Consider the already-working co...
- Robert Jacques (6/61) Aug 12 2010 Code that exploits a bug in the implementation isn't "working" in any
- KennyTM~ (11/77) Aug 12 2010 void locate_three_or_five(int[] arr) {
- KennyTM~ (8/88) Aug 12 2010 This could be resolved by just disallowing local return in this syntax.
- Robert Jacques (11/93) Aug 13 2010 I was going to say that the break statement only works with for loops,
I'm not sure whether the design of D 2.0 has stabilized as yet, but if not, I would like to suggest the ability to create custom block types. For example, say that I have an object that I'm using in a multithreaded application. In general, I would do something like: synchronized (myObject) { ...fiddle with it } But, now I want to change myObject into being guarded by a read-write mutex. By best option will be something like: { myObject.readLock(); scope (exit) myObject.readUnlock(); ...check contents } { myObject.writeLock(); scope (exit) myObject.writeUnlock(); ...fiddle with it } I'd much rather be able to say: readLock (myObject) { ...check contents } writeLock (myObject) { ...fiddle with it } It should be simple enough to add such functionality to D as it's little different from templating. I'd tenatively propose a syntax like the following, where the $ symbol is replaced with the contents of the block: interface IRWLock { void readLock(); void readUnlock(); void writeLock(); void writeUnlock(); } block_template readLock(IRWLock o) { o.readLock(); scope (exit) o.readUnlock(); $ } block_template writeLock(IRWLock o) { o.writeLock(); scope (exit) o.writeUnlock(); $ } With local, hidden variables you would also be able to do something like: block_template doOnce() { static bool hasRun = false; if (!hasRun) { hasRun = true; $ } } int main() { while (true) { ...do stuff debug { doOnce { writefln("Value %s", foo); } } ...more stuff debug { doOnce { writefln("Value %s", bar); } } } }
Aug 09 2010
Chris Williams wrote:I'm not sure whether the design of D 2.0 has stabilized as yet, but if not, I would like to suggest the ability to create custom block types.[snip] FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body }); As far as Walter and I could tell, there are no syntactical issues created by such a lowering. But we've been wrong about that in the past (me 10x more often than him). Andrei
Aug 09 2010
On Mon, 09 Aug 2010 23:21:25 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Chris Williams wrote:vote++I'm not sure whether the design of D 2.0 has stabilized as yet, but if not, I would like to suggest the ability to create custom block types.[snip] FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body }); As far as Walter and I could tell, there are no syntactical issues created by such a lowering. But we've been wrong about that in the past (me 10x more often than him). Andrei
Aug 09 2010
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleChris Williams wrote:So this would basically allow the creation of custom flow control constructs at least to a limited extent? For example: void unless(T)(T condition, void delegate() executeThis) { if(!condition) executeThis(); } void until(T)(T condition, void delegate() executeThis) { while(!condition) executeThis(); } void main() { until(someoneKnowsWhetherPequalsNP() ) { writeln("Who knows?"); } unless(P == NP) { writeln("P != NP"); } }I'm not sure whether the design of D 2.0 has stabilized as yet, but if not, I would like to suggest the ability to create custom block types.[snip] FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body }); As far as Walter and I could tell, there are no syntactical issues created by such a lowering. But we've been wrong about that in the past (me 10x more often than him). Andrei
Aug 09 2010
Wow! That looks sweet. I Imagine this could be put to good use inside template constraints.. or so I think. Thumbs up from me. On Tue, Aug 10, 2010 at 6:40 AM, dsimcha <dsimcha yahoo.com> wrote:== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleChris Williams wrote:not,I'm not sure whether the design of D 2.0 has stabilized as yet, but ifSo this would basically allow the creation of custom flow control constructs at least to a limited extent? For example: void unless(T)(T condition, void delegate() executeThis) { if(!condition) executeThis(); } void until(T)(T condition, void delegate() executeThis) { while(!condition) executeThis(); } void main() { until(someoneKnowsWhetherPequalsNP() ) { writeln("Who knows?"); } unless(P == NP) { writeln("P != NP"); } }I would like to suggest the ability to create custom block types.[snip] FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body }); As far as Walter and I could tell, there are no syntactical issues created by such a lowering. But we've been wrong about that in the past (me 10x more often than him). Andrei
Aug 10 2010
Andrei Alexandrescu Wrote:FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body });I don't think, doOnce will work. Though, it's a useful idiom.
Aug 09 2010
10.08.2010 9:19, Kagamin ïèűćò:Andrei Alexandrescu Wrote:Maybe this one would: block_template doOnce(string F = __FILE__, int L = __LINE__)() { static bool hasRun = false; if (!hasRun) { hasRun = true; $ } } or this one (with proposed lowering syntax): void doOnce(string F = __FILE__, int L = __LINE__)(void delegate() dg) { static bool hasRun = false; if (!hasRun) { hasRun = true; dg(); } } -- **FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body });I don't think, doOnce will work. Though, it's a useful idiom. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Filtered-With-Copfilter: Version 0.84beta4 (ProxSMTP 1.8) Copfilter-Filtered-With: SpamAssassin 3.2.5 Copfilter-Virus-Scanned: ClamAV 0.94.2 by Markus Madlener http://www.copfilter.org
Aug 10 2010
On 2010-08-10 05:21, Andrei Alexandrescu wrote:Chris Williams wrote:This would be awesome. I think Ruby and Scala have one of the best syntax for code blocks/delegates. Until then we can use this somewhat ugly hack: fun(a, b, c) in { // body }; For the above to work "fun" should return a struct which implements the opIn method. -- /Jacob CarlborgI'm not sure whether the design of D 2.0 has stabilized as yet, but if not, I would like to suggest the ability to create custom block types.[snip] FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body }); As far as Walter and I could tell, there are no syntactical issues created by such a lowering. But we've been wrong about that in the past (me 10x more often than him). Andrei
Aug 10 2010
On 2010-08-10 06:01:10 -0400, Jacob Carlborg <doob me.com> said:I think Ruby and Scala have one of the best syntax for code blocks/delegates. Until then we can use this somewhat ugly hack: fun(a, b, c) in { // body }; For the above to work "fun" should return a struct which implements the opIn method.But is this ugly hack (as you call it) really better than the "normal way"? fun(a, b, c, { // body }); At least with this one you know what to expect, and fun's code will be much easier to read too because you have no intermediary struct. Ugly hacks should be used only when they improve things substantially, which does not seem to be the case here. If it was part of the language then it'd be less of a hack and probably more usable. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 10 2010
Am 10.08.2010 05:21, schrieb Andrei Alexandrescu:Chris Williams wrote:Hi, I don't want to be inpolite but what if fun returns a delegate which accepts a delegate and fun is overloaded (the delegate parameter is optional): void delegate(void delegate()) fun(); void delegate(void delegate()) fun(void delegate()); ... fun(){...} //does this result in void or void delegate(void delegate()) ... It's the same as with property if they are allowed to call with parens. But this is a very unlikely to happen. I don't even know if delegate are allowed to take delegate as parameters.I'm not sure whether the design of D 2.0 has stabilized as yet, but if not, I would like to suggest the ability to create custom block types.[snip] FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body }); As far as Walter and I could tell, there are no syntactical issues created by such a lowering. But we've been wrong about that in the past (me 10x more often than him). Andrei
Aug 10 2010
On Tue, 10 Aug 2010 06:59:11 -0400, Mafi <mafi example.org> wrote:Am 10.08.2010 05:21, schrieb Andrei Alexandrescu:You're not being impolite, this is exactly what Andrei is looking for and delegates can take delegates as parameters. Although, you can't call delegates without (), so my gut says "fun {...}" would have to resolve to "fun(void delegate())". To use "delegate(void delegate()) fun()" the syntax would be "fun()() {...}". In general, overload ambiguities like these are allowed inside a module, but should be hijack errors when source coming from multiple modules.Chris Williams wrote:Hi, I don't want to be inpolite but what if fun returns a delegate which accepts a delegate and fun is overloaded (the delegate parameter is optional): void delegate(void delegate()) fun(); void delegate(void delegate()) fun(void delegate()); ... fun(){...} //does this result in void or void delegate(void delegate()) ... It's the same as with property if they are allowed to call with parens. But this is a very unlikely to happen. I don't even know if delegate are allowed to take delegate as parameters.I'm not sure whether the design of D 2.0 has stabilized as yet, but if not, I would like to suggest the ability to create custom block types.[snip] FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body }); As far as Walter and I could tell, there are no syntactical issues created by such a lowering. But we've been wrong about that in the past (me 10x more often than him). Andrei
Aug 10 2010
Andrei Alexandrescu wrote:Chris Williams wrote:Nevertheless, it would be fantastic! This is exactly what can enables Ruby code to be so pleasant, though it is not the same construct. And extensions methods of course :)I'm not sure whether the design of D 2.0 has stabilized as yet, but if not, I would like to suggest the ability to create custom block types.[snip] FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body }); As far as Walter and I could tell, there are no syntactical issues created by such a lowering. But we've been wrong about that in the past (me 10x more often than him). Andrei
Aug 10 2010
vote++ It's worth an keyword if it keeps things simple for both users and the compiler. Andrei Alexandrescu Wrote:Chris Williams wrote:I'm not sure whether the design of D 2.0 has stabilized as yet, but if not, I would like to suggest the ability to create custom block types.[snip] FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body }); As far as Walter and I could tell, there are no syntactical issues created by such a lowering. But we've been wrong about that in the past (me 10x more often than him). Andrei
Aug 10 2010
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleFWIW we've been talking a long time ago about a simple lowering - ifthelast argument to a function is a delegate, allow moving thedelegate'sbody outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body });I suppose that any method which works is fine. The advantage with a more preprocessor-like methodology is that it doesn't incur two function calls. Shipping delegates around to functions is nice for self-modifying code, but that's overkill for this sort of functionality. It has a fairly clear use for making complex thread synchronization look prettier, but if you're doing that sort of fancy footwork to begin with, then speed is probably a driving motive (or you're making code that's more complex than it needs to be. ;) ) But again, like I said, any method which works is probably fine. And possibly DMD is good at inlining such things. -Chris
Aug 10 2010
W dniu 2010-08-10 05:21, Andrei Alexandrescu pisze:Chris Williams wrote:I think it will be great to have it in language! But what about: unittest { } It could be just function call with delegate as a last parameter, but in the context e.g. of class body it is not possible to call functions... If there would be kind of static function call (in the context of class body) it would be easy to add e.g. to D runtime following signatures: unittest(void delegate() test); unittest(string name, void delegate() test); unittest(string name, string group, void delegate() test); ... or maybe function definition with anonymous, immutable last parameter? Just a few thoughts... BR Marcin Kuszczak (aarti_pl)I'm not sure whether the design of D 2.0 has stabilized as yet, but if not, I would like to suggest the ability to create custom block types.[snip] FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body }); As far as Walter and I could tell, there are no syntactical issues created by such a lowering. But we've been wrong about that in the past (me 10x more often than him). Andrei
Aug 10 2010
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s articleFWIW we've been talking a long time ago about a simple lowering - ifthelast argument to a function is a delegate, allow moving thedelegate'sbody outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body }); As far as Walter and I could tell, there are no syntactical issues created by such a lowering.Thinking about this a bit more, essentially we are doing the same thing as foreach<->opApply, where we have a function receiving a delegate that will probably be optimized into a local block. There are some key differences, though. Firstly, I can do this with your method: void doOnce(int delegate() dg) { static bool done = false; if (!done) { done = true; writefln("%s", dg()); } } int main() { for (uint i = 0; i < 5; i++) { doOnce() { return 42; } ...do stuff } return 0; } Having a return value sitting in the middle of what looks like a local block is a bit ugly. It seems like main() will end at "return 42". For creating something that operates like a code block, we would never want a return. That brings us to the second problem. Our last parameter for a custom block is always "void delegate()" and our return is always void. There's nothing to be gained by forcing the coder to write both. I'll grant that the delegate passing solution is overall prettier than the macro version I suggested in the original post. The ability to create a doOnce block that can be re-used in multiple places is lost by using delegates since the static variable will only exist in one place, but I can't say that the ability is a major one. The syntax I presented can be easily updated to match your version by the creation of an assumed void delegate() called $. block readLock(IRWLock o) { o.readLock(); scope (exit) o.readUnlock(); $(); }
Aug 10 2010
Chris Williams wrote: ...That brings us to the second problem. Our last parameter for a custom block is always "void delegate()" and our return is always void. There's nothing to be gained by forcing the coder to write both.ruby blocks have a special syntax for block parameters and foreach in D has it too. It could look like: void until(int limit, void delegate(int) dg); until(5 ; i) { ... } But maybe that is too weird, I dunno. Parameters are reversed here too wrt foreach.
Aug 10 2010
"Chris Williams" <aahz seanet.com> wrote in message news:i3s1a9$2vbc$1 digitalmars.com...int main() { for (uint i = 0; i < 5; i++) { doOnce() { return 42; } ...do stuff } return 0; } Having a return value sitting in the middle of what looks like a local block is a bit ugly. It seems like main() will end at "return 42". For creating something that operates like a code block, we would never want a return.That's a very good point.That brings us to the second problem. Our last parameter for a custom block is always "void delegate()" and our return is always void.Currently, all blocks are void, but I'm not sure that limitation should be preserved for custom blocks. Example: auto result = collection.reduce(a, b) { return a + b; };
Aug 10 2010
== Quote from Nick Sabalausky (a a.a)'s article"Chris Williams" <aahz seanet.com> wrote in messagecustomThat brings us to the second problem. Our last parameter for ashould beblock is always "void delegate()" and our return is always void.Currently, all blocks are void, but I'm not sure that limitationpreserved for custom blocks. Example: auto result = collection.reduce(a, b) { return a + b; };I considered whether there might be some value in having a block that returns a value and couldn't think of anything that wasn't better done by a true function. A one-use callback for something like QSort or whatever, makes sense though, I'd agree. But, if implemented, I'd wonder if a secondary keyword wouldn't be better like "break" instead of "return", so that there was no confusion of what scope was being referred to -- and so that one -could- actually return from the higher scope, like a regular local block. void doStuff() { lock(o) { if (o.x > 10) { break; // Leaves lock() } else { return; // Leaves doStuff() } } int res = collection.reduce(a, b) { if (a > 0 && b > 0) { break a + b; // Leaves reduce() } else { return; // Leaves doStuff() } } } That is sort of ugly, though.
Aug 11 2010
On Mon, 09 Aug 2010 20:21:25 -0700, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Chris Williams wrote:I think this way will be better: fun(a, b, c) { body } | V fun(a, b, c, { body }); so that you can pass parameters to fun itself. If you want parameters to the delegate, fun can just take ref parameters. Full example with definition: // definition: void fun(int a, int b, ref int c, void delegate() callback) { if(a == b) { c = 2; callback(); } else { c = 1; callback(); } } // call: int var = 0; fun(9, 9, var) { assert(var == 2); } this could be taken another step; if variable declarations could be allowed in a function call, it can be more localized: fun(9, 9, int var) { assert(var == 2); }I'm not sure whether the design of D 2.0 has stabilized as yet, but if not, I would like to suggest the ability to create custom block types.[snip] FWIW we've been talking a long time ago about a simple lowering - if the last argument to a function is a delegate, allow moving the delegate's body outside of the function: fun(a, b, c) { body } | V fun((a, b, c) { body }); As far as Walter and I could tell, there are no syntactical issues created by such a lowering. But we've been wrong about that in the past (me 10x more often than him). Andrei
Aug 10 2010
"cemiller" <chris dprogramming.com> wrote in message news:op.vg8kr7h9ycwdcp mapddrule1.ffe.foxeg.com...On Mon, 09 Aug 2010 20:21:25 -0700, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I was thinking something like this: void fun(int x, int y, int z, delegate void(int, int, int) dg) fun(x, y, z, a, b, c) { body } | V fun(x, y, z, (a, b, c) { body });fun(a, b, c) { body } | V fun((a, b, c) { body });I think this way will be better: fun(a, b, c) { body } | V fun(a, b, c, { body });
Aug 10 2010
On Tue, 10 Aug 2010 15:19:25 -0400, Nick Sabalausky <a a.a> wrote:"cemiller" <chris dprogramming.com> wrote in message news:op.vg8kr7h9ycwdcp mapddrule1.ffe.foxeg.com...Mixing function args with delegate args makes me think of foreach: fun(x, y, z, (a, b, c) { body }); <=> fun(a, b, c; x, y, z) { body }On Mon, 09 Aug 2010 20:21:25 -0700, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:I was thinking something like this: void fun(int x, int y, int z, delegate void(int, int, int) dg) fun(x, y, z, a, b, c) { body } | V fun(x, y, z, (a, b, c) { body });fun(a, b, c) { body } | V fun((a, b, c) { body });I think this way will be better: fun(a, b, c) { body } | V fun(a, b, c, { body });
Aug 10 2010
Robert Jacques napisaĆ:All great, but if there's no remedy for the return WTF, I'd leave this (nice) feature in the drawer. void foo() { fun(a, b, c; x, y, z) { return; // who returns? } } TomekI was thinking something like this: void fun(int x, int y, int z, delegate void(int, int, int) dg) fun(x, y, z, a, b, c) { body } | V fun(x, y, z, (a, b, c) { body });Mixing function args with delegate args makes me think of foreach: fun(x, y, z, (a, b, c) { body }); <=> fun(a, b, c; x, y, z) { body }
Aug 11 2010
On Wed, 11 Aug 2010 17:54:35 -0400, Tomek SowiĆski <just ask.me> wrote:Robert Jacques napisaĆ:Fun does. This is the same as function/delegate literals today. Of course, putting a return statement inside a foreach block is probably a buggy edge case right now; sometimes it causes the parent scope to return and sometimes it doesn't compile.All great, but if there's no remedy for the return WTF, I'd leave this (nice) feature in the drawer. void foo() { fun(a, b, c; x, y, z) { return; // who returns? } } TomekI was thinking something like this: void fun(int x, int y, int z, delegate void(int, int, int) dg) fun(x, y, z, a, b, c) { body } | V fun(x, y, z, (a, b, c) { body });Mixing function args with delegate args makes me think of foreach: fun(x, y, z, (a, b, c) { body }); <=> fun(a, b, c; x, y, z) { body }
Aug 11 2010
On Aug 12, 10 10:25, Robert Jacques wrote:On Wed, 11 Aug 2010 17:54:35 -0400, Tomek SowiĆski <just ask.me> wrote:This is an unacceptable buggy edge case. Consider the already-working code int find_three(int[] arr) { foreach (i, x; arr) { if (x == 3) return i; } return -1; } If I replace the foreach with a custom block e.g. int find_three_retro(int[] arr) { foreach_retro (i, x; arr) { if (x == 3) return i; } return -1; } then suddenly the function doesn't work anymore. It's better not to provide a feature inconsistent with other parts of the language.Robert Jacques napisaĆ:Fun does. This is the same as function/delegate literals today. Of course, putting a return statement inside a foreach block is probably a buggy edge case right now; sometimes it causes the parent scope to return and sometimes it doesn't compile.All great, but if there's no remedy for the return WTF, I'd leave this (nice) feature in the drawer. void foo() { fun(a, b, c; x, y, z) { return; // who returns? } } TomekI was thinking something like this: void fun(int x, int y, int z, delegate void(int, int, int) dg) fun(x, y, z, a, b, c) { body } | V fun(x, y, z, (a, b, c) { body });Mixing function args with delegate args makes me think of foreach: fun(x, y, z, (a, b, c) { body }); <=> fun(a, b, c; x, y, z) { body }
Aug 12 2010
On Thu, 12 Aug 2010 07:43:25 -0400, KennyTM~ <kennytm gmail.com> wrote:On Aug 12, 10 10:25, Robert Jacques wrote:Code that exploits a bug in the implementation isn't "working" in any sense of the word. One of the points I was making is that return statements inside a foreach do different things depending on what you're foreaching over. So this feature would be adding consistency, not removing it.On Wed, 11 Aug 2010 17:54:35 -0400, Tomek SowiĆski <just ask.me> wrote:This is an unacceptable buggy edge case. Consider the already-working code int find_three(int[] arr) { foreach (i, x; arr) { if (x == 3) return i; } return -1; } If I replace the foreach with a custom block e.g. int find_three_retro(int[] arr) { foreach_retro (i, x; arr) { if (x == 3) return i; } return -1; } then suddenly the function doesn't work anymore. It's better not to provide a feature inconsistent with other parts of the language.Robert Jacques napisaĆ:Fun does. This is the same as function/delegate literals today. Of course, putting a return statement inside a foreach block is probably a buggy edge case right now; sometimes it causes the parent scope to return and sometimes it doesn't compile.All great, but if there's no remedy for the return WTF, I'd leave this (nice) feature in the drawer. void foo() { fun(a, b, c; x, y, z) { return; // who returns? } } TomekI was thinking something like this: void fun(int x, int y, int z, delegate void(int, int, int) dg) fun(x, y, z, a, b, c) { body } | V fun(x, y, z, (a, b, c) { body });Mixing function args with delegate args makes me think of foreach: fun(x, y, z, (a, b, c) { body }); <=> fun(a, b, c; x, y, z) { body }
Aug 12 2010
On Aug 12, 10 23:42, Robert Jacques wrote:On Thu, 12 Aug 2010 07:43:25 -0400, KennyTM~ <kennytm gmail.com> wrote:void locate_three_or_five(int[] arr) { int res = -1; foreach (i, x; arr) { if_is_one_of(x, [3, 5]) { res = i; break; // now what? } } writeln("found 3 or 5 at ", res); }On Aug 12, 10 10:25, Robert Jacques wrote:Code that exploits a bug in the implementation isn't "working" in any sense of the word. One of the points I was making is that return statements inside a foreach do different things depending on what you're foreaching over. So this feature would be adding consistency, not removing it.On Wed, 11 Aug 2010 17:54:35 -0400, Tomek SowiĆski <just ask.me> wrote:This is an unacceptable buggy edge case. Consider the already-working code int find_three(int[] arr) { foreach (i, x; arr) { if (x == 3) return i; } return -1; } If I replace the foreach with a custom block e.g. int find_three_retro(int[] arr) { foreach_retro (i, x; arr) { if (x == 3) return i; } return -1; } then suddenly the function doesn't work anymore. It's better not to provide a feature inconsistent with other parts of the language.Robert Jacques napisaĆ:Fun does. This is the same as function/delegate literals today. Of course, putting a return statement inside a foreach block is probably a buggy edge case right now; sometimes it causes the parent scope to return and sometimes it doesn't compile.All great, but if there's no remedy for the return WTF, I'd leave this (nice) feature in the drawer. void foo() { fun(a, b, c; x, y, z) { return; // who returns? } } TomekI was thinking something like this: void fun(int x, int y, int z, delegate void(int, int, int) dg) fun(x, y, z, a, b, c) { body } | V fun(x, y, z, (a, b, c) { body });Mixing function args with delegate args makes me think of foreach: fun(x, y, z, (a, b, c) { body }); <=> fun(a, b, c; x, y, z) { body }
Aug 12 2010
On Aug 13, 10 02:56, KennyTM~ wrote:On Aug 12, 10 23:42, Robert Jacques wrote:This could be resolved by just disallowing local return in this syntax. And then make these keyword functions (foreach_retro, if_is_one_of) to be written like opApply. Of course this means things like int foo = reduce( ... ) { ... } is impossible.On Thu, 12 Aug 2010 07:43:25 -0400, KennyTM~ <kennytm gmail.com> wrote:void locate_three_or_five(int[] arr) { int res = -1; foreach (i, x; arr) { if_is_one_of(x, [3, 5]) { res = i; break; // now what? } } writeln("found 3 or 5 at ", res); }On Aug 12, 10 10:25, Robert Jacques wrote:Code that exploits a bug in the implementation isn't "working" in any sense of the word. One of the points I was making is that return statements inside a foreach do different things depending on what you're foreaching over. So this feature would be adding consistency, not removing it.On Wed, 11 Aug 2010 17:54:35 -0400, Tomek SowiĆski <just ask.me> wrote:This is an unacceptable buggy edge case. Consider the already-working code int find_three(int[] arr) { foreach (i, x; arr) { if (x == 3) return i; } return -1; } If I replace the foreach with a custom block e.g. int find_three_retro(int[] arr) { foreach_retro (i, x; arr) { if (x == 3) return i; } return -1; } then suddenly the function doesn't work anymore. It's better not to provide a feature inconsistent with other parts of the language.Robert Jacques napisaĆ:Fun does. This is the same as function/delegate literals today. Of course, putting a return statement inside a foreach block is probably a buggy edge case right now; sometimes it causes the parent scope to return and sometimes it doesn't compile.All great, but if there's no remedy for the return WTF, I'd leave this (nice) feature in the drawer. void foo() { fun(a, b, c; x, y, z) { return; // who returns? } } TomekI was thinking something like this: void fun(int x, int y, int z, delegate void(int, int, int) dg) fun(x, y, z, a, b, c) { body } | V fun(x, y, z, (a, b, c) { body });Mixing function args with delegate args makes me think of foreach: fun(x, y, z, (a, b, c) { body }); <=> fun(a, b, c; x, y, z) { body }
Aug 12 2010
On Thu, 12 Aug 2010 14:56:54 -0400, KennyTM~ <kennytm gmail.com> wrote:On Aug 12, 10 23:42, Robert Jacques wrote:I was going to say that the break statement only works with for loops, while loops and switch statments, not foreach. But the spec says otherwise: "A break exits the enclosing statement. break exits the innermost enclosing while, for, foreach, do, or switch statement, resuming execution at the statement following it." However, please remember that with opApply, the foreach body gets converted into a delegate and then all the standard delegate rules apply. Which is my point: right now these rules regarding foreach seem to have succumb to spec-rot (i.e. they haven't been re-evaluated based on the introduction of opApply.On Thu, 12 Aug 2010 07:43:25 -0400, KennyTM~ <kennytm gmail.com> wrote:void locate_three_or_five(int[] arr) { int res = -1; foreach (i, x; arr) { if_is_one_of(x, [3, 5]) { res = i; break; // now what? } } writeln("found 3 or 5 at ", res); }On Aug 12, 10 10:25, Robert Jacques wrote:Code that exploits a bug in the implementation isn't "working" in any sense of the word. One of the points I was making is that return statements inside a foreach do different things depending on what you're foreaching over. So this feature would be adding consistency, not removing it.On Wed, 11 Aug 2010 17:54:35 -0400, Tomek SowiĆski <just ask.me> wrote:This is an unacceptable buggy edge case. Consider the already-working code int find_three(int[] arr) { foreach (i, x; arr) { if (x == 3) return i; } return -1; } If I replace the foreach with a custom block e.g. int find_three_retro(int[] arr) { foreach_retro (i, x; arr) { if (x == 3) return i; } return -1; } then suddenly the function doesn't work anymore. It's better not to provide a feature inconsistent with other parts of the language.Robert Jacques napisaĆ:Fun does. This is the same as function/delegate literals today. Of course, putting a return statement inside a foreach block is probably a buggy edge case right now; sometimes it causes the parent scope to return and sometimes it doesn't compile.All great, but if there's no remedy for the return WTF, I'd leave this (nice) feature in the drawer. void foo() { fun(a, b, c; x, y, z) { return; // who returns? } } TomekI was thinking something like this: void fun(int x, int y, int z, delegate void(int, int, int) dg) fun(x, y, z, a, b, c) { body } | V fun(x, y, z, (a, b, c) { body });Mixing function args with delegate args makes me think of foreach: fun(x, y, z, (a, b, c) { body }); <=> fun(a, b, c; x, y, z) { body }
Aug 13 2010