www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Pure functions as initializers for immutable structures?

reply =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Initializing immutable structures is a source of constant grief. Anything  
non-trivial requires instancing a mutable structure, initializing it, and  
then either casting to immutable (it's up to you to ensure no alias  
leaked) or, not to violate the type system, duplicate the whole.

Yet, if there was a situation where the alias leaking is under control,  
casting would be safe. Perhaps pure* functions are such a place. They can  
only touch the immutable world, whether through globals or through their  
parameters. So if one initializes the returned structure with a reference  
to the outside world, it will be immutable. And if you stuff the structure  
with anything mutable, it must have been created within the function's  
body, so no alias leaks.

Call me crazy, but I think it is safe to implicitly convert a pure  
function's return value to immutable. What you think?

* here by pure I mean either the old pure** when it still had immutable  
arguments, or Don's "immutably pure".
** BTW, http://www.digitalmars.com/d/2.0/function.html still says  
immutable, please update.

-- 
Tomek
Oct 18 2010
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 18 Oct 2010 14:31:26 -0400, Tomek Sowiński <just ask.me> wrote:

 Initializing immutable structures is a source of constant grief.  
 Anything non-trivial requires instancing a mutable structure,  
 initializing it, and then either casting to immutable (it's up to you to  
 ensure no alias leaked) or, not to violate the type system, duplicate  
 the whole.
Aren't we supposed to get so-called immutable constructors? If that's not what you mean, can you give an example of such grief? I admit I don't use immutable structs/objects in day-to-day coding. -Steve
Oct 18 2010
parent reply =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Dnia 18-10-2010 o 20:53:15 Steven Schveighoffer <schveiguy yahoo.com>  =

napisa=B3(a):

 On Mon, 18 Oct 2010 14:31:26 -0400, Tomek Sowi=F1ski <just ask.me> wro=
te:
 Initializing immutable structures is a source of constant grief.  =
 Anything non-trivial requires instancing a mutable structure,  =
 initializing it, and then either casting to immutable (it's up to you=
=
 to ensure no alias leaked) or, not to violate the type system,  =
 duplicate the whole.
Aren't we supposed to get so-called immutable constructors?
Haven't heard, can you point to the discussion? Anyway, if these immutable ctors are defined inside the type, then the = library writer may not provide a ctor suitable for your case (very = possible). Plus, if the thing I wrote is correct, why not?
 If that's not what you mean, can you give an example of such grief?
Build an immutable dictionary that would hold the program's options.
 I admit I don't use immutable structs/objects in day-to-day coding.
Some time ago I tried, swore loud, took hours to isolate & file several = = bugs. But I'll try again, as soon as I get sufficient adrenaline lust. ;= ) -- = Tomek
Oct 18 2010
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 18 Oct 2010 15:20:39 -0400, Tomek Sowiński <just ask.me> wrote:

 Dnia 18-10-2010 o 20:53:15 Steven Schveighoffer <schveiguy yahoo.com>  
 napisał(a):

 On Mon, 18 Oct 2010 14:31:26 -0400, Tomek Sowiński <just ask.me> wrote:

 Initializing immutable structures is a source of constant grief.  
 Anything non-trivial requires instancing a mutable structure,  
 initializing it, and then either casting to immutable (it's up to you  
 to ensure no alias leaked) or, not to violate the type system,  
 duplicate the whole.
Aren't we supposed to get so-called immutable constructors?
Haven't heard, can you point to the discussion?
I think it's in TDPL, don't have a copy so I'm not sure how to refer you. I know the really really old pdf document that talks about the future direction of D2 had them.
 Anyway, if these immutable ctors are defined inside the type, then the  
 library writer may not provide a ctor suitable for your case (very  
 possible).
Yes true. However with your method, it's also very possible they don't provide a pure ctor. I think an immutable ctor has different restrictions. In light of the new version of pure, perhaps your idea could obviate the need for immutable constructors. In other words, a pure constructor just got a *lot* easier to write, and almost all ctors should be pure. If that's the case, then many would be 'immutably pure' since they take only value types.
 Plus, if the thing I wrote is correct, why not?
Not saying it's not correct, it sounds correct to me, but I think we need to verify we aren't creating too many ways to do the same thing here (which may even mean immutable constructors are redundant).
 If that's not what you mean, can you give an example of such grief?
