February 14, 2009
"Christopher Wright" <dhasenan@gmail.com> wrote in message news:gn704j$2s2u$1@digitalmars.com...
> Jarrett Billingsley wrote:
>> On Sat, Feb 14, 2009 at 8:37 AM, Christopher Wright <dhasenan@gmail.com> wrote:
>>>> void Foo(void delegate()? dg) //nullable
>>>> {
>>>>    dg();
>>>> }
>>> You're right for that small example. Now let's say you have an object a
>>> dozen methods referencing the same nullable member. They're private
>>> methods
>>> called by public methods that check if the member is null first. I don't
>>> want to have to check whether the variable is null every single time I
>>> use
>>> it; I want to do it once at the start and assume (since it's a
>>> single-threaded application and I'm not assigning to that member) that
>>> that
>>> check works for everything.
>>
>> ....that's the entire point of non-null references.
>
> No. I'm saying this class has a complex code path if some things are not null, and some other code path if they are null. It's quite valid if they are null, but I want to do other things if they aren't, and I don't want to cast constantly.

You would only need to check when you're going to derefernce or convert to a non-nullable. Nulls could still be stored and passed around without checking. If this doesn't cover what you're concerned about, perhaps you could provide an example?


February 14, 2009
"Christopher Wright" <dhasenan@gmail.com> wrote in message news:gn6h0r$1mk9$1@digitalmars.com...
> Nick Sabalausky wrote:
>> I still like this that someone else mentioned:
>>
>> T? x = something;
>> if(x !is null)
>> {
>>     // x is implicitly "T" here, not "T?"
>> }
>> else
>> {
>>     // handle null condition (x is still "T?")
>> }
>>
>>
>
> I hate it.
>
> It encourages too much nesting, and it silently changes a variable's type.

You're right, I've come to realize that in a different branch of this thread.


February 14, 2009
Andrei Alexandrescu wrote:
> Nick Sabalausky wrote:
>> "bearophile" <bearophileHUGS@lycos.com> wrote in message
>> news:gn6ism$1rgc$1@digitalmars.com...
>>> Yigal Chripun:
>>>> IMO "if" needs to be expression instead of a statement.
>>>> also See http://nemerle.org/Quick_Guide#Decisions
>>> If you want to turn D into a more functional language, then that may
>>> be positive. But I think D will not change so much, so better for you
>>> to stick to things that are more likely to change.
>>>
>>
>> D's already becoming more functional. Evidence: pure, immutable,
>> std.algorithm.
>
> ...std.functional.
>
> Andrei

Besides, such a change will allow us to remove the ugly ?: operator and will free the ? sign.

One of my favorite Ruby features (besides Blocks) is that Ruby allows using ? and ! as part of identifiers. This is used in Ruby by convention to represent methods that answer questions, and methods that are more "dangareous" like in-place modification of data.

so you can write:
if (range.more?) ..
and it also has array.sort vs. array.sort! where the former gives a sorted copy and the latter sorts in-place.
February 14, 2009
"Yigal Chripun" <yigal100@gmail.com> wrote in message news:gn771i$ded$1@digitalmars.com...
>
> Besides, such a change will allow us to remove the ugly ?: operator and will free the ? sign.
>

I like the ?: operator :-). It's short. But I agree it might be worth switching to an expression "if...else..." if that meant we could do the following...

> One of my favorite Ruby features (besides Blocks) is that Ruby allows using ? and ! as part of identifiers. This is used in Ruby by convention to represent methods that answer questions, and methods that are more "dangareous" like in-place modification of data.
>
> so you can write:
> if (range.more?) ..

When I was looking into Ruby, I was impressed by this too. I had always liked MS's convention of prepending "is" to flags, but that only works on certain flags (sometimes you really mean "has" or "exists" or "capable of" something else besides "is"). Appending "?" is much more general.

> and it also has array.sort vs. array.sort! where the former gives a sorted copy and the latter sorts in-place.

It would be kind of handy to have a nice simple convention for in-place vs non-inplace functions. Obviously "!" wouldn't work for D though, unless we were masochistic enough to revisit the old "What syntax to use for templates?" issue.


February 14, 2009
Nick Sabalausky wrote:
> "Yigal Chripun"<yigal100@gmail.com>  wrote in message
> news:gn771i$ded$1@digitalmars.com...
>> Besides, such a change will allow us to remove the ugly ?: operator and
>> will free the ? sign.
>>
>
> I like the ?: operator :-). It's short. But I agree it might be worth
> switching to an expression "if...else..." if that meant we could do the
> following...
>
>> One of my favorite Ruby features (besides Blocks) is that Ruby allows
>> using ? and ! as part of identifiers. This is used in Ruby by convention
>> to represent methods that answer questions, and methods that are more
>> "dangareous" like in-place modification of data.
>>
>> so you can write:
>> if (range.more?) ..
>
> When I was looking into Ruby, I was impressed by this too. I had always
> liked MS's convention of prepending "is" to flags, but that only works on
> certain flags (sometimes you really mean "has" or "exists" or "capable of"
> something else besides "is"). Appending "?" is much more general.
>
>> and it also has array.sort vs. array.sort! where the former gives a sorted
>> copy and the latter sorts in-place.
>
> It would be kind of handy to have a nice simple convention for in-place vs
> non-inplace functions. Obviously "!" wouldn't work for D though, unless we
> were masochistic enough to revisit the old "What syntax to use for
> templates?" issue.
>
>
well, IMO there are better syntax options for templates but I doubt it if it'll ever change, I remember that long thread about this very subject..
there's another way to mark in-place vs. copy which I don't like as much - I think it's used in Python:
array.sort vs. array.sorted
where the first form is in-place and the other is a copy. the convention is to use adjectives for copies - if you say array.sort (with a verb) you actually sort the *current* array.
this is more fragile IMO than just using a "!" since you need to be familiar with English grammar. (for non-native English speakers that can be an issue)
e.g:
egg.rot vs. egg.rotten, etc..


