| Thread overview | ||||||||
|---|---|---|---|---|---|---|---|---|
|
December 03, 2015 improving scope(finally/success) | ||||
|---|---|---|---|---|
| ||||
it'd be really helpful if scope() statements got hold of the return value or exception, e.g.,
scope(success, retval) {
writeln("the retval is", retval)
}
scope(failure, ex) {
if(typeid(ex) == typeid(MyException)) {
callTheCops();
}
}
it would make logging very easy, and since these statements are basically code-rewrites i don't suppose it would be hard to implement. from a syntax point of view:
scope(succes[, VARNAME]) // where VARNAME would be the return value (a const tmp variable?)
scope(failure[, VARNAME]) // where VARNAME would be hold the exception (a Throwable)
i mean, code such as
int f() {
scope(exit) writeln("bye");
return 5;
}
is rewritten as something like
int f() {
try {
auto tmp = 5;
}
finally {
writeln("bye");
}
return tmp;
}
so `tmp` is already there for the finally clause (modulo scoping issues)
| ||||
December 03, 2015 Re: improving scope(finally/success) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Tomer Filiba | On Thursday, 3 December 2015 at 11:41:29 UTC, Tomer Filiba wrote:
> it'd be really helpful if scope() statements got hold of the return value or exception, e.g.,
>
> scope(success, retval) {
> writeln("the retval is", retval)
> }
>
> scope(failure, ex) {
> if(typeid(ex) == typeid(MyException)) {
> callTheCops();
> }
> }
>
> it would make logging very easy, and since these statements are basically code-rewrites i don't suppose it would be hard to implement. from a syntax point of view:
>
> scope(succes[, VARNAME]) // where VARNAME would be the return value (a const tmp variable?)
> scope(failure[, VARNAME]) // where VARNAME would be hold the exception (a Throwable)
>
> i mean, code such as
>
> int f() {
> scope(exit) writeln("bye");
> return 5;
> }
>
> is rewritten as something like
>
> int f() {
> try {
> auto tmp = 5;
> }
> finally {
> writeln("bye");
> }
> return tmp;
> }
>
> so `tmp` is already there for the finally clause (modulo scoping issues)
int foo(bool cond) { // scope 1
{ // scope 2
scope(success, retval) {
writeln("the retval is", retval)
}
if (cond) { // scope 3
return 1;
}
}
return 2;
}
`foo(true)` should obviously print "the retval is 1", but what should `foo(false)` print? It's `scope(success)` block should run when it exists scope 2, but the return value is only determined at the end of scope 1.
| |||
December 03, 2015 Re: improving scope(finally/success) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | On Thursday, 3 December 2015 at 13:07:53 UTC, Idan Arye wrote:
> On Thursday, 3 December 2015 at 11:41:29 UTC, Tomer Filiba wrote:
>> int f() {
>> scope(exit) writeln("bye");
>> return 5;
>> }
>>
>> is rewritten as something like
>>
>> int f() {
>> try {
>> auto tmp = 5;
>> }
>> finally {
>> writeln("bye");
>> }
>> return tmp;
>> }
>>
>> so `tmp` is already there for the finally clause (modulo scoping issues)
>
> int foo(bool cond) { // scope 1
> { // scope 2
> scope(success, retval) {
> writeln("the retval is", retval)
> }
> if (cond) { // scope 3
> return 1;
> }
> }
> return 2;
> }
>
>
> `foo(true)` should obviously print "the retval is 1", but what should `foo(false)` print? It's `scope(success)` block should run when it exists scope 2, but the return value is only determined at the end of scope 1.
Tomer's suggested lowering can't work, because tmp's scope doesn't extend outside of the try. It would need to be hoisted up to the beginning of the function.
This would then imply that `foo(false)` would print "0" (int.init). However, I don't think this kind of lowering is a good idea, because it would create a temporary lvalue, which implies that it needs to go through the full construct/assign/destroy cycle instead of a simple move, which is a potentially observable difference to the current behaviour.
| |||
December 03, 2015 Re: improving scope(finally/success) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Tomer Filiba | You can already do it with a slight change, and it's not so painful, at least in simple functions:
int foo(bool b) {
auto result = 2;
scope(exit) writeln(result);
if (b) {
result = 1;
}
return result;
}
| |||
December 03, 2015 Re: improving scope(finally/success) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Chris Wright | On 12/3/15 10:24 AM, Chris Wright wrote:
> You can already do it with a slight change, and it's not so painful, at
> least in simple functions:
>
> int foo(bool b) {
> auto result = 2;
> scope(exit) writeln(result);
> if (b) {
> result = 1;
> }
> return result;
> }
>
auto ref logCall(alias f, Args...)(auto ref Args args) {
auto ref printResult(T)(auto ref T t)
{
writeln(t);
return t;
}
return printResult(f(args))
}
logCall!foo(true);
-Steve
| |||
December 04, 2015 Re: improving scope(finally/success) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 12/03/15 16:33, Steven Schveighoffer via Digitalmars-d wrote:
> auto ref logCall(alias f, Args...)(auto ref Args args) {
> auto ref printResult(T)(auto ref T t)
> {
> writeln(t);
> return t;
> }
> return printResult(f(args))
> }
>
> logCall!foo(true);
Which will happily accept:
bool foo(ref bool a) { return a=false; }
And, yes, it can be dealt with via a bit of introspection, but nobody will bother in practice (consider that 'f' may be overloaded). So it doesn't really work for non-trivial or generic code.
artur
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply