www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - const(Object)ref is here!

reply Michel Fortin <michel.fortin michelf.com> writes:
After a recent discussion on this list about tail-const class 
references, it became rather clear that someone interested would have 
to implement the thing if we were to have it. So I did it. See 
enhancement request 5325 for an explanation and a patch.
<http://d.puremagic.com/issues/show_bug.cgi?id=5325>

Let's hope Walter likes my patch.

In the tail-const thread, I proposed the challenge of making this code 
work when an array of const object is passed as an argument:

	T[] giveMeASortedArray(alias Predicate, T)(T[] t) {
		// creating new array of the same length but with assignable elements
		auto copy = new Unqual!(typeof(t[0]))[t.length];
		foreach (index, value; t)
			copy[index] = value;
	
		// sorting the copy
		sort!(Predicate)(copy);
		return copy;
	}

Well, with the patch I made it now works!... irrespective of the type 
attribute (const,immutable,shared,inout). The only modification 
required to Phobos is to make to!string() compile when passed a 
const(Object) because somehow 'sort' requires that.

Here is how the function is invoked:

	void main() {
		int*[] a = giveMeASortedArray!("a < b")(new int*[12]);
		Object[] b = giveMeASortedArray!("a < b")(new Object[12]);
	
		const(int*)[] c = giveMeASortedArray!("a < b")(new const(int*)[12]);
		const(Object)[] d = giveMeASortedArray!("cast(void*)a < 
cast(void*)b")(new const(Object)[12]);
	}

See the strange predicate for the const(Object) version? That's because 
opCmp() in Object doesn't work with const.

Two minor modifications are required in Phobos to make the above 
compile. First, to!string(const(Object)) needs an implementation 
because somehow 'sort' requires it. Also template std.traits.isMutable 
needed an adjustment so that swap()'s template constrains are satisfied.


-- 
Michel Fortin
michel.fortin michelf.com
http://michelf.com/
Dec 05 2010
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
That was fast. 0o

:)

On 12/6/10, Michel Fortin <michel.fortin michelf.com> wrote:
 After a recent discussion on this list about tail-const class
 references, it became rather clear that someone interested would have
 to implement the thing if we were to have it. So I did it. See
 enhancement request 5325 for an explanation and a patch.
 <http://d.puremagic.com/issues/show_bug.cgi?id=5325>

 Let's hope Walter likes my patch.

 In the tail-const thread, I proposed the challenge of making this code
 work when an array of const object is passed as an argument:

 	T[] giveMeASortedArray(alias Predicate, T)(T[] t) {
 		// creating new array of the same length but with assignable elements
 		auto copy = new Unqual!(typeof(t[0]))[t.length];
 		foreach (index, value; t)
 			copy[index] = value;
 	
 		// sorting the copy
 		sort!(Predicate)(copy);
 		return copy;
 	}

 Well, with the patch I made it now works!... irrespective of the type
 attribute (const,immutable,shared,inout). The only modification
 required to Phobos is to make to!string() compile when passed a
 const(Object) because somehow 'sort' requires that.

 Here is how the function is invoked:

 	void main() {
 		int*[] a = giveMeASortedArray!("a < b")(new int*[12]);
 		Object[] b = giveMeASortedArray!("a < b")(new Object[12]);
 	
 		const(int*)[] c = giveMeASortedArray!("a < b")(new const(int*)[12]);
 		const(Object)[] d = giveMeASortedArray!("cast(void*)a <
 cast(void*)b")(new const(Object)[12]);
 	}

 See the strange predicate for the const(Object) version? That's because
 opCmp() in Object doesn't work with const.

 Two minor modifications are required in Phobos to make the above
 compile. First, to!string(const(Object)) needs an implementation
 because somehow 'sort' requires it. Also template std.traits.isMutable
 needed an adjustment so that swap()'s template constrains are satisfied.


 --
 Michel Fortin
 michel.fortin michelf.com
 http://michelf.com/
Dec 05 2010
prev sibling next sibling parent reply Graham St Jack <Graham.StJack internode.on.net> writes:
First, I have to say that it is wonderful that someone is taking a 
serious look at this area again, and even better, you have come up with 
a compiler patch to make it happen!

Some questions (assuming your patch or something like it gets into dmd):

Does this mean that I would be able to write this:
immutable(Foo)ref foo; // create a reference
foo = new immutable(Foo)(); // re-bind it (not sure about "new" syntax 
for immutables)

Are there any other show-stopping syntax issues that are holding up 
widespread adoption/rollout of const-correctness?

What do Walter and Andrei think?

Does anyone know what the plan is for rolling const-correctness 
thoughout druntime and phobos (and shared/immutable in std.concurrency)? 
Having to do casting all the time is a real drag. I for one would be 
happy to help if help is needed.


On 06/12/10 11:21, Michel Fortin wrote:
 After a recent discussion on this list about tail-const class 
 references, it became rather clear that someone interested would have 
 to implement the thing if we were to have it. So I did it. See 
 enhancement request 5325 for an explanation and a patch.
 <http://d.puremagic.com/issues/show_bug.cgi?id=5325>

 Let's hope Walter likes my patch.

 In the tail-const thread, I proposed the challenge of making this code 
 work when an array of const object is passed as an argument:

     T[] giveMeASortedArray(alias Predicate, T)(T[] t) {
         // creating new array of the same length but with assignable 
 elements
         auto copy = new Unqual!(typeof(t[0]))[t.length];
         foreach (index, value; t)
             copy[index] = value;

         // sorting the copy
         sort!(Predicate)(copy);
         return copy;
     }

 Well, with the patch I made it now works!... irrespective of the type 
 attribute (const,immutable,shared,inout). The only modification 
 required to Phobos is to make to!string() compile when passed a 
 const(Object) because somehow 'sort' requires that.

 Here is how the function is invoked:

     void main() {
         int*[] a = giveMeASortedArray!("a < b")(new int*[12]);
         Object[] b = giveMeASortedArray!("a < b")(new Object[12]);

         const(int*)[] c = giveMeASortedArray!("a < b")(new 
 const(int*)[12]);
         const(Object)[] d = giveMeASortedArray!("cast(void*)a < 
 cast(void*)b")(new const(Object)[12]);
     }

 See the strange predicate for the const(Object) version? That's 
 because opCmp() in Object doesn't work with const.

 Two minor modifications are required in Phobos to make the above 
 compile. First, to!string(const(Object)) needs an implementation 
 because somehow 'sort' requires it. Also template std.traits.isMutable 
 needed an adjustment so that swap()'s template constrains are satisfied.
-- Graham St Jack
Dec 05 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-06 00:16:27 -0500, Graham St Jack 
<Graham.StJack internode.on.net> said:

 First, I have to say that it is wonderful that someone is taking a 
 serious look at this area again, and even better, you have come up with 
 a compiler patch to make it happen!
 
 Some questions (assuming your patch or something like it gets into dmd):
 
 Does this mean that I would be able to write this:
 immutable(Foo)ref foo; // create a reference
 foo = new immutable(Foo)(); // re-bind it (not sure about "new" syntax 
 for immutables)
That's the whole point yes. This syntax works with my patch. :-)
 Are there any other show-stopping syntax issues that are holding up 
 widespread adoption/rollout of const-correctness?
Surly there are others issues to solve. But this one is the one I kept falling into when trying to use immutable objects in my code some time ago.
 What do Walter and Andrei think?
That I'd like to know. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 06 2010
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Actually I really like the optional usage of ref here because it might
help to disambiguate between a class and a struct object:

E.g.:

class Foo
{
}

struct Bar
{
}

void main()
{
    Foo ref foo;  // I can be sure Foo is a class
    Bar bar;
}

Sometimes it happens that I forget to 'new' a class object, and to the
naked eye the code doesn't appear wrong, but using the optional ref
keyword helps in tracking this kind of bug down. I guess the compiler
should throw an error in cases where Foo is a struct.
Dec 06 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-06 13:35:27 -0500, Andrej Mitrovic 
<andrej.mitrovich gmail.com> said:

 Actually I really like the optional usage of ref here because it might
 help to disambiguate between a class and a struct object:
 
 E.g.:
 
 class Foo
 {
 }
 
 struct Bar
 {
 }
 
 void main()
 {
     Foo ref foo;  // I can be sure Foo is a class
     Bar bar;
 }
 
 Sometimes it happens that I forget to 'new' a class object, and to the
 naked eye the code doesn't appear wrong, but using the optional ref
 keyword helps in tracking this kind of bug down. I guess the compiler
 should throw an error in cases where Foo is a struct.
It does (throw an error in cases where Foo is a struct). I never though of this usage. :-) Since we're speaking of the optional use of 'ref', here's a little quiz: alias Object A; alias Object ref B; A ref a; B ref b; What happens here? Should there be an error somewhere? Where? Also, what happens if we apply different modifiers at different places? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 06 2010
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 06 Dec 2010 13:44:41 -0500, Michel Fortin  
<michel.fortin michelf.com> wrote:

 On 2010-12-06 13:35:27 -0500, Andrej Mitrovic  
 <andrej.mitrovich gmail.com> said:

 Actually I really like the optional usage of ref here because it might
 help to disambiguate between a class and a struct object:
  E.g.:
  class Foo
 {
 }
  struct Bar
 {
 }
  void main()
 {
     Foo ref foo;  // I can be sure Foo is a class
     Bar bar;
 }
  Sometimes it happens that I forget to 'new' a class object, and to the
 naked eye the code doesn't appear wrong, but using the optional ref
 keyword helps in tracking this kind of bug down. I guess the compiler
 should throw an error in cases where Foo is a struct.
