Re: Idiomatic way to express errors without resorting to exceptions

2020-03-09 Thread Simen Kjærås via Digitalmars-d-learn

On Saturday, 7 March 2020 at 15:44:38 UTC, Arine wrote:
The case when there isn't a value should be handled explicitly, 
not implicitly. Propogating a None value

isn't useful


Except when it is useful, and shouldn't be handled explicitly. I 
have code in D, C and C++ that looks like this:


ReturnValue result = someInitialValue;
auto foo = getFoo();
if (!foo) return result;
auto bar = foo.fun();
if (!bar) return result;
return bar.gun();

In C#, this would be:

return getFoo()?.fun().gun() ?? someInitialValue;

And with implicit handling in Optional!T, it looks like this:

return getFoo().oc.fun().gun().or(someInitialValue);

Clearly the latter two are more readable, and I'm not gonna care 
that it's a little slower in the 99% of cases where speed is not 
important.


--
  Simen


Re: Idiomatic way to express errors without resorting to exceptions

2020-03-07 Thread Sebastiaan Koppe via Digitalmars-d-learn

On Saturday, 7 March 2020 at 15:44:38 UTC, Arine wrote:
I feel as though that's it's greatest weakness. It makes the 
check whether there is or isn't a value hidden. The case when 
there isn't a value should be handled explicitly, not 
implicitly. Propogating a None value isn't useful and is 
computationally demanding as each subsequent call will need to 
do a check to see if it has a value as it results in an 
optional type (for binary operators). So something like `a + b 
* c` is now much more expensive than it appears. This is 
exactly the kind of abuse of operator overloading that the 
feature is shunned for.


What can I say? If you don't like the semantics, don't use it. I 
have found value in it.


Anyways not sure what you mean here with the code below. If 
"first" here returns an optional type, you can't call 
"doSomething" like that without first checking if the value 
exists. Optional just doesn't allow it and Nullable will throw 
an exception.


```
list.first.doSomething(); // error
```


You are right. Nowadays you need a `.oc` call in between. Also, 
doSomething cannot be a free-standing function (sadly).


Re: Idiomatic way to express errors without resorting to exceptions

2020-03-07 Thread Arine via Digitalmars-d-learn
On Saturday, 29 February 2020 at 15:23:02 UTC, Sebastiaan Koppe 
wrote:
Like I said, I don't use optionals when I care about errors. 
That is not what they are designed for.


If I want to type-guard potential errors I will use SumType!(T, 
Error). It forces you to handle both cases, either at compile 
time (with the match template), or at runtime (with the 
tryMatch template).


The power of optionals, however, lies in the following:

```
list.first.doSomething();
```

Here doSomething will only be called when the list contains at 
least one item. Here I don't care about cases where the list is 
empty, I just want to doSomething if it isn't.


I feel as though that's it's greatest weakness. It makes the 
check whether there is or isn't a value hidden. The case when 
there isn't a value should be handled explicitly, not implicitly. 
Propogating a None value isn't useful and is computationally 
demanding as each subsequent call will need to do a check to see 
if it has a value as it results in an optional type (for binary 
operators). So something like `a + b * c` is now much more 
expensive than it appears. This is exactly the kind of abuse of 
operator overloading that the feature is shunned for.


Anyways not sure what you mean here with the code below. If 
"first" here returns an optional type, you can't call 
"doSomething" like that without first checking if the value 
exists. Optional just doesn't allow it and Nullable will throw an 
exception.


```
list.first.doSomething(); // error
```

Which makes it odd that it forwards operator overloading to the 
underlying type, which is basically just syntactic sugar for 
calling a method on the object. Seems like a conflicting design 
decision to me.






Re: Idiomatic way to express errors without resorting to exceptions

2020-02-29 Thread Sebastiaan Koppe via Digitalmars-d-learn

On Saturday, 29 February 2020 at 13:40:11 UTC, Adnan wrote:
On Saturday, 29 February 2020 at 13:03:21 UTC, Sebastiaan Koppe 
wrote:

On Saturday, 29 February 2020 at 12:50:59 UTC, Adnan wrote:
* Option!T from the optional package: Has even worse problem 
IMO. Not only it allows None + int but also it returns a 
`[]`. This API is not to my liking. You could say well 
Haskell has fmap for Optional etc, and I am aware of that, so 
does Rust with map etc. But I am talking about basic things: 
like `+`.


I would argue it is one of its strengths.


Doesn't that pretty much defeat the entire purpose of 
type-guarding a potentially error/absent value?


Like I said, I don't use optionals when I care about errors. That 
is not what they are designed for.


If I want to type-guard potential errors I will use SumType!(T, 
Error). It forces you to handle both cases, either at compile 
time (with the match template), or at runtime (with the tryMatch 
template).


The power of optionals, however, lies in the following:

```
list.first.doSomething();
```

Here doSomething will only be called when the list contains at 
least one item. Here I don't care about cases where the list is 
empty, I just want to doSomething if it isn't.


Re: Idiomatic way to express errors without resorting to exceptions

2020-02-29 Thread Paul Backus via Digitalmars-d-learn

On Saturday, 29 February 2020 at 13:40:11 UTC, Adnan wrote:
On Saturday, 29 February 2020 at 13:03:21 UTC, Sebastiaan Koppe 
wrote:

On Saturday, 29 February 2020 at 12:50:59 UTC, Adnan wrote:
* Option!T from the optional package: Has even worse problem 
IMO. Not only it allows None + int but also it returns a 
`[]`. This API is not to my liking. You could say well 
Haskell has fmap for Optional etc, and I am aware of that, so 
does Rust with map etc. But I am talking about basic things: 
like `+`.