Build an immutable dictionary that would hold the program's options.
This particular problem should be solvable by changing the type of all literals to immutable :) I think at some point, we need something like you propose -- where given the properties of a function, you can implicitly convert its return value to immutable. This makes things much easier to deal with. -Steve
Oct 18 2010
parent =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Dnia 18-10-2010 o 21:38:07 Steven Schveighoffer <schveiguy yahoo.com>  =

napisa=B3(a):

 On Mon, 18 Oct 2010 15:20:39 -0400, Tomek Sowi=F1ski <just ask.me> wro=
te: [snip]
 Anyway, if these immutable ctors are defined inside the type, then th=
e =
 library writer may not provide a ctor suitable for your case (very  =
 possible).
Yes true. However with your method, it's also very possible they don'=
t =
 provide a pure ctor.

 I think an immutable ctor has different restrictions.  In light of the=
=
 new version of pure, perhaps your idea could obviate the need for  =
 immutable constructors.  In other words, a pure constructor just got a=
=
 *lot* easier to write, and almost all ctors should be pure.  If that's=
=
 the case, then many would be 'immutably pure' since they take only val=
ue =
 types.
I'd have to know what are the restrictions on immutable ctors. But I = expect them to be very similar to restrictions that immutable(pure) = imposes, except for mutating 'this', of course.
 Plus, if the thing I wrote is correct, why not?
Not saying it's not correct, it sounds correct to me, but I think we =
 need to verify we aren't creating too many ways to do the same thing  =
 here (which may even mean immutable constructors are redundant).
Thanks for support. Well, now you can create structs either with = constructors or with functions (especially when templatized, to infer ty= pe = from arguments). Immutable versions should cherish similar diversity.
 If that's not what you mean, can you give an example of such grief?
Build an immutable dictionary that would hold the program's options.
This particular problem should be solvable by changing the type of all=
=
 literals to immutable :)

 I think at some point, we need something like you propose -- where giv=
en =
 the properties of a function, you can implicitly convert its return  =
 value to immutable.  This makes things much easier to deal with.
Yeah, *much* easier. Plus, I think what I proposed isn't much work to = implement. But Walter would know that better. -- Tomek
Oct 18 2010
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-10-18 14:31:26 -0400, Tomek Sowiński <just ask.me> said:

 Call me crazy, but I think it is safe to implicitly convert a pure  
 function's return value to immutable. What you think?
Well, it depends on the arguments of the pure function. Here's two cases where it won't work. 1. With the new pure semantics, a pure function is allowed to mutate arguments passed to it, so a reference to the function's return value could escape through it. For instance: class C {} pure C func(C* c) { *c = new C; return *c; } C c1; immutable(C) c2 = func(*c1); // now you have mutable c1 and immutable c2 pointing to the same (mutable?) object. A pure function where all the arguments are const or immutable does not have this problem. But it could have the second one though... 2. If you pass mutable or const arguments (arguments that are not immutable) to the pure function, the function could put a reference to those arguments inside the struct, and casting it to immutable would cause someone to have an immutable reference while someone else has a mutable one to the same piece of memory: struct S { const(char)[] a; } pure S func(const(char)[] a) { S s; s.a = a; return s; } char[] someString = "hello".dup; immutable(S) s = func(someString); // now you have mutable someString and immutable s.a pointing to the same (mutable?) string. Basically, if all the arguments are immutable then it'd be guarantied that it's safe to cast the result as immutable. But a const argument can break this guaranty. So I'd precise your assertion by saying it is safe to implicitly convert a pure function's return value to immutable, but only when all the arguments you feed to it are immutable. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Oct 18 2010
parent reply Don <nospam nospam.com> writes:
Michel Fortin wrote:
 On 2010-10-18 14:31:26 -0400, Tomek Sowiński <just ask.me> said:
 
 Call me crazy, but I think it is safe to implicitly convert a pure  
 function's return value to immutable. What you think?
Well, it depends on the arguments of the pure function. Here's two cases where it won't work.
[snip]
 So I'd precise your assertion by saying it is safe to implicitly convert 
 a pure function's return value to immutable, but only when all the 
 arguments you feed to it are immutable.
Tomek stated that at the end of his original post. I think he is correct. And no, I don't think it would be difficult to implement.
Oct 18 2010
next sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-10-18 17:05:27 -0400, Don <nospam nospam.com> said:

 Michel Fortin wrote:
 On 2010-10-18 14:31:26 -0400, Tomek Sowiński <just ask.me> said:
 
 Call me crazy, but I think it is safe to implicitly convert a pure  
 function's return value to immutable. What you think?