It does (throw an error in cases where Foo is a struct). I never though of this usage. :-) Since we're speaking of the optional use of 'ref', here's a little quiz: alias Object A; alias Object ref B; A ref a; B ref b; What happens here? Should there be an error somewhere? Where? Also, what happens if we apply different modifiers at different places?
alias Object ref B should be the same as alias Object B, since Object ref is the same type as Object. So there should be no error. Now, what happens for this: alias const(Object) ref A; A ref a; My gut says this should be the same error as trying to ref a struct. But I can see it also being allowed. -Steve
Dec 06 2010
prev sibling parent reply spir <denis.spir gmail.com> writes:
On Mon, 6 Dec 2010 13:44:41 -0500
Michel Fortin <michel.fortin michelf.com> wrote:

 On 2010-12-06 13:35:27 -0500, Andrej Mitrovic=20
 <andrej.mitrovich gmail.com> said:
=20
 Actually I really like the optional usage of ref here because it might
 help to disambiguate between a class and a struct object:
=20
 E.g.:
=20
 class Foo
 {
 }
=20
 struct Bar
 {
 }
=20
 void main()
 {
     Foo ref foo;  // I can be sure Foo is a class
     Bar bar;
 }
=20
 Sometimes it happens that I forget to 'new' a class object, and to the
 naked eye the code doesn't appear wrong, but using the optional ref
 keyword helps in tracking this kind of bug down. I guess the compiler
 should throw an error in cases where Foo is a struct.
=20 It does (throw an error in cases where Foo is a struct). I never though=20 of this usage. :-) =20 Since we're speaking of the optional use of 'ref', here's a little quiz: =20 alias Object A; alias Object ref B; =20 A ref a; B ref b; =20 What happens here? Should there be an error somewhere? Where? Also,=20 what happens if we apply different modifiers at different places?
As I understand the (non-)semantics of 'ref', there should be no error. Thi= s code should considered by the compiler as equivalent to: Object a; Object b; Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Dec 06 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-06 14:46:51 -0500, spir <denis.spir gmail.com> said:

 On Mon, 6 Dec 2010 13:44:41 -0500
 Michel Fortin <michel.fortin michelf.com> wrote:
 
 Since we're speaking of the optional use of 'ref', here's a little quiz:
 
 	alias Object A;
 	alias Object ref B;
 
 	A ref a;
 	B ref b;
 
 What happens here? Should there be an error somewhere? Where? Also,
 what happens if we apply different modifiers at different places?
As I understand the (non-)semantics of 'ref', there should be no error. Thi s code should considered by the compiler as equivalent to: Object a; Object b;
And that's what my patch does. It only gets confusing when you add modifiers: alias const(Object)ref A; alias const(Object ref) B; alias const(Object) C; A ref a; B ref b; C ref c; With my patch, variables 'a', 'b', and 'c' are all of the same type: "const(Object)ref", the later 'ref' changing the constness of the reference specified in the 'B' alias. Note that while this behaviour is allowed with an alias, it is *not* allowed directly, so you can't write this for instance: const(Object ref) ref d; That's an error. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 06 2010
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 06 Dec 2010 15:01:25 -0500, Michel Fortin  
<michel.fortin michelf.com> wrote:

 On 2010-12-06 14:46:51 -0500, spir <denis.spir gmail.com> said:

 On Mon, 6 Dec 2010 13:44:41 -0500
 Michel Fortin <michel.fortin michelf.com> wrote:

 Since we're speaking of the optional use of 'ref', here's a little  
 quiz:
  	alias Object A;
 	alias Object ref B;
  	A ref a;
 	B ref b;
  What happens here? Should there be an error somewhere? Where? Also,
 what happens if we apply different modifiers at different places?
As I understand the (non-)semantics of 'ref', there should be no error. Thi s code should considered by the compiler as equivalent to: Object a; Object b;
And that's what my patch does. It only gets confusing when you add modifiers: alias const(Object)ref A; alias const(Object ref) B; alias const(Object) C; A ref a; B ref b; C ref c; With my patch, variables 'a', 'b', and 'c' are all of the same type: "const(Object)ref", the later 'ref' changing the constness of the reference specified in the 'B' alias. Note that while this behaviour is allowed with an alias, it is *not* allowed directly, so you can't write this for instance: const(Object ref) ref d; That's an error.
I don't know if that's good. Redundancy is OK as long as it is consistent. If Object ref is treated as Object everywhere it is used, that helps to be able to explain how it works. Similarly Object ref ref should probably reduce to Object. We really need to ensure that all types using this notation are reduced to their canonical types internally. Otherwise, strange results would occur. -Steve
Dec 06 2010
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-06 15:14:28 -0500, "Steven Schveighoffer" 
<schveiguy yahoo.com> said:

 On Mon, 06 Dec 2010 15:01:25 -0500, Michel Fortin  
 <michel.fortin michelf.com> wrote:
 
 On 2010-12-06 14:46:51 -0500, spir <denis.spir gmail.com> said:
 
 On Mon, 6 Dec 2010 13:44:41 -0500
 Michel Fortin <michel.fortin michelf.com> wrote:
 
 Since we're speaking of the optional use of 'ref', here's a little  quiz:
  	alias Object A;
 	alias Object ref B;
  	A ref a;
 	B ref b;
  What happens here? Should there be an error somewhere? Where? Also,
 what happens if we apply different modifiers at different places?
As I understand the (non-)semantics of 'ref', there should be no error. Thi s code should considered by the compiler as equivalent to: Object a; Object b;
And that's what my patch does. It only gets confusing when you add modifiers: alias const(Object)ref A; alias const(Object ref) B; alias const(Object) C; A ref a; B ref b; C ref c; With my patch, variables 'a', 'b', and 'c' are all of the same type: "const(Object)ref", the later 'ref' changing the constness of the reference specified in the 'B' alias. Note that while this behaviour is allowed with an alias, it is *not* allowed directly, so you can't write this for instance: const(Object ref) ref d; That's an error.
I don't know if that's good. Redundancy is OK as long as it is consistent. If Object ref is treated as Object everywhere it is used, that helps to be able to explain how it works. Similarly Object ref ref should probably reduce to Object. We really need to ensure that all types using this notation are reduced to their canonical types internally. Otherwise, strange results would occur.
Don't worry. Internally, my patch makes sure types "Object ref" and "Object" have the exact same internal representation. The double-ref check is a check against the syntax tree, not against the actual type. That's why it's still possible to have two 'ref' if one is in the alias definition and the other is part of the variable declaration. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 06 2010
prev sibling next sibling parent reply spir <denis.spir gmail.com> writes:
On Mon, 6 Dec 2010 15:01:25 -0500
Michel Fortin <michel.fortin michelf.com> wrote:

 On 2010-12-06 14:46:51 -0500, spir <denis.spir gmail.com> said:
=20
 On Mon, 6 Dec 2010 13:44:41 -0500
 Michel Fortin <michel.fortin michelf.com> wrote:
=20
 Since we're speaking of the optional use of 'ref', here's a little qui=
z:
=20
 	alias Object A;
 	alias Object ref B;
=20
 	A ref a;
 	B ref b;
=20
 What happens here? Should there be an error somewhere? Where? Also,
 what happens if we apply different modifiers at different places?
=20 As I understand the (non-)semantics of 'ref', there should be no error.=
Thi
 s code should considered by the compiler as equivalent to:
 	Object a;
 	Object b;
=20 And that's what my patch does. It only gets confusing when you add modifi=
ers:
=20
 	alias const(Object)ref A;
 	alias const(Object ref) B;
 	alias const(Object) C;
=20
 	A ref a;
 	B ref b;
 	C ref c;
=20
 With my patch, variables 'a', 'b', and 'c' are all of the same type:=20
 "const(Object)ref", the later 'ref' changing the constness of the=20
 reference specified in the 'B' alias.
Well, as your patch introduces the possibility to "const-en" the target of = ref's, it _should_ have some meaning. Else, it leaves the language unconsis= tent, no? B & C are clearly synonym (constant references to objects), but A= should not (references to constant objects). I see nothing wrong in having= a type defined as one for <references to constant objects>, and in having = this different from <constant references to objects>. Do I miss some point?
 [...]
Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Dec 06 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-07 02:32:11 -0500, spir <denis.spir gmail.com> said:

 On Mon, 6 Dec 2010 15:01:25 -0500
 Michel Fortin <michel.fortin michelf.com> wrote:
 
 And that's what my patch does. It only gets confusing when you add modifi
ers:
 
 	alias const(Object)ref A;
 	alias const(Object ref) B;
 	alias const(Object) C;
 
 	A ref a;
 	B ref b;
 	C ref c;
 
 With my patch, variables 'a', 'b', and 'c' are all of the same type:
 "const(Object)ref", the later 'ref' changing the constness of the
 reference specified in the 'B' alias.
Well, as your patch introduces the possibility to "const-en" the target of ref's, it _should_ have some meaning. Else, it leaves the language unconsis tent, no? B & C are clearly synonym (constant references to objects), but A should not (references to constant objects). I see nothing wrong in having a type defined as one for <references to constant objects>, and in having this different from <constant references to objects>. Do I miss some poin
The point is that the 'ref' in in the 'b' and 'c' variable declaration has the effect of changing the ref from B and C from const to mutable, even for B where the ref was explicitly specified to be const. I was wondering if some people would find that surprising, but if I understand you well that's what you expect when seeing this, right? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 07 2010
parent reply Jason House <jason.james.house gmail.com> writes:
Michel Fortin Wrote:
 The point is that the 'ref' in in the 'b' and 'c' variable declaration 
 has the effect of changing the ref from B and C from const to mutable, 
 even for B where the ref was explicitly specified to be const. I was 
 wondering if some people would find that surprising, but if I 
 understand you well that's what you expect when seeing this, right?