I would argue it is one of its strengths.


Doesn't that pretty much defeat the entire purpose of 
type-guarding a potentially error/absent value?


I suppose it depends on what you think that purpose is.

Optional!T will not allow you to do anything that requires a T 
unless the T is actually present. In some cases, it will allow 
you to *attempt* such operations, and return an empty Optional at 
run time if they are not allowed; in others, the attempt will 
result in a type error at compile time. This is a compromise 
between strictness and convenience, but there is no compromise to 
correctness. Unlike, say, a null pointer, Optional!T will not 
allow you to cause a run-time error by forgetting a check.


(Of course, you can explicitly unwrap the Optional without 
checking, but that's not something you're likely to do by 
accident.)


Re: Idiomatic way to express errors without resorting to exceptions

2020-02-29 Thread Basile B. via Digitalmars-d-learn

On Saturday, 29 February 2020 at 12:50:59 UTC, Adnan wrote:
I have a struct that has to arrays. Each of those must have the 
same sizes.


So while constructing the array, if you pass two arrays of 
different sizes the constructor must return nothing.


In Rust I could easily use Option. D has no answer to 
Optional types as far as I am concerned. Is throwing exceptions 
the only idiomatic way?



---

What I already considered:

* Using Nullable!T: Okay but Nullable!T has all the overloads 
for regular T which makes the  API even more unpredictable.


In Rust you don't just add a Some(44) and 34; No overloads for 
Some and i32 are allowed (purposefully).


* Option!T from the optional package: Has even worse problem 
IMO. Not only it allows None + int but also it returns a `[]`. 
This API is not to my liking. You could say well Haskell has 
fmap for Optional etc, and I am aware of that, so does Rust 
with map etc. But I am talking about basic things: like `+`.


* Value-based error handling like Go and C: well, that works 
but the error checking is opt-in. There's no such thing as 
[[nodiscard]] in D too so the user of the API might as well 
forget to check for error value.


* if specialization: Clever workaround but sometimes the struct 
may fail for complex reasons, not only for a single condition.


There's no idiomatic way since D lang is based on exceptions...

However I'd use one of those system:

1. return error, write result in ref parameter.

alias CheckedValueProto(RT, P...) = bool function(ref RT, P 
params);


2. the same using a special struct and no more ref param. So more 
like Nullable/Optional but with a dedicated generic type that 
contain a single opover used to indicate if there's been an error 
or not.


struct CheckedValue(T) {
bool noError;
T t;
B opCast(B : bool)() inout pure nothrow @safe {
return noError;
}
}

and you make your functions to return CheckedValues...

CheckedValue!int strToInt(string input);

if (const CheckedValue!int = strToInt("a") {} else {}

Although
- both still require self-discpline or a specialized linter to 
detect unchecked calls ;

- the whole standard library is incompatible ;

I have a personal preference for 2. even if it causes problems 
when T is of same size as a pointer. Now the question is also 
what's the more costly ? try/catch or this non atomic return ?


Re: Idiomatic way to express errors without resorting to exceptions

2020-02-29 Thread Adnan via Digitalmars-d-learn
On Saturday, 29 February 2020 at 13:03:21 UTC, Sebastiaan Koppe 
wrote:

On Saturday, 29 February 2020 at 12:50:59 UTC, Adnan wrote:
* Option!T from the optional package: Has even worse problem 
IMO. Not only it allows None + int but also it returns a `[]`. 
This API is not to my liking. You could say well Haskell has 
fmap for Optional etc, and I am aware of that, so does Rust 
with map etc. But I am talking about basic things: like `+`.


I would argue it is one of its strengths.


Doesn't that pretty much defeat the entire purpose of 
type-guarding a potentially error/absent value?


Re: Idiomatic way to express errors without resorting to exceptions

2020-02-29 Thread Sebastiaan Koppe via Digitalmars-d-learn

On Saturday, 29 February 2020 at 12:50:59 UTC, Adnan wrote:
* Option!T from the optional package: Has even worse problem 
IMO. Not only it allows None + int but also it returns a `[]`. 
This API is not to my liking. You could say well Haskell has 
fmap for Optional etc, and I am aware of that, so does Rust 
with map etc. But I am talking about basic things: like `+`.


I would argue it is one of its strengths.

Regardless, I don't think option/nullable/maybe is a good type 
for errors. Rather you should use something like SumType!(T, 
Error), or any other 'either' type.


Idiomatic way to express errors without resorting to exceptions

2020-02-29 Thread Adnan via Digitalmars-d-learn
I have a struct that has to arrays. Each of those must have the 
same sizes.


So while constructing the array, if you pass two arrays of 
different sizes the constructor must return nothing.


In Rust I could easily use Option. D has no answer to Optional 
types as far as I am concerned. Is throwing exceptions the only 
idiomatic way?



---

What I already considered:

* Using Nullable!T: Okay but Nullable!T has all the overloads for 
regular T which makes the  API even more unpredictable.


In Rust you don't just add a Some(44) and 34; No overloads for 
Some and i32 are allowed (purposefully).


* Option!T from the optional package: Has even worse problem IMO. 
Not only it allows None + int but also it returns a `[]`. This 
API is not to my liking. You could say well Haskell has fmap for 
Optional etc, and I am aware of that, so does Rust with map etc. 
But I am talking about basic things: like `+`.


* Value-based error handling like Go and C: well, that works but 
the error checking is opt-in. There's no such thing as 
[[nodiscard]] in D too so the user of the API might as well 
forget to check for error value.


* if specialization: Clever workaround but sometimes the struct 
may fail for complex reasons, not only for a single condition.