Thread overview | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 03, 2014 Templates: generic "return null;" | ||||
---|---|---|---|---|
| ||||
Is there a way I can make the return type in getAttribute generic? null does not work with numbers. MyStruct(T) { T[T] attributes; // .... public auto getAttribute(T attr) { if (!(attr in attributes)) { return null; // Doesn't work for numbers! } return attributes[attr]; } } void main() { auto myStr = MyStruct!int(0); // Error } |
February 03, 2014 Re: Templates: generic "return null;" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris | On Monday, 3 February 2014 at 10:25:19 UTC, Chris wrote:
> T[T] attributes;
> // ....
> public auto getAttribute(T attr) {
> if (!(attr in attributes)) {
> return null; // Doesn't work for numbers!
> }
> return attributes[attr];
> }
> }
One way would be to use std.typecons.Nullable(T) as a return type.
Another would be to retink your design :) Note that for numbers, there's no distinct "does not exist" value (well, ok, we have NaN for floating point). Neither there is for structs. Generally such methods as your getAttribute either throw, or get a second optional parameter as hint on what to return when the element is not found in the dictionoary.
|
February 03, 2014 Re: Templates: generic "return null;" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stanislav Blinov | On Monday, 3 February 2014 at 10:32:58 UTC, Stanislav Blinov wrote: > On Monday, 3 February 2014 at 10:25:19 UTC, Chris wrote: > >> T[T] attributes; >> // .... >> public auto getAttribute(T attr) { >> if (!(attr in attributes)) { >> return null; // Doesn't work for numbers! >> } >> return attributes[attr]; >> } >> } > > One way would be to use std.typecons.Nullable(T) as a return type. Thanks. I'll try this one. > Another would be to retink your design :) Note that for numbers, there's no distinct "does not exist" value (well, ok, we have NaN for floating point). Neither there is for structs. Generally such methods as your getAttribute either throw, or get a second optional parameter as hint on what to return when the element is not found in the dictionoary. I'm reluctant to (over)use throw, because I think that throw should be the last resort when you cannot easily predict all the things that can go wrong. Simple requests should give simple answers. If the key doesn't exist it returns nothing. The problem above only exists because of generic types, else it would be either 'null' or for numbers -1 or something. But if you have a good point I've overlooked, you can convince me of throw. No ideology :) |
February 03, 2014 Re: Templates: generic "return null;" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris | On Monday, 3 February 2014 at 10:55:23 UTC, Chris wrote: > I'm reluctant to (over)use throw, because I think that throw should be the last resort when you cannot easily predict all the things that can go wrong. Simple requests should give simple answers. If the key doesn't exist it returns nothing. D has no concept of "nothing" in the language. What if your dictionary contains objects, and for some key K it *does* contain a null reference? How would you distinguish absence of value from some "invalid" value? Nullable can help with that, of course. But then again, what if your dictionary does contain other Nullables? :) Generally, inability to return value is an exceptional situation. > The problem above only exists because of generic types, else it would be either 'null' or for numbers -1 or something. -1 is a number, just like 0 or 10 or 13142313. Same as above, at the call site you won't be able to tell if -1 indicates that there's no such key in the attributes dictionary or just that attribute happens to have a value of -1. |
February 03, 2014 Re: Templates: generic "return null;" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris | You have forgot to mention what behavior you are actually trying to achieve ;) Common not-so-meaningful value is simply T.init , but there can be no such thing as generic sentinel. If you need cheap and simple way to figure out that attribute was missing, change API to return value by out parameter and turn normal return value into boolean success flag. |
February 03, 2014 Re: Templates: generic "return null;" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On Monday, 3 February 2014 at 12:25:16 UTC, Dicebot wrote:
> You have forgot to mention what behavior you are actually trying to achieve ;) Common not-so-meaningful value is simply T.init , but there can be no such thing as generic sentinel.
>
> If you need cheap and simple way to figure out that attribute was missing, change API to return value by out parameter and turn normal return value into boolean success flag.
Thanks. T.init actually does the trick. The behavior:
auto name = myStruct.getAttribute("name");
if (name == "bla") {
// do something
} else {
// do something else
}
or (theoretically):
auto second = myStruct.getAttribute(1.0);
if (second > 1.5) {
// do something
} else {
// do something else.
}
I haven't got a use case for the second example, but it might be handy for data analysis and I wanted to test how far you can go with templates.
The reasoning behind it is that
string name;
try {
name = myStruct.getAttribute("name");
} // ...
is a bit awkward an OTT. I'd prefer to introduce hasAttribute("name") instead, if I want to be sure it exists.
if (myStruct.hasAttribute("name))
name = myStruct.getAttribute("name");
|
February 03, 2014 Re: Templates: generic "return null;" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | Dicebot:
> If you need cheap and simple way to figure out that attribute was missing, change API to return value by out parameter and turn normal return value into boolean success flag.
It's probably better to start using Nullable.
Bye,
bearophile
|
February 03, 2014 Re: Templates: generic "return null;" | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Monday, 3 February 2014 at 14:10:35 UTC, bearophile wrote: > Dicebot: > >> If you need cheap and simple way to figure out that attribute was missing, change API to return value by out parameter and turn normal return value into boolean success flag. > > It's probably better to start using Nullable. > > Bye, > bearophile Probably. I tried using Nullable, but it caused some problems when the attribute wasn't defined: core.exception.AssertError@/usr/include/dmd/phobos/std/typecons.d(1233): Called `get' on null Nullable!int. |
February 03, 2014 Re: Templates: generic "return null;" | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Monday, 3 February 2014 at 14:10:35 UTC, bearophile wrote:
> Dicebot:
>
>> If you need cheap and simple way to figure out that attribute was missing, change API to return value by out parameter and turn normal return value into boolean success flag.
>
> It's probably better to start using Nullable.
>
> Bye,
> bearophile
Depends. If you control system as a whole, yes, it is better to build it on top of Nullable. If interfacing with external code is intended, it will just add more boilerplate.
Also I hate name "Nullable" and use it under name "Optional" :)
|
February 03, 2014 Re: Templates: generic "return null;" | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris | On Monday, 3 February 2014 at 14:17:11 UTC, Chris wrote:
> Probably. I tried using Nullable, but it caused some problems when the attribute wasn't defined:
>
> core.exception.AssertError@/usr/include/dmd/phobos/std/typecons.d(1233): Called `get' on null Nullable!int.
This is intended. The very point of Nullable is to force you to handle `null` state before accessing actual payload.
|
Copyright © 1999-2021 by the D Language Foundation