I've been wondering if it makes more sense for 'ref' to be a storage class rather than some kind of type constructor. Doing that would make the typedef's with ref be illegal. It'd also make foo!(const(T) ref) be illegal as well as (const(T) ref)[]. As a storage class, it can only be added to variable declarations. I think the array case would be missed. I'm not sure what people would think of the template case, especially when it pops up in code such as foo!(typeof(x)). If ref isn't a storage class, then generic programmers will need an equivalent to unqual that only strips the outer-most ref. As a storage class typeof would not return the ref. How do templates work with your patch?
Dec 07 2010
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-07 09:05:20 -0500, Jason House <jason.james.house gmail.com> said:

 Michel Fortin Wrote:
 The point is that the 'ref' in in the 'b' and 'c' variable declaration
 has the effect of changing the ref from B and C from const to mutable,
 even for B where the ref was explicitly specified to be const. I was
 wondering if some people would find that surprising, but if I
 understand you well that's what you expect when seeing this, right?
I've been wondering if it makes more sense for 'ref' to be a storage class rather than some kind of type constructor. Doing that would make the typedef's with ref be illegal. It'd also make foo!(const(T) ref) be illegal as well as (const(T) ref)[]. As a storage class, it can only be added to variable declarations. I think the array case would be missed. I'm not sure what people would think of the template case, especially when it pops up in code such as foo!(typeof(x)). If ref isn't a storage class, then generic programmers will need an equivalent to unqual that only strips the outer-most ref. As a storage class typeof would not return the ref. How do templates work with your patch?
From my tests, templates work as they should. For instance, I can easily call std.algorithm.sort on an array of const(Object)ref. Which brings the question: how do you do that if 'ref' is a storage class? :-) The way I implemented the feature in the compiler is that I added the notion of head-modifiers for types. For most types, head-modifiers are just a pointer to the regular modifiers, so they're always identical. But for a class type, encountering a 'ref' suffix changes the head-modifiers to match those applied to the suffix. Then when declaring a variable, when the compiler deduces the storage class for that variable from its type, I changed it so it checks the head-modifiers of the type instead of its regular modifiers. A few other tweaks like that were required to make it work with foreach and array ops, but the end result is a very small change to the compiler that fits reasonably well within the type system. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 07 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/7/10 7:05 AM, Michel Fortin wrote:
 On 2010-12-07 09:05:20 -0500, Jason House <jason.james.house gmail.com>
 said:

 Michel Fortin Wrote:
 The point is that the 'ref' in in the 'b' and 'c' variable declaration
 has the effect of changing the ref from B and C from const to mutable,
 even for B where the ref was explicitly specified to be const. I was
 wondering if some people would find that surprising, but if I
 understand you well that's what you expect when seeing this, right?
I've been wondering if it makes more sense for 'ref' to be a storage class rather than some kind of type constructor. Doing that would make the typedef's with ref be illegal. It'd also make foo!(const(T) ref) be illegal as well as (const(T) ref)[]. As a storage class, it can only be added to variable declarations. I think the array case would be missed. I'm not sure what people would think of the template case, especially when it pops up in code such as foo!(typeof(x)). If ref isn't a storage class, then generic programmers will need an equivalent to unqual that only strips the outer-most ref. As a storage class typeof would not return the ref. How do templates work with your patch?
From my tests, templates work as they should. For instance, I can easily call std.algorithm.sort on an array of const(Object)ref.
Does it work on a general random-access range? Generally, does the feature have a solution for all issues discussed? Andrei
Dec 07 2010
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-07 11:15:33 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 On 12/7/10 7:05 AM, Michel Fortin wrote:
 From my tests, templates work as they should. For instance, I can
 easily call std.algorithm.sort on an array of const(Object)ref.
Does it work on a general random-access range?
It should. Let's try: auto array = new const(Object)ref[12]; auto range = retro(array); sort!("cast(void*)a < cast(void*)b")(range); Compiles and runs with no error. Also, if I put actual objects in the array, I can see they're properly sorted.
 Generally, does the feature have a solution for all issues discussed?
It fixes all issues about mutable references to const classes that I can think of. But it's hard to see if I missed something without a proper checklist. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 07 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 07 Dec 2010 09:05:20 -0500, Jason House  
<jason.james.house gmail.com> wrote:

 Michel Fortin Wrote:
 The point is that the 'ref' in in the 'b' and 'c' variable declaration
 has the effect of changing the ref from B and C from const to mutable,
 even for B where the ref was explicitly specified to be const. I was
 wondering if some people would find that surprising, but if I
 understand you well that's what you expect when seeing this, right?
I've been wondering if it makes more sense for 'ref' to be a storage class rather than some kind of type constructor. Doing that would make the typedef's with ref be illegal. It'd also make foo!(const(T) ref) be illegal as well as (const(T) ref)[]. As a storage class, it can only be added to variable declarations.
IIUC, I think ref in this case is a type modifier. There are other examples of keywords that are both storage classes and type modifiers (const, shared). -Steve
Dec 07 2010
prev sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Michel Fortin <michel.fortin michelf.com> wrote:

 And that's what my patch does. It only gets confusing when you add  
 modifiers:

 	alias const(Object)ref A;
 	alias const(Object ref) B;
 	alias const(Object) C;

 	A ref a;
 	B ref b;
 	C ref c;

 With my patch, variables 'a', 'b', and 'c' are all of the same type:  
 "const(Object)ref", the later 'ref' changing the constness of the  
 reference specified in the 'B' alias.
const(Object ref) is implicitly castable to const(Object) ref, no? So to me, it seems all of these should be const(Object) ref. Seeing Foo ref name, I read this as 'non-const reference to some class'. IOW, if you want a rebindable reference to a class T, the type of T should not affect what hoops you must jump through to get there. -- Simen
Dec 07 2010
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-07 05:23:34 -0500, "Simen kjaeraas" <simen.kjaras gmail.com> said:

 Michel Fortin <michel.fortin michelf.com> wrote:
 
 And that's what my patch does. It only gets confusing when you add  modifiers:
 
 	alias const(Object)ref A;
 	alias const(Object ref) B;
 	alias const(Object) C;
 
 	A ref a;
 	B ref b;
 	C ref c;
 
 With my patch, variables 'a', 'b', and 'c' are all of the same type:  
 "const(Object)ref", the later 'ref' changing the constness of the  
 reference specified in the 'B' alias.
const(Object ref) is implicitly castable to const(Object) ref, no?
Yes.
 So to me, it seems all of these should be const(Object) ref.
 Seeing Foo ref name, I read this as 'non-const reference to some
 class'. IOW, if you want a rebindable reference to a class T, the type
 of T should not affect what hoops you must jump through to get there.
Great. That's how it works. I'm glad to see it suits you. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 07 2010
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/6/10 9:56 AM, Michel Fortin wrote:
 On 2010-12-06 00:16:27 -0500, Graham St Jack
 <Graham.StJack internode.on.net> said:

 First, I have to say that it is wonderful that someone is taking a
 serious look at this area again, and even better, you have come up
 with a compiler patch to make it happen!

 Some questions (assuming your patch or something like it gets into dmd):

 Does this mean that I would be able to write this:
 immutable(Foo)ref foo; // create a reference
 foo = new immutable(Foo)(); // re-bind it (not sure about "new" syntax
 for immutables)
That's the whole point yes. This syntax works with my patch. :-)
 Are there any other show-stopping syntax issues that are holding up
 widespread adoption/rollout of const-correctness?
Surly there are others issues to solve. But this one is the one I kept falling into when trying to use immutable objects in my code some time ago.
 What do Walter and Andrei think?
That I'd like to know.
I think actually offering a patch is a great initiative! I think the syntax is not all that intuitive, but it's great to experiment with. Michel, I suggest you put together some documentation (instead of implicitly referring to an earlier newsgroup discussion) so the community knows what to expect from the patch. Also providing precompiled binaries would help people who don't care to build their own compiler. Andrei
Dec 07 2010
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-07 11:09:50 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 On 12/6/10 9:56 AM, Michel Fortin wrote:
 On 2010-12-06 00:16:27 -0500, Graham St Jack
 <Graham.StJack internode.on.net> said:
 
 First, I have to say that it is wonderful that someone is taking a
 serious look at this area again, and even better, you have come up
 with a compiler patch to make it happen!
 
 Some questions (assuming your patch or something like it gets into dmd):
 
 Does this mean that I would be able to write this:
 immutable(Foo)ref foo; // create a reference
 foo = new immutable(Foo)(); // re-bind it (not sure about "new" syntax
 for immutables)
That's the whole point yes. This syntax works with my patch. :-)
 Are there any other show-stopping syntax issues that are holding up
 widespread adoption/rollout of const-correctness?
Surly there are others issues to solve. But this one is the one I kept falling into when trying to use immutable objects in my code some time ago.
 What do Walter and Andrei think?
