Re: Adding the ?. null verification

2014-10-21 Thread Meta via Digitalmars-d
Did you ever get around to making a pull request for this? It'd 
be nice to have this in Phobos, so I can make one for you (all 
attribution to you, of course) if you don't have time to push it 
through.


Re: Adding the ?. null verification

2014-10-21 Thread H. S. Teoh via Digitalmars-d
On Tue, Oct 21, 2014 at 11:37:09PM +, Meta via Digitalmars-d wrote:
 Did you ever get around to making a pull request for this? It'd be
 nice to have this in Phobos, so I can make one for you (all
 attribution to you, of course) if you don't have time to push it
 through.

No, I've been too busy to work on this.  Feel free to make a PR on my
behalf. You don't have to attribute it to me.


T

-- 
Today's society is one of specialization: as you grow, you learn more
and more about less and less. Eventually, you know everything about
nothing.


Re: Adding the ?. null verification

2014-06-25 Thread Jacob Carlborg via Digitalmars-d

On 2014-06-24 22:52, Ary Borenszweig wrote:


And in Ruby it's just ||=. How more intuitive can it get?

a = nil
a ||= 1

The or that you are discussing here is just an || in Ruby:

b = nil || 1


Yeah, but that behaves a bit different in D.

--
/Jacob Carlborg


Re: Adding the ?. null verification

2014-06-24 Thread Yota via Digitalmars-d
On Sunday, 22 June 2014 at 08:15:45 UTC, Andrei Alexandrescu 
wrote:

On 6/21/14, 3:38 PM, H. S. Teoh via Digitalmars-d wrote:
On Sat, Jun 21, 2014 at 03:26:45PM -0700, Andrei Alexandrescu 
via Digitalmars-d wrote:

On 6/19/14, 1:29 PM, Etienne wrote:

writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));


or is really nice and terse. I think we should add that to 
std.

safeDeref isn't the best choice of name.

[...]

What's your suggestion?


That we add or to std and find a name for safeDeref that 
doesn't use the word safe in a confusing manner. -- Andrei


C# calls the ?? operator the null-coalescing operator.  I have 
absolutely no idea why, but that does give precedence for calling 
it coalesce.  Then again, who wants to memorize how that's 
spelled?  They also have GetValueOrDefault() on Nullable, but 
that is kinda long.  How about just orDefault or ifNull?


Re: Adding the ?. null verification

2014-06-24 Thread Jacob Carlborg via Digitalmars-d

On 2014-06-24 18:52, Yota wrote:

On Sunday, 22 June 2014 at 08:15:45 UTC, Andrei Alexandrescu wrote:

On 6/21/14, 3:38 PM, H. S. Teoh via Digitalmars-d wrote:

On Sat, Jun 21, 2014 at 03:26:45PM -0700, Andrei Alexandrescu via
Digitalmars-d wrote:

On 6/19/14, 1:29 PM, Etienne wrote:

writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));


or is really nice and terse. I think we should add that to std.
safeDeref isn't the best choice of name.

[...]

What's your suggestion?


That we add or to std and find a name for safeDeref that doesn't use
the word safe in a confusing manner. -- Andrei


C# calls the ?? operator the null-coalescing operator.  I have
absolutely no idea why, but that does give precedence for calling it
coalesce.


In CoffeeScript it's called The Existential Operator. It's also known as 
The Elvis Operator.


--
/Jacob Carlborg


Re: Adding the ?. null verification

2014-06-24 Thread H. S. Teoh via Digitalmars-d
On Tue, Jun 24, 2014 at 09:43:21PM +0200, Jacob Carlborg via Digitalmars-d 
wrote:
 On 2014-06-24 18:52, Yota wrote:
 On Sunday, 22 June 2014 at 08:15:45 UTC, Andrei Alexandrescu wrote:
 On 6/21/14, 3:38 PM, H. S. Teoh via Digitalmars-d wrote:
 On Sat, Jun 21, 2014 at 03:26:45PM -0700, Andrei Alexandrescu via
 Digitalmars-d wrote:
 On 6/19/14, 1:29 PM, Etienne wrote:
 writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));
 
 or is really nice and terse. I think we should add that to std.
 safeDeref isn't the best choice of name.
 [...]
 
 What's your suggestion?
 
 That we add or to std and find a name for safeDeref that doesn't use
 the word safe in a confusing manner. -- Andrei
 
 C# calls the ?? operator the null-coalescing operator.  I have
 absolutely no idea why, but that does give precedence for calling it
 coalesce.
 
 In CoffeeScript it's called The Existential Operator. It's also known as The
 Elvis Operator.
[...]

So D code is going to start looking like this now?!

if (myobj.elvis.subobj.memb.isAlive.or(false)) {
...
}


T

-- 
How are you doing? Doing what?


Re: Adding the ?. null verification

2014-06-24 Thread Ary Borenszweig via Digitalmars-d

On 6/24/14, 4:43 PM, Jacob Carlborg wrote:

On 2014-06-24 18:52, Yota wrote:

On Sunday, 22 June 2014 at 08:15:45 UTC, Andrei Alexandrescu wrote:

On 6/21/14, 3:38 PM, H. S. Teoh via Digitalmars-d wrote:

On Sat, Jun 21, 2014 at 03:26:45PM -0700, Andrei Alexandrescu via
Digitalmars-d wrote:

On 6/19/14, 1:29 PM, Etienne wrote:

writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));


or is really nice and terse. I think we should add that to std.
safeDeref isn't the best choice of name.

[...]

What's your suggestion?


That we add or to std and find a name for safeDeref that doesn't use
the word safe in a confusing manner. -- Andrei


C# calls the ?? operator the null-coalescing operator.  I have
absolutely no idea why, but that does give precedence for calling it
coalesce.


In CoffeeScript it's called The Existential Operator. It's also known as
The Elvis Operator.



And in Ruby it's just ||=. How more intuitive can it get?

a = nil
a ||= 1

The or that you are discussing here is just an || in Ruby:

b = nil || 1




Re: Adding the ?. null verification

2014-06-24 Thread Meta via Digitalmars-d
On Tuesday, 24 June 2014 at 19:56:14 UTC, H. S. Teoh via 
Digitalmars-d wrote:

So D code is going to start looking like this now?!

if (myobj.elvis.subobj.memb.isAlive.or(false)) {
...
}


What about ifExists?

if (myObj.ifExists.subobj.member.isAlive.or(false))
{
//...
}


Re: Adding the ?. null verification

2014-06-23 Thread David Gileadi via Digitalmars-d

On 6/21/14, 4:32 PM, deadalnix wrote:

On Saturday, 21 June 2014 at 22:40:32 UTC, H. S. Teoh via Digitalmars-d
wrote:

On Sat, Jun 21, 2014 at 03:26:45PM -0700, Andrei Alexandrescu via
Digitalmars-d wrote:

On 6/19/14, 1:29 PM, Etienne wrote:
writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));

or is really nice and terse. I think we should add that to std.
safeDeref isn't the best choice of name.

[...]

What's your suggestion?


T


maybe is fine. Last time I checked, it isn't only a monad in haskell,
but also vastly used by these peoples who speak english.


I like maybe too. nullSafe might also be a reasonable bikeshed color.


Re: Adding the ?. null verification

2014-06-22 Thread Andrei Alexandrescu via Digitalmars-d

On 6/21/14, 3:38 PM, H. S. Teoh via Digitalmars-d wrote:

On Sat, Jun 21, 2014 at 03:26:45PM -0700, Andrei Alexandrescu via Digitalmars-d 
wrote:

On 6/19/14, 1:29 PM, Etienne wrote:

writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));


or is really nice and terse. I think we should add that to std.
safeDeref isn't the best choice of name.

[...]

What's your suggestion?


That we add or to std and find a name for safeDeref that doesn't use 
the word safe in a confusing manner. -- Andrei




Re: Adding the ?. null verification

2014-06-22 Thread H. S. Teoh via Digitalmars-d
On Sun, Jun 22, 2014 at 01:15:46AM -0700, Andrei Alexandrescu via Digitalmars-d 
wrote:
 On 6/21/14, 3:38 PM, H. S. Teoh via Digitalmars-d wrote:
 On Sat, Jun 21, 2014 at 03:26:45PM -0700, Andrei Alexandrescu via 
 Digitalmars-d wrote:
 On 6/19/14, 1:29 PM, Etienne wrote:
 writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));
 
 or is really nice and terse. I think we should add that to std.
 safeDeref isn't the best choice of name.
 [...]
 
 What's your suggestion?
 
 That we add or to std and find a name for safeDeref that doesn't use
 the word safe in a confusing manner. -- Andrei