Well, it depends on the arguments of the pure function. Here's two cases where it won't work.
[snip]
 So I'd precise your assertion by saying it is safe to implicitly 
 convert a pure function's return value to immutable, but only when all 
 the arguments you feed to it are immutable.
Tomek stated that at the end of his original post. I think he is correct. And no, I don't think it would be difficult to implement.
Hum, you're right. Seems I overlooked that "immutably pure" reference at the end of his post. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Oct 18 2010
prev sibling parent reply =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Dnia 18-10-2010 o 23:05:27 Don <nospam nospam.com> napisa=B3(a):

 Michel Fortin wrote:
 On 2010-10-18 14:31:26 -0400, Tomek Sowi=F1ski <just ask.me> said:

 Call me crazy, but I think it is safe to implicitly convert a pure  =
=
 function's return value to immutable. What you think?
Well, it depends on the arguments of the pure function. Here's two =
 cases where it won't work.
[snip]
 So I'd precise your assertion by saying it is safe to implicitly  =
 convert a pure function's return value to immutable, but only when al=
l =
 the arguments you feed to it are immutable.
Tomek stated that at the end of his original post. I think he is corre=
ct.
 And no, I don't think it would be difficult to implement.
Thanks for support. I see two ways to go about it: pure T make(Args args) { ... } unittest { T t =3D make(...); // good immutable T t =3D make(...); // also good } Or: pure immutable(T) make(Args args) { T t =3D ...; // initialize t return t; // conversion happens here } I like the first one. -- = Tomek
Oct 18 2010
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-10-18 17:25:49 -0400, Tomek Sowiński <just ask.me> said:

 Thanks for support. I see two ways to go about it:
 
 pure T make(Args args) { ... }
 unittest {
      T t = make(...); // good
      immutable T t = make(...); // also good
 }
 
 Or:
 
 pure immutable(T) make(Args args) {
      T t = ...;
      // initialize t
      return t; // conversion happens here
 }
 
 I like the first one.
The first one has one interesting property: if at the call site you know that all the arguments you're feeding the function with are immutable, then you can automatically cast the result to immutable, even if the function can also accept const arguments. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Oct 18 2010
prev sibling parent reply =?iso-8859-2?B?VG9tZWsgU293afFza2k=?= <just ask.me> writes:
Dnia 18-10-2010 o 20:31:26 Tomek Sowi=F1ski <just ask.me> napisa=B3(a):

 Initializing immutable structures is a source of constant grief.  =
 Anything non-trivial requires instancing a mutable structure,  =
 initializing it, and then either casting to immutable (it's up to you =
to =
 ensure no alias leaked) or, not to violate the type system, duplicate =
=
 the whole.

 Yet, if there was a situation where the alias leaking is under control=
, =
 casting would be safe. Perhaps pure* functions are such a place. They =
=
 can only touch the immutable world, whether through globals or through=
=
 their parameters. So if one initializes the returned structure with a =
=
 reference to the outside world, it will be immutable. And if you stuff=
=
 the structure with anything mutable, it must have been created within =
=
 the function's body, so no alias leaks.

 Call me crazy, but I think it is safe to implicitly convert a pure  =
 function's return value to immutable. What you think?

 * here by pure I mean either the old pure** when it still had immutabl=
e =
 arguments, or Don's "immutably pure".
 ** BTW, http://www.digitalmars.com/d/2.0/function.html still says  =
 immutable, please update.
OK, I see the interest is dying down (so boring, not even one duck to = name) so I filed an enhancement request so it won't be forgotten. http://d.puremagic.com/issues/show_bug.cgi?id=3D5081 -- Tomek
Oct 19 2010
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 19 Oct 2010 14:54:32 -0400, Tomek Sowiński <just ask.me> wrote:

 OK, I see the interest is dying down (so boring, not even one duck to  
 name) so I filed an enhancement request so it won't be forgotten.
In this NG, no comments usually means nobody can find anything else wrong with it, which is a good thing. I voted for the bug report. -Steve
Oct 19 2010
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Tomek S.:

 OK, I see the interest is dying down (so boring, not even one duck to  
 name)
I didn't comment because I didn't have something useful to add to the discussion. But a clean way to initialize immutable data structures is needed in D. We have recently discussed this a little in the D.learn newsgroup. But those ideas are not boring. Bye, bearophile
Oct 19 2010