www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - A few questions

reply "Namespace" <rswhite4 googlemail.com> writes:
1.
Why are these two method header identitcal?

const Foo some_function() {

and

Foo some_function() const {

?

IMO that isn't consistent. IMO only the last is valid.
With this example, it is somewhat understandable.

// C++
class Bar {
     const Foo getFooObj() const { ... }
     const Foo& getFooObjRef const { ... }
};

// D
class Bar {
     const(Foo) getFooObj() const { ... }
     ref Foo getObjRef() { ... }
}

const(Foo) but ref Foo. This is inconsistency, if you ask me.
So why is between C++ and D such a huge difference?
Why isn't it simply const Foo instead of const(Foo)?

2.
What's about a shorthand for debug assertions?
E.g. to avoid not-null references (yes, if you're a windows user, 
you hate them):

Example:

[code]
void some_function(Foo !f) {
[/code]

will automatically converted by the compiler into:

[code]
void some_function(Foo f, string filename = __FILE__, uint line = 
__LINE__) in {
     assert(f !is null, format("Null Object   file %s on line 
%d.", filename, line));
} body {
[/code]

That would be avoid many many efforts by writing safe code. And 
it avoids Java code stil with explizit pre- and postconditions 
which blows up code.
Jul 27 2012
next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 27 July 2012 at 10:29:15 UTC, Namespace wrote:
 1.
 Why are these two method header identitcal?

 const Foo some_function() {

 and

 Foo some_function() const {

 ?

 IMO that isn't consistent. IMO only the last is valid.
 With this example, it is somewhat understandable.

Some would argue only the *first* should be valid: ---- safe const property nothrow Foo some_function(); ---- Basically, yeah, you have the option of putting qualifiers before or after.
Jul 27 2012
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-07-27 12:29, Namespace wrote:
 1.
 Why are these two method header identitcal?

 const Foo some_function() {

 and

 Foo some_function() const {

 ?

The reason "const Foo some_function" is allowed is because in D this syntax is possible: class Foo { const: Foo some_function () {} }
 IMO that isn't consistent. IMO only the last is valid.
 With this example, it is somewhat understandable.

 // C++
 class Bar {
      const Foo getFooObj() const { ... }
      const Foo& getFooObjRef const { ... }
 };

 // D
 class Bar {
      const(Foo) getFooObj() const { ... }
      ref Foo getObjRef() { ... }
 }

 const(Foo) but ref Foo. This is inconsistency, if you ask me.
 So why is between C++ and D such a huge difference?
 Why isn't it simply const Foo instead of const(Foo)?

I think the reason is the same as above. If the return value is const you need to use parentheses. I think that the syntax would conflict with the const-method syntax otherwise. The reason for why const is allowed after the paramter list is because it can be a bit confusing to have two const next to each other. class Foo { const const (Foo) foo () {} } -- /Jacob Carlborg
Jul 27 2012
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-07-27 13:14, Jacob Carlborg wrote:
 On 2012-07-27 12:29, Namespace wrote:

 const(Foo) but ref Foo. This is inconsistency, if you ask me.
 So why is between C++ and D such a huge difference?
 Why isn't it simply const Foo instead of const(Foo)?

I think the reason is the same as above. If the return value is const you need to use parentheses. I think that the syntax would conflict with the const-method syntax otherwise. The reason for why const is allowed after the paramter list is because it can be a bit confusing to have two const next to each other. class Foo { const const (Foo) foo () {} }

Forgot to say, the reason for why the ref(Foo) syntax isn't used is because there can be no conflict since methods cannot be declared as const. -- /Jacob Carlborg
Jul 27 2012
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/27/2012 04:35 PM, bearophile wrote:
 But implementing good non-null types in library code is hard

It is closer to impossible than to hard.
 (rather harder than implementing vector ops in library code on library defined
 vectors). I think  disable isn't enough to cover what Spec# shows good
 non-null types are meant to be.

Non-null types in Spec# are unsound.
Jul 29 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/29/2012 06:24 PM, bearophile wrote:
 Timon Gehr:

 Non-null types in Spec# are unsound.

Really? I didn't know it. Surely its non-null design looks quite refined and thought-out. But maybe as say it's not enough still. Do you have a link where it shows it's unsound?

Google for "freedom before commitment". The example is in the paper. Apparently the unsoundness was recently fixed though -- the faulty assignment in question is now correctly rejected by the online Spec# compiler.
Jul 29 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 The reason "const Foo some_function" is allowed is because in D 
 this syntax is possible:

 class Foo
 {
     const:

     Foo some_function () {}
 }

Good point. I had completely forgotten, that that is possible. But it seems that no one would have interest in my second proposal. :)
Jul 27 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Namespace:

 Good point. I had completely forgotten, that that is possible.
 But it seems that no one would have interest in my second 
 proposal. :)

Similar things were discussed a lot. And some people think that similar nonnull annotations are a good idea. Bye, bearophile
Jul 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Friday, 27 July 2012 at 11:50:46 UTC, bearophile wrote:
 Namespace:

 Good point. I had completely forgotten, that that is possible.
 But it seems that no one would have interest in my second 
 proposal. :)

Similar things were discussed a lot. And some people think that similar nonnull annotations are a good idea. Bye, bearophile

Then: What is the problem to introduce such shorthand? To solve the problem with a struct is IMO a really _bad_ idea. Because then you have to pack the object into the struct (or you have to create the object with a function that returns this struct, equally as "scoped" does it currently) and _then_ you can pass it to the function/method. Still the same effort as if you solve it with preconditions. Completely unnecessary work, and such shorthand can avoid this.
Jul 27 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Namespace:

 Then: What is the problem to introduce such shorthand?

I don't know. I have a partial enhancement on the topic: http://d.puremagic.com/issues/show_bug.cgi?id=4571 Bye, bearophile
Jul 27 2012
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Fri, 27 Jul 2012 14:44:35 +0200, bearophile <bearophileHUGS lycos.com>  
wrote:

 Namespace:

 Then: What is the problem to introduce such shorthand?

I don't know. I have a partial enhancement on the topic: http://d.puremagic.com/issues/show_bug.cgi?id=4571 Bye, bearophile

I believe at least part of the explanation is that Walter wants NotNull to implemented in a library. That's part of the reason for introducing disable this(). Now, one could certainly argue that int? be translated by the compiler into NotNull!int, and the implementation lie in druntime. -- Simen
Jul 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
bearophile:
Yes i know, but i see there no answers.

Simen Kjaeraas:
That's exactly what i mean. Foo? or Foo! would be converted into 
NotNull!Foo.

I wrote a quick and dirty solution:
http://dpaste.dzfl.pl/400079cb

Which converts this Code:

[code]
import std.stdio;

class Foo {
public:
	void echo() const {
		writeln("My Name is Foo.");
	}
}

void foo(Foo! f) {
	f.echo();
}

void bar(Foo! f) {
	f.echo();
}

void main() {
	Foo f = new Foo();
	Foo f2;
	
	foo(f);
	bar(f2);

	foo(new Foo());
	bar(null);
}
[/code]

into: http://dpaste.dzfl.pl/d9375eeb

It is not perfect, but a first step. It would be desirable if the 
dmd compiler could do something on its own.

What are the chances that something like this happens?
Jul 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
Short improvement: http://dpaste.dzfl.pl/f3263def
Jul 27 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Simen Kjaeraas:

 I believe at least part of the explanation is that Walter wants 
 NotNull to
 implemented in a library. That's part of the reason for 
 introducing  disable this().

Yes, I remember part of the discussions. And I agree that generally it's better to put meta-features in a language that allow library code to implement the desired features. That's why recently in the main D newsgroup I have said that built-in vector ops may be better replaced by library code (what's missing is some built-in trick to avoid the creation of intermediate arrays in complex expression). But implementing good non-null types in library code is hard (rather harder than implementing vector ops in library code on library defined vectors). I think disable isn't enough to cover what Spec# shows good non-null types are meant to be. Bye, bearophile
Jul 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
What's wrong with the solution that

void some_function(Foo? f) {

is converted to

void some_function(Foo f, string filename = __FILE__, uint line = 
__LINE__)  in {
     assert(f !is null, std.string.format("Null Object   File %s 
on Line %d.", filename, line));
} body {

? It isn't a huge effort for the compiler, or?
Jul 27 2012
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Fri, 27 Jul 2012 16:39:49 +0200, Namespace <rswhite4 googlemail.com>  
wrote:

 What's wrong with the solution that

 void some_function(Foo? f) {

 is converted to

 void some_function(Foo f, string filename = __FILE__, uint line =  
 __LINE__)  in {
      assert(f !is null, std.string.format("Null Object   File %s on Line  
 %d.", filename, line));
 } body {

 ? It isn't a huge effort for the compiler, or?

Nope. But, that's just a simple assertion. If we'd had real non-nullable types, we could remove the check completely, because you'd know it held a valid object. Now, a library solution has certain limitations a built-in solution would not - for instance, new X would return non-nullable. -- Simen
Jul 27 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, July 27, 2012 12:29:13 Namespace wrote:
 1.
 Why are these two method header identitcal?
 
 const Foo some_function() {
 
 and
 
 Foo some_function() const {
 
 ?

 const(Foo) but ref Foo. This is inconsistency, if you ask me.
 So why is between C++ and D such a huge difference?
 Why isn't it simply const Foo instead of const(Foo)?

Sadly, the reason is consistency. const is an attribute just like pure or nothrow, and you can do both pure Foo func() {} and Foo func() pure {} as well as pure { Foo func() {} } and pure : Foo func() {} If const Foo func() {} made Foo const rather than func, it would be inconsistent with the other attributes, and if const on func were only legal on the right (as in C++), then it would be inconsistent with the others. Many of us think that const Foo func() {} should just become illegal inconsistency or not because of all of this confusion, but Walter doesn't buy into that.
 2.
 What's about a shorthand for debug assertions?
 E.g. to avoid not-null references (yes, if you're a windows user,
 you hate them):

Walter's stand on this is that the OS gives you null-dereferencing detection - i.e. segfaults and access violations. He's not going to add extra syntax for it. - Jonathan M Davis
Jul 27 2012
parent Artur Skawina <art.08.09 gmail.com> writes:
On 07/27/12 21:48, Adam D. Ruppe wrote:
 On Windows, an access violation (from a null pointer or other
 causes) is an exception that is thrown and can even be caught.
 
 On Linux, a segfault is a signal that just kills the program,
 it doesn't work like a regular exception.

It's not a regular D exception, but it is a signal that /can/ be caught and used to print stacktraces, file names, line numbers etc, not to mention you optionally get a snapshot of the program as it failed (the "core" file). The only non-trivial part is getting at the debug info to map the addresses to symbols. Simple quick and dirty example below, which will not only print the address of the instruction that caused the fault, but also the address that it tried to access, and may even sometimes succeed in letting the program continue to run. Making it work with a non-gdc compiler, non-x86 ISA, hooking up w/ a library to get all the symbol names and properly handling all the required cases is left as an exercise for the reader. :) But, no, special handling for null dereferencing in the language is *not* needed. Some more runtime support, maybe. artur import std.stdio; template Seq(alias A, alias B, S...) { static if(S.length==0) alias Seq!(A, B, A) Seq; else static if (S[$-1]!=B) alias Seq!(A, B, S, S[$-1]+1) Seq; else alias S Seq; } struct hack { import core.sys.posix.ucontext, core.sys.posix.signal; alias int c_int; static: void* av; ubyte* violator; void*[4] trace; extern (C) void handler(c_int signum, siginfo_t* si, void* _ctx ) { auto ctx = cast(ucontext_t*)_ctx; av = si._sifields._sigfault.si_addr; version (X86) enum REG_RIP = 14; violator = cast(ubyte*)ctx.uc_mcontext.gregs[REG_RIP]; ctx.uc_mcontext.gregs[REG_RIP] += inslen(violator); // scan and store backtrace etc. version (GNU) { import gcc.builtins; foreach (uint i; Seq!(0, trace.length-1)) trace[i] = __builtin_return_address(i); } checkav(); // Not something you wanna do from a signal handler... } void register() { sigaction_t sa; sa.sa_sigaction = &handler; sa.sa_flags = SA_SIGINFO; if (sigaction(SIGSEGV, &sa, null)) throw new Error("sigaction failed"); } version (X86) size_t inslen(in ubyte* c) { if (c[0]==0xc6 && c[1]==0x05) return 7; if (c[0]==0x0f && c[1]==0xb6 && c[2]==0x4b) return 4; if (c[0]==0x0f && c[1]==0xb6 && c[2]==0x43) return 4; if (c[0]==0x0f && c[1]==0xb6) return 7; if (c[0]==0xa2) return 5; if (c[0]==0x65 && c[1]==0xc7) return 11; if (c[0]==0x88 && c[1]==0x4b) return 3; // ... return 1; } auto checkav() { if (av) { writefln(" 0x%08x tried to access 0x%08x", violator, av); foreach(t; trace) writef(" 0x%08x\n", t); av = null; } } } __gshared ubyte* p = null; int main() { hack.register(); p[1] = 1; hack.checkav(); p[2] = 2; hack.checkav(); p[3] = 3; hack.checkav(); p[5] = p[4]; hack.checkav(); return p[42]; }
Jul 27 2012
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Fri, 27 Jul 2012 17:35:19 +0200, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 Many of us think that

 const Foo func() {}

 should just become illegal inconsistency or not because of all of this
 confusion, but Walter doesn't buy into that.

Like monarch_dodra said, this is also a style favored by some: pure property const int foo() { //... } Having to write that pure property int foo() const { //... } at the very least feels weird. int foo() const pure property { } could work, I guess. But it feels backward. -- Simen
Jul 27 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, July 27, 2012 19:34:52 Simen Kjaeraas wrote:
 On Fri, 27 Jul 2012 17:35:19 +0200, Jonathan M Davis <jmdavisProg gmx.com>
 
 wrote:
 Many of us think that
 
 const Foo func() {}
 
 should just become illegal inconsistency or not because of all of this
 confusion, but Walter doesn't buy into that.

Like monarch_dodra said, this is also a style favored by some: pure property const int foo() { //... } Having to write that pure property int foo() const { //... } at the very least feels weird. int foo() const pure property { } could work, I guess. But it feels backward.

Personally, I _always_ put the attributes on the right-hand side save for the ones which exist in C++ and Java (which is pretty much just the access specifiers, static, override, and final), and I think that it's ugly and confusing to have them on the left, but that's a matter of personal preference. const on the other hand constantly causes issues because - unlike the others - it can be applied to the return type as well. And the question comes up often enough that I think that it's a real problem and one that merits making putting it on the left illegal. At minimum, making it illegal on the left without other attributes between it and the return type should be illegal IMHO (though that could cause even more confusion depending on the error message, since then it might be confusing why you could put it on the left but only in some positions). That change isn't going to happen at this point, but I think that we'd be better off if it were. - Jonathan M Davis
Jul 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 Walter's stand on this is that the OS gives you 
 null-dereferencing detection -
 i.e. segfaults and access violations. He's not going to add 
 extra syntax for
 it.

 - Jonathan M Davis

That is a huge mistake. My OS prints me only a funny "Access violation". And so i can search for my little null reference by myself. I _must_ debug for a ridiculous null reference. That cost time. I have not even a filename or a line number. Only the message that something went wrong. And all other i have to find by myself. So much time for such little mistakes. Why would Walter have a language which doesn't support good error handling? D hasn't support for unused variables, unused imports and even not for null references. Why should everyone use D instead of any other language? If i have a big project and i use many objects and one of them change to null, what now? Should the user really step through thousand lines of code because D prints only "Access Violation" without any further information? Or should i use the same principle as Java, and write every time again pre- and postconditions? I don't see any reasons why anybody should realize a big project with D and not with a other language, if the error handling and not null support remains as it is. Sorry. To reject even a such handy shorthand is incomprehensible to me.
Jul 27 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, July 27, 2012 20:07:56 Namespace wrote:
 Walter's stand on this is that the OS gives you
 null-dereferencing detection -
 i.e. segfaults and access violations. He's not going to add
 extra syntax for
 it.
 
 - Jonathan M Davis

That is a huge mistake. My OS prints me only a funny "Access violation". And so i can search for my little null reference by myself. I _must_ debug for a ridiculous null reference. That cost time. I have not even a filename or a line number. Only the message that something went wrong. And all other i have to find by myself. So much time for such little mistakes. Why would Walter have a language which doesn't support good error handling?

Because a debugger will show you exactly where the problem is. So, why add checking that the OS already does for you? That's his logic. There are plenty of cases where that really isn't enough (e.g. you get a segfault on a server application without core dumps turned on when it's been running for 2 weeks), but it is for all the types of programs that Walter works on, so that's the way he thinks.
 D hasn't support for unused variables, unused imports and even
 not for null references. Why should everyone use D instead of any
 other language?
 If i have a big project and i use many objects and one of them
 change to null, what now? Should the user really step through
 thousand lines of code because D prints only "Access Violation"
 without any further information? Or should i use the same
 principle as Java, and write every time again pre- and
 postconditions? I don't see any reasons why anybody should
 realize a big project with D and not with a other language, if
 the error handling and not null support remains as it is. Sorry.
 
 To reject even a such handy shorthand is incomprehensible to me.

Honestly, I think that you're blowing null pointer dereferences way out proportion. In my experience, they're rare, and I have to wonder what you're doing if you're seeing them all that often. That being said, what I think we're likely to end up with is a signal handler in druntime which prints out a stacktrace when a segfault occurs (and does whatever the Windows equivalent would be on Windows). That way, you don't have to have null checks everywhere, but you still get the debug information that you need. But no one has done that yet. - Jonathan M Davis
Jul 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
I also get null references (and every time i hate D a bit more), 
but mostly my classmates and other friends whom I've shown D. And 
most of them are already back to C++ or C#. And I can understand 
them.
If you want that D is sometimes taken seriously (and it reached 
only if you win more people for D), then perhaps you should do 
something for more usability.
Such small handy shorthands are easy to implement and even more 
understandable as a stacktrace.
Jul 27 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Friday, 27 July 2012 at 19:01:39 UTC, Namespace wrote:
 I also get null references (and every time I hate D a bit 
 more), but mostly my classmates and other friends whom I've 
 shown D. And most of them are already back to C++ or C#. And I 
 can understand them.
 If you want that D is sometimes taken seriously (and it reached 
 only if you win more people for D), then perhaps you should do 
 something for more usability.
 Such small handy shorthands are easy to implement and even more 
 understandable as a stacktrace.

I've noticed when debugging the 'segfault' is rather vague, but it depends on if you have something to catch it. In some of my code I end up surrounding the main function in a try/catch wrapper that prints the appropriate data; Like using VisualD. void main() { try { someFunc(null); } catch (Throwable x) { writeln(x); } } void someInnerFunc(Object o) in { assert(o, "Yo! my object's NULL!"); } body { //something } void someFunc(Object o) { someInnerFunc(o); //for stacktrace } core.exception.AssertError test.d(111): Yo! my object's NULL! ---------------- c:\Users\Era\My Documents\progs\d\test.d(119): void test.someFunc(Object) c:\Users\Era\My Documents\progs\d\test.d(103): _Dmain change inner function to: void someInnerFunc(Object o) { o.toHash; //something } object.Error: Access Violation ---------------- c:\Users\Era\My Documents\progs\d\test.d(116): void test.someFunc(Object) c:\Users\Era\My Documents\progs\d\test.d(103): _Dmain
Jul 27 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Windows, an access violation (from a null pointer or other
causes) is an exception that is thrown and can even be caught.

On Linux, a segfault is a signal that just kills the program,
it doesn't work like a regular exception.


The Windows exceptions can do pretty stack traces, including
on null derefs, if you have some debugging library installed...
and I've done it before, but I don't remember the link right now.
It's something from Microsoft.
Jul 27 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Friday, 27 July 2012 at 19:48:33 UTC, Adam D. Ruppe wrote:
 On Windows, an access violation (from a null pointer or other
 causes) is an exception that is thrown and can even be caught.

 On Linux, a segfault is a signal that just kills the program,
 it doesn't work like a regular exception.

Linux also dumps the state into a file. So I'd have to wonder what the problem was, you would have all the information at hand.
Jul 27 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 27 July 2012 at 19:50:46 UTC, Era Scarecrow wrote:
  Linux also dumps the state into a file.

Only if core dumps are enabled... but I think someone did a Linux stack trace signal handler somewhere for D, but it never got merged into druntime. (What it'd do is print out some info before exiting, instead of just saying "segmentation fault". Still not an exception, but a little more immediately helpful).
Jul 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
And that is the explicit way with pre- and postconditions of 
Java, which i want to avoid.

I see, the most of you prefer to write "try and catch" or use the 
java principle with explicit pre- and post conditions.
The time will show, if D get therewith enough members to get 
serious.
But this is what Java and C# have already.
Jul 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
Me again.
What's the matter if i write something for that shorthand and dmd 
has only to switch to it before the compiling begins?
My little test program works with VisualD.
I goto the build events and there i write into "Pre-Build 
Command":
[quote]not_null main.d #t[/quote]
and into "Post-Build Command":
[quote]del main.d
rename clone_main.d main.d[/quote]

Of course i have to find a way to generate this for all included 
files and not do this manually as
not_null a.d #t
not_null b.d #t

But if dmd would do this e.g. with a compiler flag like 
"-notnull" it would lighten my workload a lot.

Here is my current example code: http://dpaste.dzfl.pl/8d41468a

It replace Class? obj statements and generate two files. The 
normal file changes to valid D code which can compile. The 
"original" code with Class? obj statements will copied into 
clone_filename.d

I know it isn't perfect, but maybe it is a beginning.
Jul 27 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, July 28, 2012 01:00:22 Namespace wrote:
 Me again.
 What's the matter if i write something for that shorthand and dmd
 has only to switch to it before the compiling begins?

Doing stuff like that makes your code completely unportable. It's _bad_ practice. Don't go and try to redesign the language if you want to be playing nice with other people. If you can do something completely within the language, then that's different (other people may still hate what you're up to, but at least they can compile it), but don't use a preprocessor unless you really don't care about anyone else ever using your code but you, and even then, I'd argue against it, because if you get into the habit of doing that, you're screwed when you actually have to interact with other D programmers. - Jonathan M Davis
Jul 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
Therefore i hope that it will be official added into D.
Otherwise of course i use it only for projects between me and my 
other students.

I don't know what is wrong with this shorthand. So why don't give 
it a try?
I'm absolutely sure that Walter will _never_ add real 
non-nullable references.
All what will maybe come are further structs in std.alghorithm 
which blows up your code as assertions even do.
Jul 27 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
I started a not null struct for phobos but then had to
move, added another job, and other real life stuff
that meant I haven't finished it yet.

Fairly usable though. Look for struct NotNull:

https://github.com/adamdruppe/phobos/blob/0c97414bb4aa3c748caa42948ffec25f8a291300/std/typecons.d

(also a pull request, but for some reason, my changes to
never updated here, so the pull request is out of date
and temporarily closed

https://github.com/D-Programming-Language/phobos/pull/477 )
Jul 27 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, July 28, 2012 01:16:41 Namespace wrote:
 Therefore i hope that it will be official added into D.
 Otherwise of course i use it only for projects between me and my
 other students.
 
 I don't know what is wrong with this shorthand. So why don't give
 it a try?

I don't even know what the last time I dereferenced a null pointer or null reference was. It almost never happens to me. I really think that if you're seeing very many null dererences, you're doing something fundamentally wrong with your code. At minimum, it indicates that you're not unit testing enough, since if you do that right, it'll catch the logic errors which give you null pointers/references very quickly.
 I'm absolutely sure that Walter will _never_ add real
 non-nullable references.
 All what will maybe come are further structs in std.alghorithm
 which blows up your code as assertions even do.

We will get a NotNull struct at some point (probably in std.typecons). It'll statically prevent assignments from null where it can and use assertions where it can't. Adding something to the language doesn't buy you much more than that anyway. At this point, any new language feature must meet a very high bar, and if we can do it in the library instead, we will. D is incredibly powerful and is already plenty complex, so we'll take advantage of that power where we can rather than trying to change the language further. D arguably has too many features as it is. And as big a deal as you seem to think that this is, the _only_ C-based language that I'm aware of which has non-nullable references as part of the language is C#. So, while they may have their uses, it's actually very uncommon to have them, and since we can add a library type to do it, we can fix the problem without altering the language. - Jonathan M Davis
Jul 27 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 Adding something to the language doesn't buy you much more than 
 that anyway.

In the case of not-nullability, this isn't true. Integrating not-null in the type system allows the language to do things you can't do with NotNull, like: // x is a nullable class reference if (x == null) { ... } else { // here the type system sees x as not null. } There are some other similar things you can't do with NotNull. In my enhancement request about not-nullability there are references to articles that explain the situation.
 D arguably has too many features as it is.

I don't agree, the number of features is not important. What's important is how clean and intelligently they are designed, how cleanly they interact with the other features. etc.
 And as big a deal as you seem to think that this is, the _only_ 
 C-based language that I'm aware of which has non-nullable
 references as part of the language is C#.

This is not true. Scala, Rust, some new Java-derived languages, and more modern languages have not nullable references. In practice I think most or all new languages coming out now have this feature. In my opinion in few years programmers will expect to have it in all languages that are not too much old and that support some kind of nullable references. Bye, bearophile
Jul 27 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, July 28, 2012 01:48:00 bearophile wrote:
 Jonathan M Davis:
 Adding something to the language doesn't buy you much more than
 that anyway.

In the case of not-nullability, this isn't true. Integrating not-null in the type system allows the language to do things you can't do with NotNull, like: // x is a nullable class reference if (x == null) { ... } else { // here the type system sees x as not null. }

??? What does it matter if the type system knows whether a pointer is null unless it's trying to warn you about dereferencing null? It's not checking for it. If we had null checks built in, that would buy you something, but we don't, and we're not going to, if nothing else because Walter is completely against it.
 There are some other similar things you can't do with NotNull. In
 my enhancement request about not-nullability there are references
 to articles that explain the situation.
 
 D arguably has too many features as it is.

I don't agree, the number of features is not important. What's important is how clean and intelligently they are designed, how cleanly they interact with the other features. etc.

There's always a cost to having more features. The more there are, the more that you have to know, and the more that it takes to learn the language. Having the features be well-designed definitely helps, and for the most part, I'm fine with the number of features that D has, but there probably are a few that ideally would be dropped but can't be at this stage (as was discussed not all that long ago in a big thread on what language features weren't useful), and adding more does come at a cost. A particular feature may be worth the cost that it brings, but the more features that you have, the more value each additional feature must bring to the table.
 And as big a deal as you seem to think that this is, the _only_
 C-based language that I'm aware of which has non-nullable
 references as part of the language is C#.

This is not true.

Actually, it is. I said "that I'm aware of." I didn't say that there weren't others, just that I didn't know of any others. But out of the mainstream C- based languages, it's definitely rare, much as it may be becoming less rare as new languages come along.
 Scala, Rust, some new Java-derived languages,
 and more modern languages have not nullable references. In
 practice I think most or all new languages coming out now have
 this feature. In my opinion in few years programmers will expect
 to have it in all languages that are not too much old and that
 support some kind of nullable references.

It's not necessarily a bad feature, but I do think that it's highly overrated, and regardless, there's no way that it's being added to D at this point in its life cycle. Maybe they'll be added in D3, but I wouldn't expect to see them before then at the earliest. The push right now is to use the language that we have to get things done rather than trying to constantly add features and tweak existing ones. There are probably some features that we wouldn't even have now if we had taken that approach earlier (e.g. base two literals). - Jonathan M Davis
Jul 27 2012
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
------------htNRmWrzd4tGePoRiYC6qE
Content-Type: text/plain; charset=utf-8; format=flowed; delsp=yes
Content-Transfer-Encoding: 7bit

On Fri, 27 Jul 2012 22:16:05 +0200, Namespace <rswhite4 googlemail.com>  
wrote:

 And that is the explicit way with pre- and postconditions of Java, which  
 i want to avoid.

 I see, the most of you prefer to write "try and catch" or use the java  
 principle with explicit pre- and post conditions.
 The time will show, if D get therewith enough members to get serious.
 But this is what Java and C# have already.

This is a NotNull I just implemented. It is designed to create a strict division between things that can be null, and those that cannot. The idea being that the programmer should be aware of it when he needs to convert between them, and whole call graphs can more easily be made free of null checks. -- Simen ------------htNRmWrzd4tGePoRiYC6qE Content-Disposition: attachment; filename=NotNull.d Content-Type: application/octet-stream; name="NotNull.d" Content-Transfer-Encoding: Base64 LyogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmUuIEl0IGNvbWVzIHdpdGhv dXQgYW55IHdhcnJhbnR5LCB0bw0KICAqIHRoZSBleHRlbnQgcGVybWl0dGVkIGJ5 IGFwcGxpY2FibGUgbGF3LiBZb3UgY2FuIHJlZGlzdHJpYnV0ZSBpdA0KICAqIGFu ZC9vciBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBEbyBXaGF0IFRo ZSBGdWNrIFlvdSBXYW50DQogICogVG8gUHVibGljIExpY2Vuc2UsIFZlcnNpb24g MiwgYXMgcHVibGlzaGVkIGJ5IFNhbSBIb2NldmFyLiBTZWUNCiAgKiBodHRwOi8v c2FtLnpveS5vcmcvd3RmcGwvQ09QWUlORyBmb3IgbW9yZSBkZXRhaWxzLiAqLw0K DQppbXBvcnQgc3RkLmV4Y2VwdGlvbiA6IGVuZm9yY2U7DQp2ZXJzaW9uICggdW5p dHRlc3QgKSB7DQogICAgaW1wb3J0IHN0ZC5leGNlcHRpb24gOiBhc3NlcnRUaHJv d24sIGFzc2VydE5vdFRocm93bjsNCiAgICBpbXBvcnQgY29yZS5leGNlcHRpb24g OiBBc3NlcnRFcnJvcjsNCn0NCg0KLyoqDQogKiBBIHBvaW50ZXIgb3IgcmVmZXJl bmNlIHRoYXQgY2FuIG5ldmVyIGJlIG51bGwuDQogKiBEb2VzIG5vdCBhbGxvdyBp bXBsaWNpdCBjb252ZXJzaW9uIGZyb20gbnVsbGFibGUgdG8gTm90TnVsbC4NCioq Lw0Kc3RydWN0IE5vdE51bGwoIFQgKSBpZiAoIGlzTnVsbGFibGUhVCApIHsNCiAg ICBwcml2YXRlIFQgcGF5bG9hZDsNCiAgICANCiAgICBAZGlzYWJsZSB0aGlzKCAp Ow0KICAgIEBkaXNhYmxlIHRoaXMoIFQgKTsNCiAgICBzdGF0aWMgQHByb3BlcnR5 IEBkaXNhYmxlIE5vdE51bGwgaW5pdCgpOw0KICAgIEBwcm9wZXJ0eQ0KICAgIGlu b3V0KFQpIGdldCggKSBpbm91dCB7DQogICAgICAgIHJldHVybiBwYXlsb2FkOw0K ICAgIH0NCiAgICANCiAgICBhbGlhcyBnZXQgdGhpczsNCn0gdW5pdHRlc3Qgew0K ICAgIGNsYXNzIEEgeyBpbnQgbjsgfQ0KICAgIGFzc2VydCggIWlzKCBOb3ROdWxs IShpbnQpICkgKTsNCiAgICBhc3NlcnQoICBpcyggTm90TnVsbCEoQSkgKSApOw0K ICAgIGFzc2VydCggIGlzKCBOb3ROdWxsIShpbnQqKSApICk7DQogICAgYXNzZXJ0 KCAhaXMoIE5vdE51bGwhKGludFtdKSApICk7DQogICAgYXNzZXJ0KCAhX190cmFp dHMoIGNvbXBpbGVzLCB7IE5vdE51bGwhaW50IGE7IH0gKSApOw0KICAgIGFzc2Vy dCggIV9fdHJhaXRzKCBjb21waWxlcywgeyBOb3ROdWxsIShpbnQqKSBhOyB9ICkg KTsNCiAgICBhc3NlcnQoICFfX3RyYWl0cyggY29tcGlsZXMsIHsgTm90TnVsbCEo aW50KikgYSA9IG51bGw7IH0gKSApOw0KICAgIGFzc2VydCggIV9fdHJhaXRzKCBj b21waWxlcywgeyBOb3ROdWxsIShpbnQqKSBhID0gbmV3IGludDsgfSApICk7DQog ICAgYXNzZXJ0KCAgX190cmFpdHMoIGNvbXBpbGVzLCB7IE5vdE51bGwhKGludCop IGEgPSB2b2lkOyB9ICkgKTsNCiAgICBhc3NlcnQoICBfX3RyYWl0cyggY29tcGls ZXMsIHsgTm90TnVsbCEoaW50KikgYSA9IHZvaWQ7ICphID0gMzsgfSApICk7DQog ICAgYXNzZXJ0KCAgX190cmFpdHMoIGNvbXBpbGVzLCB7IE5vdE51bGwhKEEpIGEg PSB2b2lkOyBhLm4gPSAzOyB9ICkgKTsNCiAgICANCiAgICAvL2Fzc2VydCggIV9f dHJhaXRzKCBjb21waWxlcywgeyBOb3ROdWxsIShBKVtdIGE7IGEubGVuZ3RoID0g MzsgfSApICk7IC8vIEJ1ZyA4NDU3DQp9DQoNCi8qKg0KICogVGFrZXMgdGhlIHZh bHVlIHRocm91Z2ggdGhlIGJhY2sgZG9vciBpbnRvIE5vdE51bGwgbGFuZC4NCiAq IFRoaXMgZnVuY3Rpb24gc2hvdWxkIGhhdmUgemVybyBvdmVyaGVhZCBpbiByZWxl YXNlIG1vZGUuDQoqKi8NCk5vdE51bGwhVCBhc3N1bWVOb3ROdWxsKCBUICkoIFQg dmFsdWUgKSBpZiAoIGlzTnVsbGFibGUhVCApIHsNCiAgICBhc3NlcnQoIHZhbHVl ICFpcyBudWxsICk7DQogICAgTm90TnVsbCFUIHJlc3VsdCA9IHZvaWQ7DQogICAg cmVzdWx0LnBheWxvYWQgPSB2YWx1ZTsNCiAgICByZXR1cm4gcmVzdWx0Ow0KfSB1 bml0dGVzdCB7DQogICAgYXNzZXJ0KCAgX190cmFpdHMoIGNvbXBpbGVzLCB7IE5v dE51bGwhKGludCopIGEgPSBhc3N1bWVOb3ROdWxsKG5ldyBpbnQpOyB9ICkgKTsN CiAgICBhc3NlcnQoICFfX3RyYWl0cyggY29tcGlsZXMsIHsgTm90TnVsbCEoaW50 KikgYSA9IGFzc3VtZU5vdE51bGwobmV3IHN0cmluZyk7IH0gKSApOw0KICAgIGFz c2VydFRocm93biFBc3NlcnRFcnJvciggYXNzdW1lTm90TnVsbCEoaW50KikoIG51 bGwgKSApOw0KfQ0KDQovKioNCiAqIENoZWNrcyB0aGF0IHRoZSBwYXNzZWQgdmFs dWUgaXMgbm90IG51bGwuDQogKiBUaHJvd3MgYW4gZXhjZXB0aW9uIGlmIGl0IGlz Lg0KKiovDQpOb3ROdWxsIVQgZW5mb3JjZU5vdE51bGwoIFQgKSggVCB2YWx1ZSAp IGlmICggaXNOdWxsYWJsZSFUICkgew0KICAgIGVuZm9yY2UoIHZhbHVlICFpcyBu dWxsICk7DQogICAgTm90TnVsbCFUIHJlc3VsdCA9IHZvaWQ7DQogICAgcmVzdWx0 LnBheWxvYWQgPSB2YWx1ZTsNCiAgICByZXR1cm4gcmVzdWx0Ow0KfSB1bml0dGVz dCB7DQogICAgYXNzZXJ0KCAgX190cmFpdHMoIGNvbXBpbGVzLCB7IE5vdE51bGwh KGludCopIGEgPSBlbmZvcmNlTm90TnVsbChuZXcgaW50KTsgfSApICk7DQogICAg YXNzZXJ0KCAhX190cmFpdHMoIGNvbXBpbGVzLCB7IE5vdE51bGwhKGludCopIGEg PSBlbmZvcmNlTm90TnVsbChuZXcgc3RyaW5nKTsgfSApICk7DQogICAgYXNzZXJ0 VGhyb3duKCBlbmZvcmNlTm90TnVsbCEoaW50KikoIG51bGwgKSApOw0KfQ0KDQov KioNCiAqIENoZWNrcyBpZiBhIHR5cGUgaXMgbnVsbGFibGUuIExlZnQgb3V0IGFy cmF5cyBiZWNhdXNlIG51bGwgYXJyYXlzDQogKiBhY3R1YWxseSBkbyBtYWtlIGEg dHdpc3RlZCBzb3J0IG9mIHNlbnNlLg0KKiovDQp0ZW1wbGF0ZSBpc051bGxhYmxl KCBUICkgew0KICAgIHN0YXRpYyBpZiAoIGlzKCBUIFUgOiBVKiApICkgew0KICAg ICAgICBlbnVtIGlzTnVsbGFibGUgPSB0cnVlOw0KICAgIH0gZWxzZSAgew0KICAg ICAgICBlbnVtIGlzTnVsbGFibGUgPSBpcyggVCA9PSBjbGFzcyApOw0KICAgIH0N Cn0gdW5pdHRlc3Qgew0KICAgIGNsYXNzIEEge30NCiAgICBhc3NlcnQoIGlzTnVs bGFibGUhQSApOw0KICAgIGFzc2VydCggaXNOdWxsYWJsZSEoaW50KikgKTsNCiAg ICBhc3NlcnQoICFpc051bGxhYmxlIShpbnRbXSkgKTsNCiAgICBhc3NlcnQoICFp c051bGxhYmxlIWludCApOw0KfQ== ------------htNRmWrzd4tGePoRiYC6qE--
Jul 27 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 // x is a nullable class reference
 if (x == null) {
      ...
 } else {
      // here the type system sees x as not null.
 }

??? What does it matter if the type system knows whether a pointer is null unless it's trying to warn you about dereferencing null?

In the else branch the state of the type of x is not-null, so as example in the else branch you are allowed to call a function that only accept not null references, with the x variable. Not-nulls integrated in the type system makes sure you have well initialized variables in the class constructors in presence of inheritance and other complexities. It also statically requires you to test for null before deferencing a nullable class reference, ans so on. Those are the fruits that a good not-null implementation gives you. You can't do all this with the NotNull toy. NotNull solves only the easy part of the whole problem, and it's a small part.
 Actually, it is. I said "that I'm aware of."

Right :-) Bye, bearophile
Jul 27 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 This is a NotNull I just implemented. It is designed to create 
 a strict
 division between things that can be null, and those that 
 cannot. The idea
 being that the programmer should be aware of it when he needs 
 to convert
 between them, and whole call graphs can more easily be made 
 free of
 null checks.

Foo f = new Foo(); some_function(NotNull!Foo(f)); <-explicit conversion and because it's a struct it's better to deliver it by ref. // --- Foo f = new Foo(); some_function(f); // ... void some_function(Foo f) in { assert(f !is null); } body { ^--- explicit. Unnecessary write effort. A struct as solution to avoid not null references is a bad solution. It is a nice play tool but as solution it is crap. To pack my object into a struct with ensures that it is not null, what's the difference if i use only structs and avoid classes? Why should i initialize first my object and put it then into a struct if i can even use only structs? That isn't comprehensible to me.
Jul 28 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 Doing stuff like that makes your code completely unportable. 
 It's _bad_
 practice. Don't go and try to redesign the language if you want 
 to be playing
 nice with other people. If you can do something completely 
 within the
 language, then that's different (other people may still hate 
 what you're up to,
 but at least they can compile it), but don't use a preprocessor 
 unless you
 really don't care about anyone else ever using your code but 
 you, and even
 then, I'd argue against it, because if you get into the habit 
 of doing that,
 you're screwed when you actually have to interact with other D 
 programmers.

 - Jonathan M Davis

I can give them the "clone_*.d" files, which contains valid D code. No problem.
Jul 28 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
One more question: Where can I find an official statement by 
Walter _why_ he does not like such shorthands? Best viewed with 
understandable reasons.
Thanks in advance. :)
Jul 28 2012
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
------------o5DXsUO7OHsfvLisBeLeTV
Content-Type: text/plain; charset=utf-8; format=flowed; delsp=yes
Content-Transfer-Encoding: 7bit

On Sat, 28 Jul 2012 10:20:56 +0200, Namespace <rswhite4 googlemail.com>  
wrote:

 This is a NotNull I just implemented. It is designed to create a strict
 division between things that can be null, and those that cannot. The  
 idea
 being that the programmer should be aware of it when he needs to convert
 between them, and whole call graphs can more easily be made free of
 null checks.

Foo f = new Foo(); some_function(NotNull!Foo(f)); <-explicit conversion and because it's a struct it's better to deliver it by ref.

The conversion from a pointer to a struct containing a pointer should be without cost when compiling with optimizations on. The effect is exactly the same as with a pointer, which I hope you don't habitually pass by reference.
 A struct as solution to avoid not null references is a bad solution. It  
 is a nice play tool but as solution it is crap. To pack my object into a  
 struct with ensures that it is not null, what's the difference if i use  
 only structs and avoid classes? Why should i initialize first my object  
 and put it then into a struct if i can even use only structs?
 That isn't comprehensible to me.

Huh? I believe you have misunderstood something here. The struct is a form of smart pointer. It behaves like a pointer does, and lets you have polymorphism, inheritance and all that stuff that comes with classes. Granted, I have found a few issues with the version I posted (mostly to do with subclassing). Most have been fixed in this version, but some are unfixable until issue 1528 has been resolved. -- Simen ------------o5DXsUO7OHsfvLisBeLeTV Content-Disposition: attachment; filename=NotNull.d Content-Type: application/octet-stream; name="NotNull.d" Content-Transfer-Encoding: Base64 LyogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmUuIEl0IGNvbWVzIHdpdGhv dXQgYW55IHdhcnJhbnR5LCB0bw0KICAqIHRoZSBleHRlbnQgcGVybWl0dGVkIGJ5 IGFwcGxpY2FibGUgbGF3LiBZb3UgY2FuIHJlZGlzdHJpYnV0ZSBpdA0KICAqIGFu ZC9vciBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBEbyBXaGF0IFRo ZSBGdWNrIFlvdSBXYW50DQogICogVG8gUHVibGljIExpY2Vuc2UsIFZlcnNpb24g MiwgYXMgcHVibGlzaGVkIGJ5IFNhbSBIb2NldmFyLiBTZWUNCiAgKiBodHRwOi8v c2FtLnpveS5vcmcvd3RmcGwvQ09QWUlORyBmb3IgbW9yZSBkZXRhaWxzLiAqLw0K DQppbXBvcnQgc3RkLmNvbnYgOiB0bzsNCmltcG9ydCBzdGQuZXhjZXB0aW9uIDog ZW5mb3JjZTsNCmltcG9ydCBzdGQudHJhaXRzIDogaXNQb2ludGVyLCBwb2ludGVy VGFyZ2V0Ow0KDQp2ZXJzaW9uICggdW5pdHRlc3QgKSB7DQogICAgaW1wb3J0IHN0 ZC5leGNlcHRpb24gOiBhc3NlcnRUaHJvd24sIGFzc2VydE5vdFRocm93bjsNCiAg ICBpbXBvcnQgY29yZS5leGNlcHRpb24gOiBBc3NlcnRFcnJvcjsNCg0KICAgIGNs YXNzIEJhc2Ugew0KICAgICAgICBpbnQgbjsNCiAgICAgICAgdGhpcyggaW50IG4g KSB7DQogICAgICAgICAgICB0aGlzLm4gPSBuOw0KICAgICAgICB9DQogICAgICAg IHRoaXMoICkge30NCiAgICB9DQogICAgDQogICAgY2xhc3MgRGVyaXZlZCA6IEJh c2Ugew0KICAgICAgICB0aGlzKCApIHt9DQogICAgfQ0KICAgIA0KICAgIGNsYXNz IFNlcGFyYXRlIHt9DQp9DQoNCi8qKg0KICogQSBwb2ludGVyIG9yIHJlZmVyZW5j ZSB0aGF0IGNhbiBuZXZlciBiZSBudWxsLg0KICogRG9lcyBub3QgYWxsb3cgaW1w bGljaXQgY29udmVyc2lvbiBmcm9tIG51bGxhYmxlIHRvIE5vdE51bGwuDQoqKi8N CnN0cnVjdCBOb3ROdWxsKCBUICkgaWYgKCBpc051bGxhYmxlIVQgKSB7DQogICAg cHJpdmF0ZSBUIHBheWxvYWQ7DQogICAgDQogICAgQGRpc2FibGUgdGhpcyggKTsN CiAgICBAZGlzYWJsZSB0aGlzKCBUICk7DQogICAgc3RhdGljIEBwcm9wZXJ0eSBA ZGlzYWJsZSBOb3ROdWxsIGluaXQoICk7DQogICAgDQogICAgLy8vLyBCdWcgMTUy OA0KICAgIC8vdGhpcyggVSA6IFQgKSggTm90TnVsbCFVIG90aGVyICkgew0KICAg IC8vICAgIHBheWxvYWQgPSBvdGhlci5wYXlsb2FkOw0KICAgIC8vfQ0KICAgIA0K ICAgIEBwcm9wZXJ0eQ0KICAgIGlub3V0KFQpIGdldCggKSBpbm91dCB7DQogICAg ICAgIHJldHVybiBwYXlsb2FkOw0KICAgIH0NCiAgICANCiAgICBOb3ROdWxsIG9w QXNzaWduKCBVICkoIE5vdE51bGwhVSB2YWx1ZSApIHsNCiAgICAgICAgcGF5bG9h ZCA9IHZhbHVlOw0KICAgICAgICByZXR1cm4gdGhpczsNCiAgICB9DQogICAgDQog ICAgVSBvcENhc3QoIFUgKSggKSBpZiAoIGlzKCBUIDogVSApIHx8IGlzKCBVIDog VCAgKSApIHsNCiAgICAgICAgcmV0dXJuIHRvIVUoIHBheWxvYWQgKTsNCiAgICB9 DQogICAgDQogICAgYWxpYXMgZ2V0IHRoaXM7DQp9IHVuaXR0ZXN0IHsNCiAgICBh c3NlcnQoICFpcyggTm90TnVsbCEoaW50KSApICk7DQogICAgYXNzZXJ0KCAgaXMo IE5vdE51bGwhKEJhc2UpICkgKTsNCiAgICBhc3NlcnQoICBpcyggTm90TnVsbCEo aW50KikgKSApOw0KICAgIGFzc2VydCggIWlzKCBOb3ROdWxsIShpbnRbXSkgKSAp Ow0KICAgIGFzc2VydCggIV9fdHJhaXRzKCBjb21waWxlcywgeyBOb3ROdWxsIWlu dCBhOyB9ICkgKTsNCiAgICBhc3NlcnQoICFfX3RyYWl0cyggY29tcGlsZXMsIHsg Tm90TnVsbCEoaW50KikgYTsgfSApICk7DQogICAgYXNzZXJ0KCAhX190cmFpdHMo IGNvbXBpbGVzLCB7IE5vdE51bGwhKGludCopIGEgPSBudWxsOyB9ICkgKTsNCiAg ICBhc3NlcnQoICFfX3RyYWl0cyggY29tcGlsZXMsIHsgTm90TnVsbCEoaW50Kikg YSA9IG5ldyBpbnQ7IH0gKSApOw0KICAgIGFzc2VydCggIV9fdHJhaXRzKCBjb21w aWxlcywgeyBOb3ROdWxsIShpbnQqKSBhID0gTm90TnVsbCEoaW50KikuaW5pdDsg fSApICk7DQogICAgYXNzZXJ0KCAhX190cmFpdHMoIGNvbXBpbGVzLCB7IE5vdE51 bGwhKGludCopIGEgPSBOb3ROdWxsIShpbnQqKSggbnVsbCApOyB9ICkgKTsNCiAg ICBhc3NlcnQoICBfX3RyYWl0cyggY29tcGlsZXMsIHsgTm90TnVsbCEoaW50Kikg YSA9IHZvaWQ7IH0gKSApOw0KICAgIGFzc2VydCggIF9fdHJhaXRzKCBjb21waWxl cywgeyBOb3ROdWxsIShpbnQqKSBhID0gdm9pZDsgKmEgPSAzOyB9ICkgKTsNCiAg ICBhc3NlcnQoICBfX3RyYWl0cyggY29tcGlsZXMsIHsgTm90TnVsbCEoQmFzZSkg YSA9IHZvaWQ7IGEubiA9IDM7IH0gKSApOw0KICAgIA0KICAgIC8vYXNzZXJ0KCAh X190cmFpdHMoIGNvbXBpbGVzLCB7IE5vdE51bGwhKEEpW10gYTsgYS5sZW5ndGgg PSAzOyB9ICkgKTsgLy8gQnVnIDcwMjENCiAgICAvLy8vIEJ1ZyAxNTI4DQogICAg Ly9hc3NlcnQoICBfX3RyYWl0cyggY29tcGlsZXMsIHsgTm90TnVsbCFCYXNlIGEg PSBhc3N1bWVOb3ROdWxsKCBuZXcgRGVyaXZlZCgpICk7IH0gKSApOw0KICAgIC8v YXNzZXJ0KCAgX190cmFpdHMoIGNvbXBpbGVzLCB7IEJhc2UgYSA9IGFzc3VtZU5v dE51bGwoIG5ldyBEZXJpdmVkKCkgKTsgfSApICk7DQogICAgLy9hc3NlcnQoICFf X3RyYWl0cyggY29tcGlsZXMsIHsgRGVyaXZlZCBiID0gYXNzdW1lTm90TnVsbCgg bmV3IEJhc2UoKSApOyB9ICkgKTsNCiAgICAvL2Fzc2VydCggIF9fdHJhaXRzKCBj b21waWxlcywgeyBEZXJpdmVkIGIgPSBjYXN0KERlcml2ZWQpYXNzdW1lTm90TnVs bCggbmV3IEJhc2UoKSApOyB9ICkgKTsNCiAgICAvL2Fzc2VydCggIV9fdHJhaXRz KCBjb21waWxlcywgeyBTZXBhcmF0ZSBjID0gY2FzdChTZXBhcmF0ZSlhc3N1bWVO b3ROdWxsKCBuZXcgQmFzZSgpICk7IH0gKSApOw0KICAgIA0KICAgIEJhc2UgYTsg YSA9IGFzc3VtZU5vdE51bGwoIG5ldyBEZXJpdmVkKCkgKTsNCiAgICANCiAgICBh c3NlcnQoICBfX3RyYWl0cyggY29tcGlsZXMsIHsgTm90TnVsbCFCYXNlIGEgPSB2 b2lkOyBhID0gYXNzdW1lTm90TnVsbCggbmV3IERlcml2ZWQoKSApOyB9ICkgKTsN CiAgICBhc3NlcnQoICBfX3RyYWl0cyggY29tcGlsZXMsIHsgQmFzZSBhOyBhID0g YXNzdW1lTm90TnVsbCggbmV3IERlcml2ZWQoKSApOyB9ICkgKTsNCiAgICBhc3Nl cnQoICFfX3RyYWl0cyggY29tcGlsZXMsIHsgRGVyaXZlZCBiOyBiID0gYXNzdW1l Tm90TnVsbCggbmV3IEJhc2UoKSApOyB9ICkgKTsNCiAgICBhc3NlcnQoICBfX3Ry YWl0cyggY29tcGlsZXMsIHsgRGVyaXZlZCBiOyBiID0gY2FzdChEZXJpdmVkKWFz c3VtZU5vdE51bGwoIG5ldyBCYXNlKCkgKTsgfSApICk7DQogICAgYXNzZXJ0KCAh X190cmFpdHMoIGNvbXBpbGVzLCB7IFNlcGFyYXRlIGM7IGMgPSBjYXN0KFNlcGFy YXRlKWFzc3VtZU5vdE51bGwoIG5ldyBCYXNlKCkgKTsgfSApICk7DQp9DQoNCi8q Kg0KICogVGFrZXMgdGhlIHZhbHVlIHRocm91Z2ggdGhlIGJhY2sgZG9vciBpbnRv IE5vdE51bGwgbGFuZC4NCiAqIFRoaXMgZnVuY3Rpb24gc2hvdWxkIGhhdmUgemVy byBvdmVyaGVhZCBpbiByZWxlYXNlIG1vZGUuDQoqKi8NCk5vdE51bGwhVCBhc3N1 bWVOb3ROdWxsKCBUICkoIFQgdmFsdWUgKSBpZiAoIGlzTnVsbGFibGUhVCApIHsN CiAgICBhc3NlcnQoIHZhbHVlICFpcyBudWxsICk7DQogICAgTm90TnVsbCFUIHJl c3VsdCA9IHZvaWQ7DQogICAgcmVzdWx0LnBheWxvYWQgPSB2YWx1ZTsNCiAgICBy ZXR1cm4gcmVzdWx0Ow0KfSB1bml0dGVzdCB7DQogICAgYXNzZXJ0KCAgX190cmFp dHMoIGNvbXBpbGVzLCB7IE5vdE51bGwhKGludCopIGEgPSBhc3N1bWVOb3ROdWxs KG5ldyBpbnQpOyB9ICkgKTsNCiAgICBhc3NlcnQoICFfX3RyYWl0cyggY29tcGls ZXMsIHsgTm90TnVsbCEoaW50KikgYSA9IGFzc3VtZU5vdE51bGwobmV3IHN0cmlu Zyk7IH0gKSApOw0KICAgIGFzc2VydFRocm93biFBc3NlcnRFcnJvciggYXNzdW1l Tm90TnVsbCEoaW50KikoIG51bGwgKSApOw0KfQ0KDQovKioNCiAqIENoZWNrcyB0 aGF0IHRoZSBwYXNzZWQgdmFsdWUgaXMgbm90IG51bGwuDQogKiBUaHJvd3MgYW4g ZXhjZXB0aW9uIGlmIGl0IGlzLg0KKiovDQpOb3ROdWxsIVQgZW5mb3JjZU5vdE51 bGwoIFQgKSggVCB2YWx1ZSApIGlmICggaXNOdWxsYWJsZSFUICkgew0KICAgIGVu Zm9yY2UoIHZhbHVlICFpcyBudWxsICk7DQogICAgTm90TnVsbCFUIHJlc3VsdCA9 IHZvaWQ7DQogICAgcmVzdWx0LnBheWxvYWQgPSB2YWx1ZTsNCiAgICByZXR1cm4g cmVzdWx0Ow0KfSB1bml0dGVzdCB7DQogICAgYXNzZXJ0KCAgX190cmFpdHMoIGNv bXBpbGVzLCB7IE5vdE51bGwhKGludCopIGEgPSBlbmZvcmNlTm90TnVsbChuZXcg aW50KTsgfSApICk7DQogICAgYXNzZXJ0KCAhX190cmFpdHMoIGNvbXBpbGVzLCB7 IE5vdE51bGwhKGludCopIGEgPSBlbmZvcmNlTm90TnVsbChuZXcgc3RyaW5nKTsg fSApICk7DQogICAgYXNzZXJ0VGhyb3duKCBlbmZvcmNlTm90TnVsbCEoaW50Kiko IG51bGwgKSApOw0KfQ0KDQp0ZW1wbGF0ZSBuZXdOb3ROdWxsKCBUICkgaWYgKCBp c051bGxhYmxlIVQgKSB7DQogICAgTm90TnVsbCFUIG5ld05vdE51bGwoIFUuLi4g KSggVSBhcmdzICkgaWYgKCBpcyggVCA9PSBjbGFzcyApICYmIF9fdHJhaXRzKCBj b21waWxlcywgeyBhdXRvIGEgPSBuZXcgVCggYXJncyApOyB9ICkgKSB7DQogICAg ICAgIHJldHVybiBhc3N1bWVOb3ROdWxsKCBuZXcgVCggYXJncyApICk7DQogICAg fQ0KICAgIE5vdE51bGwhVCBuZXdOb3ROdWxsKCApKCApIGlmICggaXNQb2ludGVy IVQgKSB7DQogICAgICAgIHJldHVybiBhc3N1bWVOb3ROdWxsKCBuZXcgcG9pbnRl clRhcmdldCEoVCkgKTsNCiAgICB9DQp9IHVuaXR0ZXN0IHsNCiAgICBhc3NlcnQo ICBfX3RyYWl0cyggY29tcGlsZXMsIHsgTm90TnVsbCFCYXNlIGEgPSBuZXdOb3RO dWxsIUJhc2UoIDMgKTsgfSApICk7DQogICAgLy8vLyBCdWcgMTUyOA0KICAgIC8v YXNzZXJ0KCAgX190cmFpdHMoIGNvbXBpbGVzLCB7IE5vdE51bGwhQmFzZSBhID0g bmV3Tm90TnVsbCFEZXJpdmVkKCAzICk7IH0gKSApOw0KICAgIGFzc2VydCggIF9f dHJhaXRzKCBjb21waWxlcywgeyBuZXdOb3ROdWxsIShpbnQqKSggKTsgfSApICk7 DQp9DQoNCi8qKg0KICogQ2hlY2tzIGlmIGEgdHlwZSBpcyBudWxsYWJsZS4gTGVm dCBvdXQgYXJyYXlzIGJlY2F1c2UgbnVsbCBhcnJheXMNCiAqIGFjdHVhbGx5IGRv IG1ha2UgYSB0d2lzdGVkIHNvcnQgb2Ygc2Vuc2UuDQoqKi8NCnRlbXBsYXRlIGlz TnVsbGFibGUoIFQgKSB7DQogICAgc3RhdGljIGlmICggaXMoIFQgVSA6IFUqICkg KSB7DQogICAgICAgIGVudW0gaXNOdWxsYWJsZSA9IHRydWU7DQogICAgfSBlbHNl ICB7DQogICAgICAgIGVudW0gaXNOdWxsYWJsZSA9IGlzKCBUID09IGNsYXNzICk7 DQogICAgfQ0KfSB1bml0dGVzdCB7DQogICAgY2xhc3MgQSB7fQ0KICAgIGFzc2Vy dCggaXNOdWxsYWJsZSFBICk7DQogICAgYXNzZXJ0KCBpc051bGxhYmxlIShpbnQq KSApOw0KICAgIGFzc2VydCggIWlzTnVsbGFibGUhKGludFtdKSApOw0KICAgIGFz c2VydCggIWlzTnVsbGFibGUhaW50ICk7DQp9DQoNCnZvaWQgbWFpbiggKSB7DQp9 ------------o5DXsUO7OHsfvLisBeLeTV--
Jul 28 2012
prev sibling next sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Sat, 28 Jul 2012 05:07:44 +0200
schrieb "bearophile" <bearophileHUGS lycos.com>:

 // x is a nullable class reference
 if (x == null) {
      ...
 } else {
      // here the type system sees x as not null.
 }


example in the else branch you are allowed to call a function that only accept not null references, with the x variable. Not-nulls integrated in the type system makes sure you have well initialized variables in the class constructors in presence of inheritance and other complexities. It also statically requires you to test for null before deferencing a nullable class reference, ans so on. Those are the fruits that a good not-null implementation gives you. You can't do all this with the NotNull toy. NotNull solves only the easy part of the whole problem, and it's a small part. Bye, bearophile

I found this an interesting read. The implementation likely doesn't interfere much with other language features (in a sense like trusted does to templated functions that take potentially unsafe code as parameters). I especially like how the compiler _statically_ knows, that x is not null in the else case. The runtime cost is moved from every call on x, to a single if-statement! It could require a little logic to parse complex conditions like "if (a == 1 && !x != null)", though ;) -- Marco
Jul 28 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 Huh? I believe you have misunderstood something here. The 
 struct is a form
 of smart pointer. It behaves like a pointer does, and lets you 
 have
 polymorphism, inheritance and all that stuff that comes with 
 classes.
 Granted, I have found a few issues with the version I posted 
 (mostly to do
 with subclassing). Most have been fixed in this version, but 
 some are
 unfixable until issue 1528 has been resolved.

Some kind of smart pointer is easy to write, or not? What's wrong with this? http://dpaste.dzfl.pl/11a4d692
Jul 28 2012
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Timon Gehr:

 Non-null types in Spec# are unsound.

Really? I didn't know it. Surely its non-null design looks quite refined and thought-out. But maybe as say it's not enough still. Do you have a link where it shows it's unsound? Thank you, bye, bearophile
Jul 29 2012