digitalmars.D - Null references
- bearophile (5/5) Aug 21 2012 The very good Mark C. Chu-Carroll has written a little blog post
- Regan Heath (20/23) Aug 21 2012 This article links to:
- Regan Heath (24/27) Aug 21 2012 It's prob no obvious from my other reply, but you might have guessed, I'...
- Simen Kjaeraas (20/27) Aug 21 2012 So don't give them that access?
- Carl Sturtivant (2/9) Aug 21 2012 How about
- Simen Kjaeraas (7/14) Aug 21 2012 I guess that could work. Still won't happen though, but for other reason...
- Peter Alexander (2/18) Aug 21 2012 That's brilliant. Surprised I haven't seen that before.
- Regan Heath (7/14) Aug 21 2012 Hmm.. c# has another nice use for ??
- Nick Treleaven (14/35) Aug 21 2012 Yes, or force conversion of the Option, handling the invalid case:
- Philippe Sigaud (12/37) Aug 22 2012 Then, both Simen and you could code a generic algebraic datatype
- Nick Treleaven (6/17) Aug 24 2012 Sounds interesting. I haven't really thought about modelling sum types
- Nick Treleaven (14/23) Aug 23 2012 I've now implemented match, similar to the above:
- Namespace (5/5) Aug 23 2012 Is there any special reason why these functions doesn't get
- Nick Treleaven (7/12) Aug 24 2012 No special reason. The Maybe struct is usually pretty small so using ref...
- Simen Kjaeraas (10/11) Aug 23 2012 Here you go. After looking at your code, and with Modern C++ Design
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (5/12) Aug 21 2012 There are many characters that has been neglected by D:
- Carl Sturtivant (2/6) Aug 21 2012 Nice! No-one of the Ascii-Trapped would miss that: self
- bearophile (16/26) Aug 21 2012 Mark C. Chu-Carroll is very intelligent and well read, most times
- Namespace (3/5) Aug 22 2012 That would be nice. Anyhow a lot better as any library solution.
- Ziad Hatahet (6/13) Aug 22 2012 C++ and D have language constructs to allow you to cast away const-ness ...
- Simen Kjaeraas (4/8) Aug 22 2012 No, but a cast sticks out like a sore thumb. foo.get().bar() does not.
The very good Mark C. Chu-Carroll has written a little blog post about the lack of null-related errors in his Scala code: http://scientopia.org/blogs/goodmath/2012/08/20/nulls/ Bye, bearophile
Aug 21 2012
On Tue, 21 Aug 2012 12:32:31 +0100, bearophile <bearophileHUGS lycos.com> wrote:The very good Mark C. Chu-Carroll has written a little blog post about the lack of null-related errors in his Scala code: http://scientopia.org/blogs/goodmath/2012/08/20/nulls/This article links to: http://beust.com/weblog/2012/08/19/a-note-on-null-pointers/ very early on. Which is also a good read, and has parallels with the NaN discussion as well :p I really like the Groovy/Fantom/Kotlin syntax shown: [quote] For example, here is how Kotlin lets you ignore null values encountered along a chain of invocations: bob?.department?.head?.name If either of these accesses returns null, the result of this expression will be null. No need to put your values into monadic boxes nor mapping through them, just use the standard composition operator you are familiar with if you are using a C family language. [/quote] I think this would be a neat D feature. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Aug 21 2012
On Tue, 21 Aug 2012 12:32:31 +0100, bearophile <bearophileHUGS lycos.com> wrote:The very good Mark C. Chu-Carroll has written a little blog post about the lack of null-related errors in his Scala code: http://scientopia.org/blogs/goodmath/2012/08/20/nulls/It's prob no obvious from my other reply, but you might have guessed, I'm of the opinion that Otaku, Cedric's blog post is spot on and Mark C is wrong. Well, not wrong exactly but not right either. A Null pointer exception in Java will give you a stack trace, meaning you can be sure which method triggered it, meaning you don't have to examine "everything", just those method calls/objects used therein. If your method is so large that this is a daunting task, then you're already doing something wrong. Plus, I don't buy the argument that having to explicitly type ".get" will stop anyone from automatically coding statements like: val g: Option[T] = f.doSomething() g.get.doSomethingElse() and suffering the exact same null pointer exception/error despite using Option and boxing into a Not-Null type. Like checked exceptions people will simply ignore the possibility of error and type the above anyway. So, end result, it's just more typing for no real gain. On the other hand, the suggested syntax of "bob?.department?.head?.name" from Kotlin is pure genius, and has a good chance of actually being used. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Aug 21 2012
On Tue, 21 Aug 2012 13:55:58 +0200, Regan Heath <regan netmail.co.nz> wrote:I don't buy the argument that having to explicitly type ".get" will stop anyone from automatically coding statements like: val g: Option[T] = f.doSomething() g.get.doSomethingElse()So don't give them that access? I have an Option struct on my home computer that only allows access to the held value if the error case is simultaneously handled: Option!int a = foo(); int n = a.match!( (int x) => x, (None n) => 0 // or throw, or what have you. ); The same solution is perfectly adaptable to MaybeNull, MaybeNan, and probably a host of others of the same family. With some clever use of opDispatch, one could write an Option struct that lets you call methods and acces members of the wrapped type, and return Option!ReturnType.On the other hand, the suggested syntax of "bob?.department?.head?.name" from Kotlin is pure genius, and has a good chance of actually being used.Absolutely. Probably hard to include in D though, as a ? .b is the beginning of a conditional expression. -- Simen
Aug 21 2012
How about bob??.department??.head??.nameOn the other hand, the suggested syntax of "bob?.department?.head?.name" from Kotlin is pure genius, and has a good chance of actually being used.Absolutely. Probably hard to include in D though, as a ? .b is the beginning of a conditional expression.
Aug 21 2012
On Tue, 21 Aug 2012 16:08:23 +0200, Carl Sturtivant <sturtivant gmail.com> wrote:I guess that could work. Still won't happen though, but for other reasons. Also, reminded me of C's WTF operator: foo ??!??! exit(1); -- SimenHow about bob??.department??.head??.nameOn the other hand, the suggested syntax of "bob?.department?.head?.name" from Kotlin is pure genius, and has a good chance of actually being used.Absolutely. Probably hard to include in D though, as a ? .b is the beginning of a conditional expression.
Aug 21 2012
On Tuesday, 21 August 2012 at 14:29:56 UTC, Simen Kjaeraas wrote:On Tue, 21 Aug 2012 16:08:23 +0200, Carl Sturtivant <sturtivant gmail.com> wrote:That's brilliant. Surprised I haven't seen that before.I guess that could work. Still won't happen though, but for other reasons. Also, reminded me of C's WTF operator: foo ??!??! exit(1);How about bob??.department??.head??.nameOn the other hand, the suggested syntax of "bob?.department?.head?.name" from Kotlin is pure genius, and has a good chance of actually being used.Absolutely. Probably hard to include in D though, as a ? .b is the beginning of a conditional expression.
Aug 21 2012
On Tue, 21 Aug 2012 15:08:23 +0100, Carl Sturtivant <sturtivant gmail.com> wrote:http://msdn.microsoft.com/en-us/library/ms173224.aspx R -- Using Opera's revolutionary email client: http://www.opera.com/mail/How about bob??.department??.head??.nameOn the other hand, the suggested syntax of "bob?.department?.head?.name" from Kotlin is pure genius, and has a good chance of actually being used.Absolutely. Probably hard to include in D though, as a ? .b is the beginning of a conditional expression.
Aug 21 2012
On 21/08/2012 14:30, Simen Kjaeraas wrote:On Tue, 21 Aug 2012 13:55:58 +0200, Regan Heath <regan netmail.co.nz> wrote:Yes, or force conversion of the Option, handling the invalid case: g.valueOrElse(null).doSomethingElse(); The above being explicit that null might be returned. The code is no safer, but it is much clearer. Also sometimes the caller has a better alternative value than null to use which is actually valid.I don't buy the argument that having to explicitly type ".get" will stop anyone from automatically coding statements like: val g: Option[T] = f.doSomething() g.get.doSomethingElse()So don't give them that access?I have an Option struct on my home computer that only allows access to the held value if the error case is simultaneously handled: Option!int a = foo(); int n = a.match!( (int x) => x, (None n) => 0 // or throw, or what have you. ); The same solution is perfectly adaptable to MaybeNull, MaybeNan, and probably a host of others of the same family. With some clever use of opDispatch, one could write an Option struct that lets you call methods and acces members of the wrapped type, and return Option!ReturnType.Apart from the opDispatch bit, I've been slowly working on something similar (Boost license): https://github.com/ntrel/d-maybe/blob/master/maybe.d I'm still working on it, but the basic ideas are there. I think the best bit is apply(), which supports passing multiple Maybe values, calling the delegate only if all Maybes are valid. In fact Maybe.map() is unnecessary due to apply(). Nick
Aug 21 2012
On Tue, Aug 21, 2012 at 10:17 PM, Nick Treleaven <nospam example.net> wrote:On 21/08/2012 14:30, Simen Kjaeraas wrote:Then, both Simen and you could code a generic algebraic datatype generator, with the associated matching functions (and probably mapping / reducing) Here come the whole Haskell / ML menagerie of types :) mixin(ADT(" Tree(T): Leaf(T) | Branch(Tree, Tree) ")); or something like that... And then encode JSON like this. Or update std.typecons.Algebraic to make it deal with recursive definitions...I have an Option struct on my home computer that only allows access to the held value if the error case is simultaneously handled: Option!int a = foo(); int n = a.match!( (int x) => x, (None n) => 0 // or throw, or what have you. ); The same solution is perfectly adaptable to MaybeNull, MaybeNan, and probably a host of others of the same family. With some clever use of opDispatch, one could write an Option struct that lets you call methods and acces members of the wrapped type, and return Option!ReturnType.Apart from the opDispatch bit, I've been slowly working on something similar (Boost license): https://github.com/ntrel/d-maybe/blob/master/maybe.d I'm still working on it, but the basic ideas are there. I think the best bit is apply(), which supports passing multiple Maybe values, calling the delegate only if all Maybes are valid. In fact Maybe.map() is unnecessary due to apply().
Aug 22 2012
On 22/08/2012 16:42, Philippe Sigaud wrote:Then, both Simen and you could code a generic algebraic datatype generator, with the associated matching functions (and probably mapping / reducing) Here come the whole Haskell / ML menagerie of types:) mixin(ADT(" Tree(T): Leaf(T) | Branch(Tree, Tree) ")); or something like that... And then encode JSON like this. Or update std.typecons.Algebraic to make it deal with recursive definitions...Sounds interesting. I haven't really thought about modelling sum types yet - but I'm probably not the best person as I haven't actually used them in a functional language. I expect that D's meta-programming abilities will allow for some interesting things. BTW thanks for your template tutorial, it's been very helpful.
Aug 24 2012
On 21/08/2012 21:17, Nick Treleaven wrote:I've now implemented match, similar to the above: https://github.com/ntrel/d-maybe/blob/master/maybe.d#L222 My match() always returns Maybe!T, because for pointers the lambdas could return null. Taken from the unittest: assert(match!(to!string, ()=>"<invalid>")(maybe(2)) == "2"); assert(match!(to!string, ()=>"<invalid>")(Maybe!int()) == "<invalid>"); assert(match!((x, y)=>text(x, y), {})(maybe(2), maybe(34)) == "234"); assert(match!((x, y)=>text(x, y), {})(Maybe!int(), maybe(34)) == null); assert(match!((x, y)=>text(x, y), ()=>"none")(Maybe!int(), maybe(34)) == "none"); I'd be interested to see your Option code. NickI have an Option struct on my home computer that only allows access to the held value if the error case is simultaneously handled: Option!int a = foo(); int n = a.match!( (int x) => x, (None n) => 0 // or throw, or what have you. );
Aug 23 2012
Is there any special reason why these functions doesn't get "Maybe" as (const) ref? void show(T)(Maybe!T m) bool opEquals(Maybe!T m) void opAssign(Maybe!T m)
Aug 23 2012
On 23/08/2012 18:27, Namespace wrote:Is there any special reason why these functions doesn't get "Maybe" as (const) ref? void show(T)(Maybe!T m) bool opEquals(Maybe!T m) void opAssign(Maybe!T m)No special reason. The Maybe struct is usually pretty small so using ref didn't occur to me, but if it's good practice I should do so. I suppose ref would be necessary because T could be a struct. I hadn't thought about const at all yet. BTW show is just a test function, I recently made it private. Nick
Aug 24 2012
On Thu, 23 Aug 2012 18:27:41 +0200, Nick Treleaven <nospam example.net> wrote:I'd be interested to see your Option code.Here you go. After looking at your code, and with Modern C++ Design fresh in mind, I see that match and hasValue might have worked better as free functions. I took the liberty of implementing the optional function calls discussed earlier. If your eyes glaze over or you feel an urge to kill, you are likely looking at that part of the code. -- Simen
Aug 23 2012
On 08/21/2012 06:30 AM, Simen Kjaeraas wrote:On Tue, 21 Aug 2012 13:55:58 +0200, Regan Heath <regan netmail.co.nz> wrote:There are many characters that has been neglected by D: bob⸮.department⸮.head⸮.name :p (If not visible on your screen, that character is U+2E2E.) AliOn the other hand, the suggested syntax of "bob?.department?.head?.name" from Kotlin is pure genius, and has a good chance of actually being used.Absolutely. Probably hard to include in D though, as a ? .b is the beginning of a conditional expression.
Aug 21 2012
There are many characters that has been neglected by D: bob⸮.department⸮.head⸮.name :p (If not visible on your screen, that character is U+2E2E.) AliNice! No-one of the Ascii-Trapped would miss that: self documentation indeed.
Aug 21 2012
Regan Heath:Plus, I don't buy the argument that having to explicitly type ".get" will stop anyone from automatically coding statements like: val g: Option[T] = f.doSomething() g.get.doSomethingElse() and suffering the exact same null pointer exception/error despite using Option and boxing into a Not-Null type. Like checked exceptions people will simply ignore the possibility of error and type the above anyway. So, end result, it's just more typing for no real gain.Mark C. Chu-Carroll is very intelligent and well read, most times he's right. My Scala experience is limited, so I don't first-hand how much Mark is right this time. I think having a type for a reference/pointer that can't be null is useful. With it in many situations you need no "get", because there no risk of it being null. So the discussion here is for the other cases where you need a reference that can be null too. Such cases are surely just part of the cases where in D now you receive a generic nullable reference/pointer. So even if "get" is about as dangerous as normal references, the situation is better still. Time ago I have suggested a syntax like Foo to represent in D the subtype of Foo references that can't be null. Bye, bearophile
Aug 21 2012
Time ago I have suggested a syntax like Foo to represent in D the subtype of Foo references that can't be null.That would be nice. Anyhow a lot better as any library solution. But I think it will be resulting in a NotNullable struct in std.typecons...
Aug 22 2012
On Tue, Aug 21, 2012 at 4:55 AM, Regan Heath <regan netmail.co.nz> wrote:Plus, I don't buy the argument that having to explicitly type ".get" will stop anyone from automatically coding statements like: val g: Option[T] = f.doSomething() g.get.doSomethingElse() and suffering the exact same null pointer exception/error despite using Option and boxing into a Not-Null type. RC++ and D have language constructs to allow you to cast away const-ness and immutability, does that mean we have to do away with the concept just because there is a way around it? -- Ziad
Aug 22 2012
On Wed, 22 Aug 2012 19:37:09 +0200, Ziad Hatahet <hatahet gmail.com> wrote:C++ and D have language constructs to allow you to cast away const-ness and immutability, does that mean we have to do away with the concept just because there is a way around it?No, but a cast sticks out like a sore thumb. foo.get().bar() does not. -- Simen
Aug 22 2012