That I'd like to know.
I think actually offering a patch is a great initiative! I think the syntax is not all that intuitive, but it's great to experiment with. Michel, I suggest you put together some documentation (instead of implicitly referring to an earlier newsgroup discussion) so the community knows what to expect from the patch.
The patch itself is documented in the bug tracker where it resides. It lacks some details about the internal implementation, but beside that I'm not sure how more elaborate the documentation should be. D's documentation doesn't tell about every corner case of the language either. <http://d.puremagic.com/issues/show_bug.cgi?id=5325>
 Also providing precompiled binaries would help people who don't care to 
 build their own compiler.
I can easily provide one for Mac OS X. Can someone else build it for Linux and Windows? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 07 2010
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-07 12:54:49 -0500, Michel Fortin <michel.fortin michelf.com> said:

 On 2010-12-07 11:09:50 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 On 12/6/10 9:56 AM, Michel Fortin wrote:
 On 2010-12-06 00:16:27 -0500, Graham St Jack
 <Graham.StJack internode.on.net> said:
 
 First, I have to say that it is wonderful that someone is taking a
 serious look at this area again, and even better, you have come up
 with a compiler patch to make it happen!
 
 Some questions (assuming your patch or something like it gets into dmd):
 
 Does this mean that I would be able to write this:
 immutable(Foo)ref foo; // create a reference
 foo = new immutable(Foo)(); // re-bind it (not sure about "new" syntax
 for immutables)
That's the whole point yes. This syntax works with my patch. :-)
 Are there any other show-stopping syntax issues that are holding up
 widespread adoption/rollout of const-correctness?
Surly there are others issues to solve. But this one is the one I kept falling into when trying to use immutable objects in my code some time ago.
 What do Walter and Andrei think?
That I'd like to know.
I think actually offering a patch is a great initiative! I think the syntax is not all that intuitive, but it's great to experiment with. Michel, I suggest you put together some documentation (instead of implicitly referring to an earlier newsgroup discussion) so the community knows what to expect from the patch.
The patch itself is documented in the bug tracker where it resides. It lacks some details about the internal implementation, but beside that I'm not sure how more elaborate the documentation should be. D's documentation doesn't tell about every corner case of the language either. <http://d.puremagic.com/issues/show_bug.cgi?id=5325>
 Also providing precompiled binaries would help people who don't care to 
 build their own compiler.
I can easily provide one for Mac OS X. Can someone else build it for Linux and Windows?
Here is a Mac OS X build. It's based on SVN revision 780 (two days old). It's a debug build so it might run a little slower than release versions of the compiler. <http://michelf.com/docs/d/dmd-rev780-objconst.zip> You should be able to use it with druntime either from DMD 2.050 or the latest SVN (nothing needs to be patched in druntime). Phobos unittests will pass (except for Rebindable tests, Rebindable itself works fine but some assertions the unittests aren't expecting the new type). -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 07 2010
prev sibling parent Jason House <jason.james.house gmail.com> writes:
Andrei Alexandrescu Wrote:
 What do Walter and Andrei think?
That I'd like to know.
I think actually offering a patch is a great initiative!
Yeah, it's great initiative. Working prototypes really make it easy to fully evaluate an option and require almost no effort to formally adopt.
 I think the 
 syntax is not all that intuitive, but it's great to experiment with. 
Really? Back when this stuff was actively being bikeshedded, it was my favorite syntax for this feature. Since then, a somewhat conflicting feature was added: auto ref. I saw some posts recently about tail being someone else's favorite, but I personally like the ref syntax better. Basically, reference types have an implicit ref which you can manually specify to disambiguate your intention with const stuff.
Dec 08 2010
prev sibling next sibling parent reply so <so so.do> writes:
On Mon, 06 Dec 2010 02:51:32 +0200, Michel Fortin  
<michel.fortin michelf.com> wrote:

 <http://d.puremagic.com/issues/show_bug.cgi?id=5325>
Great!
 See the strange predicate for the const(Object) version? That's because  
 opCmp() in Object doesn't work with const.
For the same reason opEquals acting funny with const? -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Dec 05 2010
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday 05 December 2010 23:59:58 so wrote:
 On Mon, 06 Dec 2010 02:51:32 +0200, Michel Fortin
 
 <michel.fortin michelf.com> wrote:
 <http://d.puremagic.com/issues/show_bug.cgi?id=5325>
Great!
 See the strange predicate for the const(Object) version? That's because
 opCmp() in Object doesn't work with const.
