Re: "for" statement issue
On Saturday, 22 October 2016 at 17:11:26 UTC, ag0aep6g wrote: How is it guaranteed that `a` doesn't have side effects? May be a function call, since empty parentheses can be omitted in calls. I missed that case. (Insert grumble about non-UFCS parenthesis omission being allowed). The lambda itself is a value, no? int a() { import std.stdio; writeln("a"); return 1; } void main() { int delegate(int) dg = (a, b => a + b); } OK. Though AIUI from 2.072 a() must return void for the comma expression to compile (then a+b wouldn't compile either).
Re: "for" statement issue
On 22.10.2016 17:53, Nick Treleaven wrote: [1,2,3].fold!{a, b => a + b}.writeln; Probably (a, b => a + b) could be legal. It is. (It means pass a and the lambda b => a + b.)
Re: "for" statement issue
On 10/22/2016 05:53 PM, Nick Treleaven wrote: Probably (a, b => a + b) could be legal. Reasoning: 1. a could be an existing symbol in scope, otherwise it's an undefined identifier error. 2. If a was interpreted as an existing symbol which is followed by the comma operator, the expression (a) wouldn't have side effects so should be a compile error. How is it guaranteed that `a` doesn't have side effects? May be a function call, since empty parentheses can be omitted in calls. 3. The bracketed comma expression would have to return the lambda b=>a+b as a value expression, which cannot compile because there are no arguments supplied for calling the lambda to obtain a value. The lambda itself is a value, no? int a() { import std.stdio; writeln("a"); return 1; } void main() { int delegate(int) dg = (a, b => a + b); }
Re: "for" statement issue
On Friday, 21 October 2016 at 13:42:49 UTC, Adam D. Ruppe wrote: On Friday, 21 October 2016 at 13:33:26 UTC, Stefan Koch wrote: It does create a lambda? Hmm that should not happen. Eh, that's exactly what the language rules say should happen, and it actually does make sense to me... you might even want to use an immediately-called lambda to group several statements together into one expression. int j; for({j=2; int d = 3; } j+d<7; {j++; d++;}) { } I'm more surprised by the fact that `d` is declared inside the first curly braces, but is evidently still in scope outside of it...
Re: "for" statement issue
On Friday, 21 October 2016 at 15:26:12 UTC, mogu wrote: [1,2,3].fold!((a, b) => a + b).writeln; => [1,2,3].fold!{a, b => a + b}.writeln; Probably (a, b => a + b) could be legal. Reasoning: 1. a could be an existing symbol in scope, otherwise it's an undefined identifier error. 2. If a was interpreted as an existing symbol which is followed by the comma operator, the expression (a) wouldn't have side effects so should be a compile error. 3. The bracketed comma expression would have to return the lambda b=>a+b as a value expression, which cannot compile because there are no arguments supplied for calling the lambda to obtain a value. So this syntax seems available as it isn't currently used for working code. A small change, maybe, but it's good to reduce bracket nesting to help with reading complex nested expressions. Destroy.
Re: "for" statement issue
On Friday, 21 October 2016 at 16:46:08 UTC, Andrei Alexandrescu wrote: Read the example again, the lambda is not evaluated as a bool. -- Andrei My bad. In that case, what Steven said.
Re: "for" statement issue
On 10/21/2016 12:39 PM, Vladimir Panteleev wrote: On Friday, 21 October 2016 at 12:34:58 UTC, Andrei Alexandrescu wrote: What would be a good solution to forbid certain constructs in the increment part of a for statement? For this specific case, a clear solution would be to forbid evaluating lambdas as a boolean expression, because they will always be true, and thus almost always an error. Read the example again, the lambda is not evaluated as a bool. -- Andrei
Re: "for" statement issue
On Friday, 21 October 2016 at 12:34:58 UTC, Andrei Alexandrescu wrote: What would be a good solution to forbid certain constructs in the increment part of a for statement? For this specific case, a clear solution would be to forbid evaluating lambdas as a boolean expression, because they will always be true, and thus almost always an error. Same as with assignments in if statements. If intended, it can be worked around with "!is null".
Re: "for" statement issue
Allow new syntax makes codes simpler in some cases: writeln({ int a = 5; return a + 5; }()); => writeln{ int a = 5; return a + 5; }(); [1,2,3].fold!((a, b) => a + b).writeln; => [1,2,3].fold!{a, b => a + b}.writeln;
[Issue 16632] "for" statement issue
https://issues.dlang.org/show_bug.cgi?id=16632 Steven Schveighoffer <schvei...@yahoo.com> changed: What|Removed |Added Summary|"for" statemenet issue |"for" statement issue --
Re: "for" statement issue
On 10/21/16 10:38 AM, mogu wrote: On Friday, 21 October 2016 at 14:22:27 UTC, Steven Schveighoffer wrote: On 10/21/16 10:12 AM, Temtaime wrote: On Friday, 21 October 2016 at 13:42:49 UTC, Adam D. Ruppe wrote: On Friday, 21 October 2016 at 13:33:26 UTC, Stefan Koch wrote: [...] Eh, that's exactly what the language rules say should happen, and it actually does make sense to me... you might even want to use an immediately-called lambda to group several statements together into one expression. [...] Please, no. It's fully clear that { stmts } createa a lambda, just () is ommited. No, it's not. { int x; x = 2; } Is not a lambda. It's a scope. So the meaning changes based on where it's used. I totally agree that we should remove that feature. {} in swift is a lambda too. Swift doesn't have arbitrary scopes. So there is no ambiguity. I think swift has better lambda syntax. Maybe could help for a better syntax in d. We likely are not going to change the lambda syntax. However, it's possible we could remove the ambiguous cases. reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 }) reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } ) reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } ) reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } ) (s1, s2) => s1 > s2 Seems pretty good to me reversedNames = names.sorted(by: { $0 > $1 } ) With the original string lambdas, this was possible as "a > b". I'm not sure this case is worth much effort to add. reversedNames = names.sorted(by: >) Not sure if we'll ever get this in D :) someFunctionThatTakesAClosure(closure: { // closure's body goes here }) someFunctionThatTakesAClosure() { // trailing closure's body goes here } Yes, I've seen and used this. I think this is actually a little confusing. -Steve
Re: "for" statement issue
On 10/21/16 10:28 AM, Kagamin wrote: On Friday, 21 October 2016 at 14:16:26 UTC, Steven Schveighoffer wrote: How about in general forbidding lambda statements that aren't called or used anywhere? How? int main() { int a; auto b = ()=>{a++;}; b(); assert(a==1); return 0; } Oh, I see. This error that I didn't see right away wouldn't be prevented, but that's not what I was talking about. I just meant that the original problem shouldn't have happened, since the lambda is never used. I totally agree that the above sucks and should be fixed. -Steve
Re: "for" statement issue
On 10/21/2016 09:42 AM, Adam D. Ruppe wrote: I think deprecating `{ lambda }` is really the way to go. Another possibility is to disallow an ExpressionStatement that consists solely of a lambda. There is precedent for that, e.g. the statement "1 + 1;" is disallowed. -- Andrei
Re: "for" statement issue
On 10/21/16 10:28 AM, Kagamin wrote: On Friday, 21 October 2016 at 14:16:26 UTC, Steven Schveighoffer wrote: How about in general forbidding lambda statements that aren't called or used anywhere? How? int main() { int a; auto b = ()=>{a++;}; b(); assert(a==1); return 0; } This lambda is both used in an assignment, and called. If I do this: 10; It's flagged as not having any effect. Similarly if I do: () => 5; Then it's not used/called. What is the point? -Steve
Re: "for" statement issue
On Friday, 21 October 2016 at 14:22:27 UTC, Steven Schveighoffer wrote: On 10/21/16 10:12 AM, Temtaime wrote: On Friday, 21 October 2016 at 13:42:49 UTC, Adam D. Ruppe wrote: On Friday, 21 October 2016 at 13:33:26 UTC, Stefan Koch wrote: [...] Eh, that's exactly what the language rules say should happen, and it actually does make sense to me... you might even want to use an immediately-called lambda to group several statements together into one expression. [...] Please, no. It's fully clear that { stmts } createa a lambda, just () is ommited. No, it's not. { int x; x = 2; } Is not a lambda. It's a scope. So the meaning changes based on where it's used. I totally agree that we should remove that feature. -Steve {} in swift is a lambda too. I think swift has better lambda syntax. Maybe could help for a better syntax in d. reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 }) reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } ) reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } ) reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } ) reversedNames = names.sorted(by: { $0 > $1 } ) reversedNames = names.sorted(by: >) someFunctionThatTakesAClosure(closure: { // closure's body goes here }) someFunctionThatTakesAClosure() { // trailing closure's body goes here } let strings = numbers.map { (number) -> String in var number = number var output = "" repeat { output = digitNames[number % 10]! + output number /= 10 } while number > 0 return output }
Re: "for" statement issue
http://ideone.com/KBf8k9
Re: "for" statement issue
On Friday, 21 October 2016 at 14:16:26 UTC, Steven Schveighoffer wrote: How about in general forbidding lambda statements that aren't called or used anywhere? How? int main() { int a; auto b = ()=>{a++;}; b(); assert(a==1); return 0; }
Re: "for" statement issue
On 10/21/16 10:12 AM, Temtaime wrote: On Friday, 21 October 2016 at 13:42:49 UTC, Adam D. Ruppe wrote: On Friday, 21 October 2016 at 13:33:26 UTC, Stefan Koch wrote: [...] Eh, that's exactly what the language rules say should happen, and it actually does make sense to me... you might even want to use an immediately-called lambda to group several statements together into one expression. [...] Please, no. It's fully clear that { stmts } createa a lambda, just () is ommited. No, it's not. { int x; x = 2; } Is not a lambda. It's a scope. So the meaning changes based on where it's used. I totally agree that we should remove that feature. -Steve
Re: "for" statement issue
On 10/21/16 8:34 AM, Andrei Alexandrescu wrote: I got a question about what happens with this code: int j; for({j=2; int d = 3; } j+d<7; {j++; d++;}) { } My first instinct was that that won't compile but it surprisingly does. And it loops forever. So the grammar according to https://dlang.org/spec/grammar.html#ForStatement is: ForStatement: for ( Initialize Testopt ; Incrementopt ) ScopeStatement Initialize: ; NoScopeNonEmptyStatement NoScopeNonEmptyStatement: NonEmptyStatement BlockStatement NonEmptyStatement goes over a bunch of odd places such as case statement and default statement. And then BlockStatement is the matched case: BlockStatement: { } { StatementList } So it seems we have another case in which "{" "}" do not introduce a scope. Fine. The real problem is with the increment part, which is an expression. The code { j++; d++; } is... a lambda expression that never gets used, which completes a very confusing sample. What would be a good solution to forbid certain constructs in the increment part of a for statement? How about in general forbidding lambda statements that aren't called or used anywhere? -Steve
Re: "for" statement issue
On Friday, 21 October 2016 at 13:42:49 UTC, Adam D. Ruppe wrote: On Friday, 21 October 2016 at 13:33:26 UTC, Stefan Koch wrote: [...] Eh, that's exactly what the language rules say should happen, and it actually does make sense to me... you might even want to use an immediately-called lambda to group several statements together into one expression. [...] Please, no. It's fully clear that { stmts } createa a lambda, just () is ommited. foo({ code; }); is always OK and we shouldn't deprecate it.
Re: "for" statement issue
On Friday, 21 October 2016 at 13:42:49 UTC, Adam D. Ruppe wrote: On Friday, 21 October 2016 at 13:33:26 UTC, Stefan Koch wrote: It does create a lambda? Hmm that should not happen. I think deprecating `{ lambda }` is really the way to go. It'd fix this as well at that other FAQ at pretty low cost. Yes lets make it happen! { } has too many meanings. Lets deprecate this one.
Re: "for" statement issue
On Friday, 21 October 2016 at 13:33:26 UTC, Stefan Koch wrote: It does create a lambda? Hmm that should not happen. Eh, that's exactly what the language rules say should happen, and it actually does make sense to me... you might even want to use an immediately-called lambda to group several statements together into one expression. Though I have become convinced recently that we should deprecate the `{ lambdas }` in favor of `() { lambdas }`. This is the same mistake as `() => {xxx}` that we see a bunch of newbies make. If the syntax was changed to require the empty parens for the args, `() {}`, people would be a lot less likely to mess this up... and the rest of us don't seriously lose anything, adding `()` is easy enough if they aren't already there. I think deprecating `{ lambda }` is really the way to go. It'd fix this as well at that other FAQ at pretty low cost.
Re: "for" statement issue
On Friday, 21 October 2016 at 13:18:19 UTC, RazvanN wrote: On Friday, 21 October 2016 at 12:34:58 UTC, Andrei Alexandrescu wrote: [...] I am the one who raised the question. I am n00b when it comes to D language (I just started reading about it a couple of days ago) and I tried the above mentioned code expecting that either the variables j and d get incremented accordingly or at least I would get a compilation error. Instead, the program compiles and when run it sticks into an infinite loop. I haven't read anything about lambda functions in D, but the current outcome is very confusing for a beginner like myself. Thanks, RazvanN Ah. It does create a lambda? Hmm that should not happen. I agree this is confusing and unwanted. Please feel free to post this to bugzilla. I will take a look next month. If nobody resolves it before then.
Re: "for" statement issue
On Friday, 21 October 2016 at 12:34:58 UTC, Andrei Alexandrescu wrote: I got a question about what happens with this code: int j; for({j=2; int d = 3; } j+d<7; {j++; d++;}) { } My first instinct was that that won't compile but it surprisingly does. And it loops forever. So the grammar according to https://dlang.org/spec/grammar.html#ForStatement is: ForStatement: for ( Initialize Testopt ; Incrementopt ) ScopeStatement Initialize: ; NoScopeNonEmptyStatement NoScopeNonEmptyStatement: NonEmptyStatement BlockStatement NonEmptyStatement goes over a bunch of odd places such as case statement and default statement. And then BlockStatement is the matched case: BlockStatement: { } { StatementList } So it seems we have another case in which "{" "}" do not introduce a scope. Fine. The real problem is with the increment part, which is an expression. The code { j++; d++; } is... a lambda expression that never gets used, which completes a very confusing sample. What would be a good solution to forbid certain constructs in the increment part of a for statement? Thanks, Andrei I am the one who raised the question. I am n00b when it comes to D language (I just started reading about it a couple of days ago) and I tried the above mentioned code expecting that either the variables j and d get incremented accordingly or at least I would get a compilation error. Instead, the program compiles and when run it sticks into an infinite loop. I haven't read anything about lambda functions in D, but the current outcome is very confusing for a beginner like myself. Thanks, RazvanN
Re: "for" statement issue
On Friday, 21 October 2016 at 12:34:58 UTC, Andrei Alexandrescu wrote: I got a question about what happens with this code: int j; for({j=2; int d = 3; } j+d<7; {j++; d++;}) { } [...] We could restrict the initialze part to assignments only. But I am unsure of the implications. How did you find this case?
"for" statement issue
I got a question about what happens with this code: int j; for({j=2; int d = 3; } j+d<7; {j++; d++;}) { } My first instinct was that that won't compile but it surprisingly does. And it loops forever. So the grammar according to https://dlang.org/spec/grammar.html#ForStatement is: ForStatement: for ( Initialize Testopt ; Incrementopt ) ScopeStatement Initialize: ; NoScopeNonEmptyStatement NoScopeNonEmptyStatement: NonEmptyStatement BlockStatement NonEmptyStatement goes over a bunch of odd places such as case statement and default statement. And then BlockStatement is the matched case: BlockStatement: { } { StatementList } So it seems we have another case in which "{" "}" do not introduce a scope. Fine. The real problem is with the increment part, which is an expression. The code { j++; d++; } is... a lambda expression that never gets used, which completes a very confusing sample. What would be a good solution to forbid certain constructs in the increment part of a for statement? Thanks, Andrei
$250 bounty placed on D with statement issue
https://www.bountysource.com/issues/3635875-the-with-statement-does-not-observe-temporary-object-lifetime Andrei