www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - nothrow and std.exception.ifThrown

reply novice2 <sorryno em.ail> writes:
Hello.
I need use std.format.format() in nothrow function.
format() can throw.
For this case i have special default string.
I don't want embrace format into try..catch block,
and i found elegant std.exception.ifThrown.
But DMD say "ifThrown not nothrow"

https://run.dlang.io/is/kXtt5q
```d
nothrow string foo(int x, string def) {
     import std.format: format;
     import std.exception: ifThrown;

     return format("%d", x).ifThrown(def);
}

Error: function std.exception.ifThrown!(Exception, string, 
string).ifThrown is not nothrow
```

What i can use instead of ifThrown, or how it can be changed to 
nothrow?
Thanks.
Apr 29 2021
next sibling parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Thursday, 29 April 2021 at 16:02:20 UTC, novice2 wrote:
 Hello.
 I need use std.format.format() in nothrow function.
 format() can throw.
 For this case i have special default string.
 I don't want embrace format into try..catch block,
 and i found elegant std.exception.ifThrown.
 But DMD say "ifThrown not nothrow"

 https://run.dlang.io/is/kXtt5q
 ```d
 nothrow string foo(int x, string def) {
     import std.format: format;
     import std.exception: ifThrown;

     return format("%d", x).ifThrown(def);
 }

 Error: function std.exception.ifThrown!(Exception, string, 
 string).ifThrown is not nothrow
 ```

 What i can use instead of ifThrown, or how it can be changed to 
 nothrow?
 Thanks.
Try adding scope(failure) assert(0); in foo
Apr 29 2021
prev sibling next sibling parent reply Meta <jared771 gmail.com> writes:
On Thursday, 29 April 2021 at 16:02:20 UTC, novice2 wrote:
 Hello.
 I need use std.format.format() in nothrow function.
 format() can throw.
 For this case i have special default string.
 I don't want embrace format into try..catch block,
 and i found elegant std.exception.ifThrown.
 But DMD say "ifThrown not nothrow"

 https://run.dlang.io/is/kXtt5q
 ```d
 nothrow string foo(int x, string def) {
     import std.format: format;
     import std.exception: ifThrown;

     return format("%d", x).ifThrown(def);
 }

 Error: function std.exception.ifThrown!(Exception, string, 
 string).ifThrown is not nothrow
 ```

 What i can use instead of ifThrown, or how it can be changed to 
 nothrow?
 Thanks.
The reason for this, apparently, is in the definition of `ifThrown`: ``` CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, lazy scope T2 errorHandler) nothrow ``` It's not marked as `nothrow` in the function's definition, so even if the delegate passed to ifThrown _is_ nothrow, the compiler can't tell. There's no easy way around this that I can think of OTOH that doesn't involve some effort on your part. One thing you can do is wrap ifThrown with `std.exception.assumeWontThrow`: ``` import std.exception: ifThrown, assumeWontThrow; import std.functional: pipe; alias ifThrown = pipe!(std.exception.ifThrown, assumeWontThrow); nothrow string foo(int x, string def) nothrow { import std.format: format; return format("%d", x).ifThrown(def); } ```
Apr 29 2021
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 4/29/21 1:50 PM, Meta wrote:

 
 The reason for this, apparently, is in the definition of `ifThrown`:
 ```
 CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy 
 scope T1 expression, lazy scope T2 errorHandler) nothrow
 ```
 
 It's not marked as `nothrow` in the function's definition, so even if 
 the delegate passed to ifThrown _is_ nothrow, the compiler can't tell. 
 There's no easy way around this that I can think of OTOH that doesn't 
 involve some effort on your part.