For the same reason opEquals acting funny with const?
Neither are marked as const on Object itself, and that needs to happen for Object to be const correct. toHash() and toString() (or writeFrom() or whatever it's going to become) have the same problem. None of them are const in Object. - Jonathan M Davis
Dec 06 2010
parent reply Jason House <jason.james.house gmail.com> writes:
Jonathan M Davis Wrote:

 On Sunday 05 December 2010 23:59:58 so wrote:
 On Mon, 06 Dec 2010 02:51:32 +0200, Michel Fortin
 
 <michel.fortin michelf.com> wrote:
 <http://d.puremagic.com/issues/show_bug.cgi?id=5325>
Great!
 See the strange predicate for the const(Object) version? That's because
 opCmp() in Object doesn't work with const.
For the same reason opEquals acting funny with const?
Neither are marked as const on Object itself, and that needs to happen for Object to be const correct. toHash() and toString() (or writeFrom() or whatever it's going to become) have the same problem. None of them are const in Object. - Jonathan M Davis
If object did that, things deriving from Object could not be lazy or memoize. It occurs to me that things deriving from object should be able to use const-correct functions and still compile. I don't have a D compiler handy or I'd see how well dmd handles that. I'd expect changing an input argument from T to const(T) should work since it's expanding the range of valid inputs. Similarly, the method itself should be able to become const since that too is expanding the valid input (to the implicit first argument).
Dec 06 2010
next sibling parent Jason House <jason.james.house gmail.com> writes:
Jason House Wrote:

 Jonathan M Davis Wrote:
 
 On Sunday 05 December 2010 23:59:58 so wrote:
 On Mon, 06 Dec 2010 02:51:32 +0200, Michel Fortin
 
 <michel.fortin michelf.com> wrote:
 <http://d.puremagic.com/issues/show_bug.cgi?id=5325>
Great!
 See the strange predicate for the const(Object) version? That's because
 opCmp() in Object doesn't work with const.
For the same reason opEquals acting funny with const?
Neither are marked as const on Object itself, and that needs to happen for Object to be const correct. toHash() and toString() (or writeFrom() or whatever it's going to become) have the same problem. None of them are const in Object. - Jonathan M Davis
If object did that, things deriving from Object could not be lazy or memoize. It occurs to me that things deriving from object should be able to use const-correct functions and still compile. I don't have a D compiler handy or I'd see how well dmd handles that. I'd expect changing an input argument from T to const(T) should work since it's expanding the range of valid inputs. Similarly, the method itself should be able to become const since that too is expanding the valid input (to the implicit first argument).
I should have added: if anyone tests making derived object's methods const-correct and it fails to compile, then it should be filed into bugzilla.
Dec 06 2010
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 06 Dec 2010 08:47:33 -0500, Jason House  
<jason.james.house gmail.com> wrote:

 Jonathan M Davis Wrote:

 On Sunday 05 December 2010 23:59:58 so wrote:
 On Mon, 06 Dec 2010 02:51:32 +0200, Michel Fortin

 <michel.fortin michelf.com> wrote:
 <http://d.puremagic.com/issues/show_bug.cgi?id=5325>
Great!
 See the strange predicate for the const(Object) version? That's  
because
 opCmp() in Object doesn't work with const.
For the same reason opEquals acting funny with const?
Neither are marked as const on Object itself, and that needs to happen for Object to be const correct. toHash() and toString() (or writeFrom() or whatever it's going to become) have the same problem. None of them are const in Object. - Jonathan M Davis
If object did that, things deriving from Object could not be lazy or memoize. It occurs to me that things deriving from object should be able to use const-correct functions and still compile. I don't have a D compiler handy or I'd see how well dmd handles that. I'd expect changing an input argument from T to const(T) should work since it's expanding the range of valid inputs. Similarly, the method itself should be able to become const since that too is expanding the valid input (to the implicit first argument).
It doesn't work. obj == obj calls .opEquals(obj, obj), whose signature is: bool opEquals(Object obj1, Object obj2) So even if you mark a derived instance's opEquals as const, the derived class is stripped back down to Object before any calls are made. Memoization and lazy calculations are not as important as being able to compare const or immutable objects. -Steve
Dec 06 2010
parent reply so <so so.do> writes:
 It doesn't work.  obj == obj calls .opEquals(obj, obj), whose signature  
 is:

 bool opEquals(Object obj1, Object obj2)

 So even if you mark a derived instance's opEquals as const, the derived  
 class is stripped back down to Object before any calls are made.

 Memoization and lazy calculations are not as important as being able to  
 compare const or immutable objects.

 -Steve
This one is a very serious issue. Should changing their signatures to: signature and addressing "auto ref" enough to fix it? A few reports and Andrei's comment indicates that there is some misunderstanding(?) on semantics/implementation. http://d.puremagic.com/issues/show_bug.cgi?id=4215#c4 http://d.puremagic.com/issues/show_bug.cgi?id=4668 http://d.puremagic.com/issues/show_bug.cgi?id=4258 With a glance to source code, looks like all that is required is just a few lines of change. -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Dec 06 2010
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 06 Dec 2010 10:11:30 -0500, so <so so.do> wrote:

 It doesn't work.  obj == obj calls .opEquals(obj, obj), whose signature  
 is:

 bool opEquals(Object obj1, Object obj2)

 So even if you mark a derived instance's opEquals as const, the derived  
 class is stripped back down to Object before any calls are made.

 Memoization and lazy calculations are not as important as being able to  
 compare const or immutable objects.

 -Steve
This one is a very serious issue. Should changing their signatures to: signature and addressing "auto ref" enough to fix it?
auto ref doesn't matter, these are classes, they are always ref ;) All that is needed is to make opEquals const (and its arguments const) as you say.
 With a glance to source code, looks like all that is required is just a  
 few lines of change.
It should be relatively painless. Just change the signatures of the base functions, and fix any compile errors. -Steve
Dec 06 2010
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, December 06, 2010 07:37:27 Steven Schveighoffer wrote:
 On Mon, 06 Dec 2010 10:11:30 -0500, so <so so.do> wrote:
 It doesn't work.  obj == obj calls .opEquals(obj, obj), whose signature
 is:
 
 bool opEquals(Object obj1, Object obj2)
 
 So even if you mark a derived instance's opEquals as const, the derived
 class is stripped back down to Object before any calls are made.
 
 Memoization and lazy calculations are not as important as being able to
 compare const or immutable objects.
 
 -Steve
This one is a very serious issue. Should changing their signatures to: signature and addressing "auto ref" enough to fix it?
auto ref doesn't matter, these are classes, they are always ref ;) All that is needed is to make opEquals const (and its arguments const) as you say.
 With a glance to source code, looks like all that is required is just a
 few lines of change.
It should be relatively painless. Just change the signatures of the base functions, and fix any compile errors.
And watch all the code break... I'll definitely welcome the change (it's probably the first bug that I voted on in bugzilla), but there will be tons of code broken by it, since you just _know_ that a lot of user code doesn't bother to make toString() and its friends const. It's still a change that needs to be made though. Being unable to properly compare const and immutable objects is crippling. Of course, it would be more of an issue if it were easier to actually create immutable objects which are classes rather than strcuts, but that's a separate issue. - Jonathan M Davis
Dec 06 2010
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 06 Dec 2010 14:04:43 -0500, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On Monday, December 06, 2010 07:37:27 Steven Schveighoffer wrote:
 It should be relatively painless.  Just change the signatures of the  
 base
 functions, and fix any compile errors.
And watch all the code break... I'll definitely welcome the change (it's probably the first bug that I voted on in bugzilla), but there will be tons of code broken by it, since you just _know_ that a lot of user code doesn't bother to make toString() and its friends const. It's still a change that needs to be made though. Being unable to properly compare const and immutable objects is crippling. Of course, it would be more of an issue if it were easier to actually create immutable objects which are classes rather than strcuts, but that's a separate issue.
Yes, one of the issues is that const has a viral effect. If you ignore const, none of your functions are const. So if you use functions inside opEquals, those have to be marked as const, and so on. But there are very few circumstances where opEquals needs to be marked as mutable. If that is the case, there is something broken with your code (and you should fix it) or there's something wrong with code you use (and you'll have to insert casts to deal with it for now). In a very small number of circumstances, non-const opEquals can be beneficial (such as caching data that is expensive to calculate). We need to find another way to deal with that (I suggest having logical const, but that's not a popular idea with Walter :). But it shouldn't detract from the requirements. You can always circumvent if you need special cases. I'd rather start from a solid const-supporting position and add holes where they make sense then start from a base that is full of holes and try to patch them slowly. In many cases affixing const to your code is not just a simple 'slap a const on here'. It can involve careful thought and possibly redesign. But without these changes, const is very useless, the standard library needs to eat its own dogfood if we want to peddle it to others. -Steve
Dec 06 2010
parent Graham St Jack <Graham.StJack internode.on.net> writes:
On 07/12/10 05:51, Steven Schveighoffer wrote:
 On Mon, 06 Dec 2010 14:04:43 -0500, Jonathan M Davis 
 <jmdavisProg gmx.com> wrote:

 On Monday, December 06, 2010 07:37:27 Steven Schveighoffer wrote:
 It should be relatively painless.  Just change the signatures of the 
 base
 functions, and fix any compile errors.
And watch all the code break... I'll definitely welcome the change (it's probably the first bug that I voted on in bugzilla), but there will be tons of code broken by it, since you just _know_ that a lot of user code doesn't bother to make toString() and its friends const. It's still a change that needs to be made though. Being unable to properly compare const and immutable objects is crippling. Of course, it would be more of an issue if it were easier to actually create immutable objects which are classes rather than strcuts, but that's a separate issue.
Yes, one of the issues is that const has a viral effect. If you ignore const, none of your functions are const. So if you use functions inside opEquals, those have to be marked as const, and so on. But there are very few circumstances where opEquals needs to be marked as mutable. If that is the case, there is something broken with your code (and you should fix it) or there's something wrong with code you use (and you'll have to insert casts to deal with it for now). In a very small number of circumstances, non-const opEquals can be beneficial (such as caching data that is expensive to calculate). We need to find another way to deal with that (I suggest having logical const, but that's not a popular idea with Walter :). But it shouldn't detract from the requirements. You can always circumvent if you need special cases. I'd rather start from a solid const-supporting position and add holes where they make sense then start from a base that is full of holes and try to patch them slowly. In many cases affixing const to your code is not just a simple 'slap a const on here'. It can involve careful thought and possibly redesign. But without these changes, const is very useless, the standard library needs to eat its own dogfood if we want to peddle it to others. -Steve
Vote++ -- Graham St Jack
Dec 06 2010
prev sibling parent reply spir <denis.spir gmail.com> writes:
On Mon, 6 Dec 2010 00:31:41 -0800
Jonathan M Davis <jmdavisProg gmx.com> wrote:

 toString() (or writeFrom() or whatever=20
 it's going to become)
guess it was writeTo() ;-) but "writeFrom" is nice as well, we should find = some useful use for it Denis -- -- -- -- -- -- -- vit esse estrany =E2=98=A3 spir.wikidot.com
Dec 06 2010
next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
spir <denis.spir gmail.com> wrote:

 On Mon, 6 Dec 2010 00:31:41 -0800
 Jonathan M Davis <jmdavisProg gmx.com> wrote:

 toString() (or writeFrom() or whatever
 it's going to become)
guess it was writeTo() ;-) but "writeFrom" is nice as well, we should find some useful use for it
This reminded me of INTERCAL's WRITE IN and READ OUT. -- Simen
Dec 06 2010
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 06 Dec 2010 04:44:07 -0500, spir <denis.spir gmail.com> wrote:

 On Mon, 6 Dec 2010 00:31:41 -0800
 Jonathan M Davis <jmdavisProg gmx.com> wrote:

 toString() (or writeFrom() or whatever
 it's going to become)
guess it was writeTo() ;-) but "writeFrom" is nice as well, we should find some useful use for it
It was proposed as writeTo, but I'm not opposed to a different name. BTW, the proposal does properly mark writeTo as const. -Steve
Dec 06 2010
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, December 06, 2010 05:41:42 Steven Schveighoffer wrote:
 On Mon, 06 Dec 2010 04:44:07 -0500, spir <denis.spir gmail.com> wrote:
 On Mon, 6 Dec 2010 00:31:41 -0800
 
 Jonathan M Davis <jmdavisProg gmx.com> wrote:
 toString() (or writeFrom() or whatever
 it's going to become)
guess it was writeTo() ;-) but "writeFrom" is nice as well, we should find some useful use for it
It was proposed as writeTo, but I'm not opposed to a different name.
I have no problem with writeTo(). I just couldn't remember what it was and didn't want to take the time to look it up, and the name isn't as obvious as toString(), since it's not a standard name which exists in other languages, and it isn't actually returning anything. Whether it's to or from would depend on how you look at it - to the given delegate or from the object. But writeTo() is fine. Once it's used, it'll be remembered.
 BTW, the proposal does properly mark writeTo as const.
Good. It figures that you'd remember given your general take on const. - Jonathan M Davis
Dec 06 2010
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 06 Dec 2010 14:00:17 -0500, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On Monday, December 06, 2010 05:41:42 Steven Schveighoffer wrote:
 On Mon, 06 Dec 2010 04:44:07 -0500, spir <denis.spir gmail.com> wrote:
 On Mon, 6 Dec 2010 00:31:41 -0800

 Jonathan M Davis <jmdavisProg gmx.com> wrote:
 toString() (or writeFrom() or whatever
 it's going to become)
guess it was writeTo() ;-) but "writeFrom" is nice as well, we should find some useful use for it
It was proposed as writeTo, but I'm not opposed to a different name.
I have no problem with writeTo(). I just couldn't remember what it was and didn't want to take the time to look it up, and the name isn't as obvious as toString(), since it's not a standard name which exists in other languages, and it isn't actually returning anything. Whether it's to or from would depend on how you look at it - to the given delegate or from the object. But writeTo() is fine. Once it's used, it'll be remembered.
I think writeTo sounds good because it will be called like this: object.writeTo(sink); BTW, writeTo was spir's idea: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=122335 But again, the name isn't critical to me (well, it is important but writeTo is not the be-all end-all of good names :).
 BTW, the proposal does properly mark writeTo as const.
Good. It figures that you'd remember given your general take on const.
:) -Steve
Dec 06 2010
prev sibling parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 06/12/2010 19:00, Jonathan M Davis wrote:
 On Monday, December 06, 2010 05:41:42 Steven Schveighoffer wrote:
 On Mon, 06 Dec 2010 04:44:07 -0500, spir<denis.spir gmail.com>  wrote:
 On Mon, 6 Dec 2010 00:31:41 -0800

 Jonathan M Davis<jmdavisProg gmx.com>  wrote:
 toString() (or writeFrom() or whatever
 it's going to become)
guess it was writeTo() ;-) but "writeFrom" is nice as well, we should find some useful use for it
It was proposed as writeTo, but I'm not opposed to a different name.
I have no problem with writeTo(). I just couldn't remember what it was and didn't want to take the time to look it up, and the name isn't as obvious as toString(), since it's not a standard name which exists in other languages, and it isn't actually returning anything. Whether it's to or from would depend on how you look at it - to the given delegate or from the object. But writeTo() is fine. Once it's used, it'll be remembered.
I don't think it's entirely fine. It should at least have "string"/"String" somewhere in the name. (I mentioned this on the other original thread, although late in time) -- Bruno Medeiros - Software Engineer
Dec 21 2010
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 21 Dec 2010 13:10:12 -0500, Bruno Medeiros  
<brunodomedeiros+spam com.gmail> wrote:

 On 06/12/2010 19:00, Jonathan M Davis wrote:
 On Monday, December 06, 2010 05:41:42 Steven Schveighoffer wrote:
 On Mon, 06 Dec 2010 04:44:07 -0500, spir<denis.spir gmail.com>  wrote:
 On Mon, 6 Dec 2010 00:31:41 -0800

 Jonathan M Davis<jmdavisProg gmx.com>  wrote:
 toString() (or writeFrom() or whatever
 it's going to become)
guess it was writeTo() ;-) but "writeFrom" is nice as well, we should find some useful use for it
It was proposed as writeTo, but I'm not opposed to a different name.
I have no problem with writeTo(). I just couldn't remember what it was and didn't want to take the time to look it up, and the name isn't as obvious as toString(), since it's not a standard name which exists in other languages, and it isn't actually returning anything. Whether it's to or from would depend on how you look at it - to the given delegate or from the object. But writeTo() is fine. Once it's used, it'll be remembered.
I don't think it's entirely fine. It should at least have "string"/"String" somewhere in the name. (I mentioned this on the other original thread, although late in time)
First, I'll say that it's not as important to me as it seems to be to you, and I think others feel the same way. writeTo seems perfectly fine to me, and the 'string' part is implied by the char[] parameter for the delegate. Changing the name to contain 'string' is fine as long as: 1) it's not toString. This is already established as "returning a string" in both prior D and other languages. I think this would be too confusing. 2) it's short. I don't want writeAsStringTo or something similar. What did you have in mind? -Steve
Dec 21 2010
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Hmm.. if we get uniform function call syntax for all types, perhaps
this code might even work some day:

