const and immutable
Hey all, I'm having some trouble understanding the whole const and immutable of D2, especially since it seems documentation is not consistent (Or I'm missing some things). I write quite a lot of C++ code btw, so I'm familiar with that. --- http://www.digitalmars.com/d/2.0/htomodule.html says: D has const as a storage class, not a type modifier. Hence, just drop any const used as a type modifier: void foo(const int *p, char *const q); becomes: void foo(int* p, char* q); http://www.digitalmars.com/d/2.0/const3.html includes D examples like: void foo(const int* x, int* y) Is the information on the first page not updated for D2? --- Is the following correct? (this confuses me) immutable int somefunc(); means the same thing as int somefunc() immutable; and not the same thing as immutable(int) somefunc(); even though the first syntax looks very much like this: immutable int x; --- I think I understand the difference between const and immuable when considering references and pointers, but how exactly is const different from immutable in: const int x; versus immutable int x; void somefunc(const int x); versus void somefunc(immutable int x); const(int) somefunc(); versus immutable(int) somefunc(); How does this system interact with in/out/ref etc? Can I for example have const ref int somefunc()? --- Tim
Re: const and immutable
Tim Verweij tjverw...@gmail.com wrote: http://www.digitalmars.com/d/2.0/const3.html includes D examples like: void foo(const int* x, int* y) Is the information on the first page not updated for D2? That seems correct. Is the following correct? (this confuses me) immutable int somefunc(); means the same thing as int somefunc() immutable; and not the same thing as immutable(int) somefunc(); even though the first syntax looks very much like this: immutable int x; Yes. immutable always applies to the whole type, which in the function case would be int function(). I think I understand the difference between const and immuable when considering references and pointers, but how exactly is const different from immutable in: const int x; versus immutable int x; void somefunc(const int x); versus void somefunc(immutable int x); const(int) somefunc(); versus immutable(int) somefunc(); It isn't. For non-reference types, immutable and const are indistinguishable. How does this system interact with in/out/ref etc? Can I for example have const ref int somefunc()? Absolutely. -- Simen
Re: const and immutable
On Tue, 06 Jul 2010 10:56:11 -0400, Tim Verweij tjverw...@gmail.com wrote: Hey all, I'm having some trouble understanding the whole const and immutable of D2, especially since it seems documentation is not consistent (Or I'm missing some things). I write quite a lot of C++ code btw, so I'm familiar with that. --- http://www.digitalmars.com/d/2.0/htomodule.html says: D has const as a storage class, not a type modifier. Hence, just drop any const used as a type modifier: void foo(const int *p, char *const q); becomes: void foo(int* p, char* q); http://www.digitalmars.com/d/2.0/const3.html includes D examples like: void foo(const int* x, int* y) Is the information on the first page not updated for D2? Yes, the first page is not routinely updated, it looks very outdated. consider it a bug of the documentation. D1 has no const type modifier, D2 does. --- Is the following correct? (this confuses me) immutable int somefunc(); means the same thing as int somefunc() immutable; and not the same thing as immutable(int) somefunc(); even though the first syntax looks very much like this: immutable int x; This is a large part of confusion to many users. It's done this way for consistency. For example, a synchronized method looks like this: synchronized int foo(); Which does not return a synchronized int, but rather means the function is synchronized on this. In addition, many attributes can be applied in groups via: attribute { } or attribute: Similar to protection. The same goes for const. So this: const int somefunc(); and const { int somefunc(); } are supposed to be equivalent. People on this NG have petitioned without success to get Walter to remove that syntax, or make it mean what it looks like it means. Code like this: immutable immutable(int)* foo(); should not be required/allowed :) --- I think I understand the difference between const and immuable when considering references and pointers, but how exactly is const different from immutable in: const int x; versus immutable int x; Functionally, no difference. Once declared, those cannot be changed. However, semantically, there is a difference when taking the address: immutable int x; const int y; immutable(int)* yp = y; // does not compile! const(int)*xp = x; // ok, immutable implicitly converts to const. The thing to remember is that const means you cannot change that value through that pointer. But there is no guarantee that something else is able to change the value. If declaring x to be not changing, the best way to do it is declare it immutable, because that is what it is. Declaring it const means you are saying something else might be able to change the value. void somefunc(const int x); versus void somefunc(immutable int x); const(int) somefunc(); versus immutable(int) somefunc(); These are the same as above. Note that D enforces transitive const/immutability. But it also allows implicit conversions to any constancy with value types (types without any references in them) because simply copying the data completely decouples it from the original. So things like this are possible: const int x = 5; int y = x; // ok to copy const to mutable for value types. But this is not: int *xp = x; // error, because there is a reference here! How does this system interact with in/out/ref etc? Can I for example have const ref int somefunc()? Yes. in/out/ref are all storage classes and can be applied to any type. However, you can only use in and out on function parameters, and you can only apply ref to function parameters and return values. You can't declare a reference as a local variable like you can in C++. There is also a type modifier called inout, which is somewhat confusing at first but aids greatly in reducing source and gerenated code. However, it is currently very broken. Eventually, most functions will be inout. -Steve
Re: const and immutable
Hello Tim, I think I understand the difference between const and immuable when considering references and pointers, but how exactly is const different from immutable in: [...] const(int) somefunc(); versus immutable(int) somefunc(); BTW both of those are pointless. The following works: import std.stdio; const(int) Fn(){return 0;} void main() { int i = Fn(); i = 5; writef(%d\n, i); } -- ... IXOYE
Re: const and immutable
Thanks for all replies, that was very helpful. I have one more question about inout. If I understand correctly, it is always coupled to the use of a parameter and cannot be used to get rid of the double GetBar in the following C++ example: class Foo { public: const Bar GetBar() { return bar; } const Bar GetBar() { return bar; } private: Bar bar; } Is this correct? Thx for your replies.
Re: const and immutable
Not sure if I'm double posting now. Sorry if I am, but I didn't see my own post appear this time. Anyway, thanks for your replies, that was very helpful. I had one more question about inout. If I understand correctly it cannot be used to get rid of the double GetBar function in the following C++ example: class Foo { public: const Bar GetBar() { return mBar; } const Bar GetBar() { return mBar; } private: Bar mBar; }; Is that correct? Or is there a way to make this one function in D?
Re: const and immutable
On Tue, 06 Jul 2010 12:10:04 -0400, Tim Verweij tjverw...@gmail.com wrote: Not sure if I'm double posting now. Sorry if I am, but I didn't see my own post appear this time. Anyway, thanks for your replies, that was very helpful. I had one more question about inout. If I understand correctly it cannot be used to get rid of the double GetBar function in the following C++ example: class Foo { public: const Bar GetBar() { return mBar; } const Bar GetBar() { return mBar; } private: Bar mBar; }; Is that correct? Or is there a way to make this one function in D? I'm not positive, but I think the second const applies to the second function, I think you meant: const Bar GetBar() const { return mBar; } And yes, inout will reduce this to one function: ref inout(Bar) GetBar() inout { return mBar; } In addition, you do not have to specify the immutable version, therefore it actually saves 2 functions. That is why it's there :) -Steve
Re: const and immutable
== Quote from Steven Schveighoffer (schvei...@yahoo.com)'s article I'm not positive, but I think the second const applies to the second function, I think you meant: const Bar GetBar() const { return mBar; } Uh, yes, of course. Pff, I feel bad for making such an embarrasing mistake. And yes, inout will reduce this to one function: ref inout(Bar) GetBar() inout { return mBar; } In addition, you do not have to specify the immutable version, therefore it actually saves 2 functions. That is why it's there :) Excellent, thanks! So, how is inout currently very broken (as noted by Steven Schveighoffer)? I haven't had the time to try this yet. I have ordered Andrei Alexandrescu's book The D Programming Language. Does it cover inout as well, or is this feature newer than the book?
Re: const and immutable
On Tue, 06 Jul 2010 16:08:21 -0400, Tim Verweij tjverw...@gmail.com wrote: == Quote from Steven Schveighoffer (schvei...@yahoo.com)'s article I'm not positive, but I think the second const applies to the second function, I think you meant: const Bar GetBar() const { return mBar; } Uh, yes, of course. Pff, I feel bad for making such an embarrasing mistake. And yes, inout will reduce this to one function: ref inout(Bar) GetBar() inout { return mBar; } In addition, you do not have to specify the immutable version, therefore it actually saves 2 functions. That is why it's there :) Excellent, thanks! So, how is inout currently very broken (as noted by Steven Schveighoffer)? I haven't had the time to try this yet. Very broken. It works in a small subset of cases. Look for this bug to be closed when it's fixed (add yourself to the CC of the bug): http://d.puremagic.com/issues/show_bug.cgi?id=3748 Also, here is a complete overview of how it is supposed to work: http://prowiki.org/wiki4d/wiki.cgi?action=browseamp;id=LanguageDevel/DIPs/DIP2amp;oldid=DiP2 I have ordered Andrei Alexandrescu's book The D Programming Language. Does it cover inout as well, or is this feature newer than the book? It's in the book. I reviewed the book, but I don't have the final copy, so I'm not sure how much is discussed. I remember there were some omissions in the copy I reviewed. -Steve
std.pattern.. templated publisher subscriber pattern, adding events to collections
Hi, Andrei brings in the idea of std.pattern. Seems that this module is stalled; Unfortunately ! However I would like to enhance collection classes (likewise dcollections) with a Publisher - Subscriber pattern (signal - slot, or observer pattern) , if you prefer) Hope the idea of enhancing collections with events become clear with the following snippet. ---I am able to spend just a few hours a month with D programming.. in other words, please don't kill me ;) Untested Draft code which requires a lot of help and ,more important, feedback from you. struct publisherMsg(T) { T data; Action a; } mixin template Publisher(T) { private : enum Action = {INSERT, UPDATE, DELETE, READONLY}; //alias typeof(this) PT; struct receiver { Object o; callback cb; // opCall() or this() ? } receiver[] subscriber; publisherMsg!(T) msg; alias void delegate(ref msg) callback; void addSubscriber(object o, callback cb) { //subscriber ~= o; } void publish(T t, Action act) { foreach (object o ; subscriber) { // create and send message } } } mixin template Subscriber() { // see UndoList } final class Stack(T, bool observable = false ) /+ should use alias +/ { T[] data; static if (observable) mixin Observable!T; void push(T t) { publish(t, Action.INSERT) } T pop() { } bool empty() { } T top() { } size_t size() { } } /// Undo list will receive every pushed or popped item (T and Action) class UndoList(T) { private: T[] data; // should be part of the subscriber mixin template. publisherMsg!T stackMessage; void delegate(ref stackMessage) dg; alias Stack!(int) IntegerStack; IntegerStack intstack = new IntegerStack; private this() { dg = this.feedback; } public void feedback(ref stackMessage msg ) { writefln(push or pop action); } } -Bjoern
Re: std.pattern.. templated publisher subscriber pattern, adding events to collections
On 07.07.2010 2:01, BLS wrote: Hi, Andrei brings in the idea of std.pattern. Seems that this module is stalled; Unfortunately ! However I would like to enhance collection classes (likewise dcollections) with a Publisher - Subscriber pattern (signal - slot, or observer pattern) , if you prefer) Hope the idea of enhancing collections with events become clear with the following snippet. ---I am able to spend just a few hours a month with D programming.. in other words, please don't kill me ;) Untested Draft code which requires a lot of help and ,more important, feedback from you. Will do, probably both :) struct publisherMsg(T) { T data; Action a; } mixin template Publisher(T) { private : enum Action = {INSERT, UPDATE, DELETE, READONLY}; //alias typeof(this) PT; struct receiver { Object o; callback cb; // opCall() or this() ? } Why not just use plain delegate instead of pair Object,callback? The object itself could be bound like this: struct MyObject{ string name; } MyObject mb = MyObject(test); callback c = (ref msg m){ if(msg.action == INSERT) writeln(inserted ~ mb.name); // }; And better yet it's real type is known inside delegate at binding point. Not sure why msg is ref parameter? So that one subscriber can affect msg that will in turn see another one - seems weird. receiver[] subscriber; publisherMsg!(T) msg; alias void delegate(ref msg) callback; void addSubscriber(object o, callback cb) { //subscriber ~= o; } ditto. void publish(T t, Action act) { foreach (object o ; subscriber) { // create and send message } } } and then maybe just call all delegates with msg(t,act)? mixin template Subscriber() { // see UndoList } final class Stack(T, bool observable = false ) /+ should use alias +/ { T[] data; static if (observable) mixin Observable!T; void push(T t) { publish(t, Action.INSERT) } T pop() { } bool empty() { } T top() { } size_t size() { } } /// Undo list will receive every pushed or popped item (T and Action) class UndoList(T) { private: T[] data; // should be part of the subscriber mixin template. publisherMsg!T stackMessage; void delegate(ref stackMessage) dg; alias Stack!(int) IntegerStack; IntegerStack intstack = new IntegerStack; private this() { dg = this.feedback; } public void feedback(ref stackMessage msg ) { writefln(push or pop action); } } -Bjoern -- Dmitry Olshansky
Re: std.pattern.. templated publisher subscriber pattern, adding events to collections
Okay a bit better snippet than before. snippet should be almost functional.. /* Hi, Andrei brings in the idea of std.pattern. Seems that this module is stalled; Unfortunately ! However I would like to enhance collection classes (likewise dcollections) with a Publisher - Subscriber pattern (signal - slot, or observer pattern) , if you prefer) Hope the idea of enhancing collections with events become clear with the following snippet. !!! I am able to spend just a few hours a month with D programming.. in other words, please don't kill me :) Untested Draft code which requires a lot of help and ,more important, feedback from you. */ struct publisherMsg(T) { T data; Action a; } mixin template Publisher(T) { private : enum Action = {INSERT, UPDATE, DELETE, READONLY}; //alias typeof(this) PT; struct receiver { Object o; callback cb; } receiver[] subscriber; publisherMsg!(T) msg; alias void delegate(const ref msg) callback; void addSubscriber(object o, callback cb) { //subscriber ~= o; } void publish() { foreach (object o ; subscriber) { // create message and send message } } } mixin template Subscriber() { // see UndoList for implementation } final class Stack(T, bool observable = false ) { T[] data; static if (observable) mixin Observable!T; void push( T t) { data ~= t; publish(t, Action.INSERT); } T pop() { publish(t, Action.DELETE); //... } bool empty() { } T top() { publish(t, Action.READONLY); //... } size_t size() { } } // Undo list will receive every pushed or popped item -data and action) class UndoList(T) { private: T[] data; /// should be part of the sunscriber mixin templates. publisherMsg!T stackMessage; void delegate(const ref stackMessage) dg; alias Stack!(int) IntegerStack; IntegerStack intstack = new IntegerStack; private this() { dg = this.feedback; // SUBBSCRIBE Stack(T) push and pop events. intstack.addSubscriber(this, dg); } public void feedback(const ref stackMessage msg ) { writefln(Action); } }
Re: std.pattern.. templated publisher subscriber pattern, adding events to collections
Hi Dimitry, thanks for the feedback! Please have a look at the new snippet (just posted) msg is a ref parameter cause it is filled in our example from Stack. The Publisher mixin HOST. In other words. Where ever you mixin the Publisher template a message will be broad casted to all subscribers containing 2 information. 1 ) a value of type T, and an enum value INSERT, DELETE etc... will read your comments tomorrow more carefully.. have to sleep now.) bjoern
Re: Mixing operations with signed and unsigned types
Ellery Newcomer wrote: On 07/05/2010 07:59 AM, Stewart Gordon wrote: bearophile wrote: Stewart Gordon: I can also imagine promoting your mindset leading to edit wars between developers declaring an int and then putting assert (qwert = 0); in the class invariant, and those who see this and think it's brain-damaged. As opposed to doing what? Just using uint, of course! snip Another important difference is the point of non-'continuity' with a signed integer, that point is *.max/min. Assuming typical usage of integers centers around zero, this point doesn't get hit frequently. with an unsigned integer, that point is 0. Assuming the same, this point gets hit much more frequently, which has important implications for subtraction and comparison. Subtraction - yes, obviously. Comparison - how do you mean? Stewart.
Re: Mixing operations with signed and unsigned types
On 07/06/2010 07:05 PM, Stewart Gordon wrote: Ellery Newcomer wrote: On 07/05/2010 07:59 AM, Stewart Gordon wrote: bearophile wrote: Stewart Gordon: I can also imagine promoting your mindset leading to edit wars between developers declaring an int and then putting assert (qwert = 0); in the class invariant, and those who see this and think it's brain-damaged. As opposed to doing what? Just using uint, of course! For enforcing a non-negative constraint, that is brain damaged. Semantically, the two are very different. int i; assert(i = 0); says i can cross the 0 boundary, but it's an error if it does, i.e. programmer doesn't need to be perfect because it *does get caught* (extreme instances notwithstanding). uint i; says i cannot cross the 0 boundary, but it isn't an error if it does. programmer needs to be perfect and error doesn't get caught (unless what you're using it for can do appropriate bounds checking). Comparison - how do you mean? Stewart. Mmmph. Just signed/unsigned, I guess (I was thinking foggily that comparison intrinsically involves subtraction or something like that)