Wait, I don't get what you are saying. You mean it should be marked nothrow? It's a template, so it *should* be inferred nothrow if it were actually nothrow. The current definition is not marked nothrow as you alluded, and when I do mark it nothrow, it complains that the lazy parameter used for the exception handler is not nothrow. It seems there's no way to infer the throwing of the lazy parameter, lazy parameters are never nothrow. The higher order function DIP would I think help with this. -Steve
Apr 30 2021
parent reply Meta <jared771 gmail.com> writes:
On Friday, 30 April 2021 at 13:05:00 UTC, Steven Schveighoffer 
wrote:
 On 4/29/21 1:50 PM, Meta wrote:

 
 The reason for this, apparently, is in the definition of 
 `ifThrown`:
 ```
 CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, 
 T2)(lazy scope T1 expression, lazy scope T2 errorHandler) 
 nothrow
 ```
 
 It's not marked as `nothrow` in the function's definition, so 
 even if the delegate passed to ifThrown _is_ nothrow, the 
 compiler can't tell. There's no easy way around this that I 
 can think of OTOH that doesn't involve some effort on your 
 part.
Wait, I don't get what you are saying. You mean it should be marked nothrow? It's a template, so it *should* be inferred nothrow if it were actually nothrow. The current definition is not marked nothrow as you alluded, and when I do mark it nothrow, it complains that the lazy parameter used for the exception handler is not nothrow. It seems there's no way to infer the throwing of the lazy parameter, lazy parameters are never nothrow. The higher order function DIP would I think help with this. -Steve
Change it to a delegate and it's the same thing. ifThrown being a template is irrelevant in this case because it is accepting the handler as a function argument, not a template argument. You: 1. Need to make it a delegate instead of a lazy argument. 2. Need to mark the delegate as nothrow. For the function to be inferred as nothrow.
Apr 30 2021
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 4/30/21 9:24 AM, Meta wrote:
 On Friday, 30 April 2021 at 13:05:00 UTC, Steven Schveighoffer wrote:
 On 4/29/21 1:50 PM, Meta wrote:

 The reason for this, apparently, is in the definition of `ifThrown`:
 ```
 CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy 
 scope T1 expression, lazy scope T2 errorHandler) nothrow
 ```

 It's not marked as `nothrow` in the function's definition, so even if 
 the delegate passed to ifThrown _is_ nothrow, the compiler can't 
 tell. There's no easy way around this that I can think of OTOH that 
 doesn't involve some effort on your part.
Wait, I don't get what you are saying. You mean it should be marked nothrow? It's a template, so it *should* be inferred nothrow if it were actually nothrow. The current definition is not marked nothrow as you alluded, and when I do mark it nothrow, it complains that the lazy parameter used for the exception handler is not nothrow. It seems there's no way to infer the throwing of the lazy parameter, lazy parameters are never nothrow. The higher order function DIP would I think help with this.
Change it to a delegate and it's the same thing. ifThrown being a template is irrelevant in this case because it is accepting the handler as a function argument, not a template argument. You: 1. Need to make it a delegate instead of a lazy argument. 2. Need to mark the delegate as nothrow. For the function to be inferred as nothrow.
My point is that I think marking the *function* nothrow is not correct, it's the second parameter that dictates the throwing of the result. And you can probably fix the second parameter to be a templated delegate: ```d CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, scope T2 errorHandler) if (is(typeof(errorHandler(E.init)))) ``` And of course, we get into chicken-and-egg problems with this because if you pass in a lambda, there's no types for it to figure this stuff out. Another option is to overload on the delegate, but meh. I'd really like to see a language change that says "infer the attributes of this function based on the fact that it calls the delegate passed in." -Steve
Apr 30 2021
parent reply Meta <jared771 gmail.com> writes:
On Friday, 30 April 2021 at 13:42:49 UTC, Steven Schveighoffer 
wrote:
 On 4/30/21 9:24 AM, Meta wrote:

 My point is that I think marking the *function* nothrow is not 
 correct, it's the second parameter that dictates the throwing 
 of the result.

 And you can probably fix the second parameter to be a templated 
 delegate:

 ```d
 CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, 
 T2)(lazy scope T1 expression, scope T2 errorHandler) if 
 (is(typeof(errorHandler(E.init))))
 ```

 And of course, we get into chicken-and-egg problems with this 
 because if you pass in a lambda, there's no types for it to 
 figure this stuff out. Another option is to overload on the 
 delegate, but meh. I'd really like to see a language change 
 that says "infer the attributes of this function based on the 
 fact that it calls the delegate passed in."

 -Steve