import std.stdio;
import std.conv;

string toString(A)(A a)
{
    return to!string(a);
}

class A
{
    string name;
    this(string name)
    {
        this.name = name;
    }
    string writeTo()
    {
        return name;
    }
}

void main()
{
    auto foo = new A("I'm foo! ");
    writeln(foo.toString);  // using uniform function call syntax
}

Right now this code will compile but it will use Object's toString
instead of the one we defined above.




On 12/21/10, Steven Schveighoffer <schveiguy yahoo.com> wrote:
 On Tue, 21 Dec 2010 13:10:12 -0500, Bruno Medeiros
 <brunodomedeiros+spam com.gmail> wrote:

 On 06/12/2010 19:00, Jonathan M Davis wrote:
 On Monday, December 06, 2010 05:41:42 Steven Schveighoffer wrote:
 On Mon, 06 Dec 2010 04:44:07 -0500, spir<denis.spir gmail.com>  wrote:
 On Mon, 6 Dec 2010 00:31:41 -0800

 Jonathan M Davis<jmdavisProg gmx.com>  wrote:
 toString() (or writeFrom() or whatever
 it's going to become)
guess it was writeTo() ;-) but "writeFrom" is nice as well, we should find some useful use for it
It was proposed as writeTo, but I'm not opposed to a different name.
I have no problem with writeTo(). I just couldn't remember what it was and didn't want to take the time to look it up, and the name isn't as obvious as toString(), since it's not a standard name which exists in other languages, and it isn't actually returning anything. Whether it's to or from would depend on how you look at it - to the given delegate or from the object. But writeTo() is fine. Once it's used, it'll be remembered.
I don't think it's entirely fine. It should at least have "string"/"String" somewhere in the name. (I mentioned this on the other original thread, although late in time)
First, I'll say that it's not as important to me as it seems to be to you, and I think others feel the same way. writeTo seems perfectly fine to me, and the 'string' part is implied by the char[] parameter for the delegate. Changing the name to contain 'string' is fine as long as: 1) it's not toString. This is already established as "returning a string" in both prior D and other languages. I think this would be too confusing. 2) it's short. I don't want writeAsStringTo or something similar. What did you have in mind? -Steve
Dec 21 2010
parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Tue, 21 Dec 2010 19:46:11 +0100, Andrej Mitrovic  
<andrej.mitrovich gmail.com> wrote:

 Hmm.. if we get uniform function call syntax for all types, perhaps
 this code might even work some day:

 import std.stdio;
 import std.conv;

 string toString(A)(A a)
 {
     return to!string(a);
 }

 class A
 {
     string name;
     this(string name)
     {
         this.name = name;
     }
     string writeTo()
     {
         return name;
     }
 }

 void main()
 {
     auto foo = new A("I'm foo! ");
     writeln(foo.toString);  // using uniform function call syntax
 }

 Right now this code will compile but it will use Object's toString
 instead of the one we defined above.
It would still use Object's toString, as member functions would be tested for first. -- Simen
Dec 21 2010
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 12/21/10, Simen kjaeraas <simen.kjaras gmail.com> wrote:
 It would still use Object's toString, as member functions would be
 tested for first.

 --
 Simen