Yes I got that. I was asking what you thought was a better name for
safeDeref.


T

-- 
Fact is stranger than fiction.


Re: Adding the ?. null verification

2014-06-22 Thread Andrei Alexandrescu via Digitalmars-d

On 6/22/14, 7:26 AM, H. S. Teoh via Digitalmars-d wrote:

On Sun, Jun 22, 2014 at 01:15:46AM -0700, Andrei Alexandrescu via Digitalmars-d 
wrote:

On 6/21/14, 3:38 PM, H. S. Teoh via Digitalmars-d wrote:

On Sat, Jun 21, 2014 at 03:26:45PM -0700, Andrei Alexandrescu via Digitalmars-d 
wrote:

On 6/19/14, 1:29 PM, Etienne wrote:

writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));


or is really nice and terse. I think we should add that to std.
safeDeref isn't the best choice of name.

[...]

What's your suggestion?


That we add or to std and find a name for safeDeref that doesn't use
the word safe in a confusing manner. -- Andrei


Yes I got that. I was asking what you thought was a better name for
safeDeref.


I'd gotten your point too, and I jokingly answered in the subtext that I 
don't have a better name. -- Andrei




Re: Adding the ?. null verification

2014-06-21 Thread Andrei Alexandrescu via Digitalmars-d

On 6/19/14, 1:29 PM, Etienne wrote:

writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));


or is really nice and terse. I think we should add that to std. 
safeDeref isn't the best choice of name.


Andrei



Re: Adding the ?. null verification

2014-06-21 Thread H. S. Teoh via Digitalmars-d
On Sat, Jun 21, 2014 at 03:26:45PM -0700, Andrei Alexandrescu via Digitalmars-d 
wrote:
 On 6/19/14, 1:29 PM, Etienne wrote:
 writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));
 
 or is really nice and terse. I think we should add that to std.
 safeDeref isn't the best choice of name.
[...]

What's your suggestion?


T

-- 
Once the bikeshed is up for painting, the rainbow won't suffice. --
Andrei Alexandrescu


Re: Adding the ?. null verification

2014-06-21 Thread deadalnix via Digitalmars-d
On Saturday, 21 June 2014 at 22:40:32 UTC, H. S. Teoh via 
Digitalmars-d wrote:
On Sat, Jun 21, 2014 at 03:26:45PM -0700, Andrei Alexandrescu 
via Digitalmars-d wrote:

On 6/19/14, 1:29 PM, Etienne wrote:
writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));

or is really nice and terse. I think we should add that to 
std.

safeDeref isn't the best choice of name.

[...]

What's your suggestion?


T


maybe is fine. Last time I checked, it isn't only a monad in 
haskell, but also vastly used by these peoples who speak english.


Re: Adding the ?. null verification

2014-06-20 Thread Etienne via Digitalmars-d

On 2014-06-19 6:23 PM, H. S. Teoh via Digitalmars-d wrote:


Unfortunately, it appears that opDispatch has become too complex to be
inlined, so now gdc is unable to simplify it to a series of nested if's.
:-(


T



Meh, I don't mind specifying that condition manually after all... having 
a default value isn't really on top of my list =)


Re: Adding the ?. null verification

2014-06-20 Thread Etienne via Digitalmars-d

On 2014-06-19 6:30 PM, H. S. Teoh via Digitalmars-d wrote:

On Thu, Jun 19, 2014 at 03:23:33PM -0700, H. S. Teoh via Digitalmars-d wrote:
[...]

Unfortunately, it appears that opDispatch has become too complex to be
inlined, so now gdc is unable to simplify it to a series of nested
if's.  :-(

[...]

Surprisingly, if we just stick .exists in there unconditionally, like
you did, then gdc actually optimizes it away completely, so that we're
back to the equivalent of nested if's! So your solution is superior
after all.  :)


T



Oh I just saw this. Good, so I can keep my .or() method ! :)


Re: Adding the ?. null verification

2014-06-20 Thread Bienlein via Digitalmars-d

On Wednesday, 18 June 2014 at 15:57:40 UTC, Etienne wrote:

On 2014-06-18 11:55 AM, bearophile wrote:

Etienne:


writeln(obj.member?.nested?.val);


What about an approach like Scala instead?

Bye,
bearophile


You mean like this?


http://stackoverflow.com/questions/1163393/best-scala-imitation-of-groovys-safe-dereference-operator

def ?[A](block: = A) =
  try { block } catch {
case e: NullPointerException if 
e.getStackTrace()(2).getMethodName == $qmark = null

case e = throw e
  }

val a = ?(b.c.d.e)


I think he means to use the Option class instead of returning 
null. Also Rust does it that way.


Re: Adding the ?. null verification