February 14, 2009
Nick Sabalausky wrote:
> You would only need to check when you're going to derefernce or convert to a non-nullable. Nulls could still be stored and passed around without checking. If this doesn't cover what you're concerned about, perhaps you could provide an example?

Let's say I originally have this:

class Foo {
	void delegate()? dg;
	void doStuff() {
		if (dg) {
			// some long code path with code duplicated from
			// other methods in Foo
		} else {
			// some other long code path
		}
	}
}

Now I want to refactor that:


class Foo {
	void delegate()? dg;
	void doStuff() {
		if (dg) {
			doPart1;
			doPart2;
		} else {
			// some other long code path
		}
	}

	private void doPart1() {
		// use dg; why should I check?
	}
	private void doPart2() {
		// use dg; why should I check?
	}
}

Small examples don't show it very well.
February 14, 2009
On Sun, 15 Feb 2009 02:22:17 +0300, Christopher Wright <dhasenan@gmail.com> wrote:

> Nick Sabalausky wrote:
>> You would only need to check when you're going to derefernce or convert to a non-nullable. Nulls could still be stored and passed around without checking. If this doesn't cover what you're concerned about, perhaps you could provide an example?
>
> Let's say I originally have this:
>
> class Foo {
> 	void delegate()? dg;
> 	void doStuff() {
> 		if (dg) {
> 			// some long code path with code duplicated from
> 			// other methods in Foo
> 		} else {
> 			// some other long code path
> 		}
> 	}
> }
>
> Now I want to refactor that:
>
>
> class Foo {
> 	void delegate()? dg;
> 	void doStuff() {
> 		if (dg) {
> 			doPart1;
> 			doPart2;
> 		} else {
> 			// some other long code path
> 		}
> 	}
>
> 	private void doPart1() {
> 		// use dg; why should I check?
> 	}
> 	private void doPart2() {
> 		// use dg; why should I check?
> 	}
> }
>
> Small examples don't show it very well.

private void doPart1()
{
   void delegate() dg = unchecked(this.dg); // no checking done
   // use dg here without checking
   // *BUT* it someone denies the contract and calls the method without
   // ensuring that this.dg is not null, you'll get a access violation (or NPE)
}



February 15, 2009
Denis Koroskin wrote:
> private void doPart1()
> {
>    void delegate() dg = unchecked(this.dg); // no checking done
>    // use dg here without checking
>    // *BUT* it someone denies the contract and calls the method without
>    // ensuring that this.dg is not null, you'll get a access violation (or NPE)
> }

Fuck no.
February 15, 2009
"Christopher Wright" <dhasenan@gmail.com> wrote in message news:gn7jn9$1i0e$1@digitalmars.com...
>
> class Foo {
>     void delegate()? dg;
>     void doStuff() {
>         if (dg) {
>             doPart1;
>             doPart2;
>         } else {
>             // some other long code path
>         }
>     }
>
>     private void doPart1() {
>         // use dg; why should I check?

Because some other function or codepath could still accidentally be breaking your precondition convention, so you're right back to inviting hidden. The extra check prevents that. Also, in many cases (though not all), doPart1() might be better off being generalized like this:

private void doPart1(ref void delegate() dg) {
    // Do stuff
}

...or like this:

private (void delegate()) doPart1(void delegate() dg) {
    // Do stuff
    return dg;
}


>     }
>     private void doPart2() {
>         // use dg; why should I check?
>     }
> }
>
> Small examples don't show it very well.

> Denis Koroskin wrote:
>> private void doPart1()
>> {
>>    void delegate() dg = unchecked(this.dg); // no checking done
>>    // use dg here without checking
>>    // *BUT* it someone denies the contract and calls the method without
>>    // ensuring that this.dg is not null, you'll get a access violation
>> (or NPE)
>> }
>
> Fuck no.

Agreed. Although my argument against it is that if you're going to bother to do that, you may as well just check for null anyway and save yourself the potential runtime error.


February 15, 2009
"Nick Sabalausky" <a@a.a> wrote in message news:gn7vef$2nb4$1@digitalmars.com...
>
> Because some other function or codepath could still accidentally be breaking your precondition convention, so you're right back to inviting hidden. The

Sorry, that should be "...so you're right back to inviting hidden null reference errors."

> extra check prevents that. Also, in many cases (though not all), doPart1() might be better off being generalized like this:
>