I'm talking about the case where Object's toString function doesn't exist (in some future release of D), but is replaced with writeTo or some alternate name. In that case your old code could still compile by adding this toString template.
Dec 21 2010
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/21/10 12:19 PM, Steven Schveighoffer wrote:
 On Tue, 21 Dec 2010 13:10:12 -0500, Bruno Medeiros
 <brunodomedeiros+spam com.gmail> wrote:

 On 06/12/2010 19:00, Jonathan M Davis wrote:
 On Monday, December 06, 2010 05:41:42 Steven Schveighoffer wrote:
 On Mon, 06 Dec 2010 04:44:07 -0500, spir<denis.spir gmail.com> wrote:
 On Mon, 6 Dec 2010 00:31:41 -0800

 Jonathan M Davis<jmdavisProg gmx.com> wrote:
 toString() (or writeFrom() or whatever
 it's going to become)
guess it was writeTo() ;-) but "writeFrom" is nice as well, we should find some useful use for it
It was proposed as writeTo, but I'm not opposed to a different name.
I have no problem with writeTo(). I just couldn't remember what it was and didn't want to take the time to look it up, and the name isn't as obvious as toString(), since it's not a standard name which exists in other languages, and it isn't actually returning anything. Whether it's to or from would depend on how you look at it - to the given delegate or from the object. But writeTo() is fine. Once it's used, it'll be remembered.
I don't think it's entirely fine. It should at least have "string"/"String" somewhere in the name. (I mentioned this on the other original thread, although late in time)
First, I'll say that it's not as important to me as it seems to be to you, and I think others feel the same way. writeTo seems perfectly fine to me, and the 'string' part is implied by the char[] parameter for the delegate. Changing the name to contain 'string' is fine as long as: 1) it's not toString. This is already established as "returning a string" in both prior D and other languages. I think this would be too confusing. 2) it's short. I don't want writeAsStringTo or something similar. What did you have in mind? -Steve
Conversion to text should be called toText. That makes the essence of the function visible (it emits characters) without tying the representation of the text. Andrei
Dec 21 2010
parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 21/12/2010 19:17, Andrei Alexandrescu wrote:
 On 12/21/10 12:19 PM, Steven Schveighoffer wrote:
 On Tue, 21 Dec 2010 13:10:12 -0500, Bruno Medeiros
 <brunodomedeiros+spam com.gmail> wrote:

 On 06/12/2010 19:00, Jonathan M Davis wrote:
 On Monday, December 06, 2010 05:41:42 Steven Schveighoffer wrote:
 On Mon, 06 Dec 2010 04:44:07 -0500, spir<denis.spir gmail.com> wrote:
 On Mon, 6 Dec 2010 00:31:41 -0800

 Jonathan M Davis<jmdavisProg gmx.com> wrote:
 toString() (or writeFrom() or whatever
 it's going to become)
guess it was writeTo() ;-) but "writeFrom" is nice as well, we should find some useful use for it
It was proposed as writeTo, but I'm not opposed to a different name.
I have no problem with writeTo(). I just couldn't remember what it was and didn't want to take the time to look it up, and the name isn't as obvious as toString(), since it's not a standard name which exists in other languages, and it isn't actually returning anything. Whether it's to or from would depend on how you look at it - to the given delegate or from the object. But writeTo() is fine. Once it's used, it'll be remembered.
I don't think it's entirely fine. It should at least have "string"/"String" somewhere in the name. (I mentioned this on the other original thread, although late in time)
First, I'll say that it's not as important to me as it seems to be to you, and I think others feel the same way. writeTo seems perfectly fine to me, and the 'string' part is implied by the char[] parameter for the delegate. Changing the name to contain 'string' is fine as long as: 1) it's not toString. This is already established as "returning a string" in both prior D and other languages. I think this would be too confusing. 2) it's short. I don't want writeAsStringTo or something similar. What did you have in mind? -Steve
Conversion to text should be called toText. That makes the essence of the function visible (it emits characters) without tying the representation of the text. Andrei
I don't understand this point. The representation of the text is tied, it's going to be char[] ( aka UTF-8). Unless you were planning to have overloads of toText, but that sounds like an awful idea. -- Bruno Medeiros - Software Engineer
Jan 27 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 1/27/11 9:33 AM, Bruno Medeiros wrote:
 On 21/12/2010 19:17, Andrei Alexandrescu wrote:
 On 12/21/10 12:19 PM, Steven Schveighoffer wrote:
 On Tue, 21 Dec 2010 13:10:12 -0500, Bruno Medeiros
 <brunodomedeiros+spam com.gmail> wrote:

 On 06/12/2010 19:00, Jonathan M Davis wrote:
 On Monday, December 06, 2010 05:41:42 Steven Schveighoffer wrote:
 On Mon, 06 Dec 2010 04:44:07 -0500, spir<denis.spir gmail.com> wrote:
 On Mon, 6 Dec 2010 00:31:41 -0800

 Jonathan M Davis<jmdavisProg gmx.com> wrote:
 toString() (or writeFrom() or whatever
 it's going to become)
guess it was writeTo() ;-) but "writeFrom" is nice as well, we should find some useful use for it
It was proposed as writeTo, but I'm not opposed to a different name.
I have no problem with writeTo(). I just couldn't remember what it was and didn't want to take the time to look it up, and the name isn't as obvious as toString(), since it's not a standard name which exists in other languages, and it isn't actually returning anything. Whether it's to or from would depend on how you look at it - to the given delegate or from the object. But writeTo() is fine. Once it's used, it'll be remembered.
I don't think it's entirely fine. It should at least have "string"/"String" somewhere in the name. (I mentioned this on the other original thread, although late in time)
First, I'll say that it's not as important to me as it seems to be to you, and I think others feel the same way. writeTo seems perfectly fine to me, and the 'string' part is implied by the char[] parameter for the delegate. Changing the name to contain 'string' is fine as long as: 1) it's not toString. This is already established as "returning a string" in both prior D and other languages. I think this would be too confusing. 2) it's short. I don't want writeAsStringTo or something similar. What did you have in mind? -Steve
Conversion to text should be called toText. That makes the essence of the function visible (it emits characters) without tying the representation of the text. Andrei
I don't understand this point. The representation of the text is tied, it's going to be char[] ( aka UTF-8). Unless you were planning to have overloads of toText, but that sounds like an awful idea.
Could be wchar or dchar. Andrei
Jan 27 2011
parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 27/01/2011 18:12, Andrei Alexandrescu wrote:
 On 1/27/11 9:33 AM, Bruno Medeiros wrote:
 On 21/12/2010 19:17, Andrei Alexandrescu wrote:
 On 12/21/10 12:19 PM, Steven Schveighoffer wrote:
 On Tue, 21 Dec 2010 13:10:12 -0500, Bruno Medeiros
 <brunodomedeiros+spam com.gmail> wrote:

 On 06/12/2010 19:00, Jonathan M Davis wrote:
 On Monday, December 06, 2010 05:41:42 Steven Schveighoffer wrote:
 On Mon, 06 Dec 2010 04:44:07 -0500, spir<denis.spir gmail.com>
 wrote:
 On Mon, 6 Dec 2010 00:31:41 -0800

 Jonathan M Davis<jmdavisProg gmx.com> wrote:
 toString() (or writeFrom() or whatever
 it's going to become)
guess it was writeTo() ;-) but "writeFrom" is nice as well, we should find some useful use for it
It was proposed as writeTo, but I'm not opposed to a different name.
I have no problem with writeTo(). I just couldn't remember what it was and didn't want to take the time to look it up, and the name isn't as obvious as toString(), since it's not a standard name which exists in other languages, and it isn't actually returning anything. Whether it's to or from would depend on how you look at it - to the given delegate or from the object. But writeTo() is fine. Once it's used, it'll be remembered.
I don't think it's entirely fine. It should at least have "string"/"String" somewhere in the name. (I mentioned this on the other original thread, although late in time)
First, I'll say that it's not as important to me as it seems to be to you, and I think others feel the same way. writeTo seems perfectly fine to me, and the 'string' part is implied by the char[] parameter for the delegate. Changing the name to contain 'string' is fine as long as: 1) it's not toString. This is already established as "returning a string" in both prior D and other languages. I think this would be too confusing. 2) it's short. I don't want writeAsStringTo or something similar. What did you have in mind? -Steve
Conversion to text should be called toText. That makes the essence of the function visible (it emits characters) without tying the representation of the text. Andrei
I don't understand this point. The representation of the text is tied, it's going to be char[] ( aka UTF-8). Unless you were planning to have overloads of toText, but that sounds like an awful idea.
Could be wchar or dchar. Andrei
You mean to say that there would be three possible signatures for toText (for char[], wchar[], dchar[]), that the class coder can choose? But of course, the coder would only need to define one, right? (otherwise that would be the awful idea) -- Bruno Medeiros - Software Engineer
Jan 28 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 1/28/11 5:37 AM, Bruno Medeiros wrote:
 You mean to say that there would be three possible signatures for toText
 (for char[], wchar[], dchar[]), that the class coder can choose?
 But of course, the coder would only need to define one, right?
 (otherwise that would be the awful idea)
Probably standardizing on one width is a good idea. Andrei
Jan 28 2011
parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 28/01/2011 15:19, Andrei Alexandrescu wrote:
 On 1/28/11 5:37 AM, Bruno Medeiros wrote:
 You mean to say that there would be three possible signatures for toText
 (for char[], wchar[], dchar[]), that the class coder can choose?
 But of course, the coder would only need to define one, right?
 (otherwise that would be the awful idea)
Probably standardizing on one width is a good idea. Andrei
Indeed. -- Bruno Medeiros - Software Engineer
Feb 01 2011
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 21/12/2010 18:19, Steven Schveighoffer wrote:
 On Tue, 21 Dec 2010 13:10:12 -0500, Bruno Medeiros
 <brunodomedeiros+spam com.gmail> wrote:

 On 06/12/2010 19:00, Jonathan M Davis wrote:
 On Monday, December 06, 2010 05:41:42 Steven Schveighoffer wrote:

 I have no problem with writeTo(). I just couldn't remember what it
 was and
 didn't want to take the time to look it up, and the name isn't as
 obvious as
 toString(), since it's not a standard name which exists in other
 languages, and
 it isn't actually returning anything. Whether it's to or from would
 depend on
 how you look at it - to the given delegate or from the object. But
 writeTo() is
 fine. Once it's used, it'll be remembered.
I don't think it's entirely fine. It should at least have "string"/"String" somewhere in the name. (I mentioned this on the other original thread, although late in time)
First, I'll say that it's not as important to me as it seems to be to you, and I think others feel the same way. writeTo seems perfectly fine to me, and the 'string' part is implied by the char[] parameter for the delegate. Changing the name to contain 'string' is fine as long as: 1) it's not toString. This is already established as "returning a string" in both prior D and other languages. I think this would be too confusing. 2) it's short. I don't want writeAsStringTo or something similar. What did you have in mind? -Steve
Sorry for the long delay in replying.. I don't have any specific favorite name. Could be writeString, asString, stringWrite, ouputString, even toString (despite a different signature from other languages), etc. Or a similar name with Text instead of String, as Andrei suggested (although I'm not 100% sure about that last one). It's just that I would prefer the String connotation to be implied in the function name, not just implied in the parameter (makes the code clearer, in a somewhat subjective opinion). And also to not take up the "writeTo" overload in all Objects ever, as some might want to use that overload name for their own stuff. -- Bruno Medeiros - Software Engineer
Jan 27 2011
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
Michel Fortin wrote:
 After a recent discussion on this list about tail-const class 
 references, it became rather clear that someone interested would have to 
 implement the thing if we were to have it. So I did it. See enhancement 
 request 5325 for an explanation and a patch.
 <http://d.puremagic.com/issues/show_bug.cgi?id=5325>
I think it's great that you're trying this out. I failed at getting tail const to work. I don't think it can work, but I might be wrong.
Dec 08 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-08 03:43:45 -0500, Walter Bright <newshound2 digitalmars.com> said:

 Michel Fortin wrote:
 After a recent discussion on this list about tail-const class 
 references, it became rather clear that someone interested would have 
 to implement the thing if we were to have it. So I did it. See 
 enhancement request 5325 for an explanation and a patch.
 <http://d.puremagic.com/issues/show_bug.cgi?id=5325>
I think it's great that you're trying this out. I failed at getting tail const to work. I don't think it can work, but I might be wrong.
Is there something I can do to convince you this patch works? Because it does. There is still some rough edges for which I wasn't sure what was the best solution -- head-modifiers not reflected in TypeInfo or with is(T == const) -- but they're relatively minor and easy to fix once we know what we want. By the way, I pushed this into a separate branch in my dmd-objc git repository (this branch does not include the Objective-C-related changes). So you can get the source with the patch pre-applied this way: git clone http://git.michelf.com/dmd-objc/ cd dmd-objc git checkout objconst -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 08 2010
parent reply Walter Bright <newshound2 digitalmars.com> writes:
Michel Fortin wrote:
 On 2010-12-08 03:43:45 -0500, Walter Bright <newshound2 digitalmars.com> 
 said:
 
 Michel Fortin wrote:
 After a recent discussion on this list about tail-const class 
 references, it became rather clear that someone interested would have 
 to implement the thing if we were to have it. So I did it. See 
 enhancement request 5325 for an explanation and a patch.
 <http://d.puremagic.com/issues/show_bug.cgi?id=5325>