2014-06-20 Thread H. S. Teoh via Digitalmars-d
On Fri, Jun 20, 2014 at 08:57:46AM -0400, Etienne via Digitalmars-d wrote:
 On 2014-06-19 6:23 PM, H. S. Teoh via Digitalmars-d wrote:
 
 Unfortunately, it appears that opDispatch has become too complex to
 be inlined, so now gdc is unable to simplify it to a series of nested
 if's.
 :-(
 
 
 T
 
 
 Meh, I don't mind specifying that condition manually after all...
 having a default value isn't really on top of my list =)

True. Actually, I did my disassembly test again, and now I can't seem to
coax gdc to optimize out the .exists flag, esp. when .or is involved.
Perhaps that was a little too ambitious; maybe it's better to stick with
the original simple solution after all. :P


T

-- 
Laissez-faire is a French term commonly interpreted by Conservatives to mean 
'lazy fairy,' which is the belief that if governments are lazy enough, the Good 
Fairy will come down from heaven and do all their work for them.


Re: Adding the ?. null verification

2014-06-20 Thread Etienne via Digitalmars-d

On 2014-06-20 10:29 AM, H. S. Teoh via Digitalmars-d wrote:

True. Actually, I did my disassembly test again, and now I can't seem to
coax gdc to optimize out the .exists flag, esp. when .or is involved.
Perhaps that was a little too ambitious; maybe it's better to stick with
the original simple solution after all. :P


T



Try marking the or method as const, and the bool as immutable maybe?


Re: Adding the ?. null verification

2014-06-20 Thread Jacob Carlborg via Digitalmars-d

On 2014-06-19 16:37, Craig Dillabaugh wrote:


Is this any better than?

if(!a) a = b;


I would say it's about the same as a ?? b is better than a ? a : b. 
It's get better since you can use it directly in a return statement:


void a ()
{
return a ??= new Object;
}

--
/Jacob Carlborg


Re: Adding the ?. null verification

2014-06-20 Thread Jacob Carlborg via Digitalmars-d

On 2014-06-18 21:36, H. S. Teoh via Digitalmars-d wrote:


Here's a first stab at a library solution:


I thought of adding a field to indicate if a value if present or not. If 
the value is accessed when it's not present it would assert/throw.


--
/Jacob Carlborg


Re: Adding the ?. null verification

2014-06-19 Thread Andrei Alexandrescu via Digitalmars-d

On 6/18/14, 12:26 PM, Etienne wrote:

Use a maybe monad :
Maybe(obj).memeber.nested.val

This doesn't require a language construct. Also, if null check are
pervasive in your code, you probably have a problem somewhere.


There seems to be an implementation here:

https://bitbucket.org/qznc/d-monad/src/5b9d41c611093db74485b017a72473447f8d5595/generic.d?at=master


It doesn't look as good as what you're suggesting,

auto rht = Applicative!Maybe.right(r1, r2);

auto ii42 = Maybe!(Maybe!int).just(i42);

Any idea how that maybe monad would cascade through into the pointer
accessors?


opDispatch?


Re: Adding the ?. null verification

2014-06-19 Thread Timon Gehr via Digitalmars-d

On 06/18/2014 09:36 PM, H. S. Teoh via Digitalmars-d wrote:

Here's a first stab at a library solution:

/**
 * Simple-minded implementation of a Maybe monad.
 *


Nitpick: Please do not call it a 'Maybe monad'.
It is not a monad: It's neither a functor not does it have a μ operator. 
(This could be fixed though.) Furthermore, opDispatch does not behave 
analogously to a (restricted) monadic bind operator:


class C{ auto foo=maybe(C.init); }

void main(){
import std.stdio;
C c=new C;
writeln(maybe(c).foo); // Maybe(Maybe(null))
}

The result should be Maybe(null), if the data type was to remotely 
resemble a monad.


Furthermore, 'Maybe' is a more natural name for a type constructor that 
adds an additional element to another type, and 'Maybe monad' in 
particular is a term that already refers to this different meaning even 
more strongly in other communities.




Re: Adding the ?. null verification

2014-06-19 Thread Nordlöw

On Thursday, 19 June 2014 at 03:10:50 UTC, logicchains wrote:
Somebody should blog on this or put it on the front page or 
something; how many other languages allow a cost-free maybe 
monad to be implemented in library code?


I agree. This is supercool!


Re: Adding the ?. null verification

2014-06-19 Thread Jacob Carlborg via Digitalmars-d

On 2014-06-18 17:46, Kapps wrote:


C# is getting the same syntax, and I remember there being some
discussion about it here. It's somewhat useful I suppose, though I think
it's made significantly more useful in C# with 'a ?? b' (a if a is not
null, else b).


And a ??= b, assigne b to a, only if a is null.

--
/Jacob Carlborg


Re: Adding the ?. null verification

2014-06-19 Thread Etienne via Digitalmars-d

Nitpick: Please do not call it a 'Maybe monad'.
It is not a monad: It's neither a functor not does it have a μ operator.
(This could be fixed though.) Furthermore, opDispatch does not behave
analogously to a (restricted) monadic bind operator


Yes, it's more like a failsafe than a maybe. failsafe(c).left.right ...


Re: Adding the ?. null verification

2014-06-19 Thread bearophile via Digitalmars-d

Etienne:

Yes, it's more like a failsafe than a maybe. 
failsafe(c).left.right ...


I suggest to not call it Maybe/maybe to not confuse it with the 
Haskell ones.


Bye,
bearophile


Re: Adding the ?. null verification

2014-06-19 Thread Nick Treleaven via Digitalmars-d
On 18/06/2014 21:20, Ola Fosheim Grøstad 
ola.fosheim.grostad+dl...@gmail.com wrote:

On Wednesday, 18 June 2014 at 15:42:04 UTC, Etienne wrote:


writeln(obj.member?.nested?.val);



Optional chaining in swift is meant to be used more like this:

if let v = ptr?.attr?.getobj?()?.attr? {
   writeln(v)
} else {
   writeln(oops?!)
}

(I don't think Maybe will look as good.)


Perhaps Maybe could implement opCast!bool, then we could do:

if (auto v = ...)


Re: Adding the ?. null verification

2014-06-19 Thread Etienne via Digitalmars-d

On 2014-06-19 7:31 AM, Nick Treleaven wrote:

Perhaps Maybe could implement opCast!bool, then we could do:

if (auto v = ...)


That would be amazing, but maybe is used in haskell for a different 
purpose, so failsafe could be a more appropriate name I think:



if (auto k = tree.failsafe.left  auto v = 
tree.failsafe.right.leftArr.front.rightMap[k].left)

{
...
}

Would be great


Re: Adding the ?. null verification

2014-06-19 Thread Craig Dillabaugh via Digitalmars-d

On Thursday, 19 June 2014 at 10:10:30 UTC, Jacob Carlborg wrote:

On 2014-06-18 17:46, Kapps wrote:


C# is getting the same syntax, and I remember there being some
discussion about it here. It's somewhat useful I suppose, 
though I think
it's made significantly more useful in C# with 'a ?? b' (a if 
a is not

null, else b).


And a ??= b, assigne b to a, only if a is null.


Is this any better than?

if(!a) a = b;


Re: Adding the ?. null verification

2014-06-19 Thread H. S. Teoh via Digitalmars-d
On Thu, Jun 19, 2014 at 09:15:47AM -0400, Etienne via Digitalmars-d wrote:
 On 2014-06-19 7:31 AM, Nick Treleaven wrote:
 Perhaps Maybe could implement opCast!bool, then we could do:
 
 if (auto v = ...)
 
 That would be amazing, but maybe is used in haskell for a different
 purpose, so failsafe could be a more appropriate name I think:
[...]

I've been thinking about the name. I realize that it's not a true monad
in the Haskell sense, even though the implementation *was* inspired by
deadalnix's mentioning of the Maybe monad, so we really should call it
something else.  failsafe sounds a bit too generic. What about
safeDeref or just deref?

OTOH, I wonder how easy it would be to refine the current implementation
to become a true monad?


T

-- 
What is Matter, what is Mind? Never Mind, it doesn't Matter.


Re: Adding the ?. null verification

2014-06-19 Thread Etienne via Digitalmars-d

I've been thinking about the name. I realize that it's not a true monad
in the Haskell sense, even though the implementation *was* inspired by
deadalnix's mentioning of the Maybe monad, so we really should call it
something else.  failsafe sounds a bit too generic. What about
safeDeref or just deref?

OTOH, I wonder how easy it would be to refine the current implementation
to become a true monad?


T



ValueType!T / valueType(t) maybe? Its only purpose is to treat ref types 
as value types in a cascading way without restriction even when they're 
null... No idea how it could become a monad.


Re: Adding the ?. null verification

2014-06-19 Thread Nick Treleaven via Digitalmars-d

On 19/06/2014 16:04, H. S. Teoh via Digitalmars-d wrote:

we really should call it
something else.  failsafe sounds a bit too generic. What about
safeDeref or just deref?


fallback? It could have an optional argument to override init.


Re: Adding the ?. null verification

2014-06-19 Thread Tofu Ninja via Digitalmars-d

On Thursday, 19 June 2014 at 15:40:29 UTC, Nick Treleaven wrote:


fallback? It could have an optional argument to override init.


I like that, makes it obvious what it does. The optional override 
is also very good and stays in line with the idea of a fallback.


Re: Adding the ?. null verification

2014-06-19 Thread H. S. Teoh via Digitalmars-d
On Thu, Jun 19, 2014 at 10:35:59AM +0200, Timon Gehr via Digitalmars-d wrote:
 On 06/18/2014 09:36 PM, H. S. Teoh via Digitalmars-d wrote:
 Here's a first stab at a library solution:
 
  /**
   * Simple-minded implementation of a Maybe monad.
   *
 
 Nitpick: Please do not call it a 'Maybe monad'.
 It is not a monad: It's neither a functor not does it have a μ
 operator.  (This could be fixed though.) Furthermore, opDispatch does
 not behave analogously to a (restricted) monadic bind operator:
 
 class C{ auto foo=maybe(C.init); }
 
 void main(){
 import std.stdio;
 C c=new C;
 writeln(maybe(c).foo); // Maybe(Maybe(null))
 }
 
 The result should be Maybe(null), if the data type was to remotely
 resemble a monad.

Here's a slightly improved version that collapses nested wrappers into a
single wrapper, so that Maybe!(Maybe!(Maybe!...Maybe!T)...) == Maybe!T:

/**
 * A safe-dereferencing wrapper resembling a Maybe monad.
 *
 * If the wrapped object is null, any further member dereferences will 
simply
 * return a wrapper around the .init value of the member's type. Since 
non-null
 * member dereferences will also return a wrapped value, any null value 
in the
 * middle of a chain of nested dereferences will simply cause the final 
result
 * to default to the .init value of the final member's type.
 */
template SafeDeref(T)
{
static if (is(T U == SafeDeref!V, V))
{
// Merge SafeDeref!(SafeDeref!X) into just SafeDeref!X.
alias SafeDeref = U;
}
else
{
struct SafeDeref
{
T t;

// Make the wrapper as transparent as possible.
alias t this;

// This is the magic that makes it all work.
auto opDispatch(string field)()
if (is(typeof(__traits(getMember, t, field
{
alias Memb = typeof(__traits(getMember, t, field));

// If T is comparable with null, then we do a null 
check.
// Otherwise, we just dereference the member since it's
// guaranteed to be safe of null dereferences.
//
// N.B.: we always return a wrapped type in case the 
return
// type contains further nullable fields.
static if (is(typeof(t is null)))
{
return safeDeref((t is null) ? Memb.init
 : __traits(getMember, 
t,
field));
} else {
return safeDeref(__traits(getMember, t, field));
}
}
}
}
}

/**
 * Wraps an object in a safe dereferencing wrapper resembling a Maybe 
monad.
 *
 * If the object is null, then any further member dereferences will 
just return
 * a wrapper around the .init value of the wrapped type, instead of
 * dereferencing null. This applies recursively to any element in a 
chain of
 * dereferences.
 *
 * Params: t = data to wrap.
 * Returns: A wrapper around the given type, with safe member 
dereference
 * semantics.
 */
auto safeDeref(T)(T t)
{
return SafeDeref!T(t);
}

unittest
{
class Node
{
int val;
Node left, right;

this(int _val, Node _left=null, Node _right=null)
{
val = _val;
left = _left;
right = _right;
}
}

auto tree = new Node(1,
new Node(2),
new Node(3,
null,
new Node(4)
)
);

import std.stdio;
writeln(safeDeref(tree).right.right.val);
writeln(safeDeref(tree).left.right.left.right);
writeln(safeDeref(tree).left.right.left.right.val);
}

// Static test of monadic composition of SafeDeref.
unittest
{
{
struct Test {}
alias A = SafeDeref!Test;
alias B = SafeDeref!A;

static assert(is(B == SafeDeref!Test));
static assert(is(SafeDeref!B == SafeDeref!Test));
}

// Timon Gehr's original test case
{
class C
{
   

Re: Adding the ?. null verification

2014-06-19 Thread Yota via Digitalmars-d
On Wednesday, 18 June 2014 at 19:37:42 UTC, H. S. Teoh via 
Digitalmars-d wrote:
On Wed, Jun 18, 2014 at 07:04:33PM +, via Digitalmars-d 
wrote:

On Wednesday, 18 June 2014 at 17:56:46 UTC, Mattcoder wrote:
On Wednesday, 18 June 2014 at 15:42:04 UTC, Etienne wrote:
it would be a little more practical to be able to write

writeln(obj.member?.nested?.val);

If one of these: member, nested or val == null, what will 
happen with

writeln()? It will print null or it will be avoided?

The expression needs to have exactly one type, and because all 
of the

components can be non-null, it needs to be the type of the last
component, in this case `val`. This means that if the one of 
the
components is null, the entire expression needs to return a 
value of

this type, presumably the `.init` value.

The alternative is to raise an exception (or error), but that 
would

defeat the purpose (almost, as it would be slightly better than
segfaulting).


Here's a first stab at a library solution:
...
T


Won't opDispatch here destroy any hope for statement completion 
in the future?  I feel like D already has little hope for such 
tooling features, but this puts the final nail in the coffin.


Re: Adding the ?. null verification

2014-06-19 Thread Tofu Ninja via Digitalmars-d

On Thursday, 19 June 2014 at 16:58:03 UTC, Yota wrote:
Won't opDispatch here destroy any hope for statement completion 
in the future?  I feel like D already has little hope for such 
tooling features, but this puts the final nail in the coffin.


Yeah D is already really bad for auto completion, opDispatch 
just makes it harder. If we ever get to the point where the 
compiler is usable in a library form, that might pave the way to 
much better auto complete, but it looks far off.


Re: Adding the ?. null verification

2014-06-19 Thread H. S. Teoh via Digitalmars-d
On Thu, Jun 19, 2014 at 05:26:31PM +, Tofu Ninja via Digitalmars-d wrote:
 On Thursday, 19 June 2014 at 16:58:03 UTC, Yota wrote:
 Won't opDispatch here destroy any hope for statement completion in
 the future?  I feel like D already has little hope for such tooling
 features, but this puts the final nail in the coffin.
 
 Yeah D is already really bad for auto completion, opDispatch just
 makes it harder. If we ever get to the point where the compiler is
 usable in a library form, that might pave the way to much better auto
 complete, but it looks far off.

In this case, the signature constraint on opDispatch could be used for
auto completion:

auto opDispatch(string field)()
if (is(typeof(__traits(getMember, t, field
...

From the signature constraint, it should be obvious that field must be
among the members of t.

Of course, checking signature constraints isn't always practical in the
general case where it may be arbitrarily complex, but obvious cases like
this one should be easily manageable, no?


T

-- 
Let's not fight disease by killing the patient. -- Sean 'Shaleh' Perry


Re: Adding the ?. null verification

2014-06-19 Thread Tobias Pankrath via Digitalmars-d




In this case, the signature constraint on opDispatch could be 
used for

auto completion:

auto opDispatch(string field)()
if (is(typeof(__traits(getMember, t, field
...

From the signature constraint, it should be obvious that 
field must be

among the members of t.

Of course, checking signature constraints isn't always 
practical in the
general case where it may be arbitrarily complex, but obvious 
cases like

this one should be easily manageable, no?


In this case auto completion could work flawless because of

alias this t;

At least for cases where even a frontend based tool has a hard 
time, we could introduce a ddoc section for this, if there really 
is a need.


/**
 * Dispatch method call.
 * Completion: LIKE t
 */
auto opDispatch(string field)() { ... }

If phobos does this consistently the tools will recognize this.



Re: Adding the ?. null verification

2014-06-19 Thread Etienne via Digitalmars-d

In this case auto completion could work flawless because of

alias this t;

At least for cases where even a frontend based tool has a hard time, we
could introduce a ddoc section for this, if there really is a need.

/**
  * Dispatch method call.
  * Completion: LIKE t
  */
auto opDispatch(string field)() { ... }

If phobos does this consistently the tools will recognize this.



Nice, that's a great trick (recognizing alias this t). Mono-D doesn't 
have that yet, I'll get the word accross


Re: Adding the ?. null verification

2014-06-19 Thread H. S. Teoh via Digitalmars-d
On Thu, Jun 19, 2014 at 04:40:22PM +0100, Nick Treleaven via Digitalmars-d 
wrote:
 On 19/06/2014 16:04, H. S. Teoh via Digitalmars-d wrote:
 we really should call it something else.  failsafe sounds a bit too
 generic. What about safeDeref or just deref?
 
 fallback? It could have an optional argument to override init.

I've thought about adding an optional argument to override init, but
unfortunately I can't think of a nice way to implement it. The problem
is that in order for the wrapper to work, it has to wrap around each
individual component of the dereferencing chain. So if you have a chain
like this:

safeDeref(obj).subobj.prop.field.val

then the safeDeref wrapper only knows about obj, so it wouldn't know
what type .val is, because it can't tell beforehand which field you're
going to dereference next, and different fields may have different
types, nor where is the end of the chain. So it wouldn't know when to
return the specified default value.

As of now, I don't know of any way of passing the entire chain to
safeDeref without making it really ugly. Writing:

safeDeref(obj.subobj.prop.field.val, defaultValue)

doesn't work because before the wrapper even gets invoked, you've
already dereferenced all the fields (and crashed on the null if there's
one in there). The only way I can think of to pass everything to the
wrapper is via a variadic list of alias parameters, but it looks very
ugly in practice:

safeDeref!(defaultValue, obj, subobj, prop, field, val)

I've thought about having a penultimate wrapper in the chain:

safeDeref(obj).subobj.prop.field.failsafe(defaultVal).val

But this doesn't work either for the same reason: failsafe() doesn't
know the next item in the chain will be .val (instead of, say, .length
which has a different type).

A possible compromise is:

safeDeref(obj).subobj.prop.field.failsafe!val(defaultVal)

where the last element is passed as an alias to the failsafe template,
which then does the .init-replacement magic. It looks a lot uglier,
though. :-(


T

-- 
People demand freedom of speech to make up for the freedom of thought which 
they avoid. -- Soren Aabye Kierkegaard (1813-1855)


Re: Adding the ?. null verification

2014-06-19 Thread Timon Gehr via Digitalmars-d

On 06/19/2014 06:58 PM, Yota wrote:


Won't opDispatch here destroy any hope for statement completion in the
future?  I feel like D already has little hope for such tooling
features, but this puts the final nail in the coffin.


auto opDispatch(string field)()
if(is(typeof(__traits(getMember, t, field // -- not a nail


Re: Adding the ?. null verification

2014-06-19 Thread Etienne via Digitalmars-d

On 2014-06-19 3:11 PM, H. S. Teoh via Digitalmars-d wrote:


safeDeref(obj).subobj.prop.field.failsafe!val(defaultVal)

where the last element is passed as an alias to the failsafe template,
which then does the .init-replacement magic. It looks a lot uglier,
though. :-(


T



meh, this works:


writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));

..
static struct SafeDeref {
T t;

// Make the wrapper as transparent as possible.
alias t this;

// this overrides if null
T or(T defVal){
if (t is t.init)
{
return defVal;
}
else
{
return t;
}

}
..


Re: Adding the ?. null verification

2014-06-19 Thread H. S. Teoh via Digitalmars-d
On Thu, Jun 19, 2014 at 04:29:12PM -0400, Etienne via Digitalmars-d wrote:
 On 2014-06-19 3:11 PM, H. S. Teoh via Digitalmars-d wrote:
 
  safeDeref(obj).subobj.prop.field.failsafe!val(defaultVal)
 
 where the last element is passed as an alias to the failsafe template,
 which then does the .init-replacement magic. It looks a lot uglier,
 though. :-(
 
 
 T
 
 
 meh, this works:
 
 
 writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));
 
 ..
   static struct SafeDeref {
   T t;
   
   // Make the wrapper as transparent as possible.
   alias t this;
 
   // this overrides if null
   T or(T defVal){
   if (t is t.init)

This assumes that t.init is not a possible valid field value. But in
that case, there's no need to remap it, you just check for t.init
instead. For pointers, where .init is null, this isn't a problem, but
for things like int, where 0 is possible valid value, you may be
accidentally mapping 0 to the default value when the given field
actually exists (and has value 0)!


   {
   return defVal;
   }
   else
   {
   return t;
   }
   
   }
 ..


T

-- 
Gone Chopin. Bach in a minuet.


Re: Adding the ?. null verification

2014-06-19 Thread H. S. Teoh via Digitalmars-d
On Thu, Jun 19, 2014 at 01:51:17PM -0700, H. S. Teoh via Digitalmars-d wrote:
 On Thu, Jun 19, 2014 at 04:29:12PM -0400, Etienne via Digitalmars-d wrote:
[...]
  meh, this works:
  
  
  writeln(currAssignment.safeDeref.typeInfo.ident.or(meh));
  
  ..
  static struct SafeDeref {
  T t;
  
  // Make the wrapper as transparent as possible.
  alias t this;
  
  // this overrides if null
  T or(T defVal){
  if (t is t.init)
 
 This assumes that t.init is not a possible valid field value. But in
 that case, there's no need to remap it, you just check for t.init
 instead. For pointers, where .init is null, this isn't a problem, but
 for things like int, where 0 is possible valid value, you may be
 accidentally mapping 0 to the default value when the given field
 actually exists (and has value 0)!
[...]

Actually, on second thoughts, maybe it *is* possible after all. The key
is to differentiate between null-able types, and non-nullable types. For
the latter, we expand the SafeDeref struct to store a boolean flag to
indicate whether or not the value exists, then .or() can check that flag
to see if it should return the default value. Basically, something like
this:

struct SafeDeref {
T t;

static if (!is(t = null))
bool exists = true;

...
T or(T defVal) {
return (exists) ? t : defVal;
}
...
auto opDispatch(...) {
...
if (t is null)
return safeDeref(Memb.init, false)
else
return safeDeref(__traits(getMember...), true);
}
}

I'll try this out to see if it works!

This also has the advantage of becoming even closer to a real monad: by
checking for .exists, we can also overload operators to return a wrapper
with exists=false whenever one of the operands also has exists=false.


T

-- 
Why can't you just be a nonconformist like everyone else? -- YHL


Re: Adding the ?. null verification

2014-06-19 Thread Etienne via Digitalmars-d

On 2014-06-19 4:51 PM, H. S. Teoh via Digitalmars-d wrote:

This assumes that t.init is not a possible valid field value. But in
that case, there's no need to remap it, you just check for t.init
instead. For pointers, where .init is null, this isn't a problem, but
for things like int, where 0 is possible valid value, you may be
accidentally mapping 0 to the default value when the given field
actually exists (and has value 0)!


True, you need to mark failure and drag it to the end. Here's another 
try at it:


auto safeDeref(T)(T t, bool failed = false) {
static struct SafeDeref {
T t;
bool fail;
// Make the wrapper as transparent as possible.
alias t this;

auto or(T defVal){
if (fail)
{
return defVal;
}
else
{
return t;
}

}
// This is the magic that makes it all work.
auto opDispatch(string field)()
if (is(typeof(__traits(getMember, t, field
{
alias Memb = typeof(__traits(getMember, t, field));


static if (is(typeof(t is null))) {
return safeDeref((t is null) ? Memb.init
 : __traits(getMember, t, field), (t is null) ? true 
: false);

} else {
return safeDeref(__traits(getMember, t, field), 
fail);
}
}
}
return SafeDeref(t, failed);
}




Re: Adding the ?. null verification

2014-06-19 Thread Etienne via Digitalmars-d

On 2014-06-19 5:05 PM, Etienne wrote:

: __traits(getMember, t, field), (t is null) ? true : false);



(t is null || fail) ? true : false


Re: Adding the ?. null verification

2014-06-19 Thread Andrei Alexandrescu via Digitalmars-d

On 6/18/14, 10:39 AM, deadalnix wrote:

Use a maybe monad :
Maybe(obj).memeber.nested.val


Yah, I keep on thinking we should explore the maybe monad more 
thoroughly as a library in D. -- Andrei




Re: Adding the ?. null verification

2014-06-19 Thread H. S. Teoh via Digitalmars-d
On Thu, Jun 19, 2014 at 05:05:51PM -0400, Etienne via Digitalmars-d wrote:
 On 2014-06-19 4:51 PM, H. S. Teoh via Digitalmars-d wrote:
 This assumes that t.init is not a possible valid field value. But in
 that case, there's no need to remap it, you just check for t.init
 instead. For pointers, where .init is null, this isn't a problem, but
 for things like int, where 0 is possible valid value, you may be
 accidentally mapping 0 to the default value when the given field
 actually exists (and has value 0)!
 
 True, you need to mark failure and drag it to the end. Here's another
 try at it:
 
 auto safeDeref(T)(T t, bool failed = false) {
   static struct SafeDeref {
   T t;
   bool fail;

The trouble with this is that you pay for the storage cost of .fail even
if T already has a perfectly fine null value which serves the same
purpose. Here's my take on it:

/**
 * A safe-dereferencing wrapper resembling a Maybe monad.
 *
 * If the wrapped object is null, any further member dereferences will 
simply
 * return a wrapper around the .init value of the member's type. Since 
non-null
 * member dereferences will also return a wrapped value, any null value 
in the
 * middle of a chain of nested dereferences will simply cause the final 
result
 * to default to the .init value of the final member's type.
 */
template SafeDeref(T)
{
static if (is(T U == SafeDeref!V, V))
{
// Merge SafeDeref!(SafeDeref!X) into just SafeDeref!X.
alias SafeDeref = U;
}
else
{
enum hasNullValue(U) = is(typeof(U is null));

struct SafeDeref
{
T t;

// Make the wrapper as transparent as possible.
alias t this;

// Wrapped types that don't have a null value get an 
additional
// flag to indicate existence.
static if (!hasNullValue!T)
{
bool exists = true;

T or(T defaultVal) { return exists ? t : defaultVal; }
}
else
{
T or(T defaultVal) { return t is null ? T.init : t; }
}

// This is the magic that makes it all work.
auto opDispatch(string field)()
if (is(typeof(__traits(getMember, t, field
{
alias Memb = typeof(__traits(getMember, t, field));

// If T is comparable with null, then we do a null 
check.
// Otherwise, we just dereference the member since it's
// guaranteed to be safe of null dereferences.
//
// N.B.: we always return a wrapped type in case the 
return
// type contains further nullable fields.
static if (is(typeof(t is null)))
{
if (t is null)
{
static if (hasNullValue!Memb)
return SafeDeref!Memb(Memb.init);
else
return SafeDeref!Memb(Memb.init, false);
}
return SafeDeref!Memb(__traits(getMember, t, 
field));
} else {
return SafeDeref!Memb(__traits(getMember, t, 
field));
}
}
}
}
}

/**
 * Wraps an object in a safe dereferencing wrapper resembling a Maybe 
monad.
 *
 * If the object is null, then any further member dereferences will 
just return
 * a wrapper around the .init value of the wrapped type, instead of
 * dereferencing null. This applies recursively to any element in a 
chain of
 * dereferences.
 *
 * Params: t = data to wrap.
 * Returns: A wrapper around the given type, with safe member 
dereference
 * semantics.
 */
auto safeDeref(T)(T t)
{
return SafeDeref!T(t);
}

///
unittest
{
class Node
{
int val;
Node left, right;

this(int _val, Node _left=null, Node _right=null)
{
val = _val;
left = _left;
right = _right;
}
}

auto tree = new Node(1,
new Node(2),
new 

Re: Adding the ?. null verification

2014-06-19 Thread Meta via Digitalmars-d
On Thursday, 19 June 2014 at 21:34:07 UTC, Andrei Alexandrescu 
wrote:

On 6/18/14, 10:39 AM, deadalnix wrote:

Use a maybe monad :
Maybe(obj).memeber.nested.val


Yah, I keep on thinking we should explore the maybe monad more 
thoroughly as a library in D. -- Andrei


The other night for fun I tried implementing an Option type as a 
RandomAccessRange. When a value exists, the range is not empty 
and has length 1, otherwise it is empty and has length 0, with 
the other primitives doing as expected. It's neat how you then 
automatically get all current and future range algorithms for 
free. One problem I found trying to use map like bind in Haskell 
is that it does the exact opposite of what I want. The result is 
not Option!int, but MapResult!(__lambda3, Option!int).


Re: Adding the ?. null verification

2014-06-19 Thread H. S. Teoh via Digitalmars-d
On Thu, Jun 19, 2014 at 02:37:33PM -0700, H. S. Teoh via Digitalmars-d wrote:
[...]
 Here, I've made it so that the .exists field is only present if the
 wrapped type T doesn't have a null value that can serve as an
 existence marker.
 
 I'm not sure if this is the right thing to do 100% of the time,
 because conceivably, somebody might want to distinguish between a
 pointer field that has null as a value, as opposed to a pointer field
 that doesn't exist. But I think such cases should be very rare; and
 cutting out the .exists field where unnecessary also keeps the size of
 the wrapper struct minimal, so that it's easier for the compiler's
 optimizer to completely optimize it out for pointer values.
 (Unfortunately I ran into a snag with gdc due to latest dmd features
 that haven't made it into gdc, so I haven't been able to actually
 check the assembly output -- I'll try to iron that out and post the
 results.)
[...]

Unfortunately, it appears that opDispatch has become too complex to be
inlined, so now gdc is unable to simplify it to a series of nested if's.
:-(


T

-- 
It's bad luck to be superstitious. -- YHL


Re: Adding the ?. null verification

2014-06-19 Thread H. S. Teoh via Digitalmars-d
On Thu, Jun 19, 2014 at 03:23:33PM -0700, H. S. Teoh via Digitalmars-d wrote:
[...]
 Unfortunately, it appears that opDispatch has become too complex to be
 inlined, so now gdc is unable to simplify it to a series of nested
 if's.  :-(
[...]

Surprisingly, if we just stick .exists in there unconditionally, like
you did, then gdc actually optimizes it away completely, so that we're
back to the equivalent of nested if's! So your solution is superior
after all.  :)


T

-- 
No, John.  I want formats that are actually useful, rather than over-featured 
megaliths that address all questions by piling on ridiculous internal links in 
forms which are hideously over-complex. -- Simon St. Laurent on xml-dev


Adding the ?. null verification

2014-06-18 Thread Etienne via Digitalmars-d

I find myself often repeating this boilerplate:

if (obj.member !is null)
{
if (obj.member.nested !is null)
{
if (obj.member.nested.val !is null)
{
writeln(obj.member.nested.val);
}
}
}

I have to admit it's a little frustrating when you see swift's ?. syntax 
notation, it would be a little more practical to be able to write


writeln(obj.member?.nested?.val);


Based on http://appventure.me/2014/06/13/swift-optionals-made-simple/


Any thoughts?



Re: Adding the ?. null verification

2014-06-18 Thread Kapps via Digitalmars-d

On Wednesday, 18 June 2014 at 15:42:04 UTC, Etienne wrote:

I find myself often repeating this boilerplate:

if (obj.member !is null)
{
if (obj.member.nested !is null)
{
if (obj.member.nested.val !is null)
{
writeln(obj.member.nested.val);
}
}
}

I have to admit it's a little frustrating when you see swift's 
?. syntax notation, it would be a little more practical to be 
able to write


writeln(obj.member?.nested?.val);


Based on 
http://appventure.me/2014/06/13/swift-optionals-made-simple/



Any thoughts?


C# is getting the same syntax, and I remember there being some 
discussion about it here. It's somewhat useful I suppose, though 
I think it's made significantly more useful in C# with 'a ?? b' 
(a if a is not null, else b).


Re: Adding the ?. null verification

2014-06-18 Thread Etienne via Digitalmars-d

C# is getting the same syntax, and I remember there being some
discussion about it here. It's somewhat useful I suppose, though I think
it's made significantly more useful in C# with 'a ?? b' (a if a is not
null, else b).



I've seen too many bugs where you end up dereferencing a null pointer, 
also with the - being replaced by . in D this is even more confusing 
when you switch a member from a pointer to a struct. The compiler could 
easily advise you to use the .? notation when you're moving in too deep 
into no man's land.


Re: Adding the ?. null verification

2014-06-18 Thread Lionello Lunesu via Digitalmars-d

On 18/06/14 23:42, Etienne wrote:

I find myself often repeating this boilerplate:

if (obj.member !is null)
{
 if (obj.member.nested !is null)
 {
 if (obj.member.nested.val !is null)
 {
 writeln(obj.member.nested.val);
 }
 }
}

I have to admit it's a little frustrating when you see swift's ?. syntax
notation, it would be a little more practical to be able to write

writeln(obj.member?.nested?.val);


Based on http://appventure.me/2014/06/13/swift-optionals-made-simple/


Any thoughts?


I want non-null in the type system! To put a nullable reference into a 
non-null variable you need to check first, but from then on the compiler 
can ensure it's never null!


Re: Adding the ?. null verification

2014-06-18 Thread bearophile via Digitalmars-d

Etienne:


writeln(obj.member?.nested?.val);


What about an approach like Scala instead?

Bye,
bearophile


Re: Adding the ?. null verification

2014-06-18 Thread Etienne via Digitalmars-d

On 2014-06-18 11:55 AM, bearophile wrote:

Etienne:


writeln(obj.member?.nested?.val);


What about an approach like Scala instead?

Bye,
bearophile


You mean like this?


http://stackoverflow.com/questions/1163393/best-scala-imitation-of-groovys-safe-dereference-operator

def ?[A](block: = A) =
  try { block } catch {
case e: NullPointerException if e.getStackTrace()(2).getMethodName 
== $qmark = null

case e = throw e
  }

val a = ?(b.c.d.e)



Re: Adding the ?. null verification

2014-06-18 Thread Etienne via Digitalmars-d

I want non-null in the type system! To put a nullable reference into a
non-null variable you need to check first, but from then on the compiler
can ensure it's never null!


That would be great but useless for my situation involving some complex 
AST's


class AEntity
{
Module head;
string ident;
Type type;
AEntity typeInfo;
AEntity[] members; // for definitions
AEntity[] parameters; // if parameterized
...
}

It's very useful to descend through parts of a complex tree without 
adding plenty of bool checks


foreach (AEntity member; entity.members)
{
if (member.typeInfo !is null)
{
AEntity curr = member;
member.ident ~= member.typeInfo.ident;
curr = member.typeInfo;
while (curr.typeInfo !is null)
{
member.ident ~= . ~ curr.typeInfo.ident;
curr = curr.typeInfo;
}
}
}


Re: Adding the ?. null verification

2014-06-18 Thread Ary Borenszweig via Digitalmars-d

On 6/18/14, 1:17 PM, Etienne wrote:

I want non-null in the type system! To put a nullable reference into a
non-null variable you need to check first, but from then on the compiler
can ensure it's never null!


That would be great but useless for my situation involving some complex
AST's

class AEntity
{
 Module head;
 string ident;
 Type type;
 AEntity typeInfo;
 AEntity[] members; // for definitions
 AEntity[] parameters; // if parameterized
...
}

It's very useful to descend through parts of a complex tree without
adding plenty of bool checks

foreach (AEntity member; entity.members)
{
 if (member.typeInfo !is null)
 {
 AEntity curr = member;
 member.ident ~= member.typeInfo.ident;
 curr = member.typeInfo;
 while (curr.typeInfo !is null)
 {
 member.ident ~= . ~ curr.typeInfo.ident;
 curr = curr.typeInfo;
 }
 }
}


But if you don't add the bool checks you might get segmentation fault. 
Or am I missing something?




Re: Adding the ?. null verification

2014-06-18 Thread Etienne via Digitalmars-d

But if you don't add the bool checks you might get segmentation fault.
Or am I missing something?



In D all pointers are zero-filled on initialization so it counts as a 
bool for me and null is the same as if you had a *.init


Re: Adding the ?. null verification

2014-06-18 Thread Frustrated via Digitalmars-d

On Wednesday, 18 June 2014 at 15:42:04 UTC, Etienne wrote:

I find myself often repeating this boilerplate:

if (obj.member !is null)
{
if (obj.member.nested !is null)
{
if (obj.member.nested.val !is null)
{
writeln(obj.member.nested.val);
}
}
}

I have to admit it's a little frustrating when you see swift's 
?. syntax notation, it would be a little more practical to be 
able to write


writeln(obj.member?.nested?.val);


Based on 
http://appventure.me/2014/06/13/swift-optionals-made-simple/



Any thoughts?


Would be great! I think though, one could simplify it, you don't 
need multiple ?'s(one would do)


if (?obj.member.nested.val == null)
{
...
}

?object returns null if the object is null, even if it is 
dereferenced.


possibly a better syntax would be

if (??obj.member.nested.val == null)

If used as a rval one could have

auto x = ??obj.member.nested.val;

x is null if obj, obj.member, or obj.member.nested is null. Else 
obj.member.nested.val.


I'm just curious who is going to add the the code to D?

If you don't like ?? (confusing it with the null-coalescing 
operator) then what about ?*, *?, ?, ?, ???, etc...




Re: Adding the ?. null verification

2014-06-18 Thread deadalnix via Digitalmars-d

On Wednesday, 18 June 2014 at 15:42:04 UTC, Etienne wrote:

I find myself often repeating this boilerplate:

if (obj.member !is null)
{
if (obj.member.nested !is null)
{
if (obj.member.nested.val !is null)
{
writeln(obj.member.nested.val);
}
}
}

I have to admit it's a little frustrating when you see swift's 
?. syntax notation, it would be a little more practical to be 
able to write


writeln(obj.member?.nested?.val);


Based on 
http://appventure.me/2014/06/13/swift-optionals-made-simple/



Any thoughts?


Use a maybe monad :
Maybe(obj).memeber.nested.val

This doesn't require a language construct. Also, if null check 
are pervasive in your code, you probably have a problem somewhere.


Re: Adding the ?. null verification

2014-06-18 Thread Mattcoder via Digitalmars-d

On Wednesday, 18 June 2014 at 15:42:04 UTC, Etienne wrote:

it would be a little more practical to be able to write

writeln(obj.member?.nested?.val);


If one of these: member, nested or val == null, what will happen 
with writeln()? It will print null or it will be avoided?


Matheus.


Re: Adding the ?. null verification

2014-06-18 Thread via Digitalmars-d

On Wednesday, 18 June 2014 at 17:56:46 UTC, Mattcoder wrote:

On Wednesday, 18 June 2014 at 15:42:04 UTC, Etienne wrote:

it would be a little more practical to be able to write

writeln(obj.member?.nested?.val);


If one of these: member, nested or val == null, what will 
happen with writeln()? It will print null or it will be avoided?


The expression needs to have exactly one type, and because all of 
the components can be non-null, it needs to be the type of the 
last component, in this case `val`. This means that if the one of 
the components is null, the entire expression needs to return a 
value of this type, presumably the `.init` value.


The alternative is to raise an exception (or error), but that 
would defeat the purpose (almost, as it would be slightly better 
than segfaulting).


Re: Adding the ?. null verification

2014-06-18 Thread Etienne via Digitalmars-d

Use a maybe monad :
Maybe(obj).memeber.nested.val

This doesn't require a language construct. Also, if null check are
pervasive in your code, you probably have a problem somewhere.


There seems to be an implementation here:

https://bitbucket.org/qznc/d-monad/src/5b9d41c611093db74485b017a72473447f8d5595/generic.d?at=master

It doesn't look as good as what you're suggesting,

auto rht = Applicative!Maybe.right(r1, r2);

auto ii42 = Maybe!(Maybe!int).just(i42);

Any idea how that maybe monad would cascade through into the pointer 
accessors?


Re: Adding the ?. null verification

2014-06-18 Thread Mattcoder via Digitalmars-d

On Wednesday, 18 June 2014 at 19:04:34 UTC, Marc Schütz wrote:
... This means that if the one of the components is null, the 
entire expression needs to return a value of this type, 
presumably the `.init` value.


I got it! Thanks.

Matheus.


Re: Adding the ?. null verification

2014-06-18 Thread H. S. Teoh via Digitalmars-d
On Wed, Jun 18, 2014 at 07:04:33PM +, via Digitalmars-d wrote:
 On Wednesday, 18 June 2014 at 17:56:46 UTC, Mattcoder wrote:
 On Wednesday, 18 June 2014 at 15:42:04 UTC, Etienne wrote:
 it would be a little more practical to be able to write
 
 writeln(obj.member?.nested?.val);
 
 If one of these: member, nested or val == null, what will happen with
 writeln()? It will print null or it will be avoided?
 
 The expression needs to have exactly one type, and because all of the
 components can be non-null, it needs to be the type of the last
 component, in this case `val`. This means that if the one of the
 components is null, the entire expression needs to return a value of
 this type, presumably the `.init` value.
 
 The alternative is to raise an exception (or error), but that would
 defeat the purpose (almost, as it would be slightly better than
 segfaulting).

Here's a first stab at a library solution:

/**
 * Simple-minded implementation of a Maybe monad.
 *
 * Params: t = data to wrap.
 * Returns: A wrapper around the given type, with safe member 
dereference
 * semantics, that is, if t is null, then any further member 
dereferences will
 * just return a wrapper around the .init value of the wrapped type, 
instead of
 * deferencing the null and crashing.
 */
auto maybe(T)(T t) {
static struct Maybe {
T t;

// Make the wrapper as transparent as possible.
alias t this;

// This is the magic that makes it all work.
auto opDispatch(string field)()
if (is(typeof(__traits(getMember, t, field
{
alias Memb = typeof(__traits(getMember, t, 
field));

// If T is comparable with null, then we do a 
null
// check. Otherwise, we just dereference the 
member
// since it's guaranteed to be safe of null
// dereferences.
//
// N.B.: we always return a wrapped type in 
case the
// return type contains further nullable fields.
static if (is(typeof(t is null))) {
return maybe((t is null) ? Memb.init
: 
__traits(getMember, t, field));
} else {
return maybe(__traits(getMember, t, 
field));
}
}
}
return Maybe(t);
}

/**
 * A sample tree structure to test the above code.
 */
class Node {
int val;
Node left, right;

this(int _val, Node _left=null, Node _right=null) {
val = _val;
left = _left;
right = _right;
}
}

void main() {
import std.stdio;

auto tree = new Node(1,
new Node(2),
new Node(3,
null,
new Node(4)
)
);

writeln(maybe(tree).right.right.val);
writeln(maybe(tree).left.right.left.right);
writeln(maybe(tree).left.right.left.right.val);
}

Program output:

4
Maybe(null)
0

It's not perfect, but as you can see, attempting to dereference null
just returns the result type's .init value. You can also modify the code
where it returns Memb.init, to also log a message to a debug log that
indicates a possible logic problem with the code (failure to check for
null, etc.).

This also allows you to do a complete null check in a single statement:

if (maybe(tree).left.right.right.left.right !is null) {
// do something with that value
}

If nothing else, this at least saves you the trouble of having to check
every intermediate reference in the chain. :)

The only wart I can see currently is the Maybe(null) appearing in the
writeln output, instead of just null, but that can be worked around by
implementing a toString method in the Maybe struct that forwards to the
wrapped type's toString method (or something along those lines).

Anyway, this is just a first shot at it. You can probably build
something more sophisticated out of it. :)


T

-- 
Just because you survived after you did it, doesn't mean it wasn't stupid!


Re: Adding the ?. null verification

2014-06-18 Thread Etienne via Digitalmars-d

This also allows you to do a complete null check in a single statement:

if (maybe(tree).left.right.right.left.right !is null) {
// do something with that value
}

If nothing else, this at least saves you the trouble of having to check
every intermediate reference in the chain. :)



Very clever, this should go straight to std.typecons. I'm definitely 
ripping it for my project, if you can just scratch something like a 
boost license on it ;)


Re: Adding the ?. null verification

2014-06-18 Thread Meta via Digitalmars-d
On Wednesday, 18 June 2014 at 19:37:42 UTC, H. S. Teoh via 
Digitalmars-d wrote:

Here's a first stab at a library solution:

/**
 * Simple-minded implementation of a Maybe monad.
 *
 * Params: t = data to wrap.
	 * Returns: A wrapper around the given type, with safe 
member dereference
	 * semantics, that is, if t is null, then any further member 
dereferences will
	 * just return a wrapper around the .init value of the wrapped 
type, instead of

 * deferencing the null and crashing.
 */
auto maybe(T)(T t) {
static struct Maybe {
T t;

// Make the wrapper as transparent as possible.
alias t this;

// This is the magic that makes it all work.
auto opDispatch(string field)()
if (is(typeof(__traits(getMember, t, field
{
alias Memb = typeof(__traits(getMember, t, 
field));

// If T is comparable with null, then we do a 
null
// check. Otherwise, we just dereference the 
member
// since it's guaranteed to be safe of null
// dereferences.
//
// N.B.: we always return a wrapped type in 
case the
// return type contains further nullable fields.
static if (is(typeof(t is null))) {
return maybe((t is null) ? Memb.init
: 
__traits(getMember, t, field));
} else {
return maybe(__traits(getMember, t, 
field));
}
}
}
return Maybe(t);
}

/**
 * A sample tree structure to test the above code.
 */
class Node {
int val;
Node left, right;

this(int _val, Node _left=null, Node _right=null) {
val = _val;
left = _left;
right = _right;
}
}

void main() {
import std.stdio;

auto tree = new Node(1,
new Node(2),
new Node(3,
null,
new Node(4)
)
);

writeln(maybe(tree).right.right.val);
writeln(maybe(tree).left.right.left.right);
writeln(maybe(tree).left.right.left.right.val);
}

Program output:

4
Maybe(null)
0

It's not perfect, but as you can see, attempting to dereference 
null
just returns the result type's .init value. You can also modify 
the code
where it returns Memb.init, to also log a message to a debug 
log that
indicates a possible logic problem with the code (failure to 
check for

null, etc.).

This also allows you to do a complete null check in a single 
statement:


if (maybe(tree).left.right.right.left.right !is null) {
// do something with that value
}

If nothing else, this at least saves you the trouble of having 
to check

every intermediate reference in the chain. :)

The only wart I can see currently is the Maybe(null) 
appearing in the
writeln output, instead of just null, but that can be worked 
around by
implementing a toString method in the Maybe struct that 
forwards to the

wrapped type's toString method (or something along those lines).

Anyway, this is just a first shot at it. You can probably build
something more sophisticated out of it. :)


T


That's nifty. opDispatch can do some cool stuff.


Re: Adding the ?. null verification

2014-06-18 Thread Dmitry Olshansky via Digitalmars-d

18-Jun-2014 23:36, H. S. Teoh via Digitalmars-d пишет:


Here's a first stab at a library solution:


[snip]


The only wart I can see currently is the Maybe(null) appearing in the
writeln output, instead of just null, but that can be worked around by
implementing a toString method in the Maybe struct that forwards to the
wrapped type's toString method (or something along those lines).

Anyway, this is just a first shot at it. You can probably build
something more sophisticated out of it. :)



And most importantly make a pull request!


--
Dmitry Olshansky


Re: Adding the ?. null verification

2014-06-18 Thread deadalnix via Digitalmars-d

On Wednesday, 18 June 2014 at 19:26:21 UTC, Etienne wrote:

Use a maybe monad :
Maybe(obj).memeber.nested.val

This doesn't require a language construct. Also, if null check 
are

pervasive in your code, you probably have a problem somewhere.


There seems to be an implementation here:

https://bitbucket.org/qznc/d-monad/src/5b9d41c611093db74485b017a72473447f8d5595/generic.d?at=master

It doesn't look as good as what you're suggesting,

auto rht = Applicative!Maybe.right(r1, r2);

auto ii42 = Maybe!(Maybe!int).just(i42);

Any idea how that maybe monad would cascade through into the 
pointer accessors?


With opDispatch. That is how it is supposed to work.


Re: Adding the ?. null verification

2014-06-18 Thread bearophile via Digitalmars-d

H. S. Teoh:

This also allows you to do a complete null check in a single 
statement:


if (maybe(tree).left.right.right.left.right !is null) {


Better with UFCS?

if (tree.perhaps.left.right.right.left.right !is null) {

Bye,
bearophile


Re: Adding the ?. null verification

2014-06-18 Thread H. S. Teoh via Digitalmars-d
On Wed, Jun 18, 2014 at 03:46:40PM -0400, Etienne via Digitalmars-d wrote:
 This also allows you to do a complete null check in a single
 statement:
 
  if (maybe(tree).left.right.right.left.right !is null) {
  // do something with that value
  }
 
 If nothing else, this at least saves you the trouble of having to
 check every intermediate reference in the chain. :)
 
 
 Very clever, this should go straight to std.typecons. I'm definitely
 ripping it for my project, if you can just scratch something like a
 boost license on it ;)

Feel free to copy it and do whatever you want with it. It's public
domain code, as of right now. :)


T

-- 
Marketing: the art of convincing people to pay for what they didn't need
before which you can't deliver after.


Re: Adding the ?. null verification

2014-06-18 Thread Adam D. Ruppe via Digitalmars-d
Fun fact btw: if you are using methods via ufcs you can check for 
null in there:


class Foo {}

void something(Foo foo) {
   if(foo is null) return;
   foo.something_internal();
}

auto foo = new Foo();
foo.something(); // cool

foo = null;
foo.something(); // still cool


Re: Adding the ?. null verification

2014-06-18 Thread via Digitalmars-d

On Wednesday, 18 June 2014 at 15:42:04 UTC, Etienne wrote:


writeln(obj.member?.nested?.val);



Optional chaining in swift is meant to be used more like this:

if let v = ptr?.attr?.getobj?()?.attr? {
  writeln(v)
} else {
  writeln(oops?!)
}

(I don't think Maybe will look as good.)


Re: Adding the ?. null verification

2014-06-18 Thread H. S. Teoh via Digitalmars-d
On Wed, Jun 18, 2014 at 12:36:01PM -0700, H. S. Teoh via Digitalmars-d wrote:
 On Wed, Jun 18, 2014 at 07:04:33PM +, via Digitalmars-d wrote:
[...]
  The expression needs to have exactly one type, and because all of the
  components can be non-null, it needs to be the type of the last
  component, in this case `val`. This means that if the one of the
  components is null, the entire expression needs to return a value of
  this type, presumably the `.init` value.
  
  The alternative is to raise an exception (or error), but that would
  defeat the purpose (almost, as it would be slightly better than
  segfaulting).
 
 Here's a first stab at a library solution:
[...]

I decided to run some tests on the compiled code to see how performant
it was. With dmd, I was unable to get it to inline all the opDispatch
calls, even with -O -inline, so the result was rather disappointing.
However, with gdc -O3 -finline, all of the opDispatch calls got inlined,
and the assembly is the direct equivalent of:

if (tree !is null)
if (tree.left !is null)
...
writeln(tree.left.right. ... .val);

So this is evidence that even this preliminary implementation already
has rather good potential. Perhaps I'll kick up a pull request for it
soon. :)


T

-- 
In theory, software is implemented according to the design that has been
carefully worked out beforehand. In practice, design documents are
written after the fact to describe the sorry mess that has gone on
before.


Re: Adding the ?. null verification

2014-06-18 Thread Lionello Lunesu via Digitalmars-d

On 19/06/14 00:17, Etienne wrote:

I want non-null in the type system! To put a nullable reference into a
non-null variable you need to check first, but from then on the compiler
can ensure it's never null!


That would be great but useless for my situation involving some complex
AST's

class AEntity
{
 Module head;
 string ident;
 Type type;
 AEntity typeInfo;
 AEntity[] members; // for definitions
 AEntity[] parameters; // if parameterized
...
}

It's very useful to descend through parts of a complex tree without
adding plenty of bool checks

foreach (AEntity member; entity.members)
{
 if (member.typeInfo !is null)
 {
 AEntity curr = member;
 member.ident ~= member.typeInfo.ident;
 curr = member.typeInfo;
 while (curr.typeInfo !is null)
 {
 member.ident ~= . ~ curr.typeInfo.ident;
 curr = curr.typeInfo;
 }
 }
}


And all of those references can be null at any time? Non-null would 
force you to initialize some/all of those values to a non-null 
reference, with the compiler ensuring that that is really the case.




Re: Adding the ?. null verification

2014-06-18 Thread Vladimir Panteleev via Digitalmars-d

On Wednesday, 18 June 2014 at 15:42:04 UTC, Etienne wrote:

writeln(obj.member?.nested?.val);


You can implement something similar to this using UFCS:

auto q(C)(auto ref C c)
{
struct Q
{
template opDispatch(string name)
{
@property auto opDispatch()
{
return c ? mixin(q{c.}~name) : null;
}
}

@property auto dummy() { }
}
return Q();
}

unittest
{
class C { C c; }
C c = new C;
c.c = new C;

assert(c.q.c !is null);
assert(c.q.c.q.c is null);
assert(c.q.c.q.c.q.c is null);
}


Re: Adding the ?. null verification

2014-06-18 Thread logicchains via Digitalmars-d
On Thursday, 19 June 2014 at 00:36:23 UTC, H. S. Teoh via 
Digitalmars-d wrote:
I decided to run some tests on the compiled code to see how 
performant
However, with gdc -O3 -finline, all of the opDispatch calls got 
inlined,

and the assembly is the direct equivalent of:

if (tree !is null)
if (tree.left !is null)
...
writeln(tree.left.right. ... .val);



Somebody should blog on this or put it on the front page or 
something; how many other languages allow a cost-free maybe monad 
to be implemented in library code?