Now that you mention it, I don't see why lazy parameters can't have their attributes inferred. What happened to the DIP to replace lazy parameters with automatic conversion of passed values to delegates, anyway? I.e.: ``` CommonType!(T1, T2) ifThrown(E: Throwable = Exception, T1, T2)(scope T1 delegate() expression, scope T2 delegate() errorHandler); //getString() and "some string" automatically converted to `string delegate()` auto s = getString().ifThrown("some string"); ```
Apr 30 2021
parent novice2 <sorryno em.ail> writes:
btw for my immediate needs i replace second delegate with value
i.e. remove "lazy" from declaration and remove "()" in return

so ifThrown loose some generity

```d
nothrow
CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)
                             (lazy scope T1 expression, scope T2 
expression2)
...
     try
         return expression();
     catch (E)
         return expression2;
```
May 01 2021
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 4/29/21 9:02 AM, novice2 wrote:

 format() can throw.
In order to throw for an int, I added a foo(x) expression to prove that the code works.
 I don't want embrace format into try..catch block,
 and i found elegant std.exception.ifThrown.
There are collectException and collectExceptionMsg as well. The following code works for 42 and uses the default string "error" for 43. int foo(int x) { import std.exception : enforce; enforce(x == 42, "some error"); return x; } nothrow string foo(int x, string def) { import std.format: format; import std.exception: collectException; string result; auto exc = collectException(format("%d", foo(x)), result); return (exc is null) ? result : def; } void main() { import std.stdio: writeln; writeln(foo(42, "error")); writeln(foo(43, "error")); } Ali
Apr 29 2021
parent reply novice2 <sorryno em.ail> writes:
Thank you Imperatron, Ali
both variants
```d
   scope(failure) assert(0);
```
```d
   collectException
```
works!

Thank Meta
 The reason for this, apparently, is in the definition of 
 `ifThrown`
i tried to modify ifThrown adding nothrow, but compiler dont understand, that second parameter cant throw, it just expression. i dont understand why (templates too dificult for me yet), but if i comment "lazy" from T2, then compiler allow add "nothrow" to "ifThrown" ```d CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, /*lazy*/ scope T2 errorHandler) nothrow ``` https://run.dlang.io/is/KTdd3G
Apr 29 2021
parent Meta <jared771 gmail.com> writes:
On Thursday, 29 April 2021 at 20:00:23 UTC, novice2 wrote:
 i dont understand why (templates too dificult for me yet),
 but if i comment "lazy" from T2,
 then compiler allow add "nothrow" to "ifThrown"

 ```d
 CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, 
 T2)(lazy scope T1 expression, /*lazy*/ scope T2 errorHandler) 
 nothrow
 ```
 https://run.dlang.io/is/KTdd3G
This is because marking a function parameter as `lazy` is just syntax sugar for the following: ``` CommonType!(T1, T2) ifThrown(E: Throwable = Exception, T1, T2)(scope T1 delegate() expression, scope T2 delegate() errorHandler); string def = "some string"; auto s = format("%d", x).ifThrown({ return def; }); ``` Behind the scenes, a `lazy` parameter is not really a value - it's a function that _returns_ a value. The problem is that this function is not `nothrow`, and can't be marked as such (this is arguably a gap in the language). Removing `lazy` changes `errorHandler` to be a plain old value again - which cannot throw an exception, of course - so `ifThrown` can be marked `nothrow`. However, you lose all the benefits of `errorHandler` being lazily computed.
Apr 30 2021