I think it's great that you're trying this out. I failed at getting tail const to work. I don't think it can work, but I might be wrong.
Is there something I can do to convince you this patch works? Because it does. There is still some rough edges for which I wasn't sure what was the best solution -- head-modifiers not reflected in TypeInfo or with is(T == const) -- but they're relatively minor and easy to fix once we know what we want.
I haven't been able to look at it yet. But the const system in dmd is rather complex, and I'm not at all comfortable with saying it works without quite a lot of testing. Some things to test: 1. auto variable declarations 2. typeof 3. mangleof 4. template type deduction 5. interaction with inout 6. arrays of, pointers to, functions returning 7. tail const functions 8. tail immutable 9. tail shared const 10. tail inout
Dec 08 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-08 14:17:10 -0500, Walter Bright <newshound2 digitalmars.com> said:

 I haven't been able to look at it yet.
 
 But the const system in dmd is rather complex, and I'm not at all 
 comfortable with saying it works without quite a lot of testing. Some 
 things to test:
 
 1. auto variable declarations
 2. typeof
 3. mangleof
 4. template type deduction
 5. interaction with inout
 6. arrays of, pointers to, functions returning
 7. tail const functions
 8. tail immutable
 9. tail shared const
 10. tail inout
I've already tested most of this, but I'll make sure my unit tests cover it all. That said, what's a "tail const function"? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 08 2010
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 08 Dec 2010 15:21:38 -0500, Michel Fortin  
<michel.fortin michelf.com> wrote:

 On 2010-12-08 14:17:10 -0500, Walter Bright <newshound2 digitalmars.com>  
 said:

 I haven't been able to look at it yet.
  But the const system in dmd is rather complex, and I'm not at all  
 comfortable with saying it works without quite a lot of testing. Some  
 things to test:
  1. auto variable declarations
 2. typeof
 3. mangleof
 4. template type deduction
 5. interaction with inout
 6. arrays of, pointers to, functions returning
 7. tail const functions
 8. tail immutable
 9. tail shared const
 10. tail inout
I've already tested most of this, but I'll make sure my unit tests cover it all. That said, what's a "tail const function"?
it's not necessary to have a tail-const function for a class. The only advantage of having a tail-const function would be if you wanted to change the 'this' pointer, which you shouldn't do anyways. tail-const for a struct would then require tail-const functions (and would require being able to mark member functions to pass 'this' by value), but I don't think your patch addresses those. Also note that inout doesn't really work at all, so I wouldn't bother testing anything with inout. -Steve
Dec 08 2010
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
Michel Fortin wrote:
 That said, what's a "tail const function"?
applying tail const to a function type
Dec 08 2010
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-12-08 17:26:02 -0500, Walter Bright <newshound2 digitalmars.com> said:

 Michel Fortin wrote:
 That said, what's a "tail const function"?
applying tail const to a function type
You mean as the return type? I'll add a unit test for that. But on the whole, I'd be very surprised to find problems in the list of things you mentioned given how the patch works. Would you like some documentation on the changes I've made? This might be useful when reviewing it. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 08 2010
next sibling parent Jason House <jason.james.house gmail.com> writes:
Michel Fortin Wrote:

 On 2010-12-08 17:26:02 -0500, Walter Bright <newshound2 digitalmars.com> said:
 
 Michel Fortin wrote:
 That said, what's a "tail const function"?
applying tail const to a function type
You mean as the return type? I'll add a unit test for that. But on the whole, I'd be very surprised to find problems in the list of things you mentioned given how the patch works.
He might mean functions and delegates... A rebindable function pointer, etc... He might also mean a member function that is "const ref". If I understand your design, I don't those are allowed.
Dec 08 2010
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
Michel Fortin wrote:
 On 2010-12-08 17:26:02 -0500, Walter Bright <newshound2 digitalmars.com> 
 said:
 
 Michel Fortin wrote:
 That said, what's a "tail const function"?
applying tail const to a function type
You mean as the return type? I'll add a unit test for that. But on the whole, I'd be very surprised to find problems in the list of things you mentioned given how the patch works. Would you like some documentation on the changes I've made? This might be useful when reviewing it.
A test suite for it would be better.
Dec 08 2010
prev sibling parent reply Fawzi Mohamed <fawzi gmx.ch> writes:
It is nice that Michel Fortin made the effort to propose a patch  
trying to address the ability to rebind const objects.

Looking at the "uglification" of my code to support const, I saw that  
many cases I actually had a unique type, or partially unique type.

There are several examples of similar attempts, like linear types, or  
various uniqueness types systems (more or less related to the Clean  
example).
It is known that some uniqueness settings are equivalent to shared, so  
maybe using uniqueness with const might be meaningful.

This is a difficult topic, as pushing those concepts into the type  
system is always tricky, and the consequences of various choices are  
often non obvious, anyway here is what I thought.

If one could declare return or out types as unique (note that unique  
is *not* part of the type, it is like the storage attributes), these  
methods could be implicitly castable to const or immutable, allowing  
nicer code.

Constructors *might* return unique objects (an object is unique only  
if all its references are to unique or immutable objects).

In several cases uniqueness could be checked by the compiler. I think  
that such a change would improve part of my code, removing the need  
for several spurious casts, while at the same time making the code  
safer.

I did also think about having a front_unique attribute that can be  
applied to any local variable or argument that would make it tail  
const in the sense discussed previously, and still implicitly castable  
to full const.
In that case the situation is more complex (one should ensure that  
local references cannot spill out, otherwise a full const is needed,  
and for immutable, making it immutable is "irreversible".
The front_unique property can almost always be checked by the  
compiler, but activating it implicitly would have effects that would  
probably deemed surprising by the programmer (front_unique immutable  
objects would be rebindable).
Thus I am not sold on front_unique, but I still find it interesting,  
due to its relationship with tail const.

Fawzi
Dec 10 2010
parent reply Don <nospam nospam.com> writes:
Fawzi Mohamed wrote:

 If one could declare return or out types as unique (note that unique is 
 *not* part of the type, it is like the storage attributes), these 
 methods could be implicitly castable to const or immutable, allowing 
 nicer code.
 
 Constructors *might* return unique objects (an object is unique only if 
 all its references are to unique or immutable objects).
 
 In several cases uniqueness could be checked by the compiler. I think 
 that such a change would improve part of my code, removing the need for 
 several spurious casts, while at the same time making the code safer.
Any mutable object returned from a strongly pure function, is guaranteed to be unique.
Dec 10 2010
next sibling parent Michal Minich <michal.minich gmail.com> writes:
V Fri, 10 Dec 2010 11:53:04 +0100, Don wrote:

 Any mutable object returned from a strongly pure function, is guaranteed
 to be unique.
the function should be probably be safe too, to guarentee to not cast const away.
Dec 10 2010
prev sibling parent reply Fawzi Mohamed <fawzi gmx.ch> writes:
On 10-dic-10, at 11:53, Don wrote:

 Fawzi Mohamed wrote:

 If one could declare return or out types as unique (note that  
 unique is *not* part of the type, it is like the storage  
 attributes), these methods could be implicitly castable to const or  
 immutable, allowing nicer code.
 Constructors *might* return unique objects (an object is unique  
 only if all its references are to unique or immutable objects).
 In several cases uniqueness could be checked by the compiler. I  
 think that such a change would improve part of my code, removing  
 the need for several spurious casts, while at the same time making  
 the code safer.
Any mutable object returned from a strongly pure function, is guaranteed to be unique.
indeed good catch, I was saying that in some occasions the compiler can verify uniqueness, that is indeed an important case. But I don't understand if you want to imply that uniqueness should not be explicit, but just guaranteed to be detected and used in some occasions, as in the case you gave. Because any object builder (as for example an array concatenate object) cannot be pure, but can still return an unique object. about front_const , there I thought harder about having an implicit only use of it, but also there I think that it is not such a good idea
Dec 10 2010
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 10 Dec 2010 07:40:49 -0500, Fawzi Mohamed <fawzi gmx.ch> wrote:

 On 10-dic-10, at 11:53, Don wrote:

 Fawzi Mohamed wrote:

 If one could declare return or out types as unique (note that unique  
 is *not* part of the type, it is like the storage attributes), these  
 methods could be implicitly castable to const or immutable, allowing  
 nicer code.
 Constructors *might* return unique objects (an object is unique only  
 if all its references are to unique or immutable objects).
 In several cases uniqueness could be checked by the compiler. I think  
 that such a change would improve part of my code, removing the need  
 for several spurious casts, while at the same time making the code  
 safer.
Any mutable object returned from a strongly pure function, is guaranteed to be unique.
indeed good catch, I was saying that in some occasions the compiler can verify uniqueness, that is indeed an important case. But I don't understand if you want to imply that uniqueness should not be explicit, but just guaranteed to be detected and used in some occasions, as in the case you gave. Because any object builder (as for example an array concatenate object) cannot be pure, but can still return an unique object.
I'm not sure I understand your example, but why not? Pure functions have gotten a lot better in the last release (with the possibility of weakly-pure functions). I agree with Don, let's make strongly-pure functions implicitly castable and see how far we can get. If we can do uniqueness without having to mess with the type system, then it will be much easier to deal with. -Steve
Dec 10 2010