This or a variation of it seem like a really nice way of handling possibly-nil-ed values. (Mostly because it avoids looping: even though Maybe<> enumerates 0 or 1 times only, it's still confusing to see a loop.)
David Millington Oxygene's colon operator or C# null propagating operator syntax is very good but I prefer Java Optional type because it is more flexible. Also, colon operator makes no sense if language contains primitive types, due to the issues Lars described, IMO.
Lars Fosdal I like your parenthesis syntax - it's neat! (Reminds me of ?:, actually, which I'd quite like a Delphi version of ;))
But to answer your question - what about the default value being the compiler intrinsic Default(T) value? Eg for Integer, 0; pointer/ref, nil; string, ''; etc.
But being able to specify the fallback value, a la your example syntax, would be essential. I saw you used -1 as a default and that's a good example why :)
Linas Naginionis Could you write a little about why Java's nullable types are more flexible, or rather what advantages they give over the : syntax? I know a little about them but not enough to see a clear advantage really.
David Millington Firstly, do not confuse Nullable types with Optional, they are different things. With Optional you can apply transformations or take some actions if value does not exist. Just today I wrote, e.g. documentDetails.getString("TotalPages").map(Integer::valueOf).map(PackageDetails::new).orElseThrow(() -> new IllegalArgumentException("TotalPages should be present")); To clarify, documentDetails.getString returns Optional, then we are converting it into Integer and mapping to PackageDetails class by calling PackageDetails constructor with this Integer as an argument. Otherwise we just throw an exception. It could be difficult to grasp at first if you are not familiar with functional programming but once you do, you can write much better code IMO.
Евгений Савин - Well, I am pretty sure that I do NOT want to "manually" create a nullable result type for every possible function result type that I have. Unless nullable variables and a common root type is added to Delphi - I am definitively leaning towards adding a fallback value as outlined in my previous comment.
What are the performance implications of this sort of code? My instincts tell me that performance of any interface based mechanism is weak. Hard to scale due to heap manager contention. And the reference counting is expensive too. Or am I being too nervous?
Nice, but it is better not to return NIL or even better not to return at all ;-) . Just call anonymous method instead of return ;-)
ReplyDeleteI like Java 8's Nullable approach for when anon methods aren't practical.
ReplyDeleteDavid Schwartz I guess you mean Optional since there is no Nullable type in Java 8?
ReplyDeleteWhat's your opinion of Oxygene's colon operator? http://www.elementscompiler.com/elements/oxygene/language.aspx#grabbag
ReplyDeleteThis or a variation of it seem like a really nice way of handling possibly-nil-ed values. (Mostly because it avoids looping: even though Maybe<> enumerates 0 or 1 times only, it's still confusing to see a loop.)
I like that colon operator, but I think it is difficult to align with Delphi without an addendum, since our types are not nullable.
ReplyDeletevar
ix: Integer;
begin
ix := SomeObject:Property:Object:IntValue;
What should ix be here?
Addendum example:
var
ix: Integer;
begin
ix := SomeObject:Property:Object:IntValue:(-1);
i.e. ix would default to -1 if no IntValue was accessible. I suggest manadatory paranthesis for readability.
ix := SomeObject:Property:Object:IntValue:(SomeOtherFunction + 1);
The ugly alternative is:
try
ix := SomeObject.Property.Object.IntValue;
except
ix := -1;
end;
David Millington Oxygene's colon operator or C# null propagating operator syntax is very good but I prefer Java Optional type because it is more flexible. Also, colon operator makes no sense if language contains primitive types, due to the issues Lars described, IMO.
ReplyDeleteLars Fosdal I like your parenthesis syntax - it's neat! (Reminds me of ?:, actually, which I'd quite like a Delphi version of ;))
ReplyDeleteBut to answer your question - what about the default value being the compiler intrinsic Default(T) value? Eg for Integer, 0; pointer/ref, nil; string, ''; etc.
But being able to specify the fallback value, a la your example syntax, would be essential. I saw you used -1 as a default and that's a good example why :)
Linas Naginionis Could you write a little about why Java's nullable types are more flexible, or rather what advantages they give over the : syntax? I know a little about them but not enough to see a clear advantage really.
David Millington Firstly, do not confuse Nullable types with Optional, they are different things. With Optional you can apply transformations or take some actions if value does not exist. Just today I wrote, e.g. documentDetails.getString("TotalPages").map(Integer::valueOf).map(PackageDetails::new).orElseThrow(() -> new IllegalArgumentException("TotalPages should be present"));
ReplyDeleteTo clarify, documentDetails.getString returns Optional, then we are converting it into Integer and mapping to PackageDetails class by calling PackageDetails constructor with this Integer as an argument. Otherwise we just throw an exception. It could be difficult to grasp at first if you are not familiar with functional programming but once you do, you can write much better code IMO.
Lars Fosdal
ReplyDeletevar
ix: Integer;
begin
ix := SomeObject:Property:Object:IntValue;
What should ix be here?
Compile time error. ix should be nullable type (class/interface or nullable)
Евгений Савин - Well, I am pretty sure that I do NOT want to "manually" create a nullable result type for every possible function result type that I have. Unless nullable variables and a common root type is added to Delphi - I am definitively leaning towards adding a fallback value as outlined in my previous comment.
ReplyDeleteLinas Naginionis "I guess you mean Optional since there is no Nullable type in Java 8?"
ReplyDeleteProbably. :)
Lars Fosdal
ReplyDeleteWell, In c#6 you can write:
var nullableIntVar = obj?.IntProp;
or
var intVar = obj?.IntProp ?? -1;
//obj?.IntProp means obj != null ? new Nullable(obj.IntProp) : null
nullableVar ?? -1 means nullableVar.HasValue ? nullableVar.Value : -1
There's something similar in Swift.
ReplyDeleteWhat are the performance implications of this sort of code? My instincts tell me that performance of any interface based mechanism is weak. Hard to scale due to heap manager contention. And the reference counting is expensive too. Or am I being too nervous?
ReplyDeleteDavid Heffernan Where have you seen interfaces and heap allocations in Maybe record ?
ReplyDeleteЕвгений Савин You usually get an interface by creating and instance of an object that implements said interface
ReplyDeleteDavid Heffernan We all know that but what it has to do with given Maybe record?
ReplyDeleteLinas Naginionis My mistake.
ReplyDelete