Re: partially mutable immutable type problem, crazy idea

2018-05-08 Thread Yuxuan Shui via Digitalmars-d

On Wednesday, 9 May 2018 at 00:58:51 UTC, jmh530 wrote:

On Tuesday, 8 May 2018 at 22:31:10 UTC, Yuxuan Shui wrote:

snip]


This doesn't compile for me on run.dlang.io:

onlineapp.d(22): Error: template onlineapp.f cannot deduce 
function from argument types !()(B), candidates are:

onlineapp.d(1):onlineapp.f(T)(immutable T a)


Not supposed to. Was proposing an (crazy) idea here.


Re: partially mutable immutable type problem, crazy idea

2018-05-08 Thread jmh530 via Digitalmars-d

On Tuesday, 8 May 2018 at 22:31:10 UTC, Yuxuan Shui wrote:

snip]


This doesn't compile for me on run.dlang.io:

onlineapp.d(22): Error: template onlineapp.f cannot deduce 
function from argument types !()(B), candidates are:

onlineapp.d(1):onlineapp.f(T)(immutable T a)


Re: partially mutable immutable type problem, crazy idea

2018-05-08 Thread Yuxuan Shui via Digitalmars-d
After watching the DConf 2018 video, I came up with this wild 
idea:


auto f(T)(immutable T a) {
// If T is a aggregate type, and I only use (directly
// or indirectly) the immutable fields of T,
// Then it should be OK to call f() with a partially mutable 
type

return a.x+1;
}

void main() {
struct A {
int x;
}
A a;
immutable(A) b;
f(a); // <- not fine
f(b); // <- fine

class B {
immutable int x = 10;
double f;
}
auto c = new B;
f(c); // <- fine too
}

I think this should solve the reference counting an immutable 
object, no? To f(), T will just looks like a normal immutable, 
uncopyable (because copying means modifying the reference 
counter) type


Re: sorting a mutable array of immutable objects

2016-04-20 Thread Jeff Thompson via Digitalmars-d

On Wednesday, 20 April 2016 at 12:34:28 UTC, Anonymouse wrote:
On Wednesday, 20 April 2016 at 10:32:42 UTC, Jeff Thompson 
wrote:
On Wednesday, 20 April 2016 at 09:54:13 UTC, Jeff Thompson 
wrote:
I can create a mutable array of immutable objects, thanks to 
the answers to my other question 
https://forum.dlang.org/post/nf57f5$e6v$1...@digitalmars.com .


Now I want to sort the array.


I found a solution, but I'm not sure it is the best way. 
Instead of overriding opCmp, class C just defines a static 
comparison to use with sort (which automatically works with 
Rebindable). Is there a way to do this where I don't need to 
specify C.isLess every time I sort?


class C {
  this(int x) immutable { this.x = x; }
  static bool isLess(const C a, const C b) @safe pure nothrow 
{ return a.x < b.x; }

  int x;
}

void
main(string[] args)
{
  auto array = new Rebindable!(immutable(C))[2];
  array[0] = new immutable C(20);
  array[1] = new immutable C(10);
  sort!(C.isLess)(array);
}


int opCmp(immutable Object o) immutable {}


Thanks for a better solution, but I never would have thought to 
try opCmp without "override" since I assumed that sort was 
looking for the opCmp defined by Object. So many 
counter-intuitive mysteries in D. That's why this forum is 
indipensable.


Re: sorting a mutable array of immutable objects

2016-04-20 Thread Anonymouse via Digitalmars-d

On Wednesday, 20 April 2016 at 12:34:28 UTC, Anonymouse wrote:

On Wednesday, 20 April 2016 at 10:32:42 UTC, Jeff Thompson [...]
Also note that sort (std.algorithm.sorting : sort) returns a 
range and doesn't sort in place.


(Lastly this is probably more at home in the Learn forum.)


It does sort in place as well apparently, my bad.


Re: sorting a mutable array of immutable objects

2016-04-20 Thread Anonymouse via Digitalmars-d

On Wednesday, 20 April 2016 at 10:32:42 UTC, Jeff Thompson wrote:
On Wednesday, 20 April 2016 at 09:54:13 UTC, Jeff Thompson 
wrote:
I can create a mutable array of immutable objects, thanks to 
the answers to my other question 
https://forum.dlang.org/post/nf57f5$e6v$1...@digitalmars.com .


Now I want to sort the array.


I found a solution, but I'm not sure it is the best way. 
Instead of overriding opCmp, class C just defines a static 
comparison to use with sort (which automatically works with 
Rebindable). Is there a way to do this where I don't need to 
specify C.isLess every time I sort?


class C {
  this(int x) immutable { this.x = x; }
  static bool isLess(const C a, const C b) @safe pure nothrow { 
return a.x < b.x; }

  int x;
}

void
main(string[] args)
{
  auto array = new Rebindable!(immutable(C))[2];
  array[0] = new immutable C(20);
  array[1] = new immutable C(10);
  sort!(C.isLess)(array);
}


int opCmp(immutable Object o) immutable {}

That seems to work for me. You want to make it const Object and 
inout if you want it to work on const and mutable C's as well. 
Also note that sort (std.algorithm.sorting : sort) returns a 
range and doesn't sort in place.


(Lastly this is probably more at home in the Learn forum.)


Re: sorting a mutable array of immutable objects

2016-04-20 Thread Jeff Thompson via Digitalmars-d

On Wednesday, 20 April 2016 at 09:54:13 UTC, Jeff Thompson wrote:
I can create a mutable array of immutable objects, thanks to 
the answers to my other question 
https://forum.dlang.org/post/nf57f5$e6v$1...@digitalmars.com .


Now I want to sort the array.


I found a solution, but I'm not sure it is the best way. Instead 
of overriding opCmp, class C just defines a static comparison to 
use with sort (which automatically works with Rebindable). Is 
there a way to do this where I don't need to specify C.isLess 
every time I sort?


class C {
  this(int x) immutable { this.x = x; }
  static bool isLess(const C a, const C b) @safe pure nothrow { 
return a.x < b.x; }

  int x;
}

void
main(string[] args)
{
  auto array = new Rebindable!(immutable(C))[2];
  array[0] = new immutable C(20);
  array[1] = new immutable C(10);
  sort!(C.isLess)(array);
}



Re: sorting a mutable array of immutable objects

2016-04-20 Thread Jeff Thompson via Digitalmars-d

On Wednesday, 20 April 2016 at 09:54:13 UTC, Jeff Thompson wrote:
I can create a mutable array of immutable objects, thanks to 
the answers to my other question 
https://forum.dlang.org/post/nf57f5$e6v$1...@digitalmars.com .


Now I want to sort the array, but the sort function doesn't 
"see" the opCmp in class C. Do I need to define a custom 
compare function for each class where I want to use Rebindable? 
Or can Rebindable itself be updated to "pass through" methods 
like opCmp?


class C {
  this(int x) immutable { this.x = x; }
  override int opCmp(Object o) const { return x - (cast(C)o).x; 
}

  int x;
}

void main(string[] args)
{
  auto array = new Rebindable!(immutable(C))[2];
  array[0] = new immutable C(20);
  array[1] = new immutable C(10);
  sort(array); // Error: "Invalid predicate passed to sort: "a 
< b""

}


Actually, maybe my problem is that the opCmp override should take 
a const Object (for comparing with an immutable object). Is there 
a way to do that?


sorting a mutable array of immutable objects

2016-04-20 Thread Jeff Thompson via Digitalmars-d
I can create a mutable array of immutable objects, thanks to the 
answers to my other question 
https://forum.dlang.org/post/nf57f5$e6v$1...@digitalmars.com .


Now I want to sort the array, but the sort function doesn't "see" 
the opCmp in class C. Do I need to define a custom compare 
function for each class where I want to use Rebindable? Or can 
Rebindable itself be updated to "pass through" methods like opCmp?


class C {
  this(int x) immutable { this.x = x; }
  override int opCmp(Object o) const { return x - (cast(C)o).x; }
  int x;
}

void main(string[] args)
{
  auto array = new Rebindable!(immutable(C))[2];
  array[0] = new immutable C(20);
  array[1] = new immutable C(10);
  sort(array); // Error: "Invalid predicate passed to sort: "a < 
b""

}



Re: mutable array of immutable objects

2016-04-19 Thread Timon Gehr via Digitalmars-d

On 19.04.2016 14:07, Jeff Thompson wrote:

On Tuesday, 19 April 2016 at 11:43:22 UTC, Anonymouse wrote:

On Tuesday, 19 April 2016 at 10:41:05 UTC, Jeff Thompson wrote:

I want to create a mutable array of immutable objects, but the code
below gives the error shown below. It seems that "new
immutable(C)[1]" makes the entire array immutable, but it seems I
should be able to change the elements of an array of pointers to an
object even though the objects are immutable. How to do that?

class C {
  this(int x) immutable { this.x = x; }
  int x;
}

void main(string[] args)
{
  auto array = new immutable(C)[1];
  array[0] = new immutable C(10); // Error: Cannot modify immutable
expression array[0].
}


Mind that this is akin to declaring a string (immutable(char)[]) and
trying to modify an element.

You can append, though. Or rather, make a new array/slice with the new
elements concatenated into it.


Thanks but then I'm confused as to why the following code is allowed. It
is a mutable array of immutable strings.


mutable array of mutable strings, actually. immutable(string)[] would be 
a mutable array of immutable strings.



I can modify the array but not
the elements they point to. What's so special about a string?


string is not a class. It is an alias for immutable(char)[].


Why can't I do that with my own class?
...


D has no built-in way to express it.
There is https://dlang.org/phobos/std_typecons.html#.Rebindable.



Re: mutable array of immutable objects

2016-04-19 Thread Sönke Ludwig via Digitalmars-d

Am 19.04.2016 um 12:41 schrieb Jeff Thompson:

I want to create a mutable array of immutable objects, but the code
below gives the error shown below. It seems that "new immutable(C)[1]"
makes the entire array immutable, but it seems I should be able to
change the elements of an array of pointers to an object even though the
objects are immutable. How to do that?

class C {
   this(int x) immutable { this.x = x; }
   int x;
}

void main(string[] args)
{
   auto array = new immutable(C)[1];
   array[0] = new immutable C(10); // Error: Cannot modify immutable
expression array[0].
}



Due to an omission in the type system, this requires the use of the 
helper type std.typecons.Rebindable:


auto array = new Rebindable!(immutable(C))[1];
array[0] = new immutable C(10);


Re: mutable array of immutable objects

2016-04-19 Thread Jeff Thompson via Digitalmars-d

On Tuesday, 19 April 2016 at 11:43:22 UTC, Anonymouse wrote:

On Tuesday, 19 April 2016 at 10:41:05 UTC, Jeff Thompson wrote:
I want to create a mutable array of immutable objects, but the 
code below gives the error shown below. It seems that "new 
immutable(C)[1]" makes the entire array immutable, but it 
seems I should be able to change the elements of an array of 
pointers to an object even though the objects are immutable. 
How to do that?


class C {
  this(int x) immutable { this.x = x; }
  int x;
}

void main(string[] args)
{
  auto array = new immutable(C)[1];
  array[0] = new immutable C(10); // Error: Cannot modify 
immutable expression array[0].

}


Mind that this is akin to declaring a string 
(immutable(char)[]) and trying to modify an element.


You can append, though. Or rather, make a new array/slice with 
the new elements concatenated into it.


Thanks but then I'm confused as to why the following code is 
allowed. It is a mutable array of immutable strings. I can modify 
the array but not the elements they point to. What's so special 
about a string? Why can't I do that with my own class?


void main(string[] args)
{
  auto array = new string[1];
  array[0] = "a";
}



Re: mutable array of immutable objects

2016-04-19 Thread Anonymouse via Digitalmars-d

On Tuesday, 19 April 2016 at 10:41:05 UTC, Jeff Thompson wrote:
I want to create a mutable array of immutable objects, but the 
code below gives the error shown below. It seems that "new 
immutable(C)[1]" makes the entire array immutable, but it seems 
I should be able to change the elements of an array of pointers 
to an object even though the objects are immutable. How to do 
that?


class C {
  this(int x) immutable { this.x = x; }
  int x;
}

void main(string[] args)
{
  auto array = new immutable(C)[1];
  array[0] = new immutable C(10); // Error: Cannot modify 
immutable expression array[0].

}


Mind that this is akin to declaring a string (immutable(char)[]) 
and trying to modify an element.


You can append, though. Or rather, make a new array/slice with 
the new elements concatenated into it.


mutable array of immutable objects

2016-04-19 Thread Jeff Thompson via Digitalmars-d
I want to create a mutable array of immutable objects, but the 
code below gives the error shown below. It seems that "new 
immutable(C)[1]" makes the entire array immutable, but it seems I 
should be able to change the elements of an array of pointers to 
an object even though the objects are immutable. How to do that?


class C {
  this(int x) immutable { this.x = x; }
  int x;
}

void main(string[] args)
{
  auto array = new immutable(C)[1];
  array[0] = new immutable C(10); // Error: Cannot modify 
immutable expression array[0].

}



Re: @mutable

2016-02-23 Thread Timon Gehr via Digitalmars-d

On 22.02.2016 19:03, Nick Treleaven wrote:

On Monday, 22 February 2016 at 17:28:03 UTC, Guillaume Chatelet wrote:

static make() {


The return type is missing for the make() function:


I'm pretty sure static here works just like 'static auto'. In D I think
you can use storage classes (and even attributes) to imply auto:

const foo(){return 5;}

assert(foo() == 5);


It does not really "imply auto". 'auto' means nothing in this context, 
it's just a crutch for  the parser. The return type is deduced if it is 
left out. In order to leave it out, you need to provide some storage 
class. 'auto' is just one possibility.


Re: @mutable

2016-02-23 Thread Guillaume Chatelet via Digitalmars-d

On Monday, 22 February 2016 at 18:03:03 UTC, Nick Treleaven wrote:
On Monday, 22 February 2016 at 17:28:03 UTC, Guillaume Chatelet 
wrote:

static make() {


The return type is missing for the make() function:


I'm pretty sure static here works just like 'static auto'. In D 
I think you can use storage classes (and even attributes) to 
imply auto:


const foo(){return 5;}

assert(foo() == 5);


Ha right indeed it's probably going to work. It was just a bit 
surprising.


Re: @mutable

2016-02-22 Thread Nick Treleaven via Digitalmars-d
On Monday, 22 February 2016 at 17:28:03 UTC, Guillaume Chatelet 
wrote:

static make() {


The return type is missing for the make() function:


I'm pretty sure static here works just like 'static auto'. In D I 
think you can use storage classes (and even attributes) to imply 
auto:


const foo(){return 5;}

assert(foo() == 5);


Re: @mutable

2016-02-22 Thread Guillaume Chatelet via Digitalmars-d

static make() {


The return type is missing for the make() function:


Re: @mutable

2016-02-21 Thread Nick Treleaven via Digitalmars-d

On Sunday, 21 February 2016 at 15:03:39 UTC, Marc Schütz wrote:
I've adapted my previous DIP on lazy initialization to make it 
usable for logical immutability, as is useful for reference 
counting, among other things:


http://wiki.dlang.org/DIP89


From the DIP:

The second rule (@system) prevents accidental accesses that 
violate [logical const-ness]


It seems we could use @mutable as a method attribute instead of 
@trusted const. The advantage would be that code is still checked 
for @safety. Requiring it still helps to prevent unintentional 
mutation and remind the programmer about correct logical const 
encapsulation. I realise @trusted has more impact but really here 
this use isn't related to memory safety, (or is it)?


Re: @mutable

2016-02-21 Thread Marc Schütz via Digitalmars-d

On Sunday, 21 February 2016 at 18:19:35 UTC, Nick Treleaven wrote:
BTW the Usage section still uses lazy. I think the RCObject 
code shouldn't use new to construct the struct here:


auto o = new immutable(RCObject);

It probably needs to be on the stack instead.



Thanks, fixed.

(I also made a minor edit for formatting/readability, hope 
that's OK).


Sure :-)


Re: @mutable

2016-02-21 Thread Nick Treleaven via Digitalmars-d

On Sunday, 21 February 2016 at 15:03:39 UTC, Marc Schütz wrote:
I've adapted my previous DIP on lazy initialization to make it 
usable for logical immutability, as is useful for reference 
counting, among other things:


http://wiki.dlang.org/DIP89


BTW the Usage section still uses lazy. I think the RCObject code 
shouldn't use new to construct the struct here:


auto o = new immutable(RCObject);

It probably needs to be on the stack instead.

(I also made a minor edit for formatting/readability, hope that's 
OK).


@mutable

2016-02-21 Thread Marc Schütz via Digitalmars-d
I've adapted my previous DIP on lazy initialization to make it 
usable for logical immutability, as is useful for reference 
counting, among other things:


http://wiki.dlang.org/DIP89


Re: [idea] Mutable pointee/ RCString

2016-02-07 Thread Iakh via Digitalmars-d

On Sunday, 7 February 2016 at 14:00:24 UTC, Iakh wrote:

Explanations:
As far as "immutable" transitive:
--
immutable RCString str;
*str.counter++; // Impossible/error/undefined behavior(with const 
cast)

--
Language defines immutable to do some optimizations based on true
constness of str, fields, and variables pointed by fields. But if
pointer would be treated by optimizer(not by GC) as void* (or 
size_t)

pointee "true constness" does not matter.

The only drawback is the immutable function that reads @mutable 
field

can't be @pure because it reads "global variable".


[idea] Mutable pointee/ RCString

2016-02-07 Thread Iakh via Digitalmars-d

Is it hard to make pointee data mutable?
E.g. if have:
--
struct RCString
{
private char[] data;
private @mutable int* counter;
}
--
So for optimiser (in case of immutable) this looks like
--
struct RCString
{
private char[] data;
private @mutable void* counter; // pointer to garbage
}
--


Re: implicit conversion to mutable via alias this

2014-06-21 Thread Nils Boßung via Digitalmars-d
On Saturday 21 June 2014 21:55,  wrote:

> I can only guess Kenji's reasons, but I believe it's related to
> DIP49, which he created:
> 
> http://wiki.dlang.org/DIP49

Thanks a bunch. That sheds quite some light on it.


Re: implicit conversion to mutable via alias this

2014-06-21 Thread via Digitalmars-d
I can only guess Kenji's reasons, but I believe it's related to 
DIP49, which he created:


http://wiki.dlang.org/DIP49

The DIP describes how copying between differently qualified types 
should work. I guess his stance is that this should always go via 
the postblit, probably to avoid uncertainties about postblit or 
alias this has priority over the other. IMO this makes sense.


(And you're right, this is currently not implemented.)


Re: implicit conversion to mutable via alias this

2014-06-21 Thread Nils Boßung via Digitalmars-d
I'd still appreciate feedback on this.


Re: implicit conversion to mutable via alias this

2014-06-19 Thread Nils Boßung via Digitalmars-d
bump


Re: implicit conversion to mutable via alias this

2014-06-17 Thread Nils Boßung via Digitalmars-d
Anyone?


implicit conversion to mutable via alias this

2014-06-16 Thread Nils Boßung via Digitalmars-d
Last week I filed issues 12883 [1] and 12884 [2], and made dmd pull request 
#3654 [3] to fix them. The changes would make it possible to use alias this 
for implicit conversion to mutable when the conversion is otherwise not 
possible.

Issue 12883 is about structs. dmd's current rules for conversion of structs 
are essentially:
1) If the unqualified source and target types match, and the members can be 
converted, do that.
2) Otherwise, if the unqualified types do not match, try alias this.
3) Otherwise, fail.

I'd like to change step 2 to
2) Otherwise, try alias this.

That is, in particular, if the unqualified types match but the members can't 
be converted, try alias this.

Kenji rejected the pull request saying that conversion to mutable should be 
handled by postblit. As far as I can see, that doesn't work right now. And I 
don't see how it's supposed to work. We can't allow conversion to mutable 
just because there's a postblit. And there is no way to mark/overload the 
postblit for a const-stripping conversion, is there?

Kenji, could you elaborate on how postblit is supposed to take care of this?
Or maybe someone else has some insight?
Or maybe you think that PR #3654 is totally awesome and should be pulled? ;)

As for classes (issue 12884), dmd already accepts alias this to mutable 
here. But one way or the other it's buggy.

The motivation for all this came from issue 12885 [4]:
There is a hack in place in dmd to allow implicit conversion of 
const(Rebindable!(const Object)) to mutable. In my opinion it's too 
permissive and lets code be accepted that should be rejected. With to-
mutable-via-alias-this the conversion could be implemented in Rebindable 
itself and the hack could be reverted.

[1] https://issues.dlang.org/show_bug.cgi?id=12883
[2] https://issues.dlang.org/show_bug.cgi?id=12884
[3] https://github.com/D-Programming-Language/dmd/pull/3654
[4] https://issues.dlang.org/show_bug.cgi?id=12885



Re: How do you copy a const struct to a mutable?

2012-10-31 Thread bearophile

Malte Skarupke:


What am I missing in order to do this?


In D when you define a struct inside a function, it's not a POD 
any more.


If you define it as "static struct A" instead of "struct A", your 
code will compile.


Unfortunately DMD gives a too much generic error message in this 
case, it doesn't explain what's the problem:


test.d(7): Error: cannot implicitly convert expression (a) of 
type const(A) to A


Bye,
bearophile


How do you copy a const struct to a mutable?

2012-10-31 Thread Malte Skarupke

I want to get this to compile:

void main()
{
struct A
{
this(int x) { this.x = x; }
int x;
}
const(A) a = A(5);
A b = a;
}

It should clearly be legal to create a non-const copy of the 
struct. What am I missing in order to do this?


Cheers,

Malte


Re: How mutable is immutable?

2012-10-22 Thread Don Clugston

On 18/10/12 19:43, Timon Gehr wrote:

On 10/18/2012 10:08 AM, Don Clugston wrote:

On 17/10/12 18:02, Timon Gehr wrote:

On 10/17/2012 01:49 PM, Don Clugston wrote:

...

That's the point -- *which* checks are missing from @safe?


Escaping stack data and arbitrarily freeing memory are not operations
found in memory safe languages.


HOW do you propose to check for escaping stack data?



Static escape analysis. Use the 'scope' qualifier to designate
data that is not allowed to be escaped in order to make it modular.


...


The implementation of the 'scope' storage class should be fixed. We
could then require an unsafe cast(scope) to disable prevention of stack
address escaping.


No we can't. f cannot know that the string it has been given is on the
stack. So main() must prevent it from being given to f() in the first
place. How can it do that?



f can know that it mustn't escape it, which is enough.


void foo(bool b, string y)
{
   immutable (char)[4] x = "abba";
   string s = b ? x : y;
   f(s);
}

Make it safe.



It is safe if the parameter to f is marked with 'scope'. (and this in
turn obliges f not to escape it.)


Well, OK, but that involves changing the semantics of immutable. You 
could not pass this kind of "local immutable" to _any_ existing code.

It would render almost all existing code that uses immutable obsolete.

And what do you get in exchange? Practically nothing!



Analyze scope on the expression level.

The analysis would determine that x[] is 'scope'. It would
conservatively propagate this fact to (b ? x[] : y). Then the local
variable 's' will get the 'scope' storage class.

In general, use a fixed-point iteration to determine all local
variables that might refer to scope'd data and prevent that they get
escaped.




Rust's borrowed pointers may give some hints on how
to extend 'scope' to fields of structs.


I think it is more fundamental than that.


As to delete, delete is as unsafe when the involved data is immutable
as when it is mutable. Why require an additional cast in one case?


This is not about safety.
Modifying immutable data breaks the type system. Deleting mutable data
does not.
AFAIK it is safe to implement delete as a call to the
finalizer, followed by setting the memory to T.init.
...



Now I see where you are coming from. This is indeed a safe approach for
references to/arrays of fully mutable value types, but not for delete
in general.

Make sure to treat void* specially though.

struct S{ immutable int x; this(int x){this.x=x;}}

void main()@safe{
 void* s = new S(2);
 delete s;
}

Class instance memory does not have a T.init, because it is not
assigned a T. And even if it was, how would you know at compile time if
the bound instance has any immutable fields?
Should that be a runtime exception?


Probably. Yeah, it's a bit hard if you have a base class, you can't 
statically check if it has immutable members in a derived class.
Or you could be conservative and disallow delete of anything where you 
don't know the exact type at compile time.





Re: How mutable is immutable?

2012-10-18 Thread Timon Gehr

On 10/18/2012 10:08 AM, Don Clugston wrote:

On 17/10/12 18:02, Timon Gehr wrote:

On 10/17/2012 01:49 PM, Don Clugston wrote:

...

That's the point -- *which* checks are missing from @safe?


Escaping stack data and arbitrarily freeing memory are not operations
found in memory safe languages.


HOW do you propose to check for escaping stack data?



Static escape analysis. Use the 'scope' qualifier to designate
data that is not allowed to be escaped in order to make it modular.


...


The implementation of the 'scope' storage class should be fixed. We
could then require an unsafe cast(scope) to disable prevention of stack
address escaping.


No we can't. f cannot know that the string it has been given is on the
stack. So main() must prevent it from being given to f() in the first
place. How can it do that?



f can know that it mustn't escape it, which is enough.


void foo(bool b, string y)
{
   immutable (char)[4] x = "abba";
   string s = b ? x : y;
   f(s);
}

Make it safe.



It is safe if the parameter to f is marked with 'scope'. (and this in
turn obliges f not to escape it.)

Analyze scope on the expression level.

The analysis would determine that x[] is 'scope'. It would
conservatively propagate this fact to (b ? x[] : y). Then the local
variable 's' will get the 'scope' storage class.

In general, use a fixed-point iteration to determine all local
variables that might refer to scope'd data and prevent that they get
escaped.




Rust's borrowed pointers may give some hints on how
to extend 'scope' to fields of structs.


I think it is more fundamental than that.


As to delete, delete is as unsafe when the involved data is immutable
as when it is mutable. Why require an additional cast in one case?


This is not about safety.
Modifying immutable data breaks the type system. Deleting mutable data
does not.
AFAIK it is safe to implement delete as a call to the
finalizer, followed by setting the memory to T.init.
...



Now I see where you are coming from. This is indeed a safe approach for
references to/arrays of fully mutable value types, but not for delete
in general.

Make sure to treat void* specially though.

struct S{ immutable int x; this(int x){this.x=x;}}

void main()@safe{
void* s = new S(2);
delete s;
}

Class instance memory does not have a T.init, because it is not
assigned a T. And even if it was, how would you know at compile time if
the bound instance has any immutable fields?
Should that be a runtime exception?



Re: How mutable is immutable?

2012-10-18 Thread Artur Skawina
On 10/18/12 10:08, Don Clugston wrote:
> On 17/10/12 18:02, Timon Gehr wrote:
>> On 10/17/2012 01:49 PM, Don Clugston wrote:
>>> On 01/01/12 13:50, Timon Gehr wrote:
>>>> On 01/01/2012 10:40 AM, Denis Shelomovskij wrote:
>>>>> So, I'm a function `f`, I have an `immutable(type)[]` argument and I
>>>>> want to store it for my friend `g` in an TLS variable `v`:
>>>>> ---
>>>>> string v;
>>>>> debug string sure;
>>>>>
>>>>> void f(string s) { v = s; debug sure = s.idup; }
>>>>> void g() { assert(v == sure); }
>>>>> ---
>>>>> I also store a copy of `s` into `sure` for my friend to ensure
>>>>> immutable
>>>>> date hasn't been mutated.
>>>>> Can my friend's assertion ever fail without breaking a type-system?
>>>>> Sure. Just consider this:
>>>>> ---
>>>>> void main() {
>>>>> auto s = "abba".idup;
>>>>> f(s);
>>>>> delete s;
>>>>> g();
>>>>> }
>>>>> ---
>>>>> Is it by-design? Looks like deleting immutable (and const because of
>>>>> implicit conversion) data should be prohibited.
>>>>> OK. Let `delete` be fixed. Can we still fail?
>>>>> ---
>>>>> void h() {
>>>>> immutable(char)[4] s = "abba";
>>>>> f(s);
>>>>> }
>>>>> void main() {
>>>>> h();
>>>>> g();
>>>>> }
>>>>> ---
>>>>> Damn! So, what can we do with it? Not sure, but I have a proposal.
>>>>>
>>>>> Fix it in language:
>>>>> * disallow `delete` of const/immutable data
>>>>> * disallow immutable data on the stack
>>>>>
>>>>> This makes data really immutable if I don't miss something. Anyway, I
>>>>> want `immutable` qualified data to be immutable without breaking a
>>>>> type-system (if one do it, its his own responsibility), so some changes
>>>>> should be made (IMHO).
>>>>
>>>> You are using unsafe language features to break the type system. That is
>>>> not the fault of the type system.
>>>>
>>>> '@safe:' at the top of the program should stop both examples from
>>>> working, it is a bug that it does not.
>>>
>>> That's the point -- *which* checks are missing from @safe?
>>
>> Escaping stack data and arbitrarily freeing memory are not operations
>> found in memory safe languages.
> 
> HOW do you propose to check for escaping stack data?

/How/ is not a problem (ignoring implementation costs), the /language 
definition/
part is trickier - you need a very precise definition of what is allowed and 
what
isn't; otherwise different compilers will make different decisions and every
compiler will support only a vendor-specific non-std dialect...
(eg storing a scoped-ref into some kind of container, passing that down to other
functions could work, but what if you then need to let the container escape and
want to do that by removing the scoped-ref? It might be possible for the 
compiler
to prove that it's safe, but it's unlikely that every compiler will act the 
same)

>>> But I'm not sure that you're right, this looks broken to me, even
>>> without @safe.
>>>
>>> What does it mean to create immutable data on the stack? The stack is
>>> intrinsically mutable!
>>
>> So is the heap.
> 
> No it is not. Data on the stack *cannot* survive past the end of the function 
> call. Data on the heap can last forever.

Lifetime and mutability are different things.

>> What does it mean to garbage collect immutable data?
> 
> From the point of view of the application, it doesn't happen. There are no 
> observable semantics. It's merely an implementation detail.
> 
>> What does it mean to allocate an 'int' on the stack?
>>
>>> What does it mean to delete immutable data?
>>
>> Deallocate the storage for it and make it available for reuse.
>> Accessing it afterwards leads to arbitrary behaviour. This is the same
>> with mutable data. As the program may behave arbitrarily in this case,
>> it is valid behaviour to act as if immutable data changed.
> 
> No, you've broken the type system if you've deleted immutable data.
> If I have a reference to an immutable variable, I have a guarantee that it 
> w

Re: How mutable is immutable?

2012-10-18 Thread Don Clugston

On 17/10/12 18:02, Timon Gehr wrote:

On 10/17/2012 01:49 PM, Don Clugston wrote:

On 01/01/12 13:50, Timon Gehr wrote:

On 01/01/2012 10:40 AM, Denis Shelomovskij wrote:

So, I'm a function `f`, I have an `immutable(type)[]` argument and I
want to store it for my friend `g` in an TLS variable `v`:
---
string v;
debug string sure;

void f(string s) { v = s; debug sure = s.idup; }
void g() { assert(v == sure); }
---
I also store a copy of `s` into `sure` for my friend to ensure
immutable
date hasn't been mutated.
Can my friend's assertion ever fail without breaking a type-system?
Sure. Just consider this:
---
void main() {
auto s = "abba".idup;
f(s);
delete s;
g();
}
---
Is it by-design? Looks like deleting immutable (and const because of
implicit conversion) data should be prohibited.
OK. Let `delete` be fixed. Can we still fail?
---
void h() {
immutable(char)[4] s = "abba";
f(s);
}
void main() {
h();
g();
}
---
Damn! So, what can we do with it? Not sure, but I have a proposal.

Fix it in language:
* disallow `delete` of const/immutable data
* disallow immutable data on the stack

This makes data really immutable if I don't miss something. Anyway, I
want `immutable` qualified data to be immutable without breaking a
type-system (if one do it, its his own responsibility), so some changes
should be made (IMHO).


You are using unsafe language features to break the type system. That is
not the fault of the type system.

'@safe:' at the top of the program should stop both examples from
working, it is a bug that it does not.


That's the point -- *which* checks are missing from @safe?


Escaping stack data and arbitrarily freeing memory are not operations
found in memory safe languages.


HOW do you propose to check for escaping stack data?


But I'm not sure that you're right, this looks broken to me, even
without @safe.

What does it mean to create immutable data on the stack? The stack is
intrinsically mutable!


So is the heap.


No it is not. Data on the stack *cannot* survive past the end of the 
function call. Data on the heap can last forever.



What does it mean to garbage collect immutable data?


From the point of view of the application, it doesn't happen. There are 
no observable semantics. It's merely an implementation detail.



What does it mean to allocate an 'int' on the stack?


What does it mean to delete immutable data?


Deallocate the storage for it and make it available for reuse.
Accessing it afterwards leads to arbitrary behaviour. This is the same
with mutable data. As the program may behave arbitrarily in this case,
it is valid behaviour to act as if immutable data changed.


No, you've broken the type system if you've deleted immutable data.
If I have a reference to an immutable variable, I have a guarantee that 
it will never change. delete will break that guarantee.


With a mutable variable, I have no such guarantee. (It's not safe to 
allocate something different in the deleted location, but it's OK to run 
the finalizer and then wipe all the memory).



I think it's reasonable for both of them to require a cast, even in
@system code.



The implementation of the 'scope' storage class should be fixed. We
could then require an unsafe cast(scope) to disable prevention of stack
address escaping.


No we can't. f cannot know that the string it has been given is on the 
stack. So main() must prevent it from being given to f() in the first 
place. How can it do that?


void foo(bool b, string y)
{
  immutable (char)[4] x = "abba";
  string s = b ? x : y;
  f(s);
}

Make it safe.



Rust's borrowed pointers may give some hints on how
to extend 'scope' to fields of structs.


I think it is more fundamental than that.


As to delete, delete is as unsafe when the involved data is immutable
as when it is mutable. Why require an additional cast in one case?


This is not about safety.
Modifying immutable data breaks the type system. Deleting mutable data 
does not. AFAIK it is safe to implement delete as a call to the 
finalizer, followed by setting the memory to T.init. Only the GC can 
determine if it is safe to reuse the memory.


Deleting immutable data just doesn't make sense.


Re: How mutable is immutable?

2012-10-17 Thread Malte Skarupke

The issue is that you're thinking as you would in Java.

I guess the rule in D for immutable is this: Immutable data won't 
change as long as it exists.


The last part of that sentence would be a stupid thing to say in 
Java because things don't just cease to exist while you're still 
doing something with them. That is not the case in D.


That being said it's very unlikely that you will ever run into 
this situation. You have to end the lifetime of the object 
manually to run into these issues. And in that case it'll be very 
easy to figure out what's wrong.


Re: How mutable is immutable?

2012-10-17 Thread Timon Gehr

On 10/17/2012 01:49 PM, Don Clugston wrote:

On 01/01/12 13:50, Timon Gehr wrote:

On 01/01/2012 10:40 AM, Denis Shelomovskij wrote:

So, I'm a function `f`, I have an `immutable(type)[]` argument and I
want to store it for my friend `g` in an TLS variable `v`:
---
string v;
debug string sure;

void f(string s) { v = s; debug sure = s.idup; }
void g() { assert(v == sure); }
---
I also store a copy of `s` into `sure` for my friend to ensure immutable
date hasn't been mutated.
Can my friend's assertion ever fail without breaking a type-system?
Sure. Just consider this:
---
void main() {
auto s = "abba".idup;
f(s);
delete s;
g();
}
---
Is it by-design? Looks like deleting immutable (and const because of
implicit conversion) data should be prohibited.
OK. Let `delete` be fixed. Can we still fail?
---
void h() {
immutable(char)[4] s = "abba";
f(s);
}
void main() {
h();
g();
}
---
Damn! So, what can we do with it? Not sure, but I have a proposal.

Fix it in language:
* disallow `delete` of const/immutable data
* disallow immutable data on the stack

This makes data really immutable if I don't miss something. Anyway, I
want `immutable` qualified data to be immutable without breaking a
type-system (if one do it, its his own responsibility), so some changes
should be made (IMHO).


You are using unsafe language features to break the type system. That is
not the fault of the type system.

'@safe:' at the top of the program should stop both examples from
working, it is a bug that it does not.


That's the point -- *which* checks are missing from @safe?


Escaping stack data and arbitrarily freeing memory are not operations
found in memory safe languages.


But I'm not sure that you're right, this looks broken to me, even
without @safe.

What does it mean to create immutable data on the stack? The stack is
intrinsically mutable!


So is the heap.

What does it mean to garbage collect immutable data?

What does it mean to allocate an 'int' on the stack?


What does it mean to delete immutable data?


Deallocate the storage for it and make it available for reuse.
Accessing it afterwards leads to arbitrary behaviour. This is the same
with mutable data. As the program may behave arbitrarily in this case,
it is valid behaviour to act as if immutable data changed.


I think it's reasonable for both of them to require a cast, even in
@system code.



The implementation of the 'scope' storage class should be fixed. We 
could then require an unsafe cast(scope) to disable prevention of stack 
address escaping. Rust's borrowed pointers may give some hints on how

to extend 'scope' to fields of structs.

As to delete, delete is as unsafe when the involved data is immutable
as when it is mutable. Why require an additional cast in one case?



Re: How mutable is immutable?

2012-10-17 Thread Don Clugston

On 01/01/12 13:50, Timon Gehr wrote:

On 01/01/2012 10:40 AM, Denis Shelomovskij wrote:

So, I'm a function `f`, I have an `immutable(type)[]` argument and I
want to store it for my friend `g` in an TLS variable `v`:
---
string v;
debug string sure;

void f(string s) { v = s; debug sure = s.idup; }
void g() { assert(v == sure); }
---
I also store a copy of `s` into `sure` for my friend to ensure immutable
date hasn't been mutated.
Can my friend's assertion ever fail without breaking a type-system?
Sure. Just consider this:
---
void main() {
auto s = "abba".idup;
f(s);
delete s;
g();
}
---
Is it by-design? Looks like deleting immutable (and const because of
implicit conversion) data should be prohibited.
OK. Let `delete` be fixed. Can we still fail?
---
void h() {
immutable(char)[4] s = "abba";
f(s);
}
void main() {
h();
g();
}
---
Damn! So, what can we do with it? Not sure, but I have a proposal.

Fix it in language:
* disallow `delete` of const/immutable data
* disallow immutable data on the stack

This makes data really immutable if I don't miss something. Anyway, I
want `immutable` qualified data to be immutable without breaking a
type-system (if one do it, its his own responsibility), so some changes
should be made (IMHO).


You are using unsafe language features to break the type system. That is
not the fault of the type system.

'@safe:' at the top of the program should stop both examples from
working, it is a bug that it does not.


That's the point -- *which* checks are missing from @safe?
But I'm not sure that you're right, this looks broken to me, even 
without @safe.


What does it mean to create immutable data on the stack? The stack is 
intrinsically mutable!

What does it mean to delete immutable data?
I think it's reasonable for both of them to require a cast, even in 
@system code.





Re: mutable reference > pointer

2012-06-06 Thread Nathan M. Swan

On Wednesday, 6 June 2012 at 11:45:34 UTC, Gor Gyolchanyan wrote:
I had this idea for a long time now and was trying to find a 
reason

why it was a bad idea.
I failed to find that reason, so here it is:

The idea is to have a mutable reference:

int& a; // This is a mutable reference (essentially a pointer, 
but

with reversed behavior).
assert(&a is null); // the address must be taken before
address-related operations can be performed
a = 20; // Access violation error due to null pointer 
dereferencing.
&a = new int; // Addresses, taken from mutable references are 
lvalues.

a = 20;
assert(a == 20);
&c = null;
assert(&c is null);

The idea here is to further reduce the need to explicitly deal 
with

addresses, while providing the number one reason why people use
pointers: indirection.
This mechanism will exclude indirection from the list of 
reasons why

one would use pointers.
This is also good for reducing compiler magic, when dealing 
with ref

parameters and return types for functions.
This mutable reference would be the complete compliment of 
pointers:
dereferencing a pointer yields a mutable reference, taking 
address of

a mutable reference yields a mutable pointer.

This is not a proposition to add to D, but rather an idea, 
which could

eventually end up in D if you guys think it's worth it.
It could also be used to remove the magic from reference types, 
by
adding their non-reference counter-parts and have their 
"constructors"

return such a mutable reference.


Here's a consideration: when I was a beginner learning C++ the 
difference between reference and pointer types (and their 
operators) confused me so much I avoided learning what pointers 
were for a long time:


type create from t
T* ptr = &t
T& ref = t


Re: mutable reference > pointer

2012-06-06 Thread Paulo Pinto

On Wednesday, 6 June 2012 at 11:58:12 UTC, Dmitry Olshansky wrote:

On 06.06.2012 15:45, Gor Gyolchanyan wrote:
I had this idea for a long time now and was trying to find a 
reason

why it was a bad idea.
I failed to find that reason, so here it is:



There is. For one thing I like pointer for being explicit about 
dereferencing something. In this sense having ref arguments of 
function is IMO step backwards:

mutator(a, b);
vs
mutator(a, &b);

which one more likely to mutate arguments?
In today's D you'll never know.


I never had any issue with this in the Pascal language family.

You need anyway always to look the function code, as you cannot 
know
what other side-effects might also be affected by the function 
call.


Plus any modern IDE can show the definition as tooltip.

--
Paulo


Re: mutable reference > pointer

2012-06-06 Thread Gor Gyolchanyan
On Wed, Jun 6, 2012 at 3:58 PM, Dmitry Olshansky  wrote:
> On 06.06.2012 15:45, Gor Gyolchanyan wrote:
>>
>> I had this idea for a long time now and was trying to find a reason
>> why it was a bad idea.
>> I failed to find that reason, so here it is:
>>
>
> There is. For one thing I like pointer for being explicit about
> dereferencing something. In this sense having ref arguments of function is
> IMO step backwards:
> mutator(a, b);
> vs
> mutator(a, &b);
>
> which one more likely to mutate arguments?
> In today's D you'll never know.
>
>
>> The idea is to have a mutable reference:
>>
>> int&  a; // This is a mutable reference (essentially a pointer, but
>> with reversed behavior).
>> assert(&a is null); // the address must be taken before
>> address-related operations can be performed
>> a = 20; // Access violation error due to null pointer dereferencing.
>> &a = new int; // Addresses, taken from mutable references are lvalues.
>> a = 20;
>> assert(a == 20);
>> &c = null;
>> assert(&c is null);
>>
>> The idea here is to further reduce the need to explicitly deal with
>> addresses, while providing the number one reason why people use
>> pointers: indirection.
>> This mechanism will exclude indirection from the list of reasons why
>> one would use pointers.
>> This is also good for reducing compiler magic, when dealing with ref
>> parameters and return types for functions.
>> This mutable reference would be the complete compliment of pointers:
>> dereferencing a pointer yields a mutable reference, taking address of
>> a mutable reference yields a mutable pointer.
>>
>> This is not a proposition to add to D, but rather an idea, which could
>> eventually end up in D if you guys think it's worth it.
>> It could also be used to remove the magic from reference types, by
>> adding their non-reference counter-parts and have their "constructors"
>> return such a mutable reference.
>>
>
>
> --
> Dmitry Olshansky

This is completely dependent on the logic of your code, including the
data type in question. Explicit knowledge of mutability is not
necessary only for value types. Reference types are inherently
mutable. This reference idea just produces a reference version of a
given type. If you're concerned about the mutability - use pointers.
This is not a replacement of pointers, but a complement for them.

-- 
Bye,
Gor Gyolchanyan.


Re: mutable reference > pointer

2012-06-06 Thread Dmitry Olshansky

On 06.06.2012 15:45, Gor Gyolchanyan wrote:

I had this idea for a long time now and was trying to find a reason
why it was a bad idea.
I failed to find that reason, so here it is:



There is. For one thing I like pointer for being explicit about 
dereferencing something. In this sense having ref arguments of function 
is IMO step backwards:

mutator(a, b);
vs
mutator(a, &b);

which one more likely to mutate arguments?
In today's D you'll never know.


The idea is to have a mutable reference:

int&  a; // This is a mutable reference (essentially a pointer, but
with reversed behavior).
assert(&a is null); // the address must be taken before
address-related operations can be performed
a = 20; // Access violation error due to null pointer dereferencing.
&a = new int; // Addresses, taken from mutable references are lvalues.
a = 20;
assert(a == 20);
&c = null;
assert(&c is null);

The idea here is to further reduce the need to explicitly deal with
addresses, while providing the number one reason why people use
pointers: indirection.
This mechanism will exclude indirection from the list of reasons why
one would use pointers.
This is also good for reducing compiler magic, when dealing with ref
parameters and return types for functions.
This mutable reference would be the complete compliment of pointers:
dereferencing a pointer yields a mutable reference, taking address of
a mutable reference yields a mutable pointer.

This is not a proposition to add to D, but rather an idea, which could
eventually end up in D if you guys think it's worth it.
It could also be used to remove the magic from reference types, by
adding their non-reference counter-parts and have their "constructors"
return such a mutable reference.




--
Dmitry Olshansky


mutable reference > pointer

2012-06-06 Thread Gor Gyolchanyan
I had this idea for a long time now and was trying to find a reason
why it was a bad idea.
I failed to find that reason, so here it is:

The idea is to have a mutable reference:

int& a; // This is a mutable reference (essentially a pointer, but
with reversed behavior).
assert(&a is null); // the address must be taken before
address-related operations can be performed
a = 20; // Access violation error due to null pointer dereferencing.
&a = new int; // Addresses, taken from mutable references are lvalues.
a = 20;
assert(a == 20);
&c = null;
assert(&c is null);

The idea here is to further reduce the need to explicitly deal with
addresses, while providing the number one reason why people use
pointers: indirection.
This mechanism will exclude indirection from the list of reasons why
one would use pointers.
This is also good for reducing compiler magic, when dealing with ref
parameters and return types for functions.
This mutable reference would be the complete compliment of pointers:
dereferencing a pointer yields a mutable reference, taking address of
a mutable reference yields a mutable pointer.

This is not a proposition to add to D, but rather an idea, which could
eventually end up in D if you guys think it's worth it.
It could also be used to remove the magic from reference types, by
adding their non-reference counter-parts and have their "constructors"
return such a mutable reference.

-- 
Bye,
Gor Gyolchanyan.


Re: Add compile time mutable variable type

2012-06-04 Thread Chang Long

On Tuesday, 5 June 2012 at 05:39:34 UTC, Ali Çehreli wrote:

On 06/04/2012 06:22 PM, Chang Long wrote:

> The previous two example is not correct, please see this one:

Your post sounds interesting but there are lots of errors:

> size_t line l;  <-- ERROR

> void this(string name) { <-- ERROR

etc. Can you actually compile that code?

It would be better if you can present your question with less 
code.


Ali

this is what I mean, I can't make it more smaller.
---
abstract class Template_parameter_Base{
TypeInto ti;
string name ;
this(TypeInto ti, string name) {
this.ti = ti ;
this.name = name ;
}
}
class Template_parameter(T) : Template_parameter_Base {
T   value ;
alias value this;
void assign(ref T t){
value = t ;
}
}
class Template_Engine {
string name ;
Template_parameter_Base[string] parameters ;
void this(string name) {
this.name = name ;
}
}
class Template(string name) {
	static compile_time_mutable(Template_Engine)  engine = new 
Template_Engine!name ;

void assign(string name, T)(ref T t){
static if(name in vars) {
			static const parameter	= cast(Template_parameter!T) 
engine.parameters[name];

static assert( parameter.ti == typeid(T) );
} else {
			static const parameter	=  new Template_parameter!T(typeid(T), 
name) ;

static engine.parameters[name]  =  parameter ;
}
parameter.assign(t);
}
}
void main(){
static tpl = new Template!"home_page" ;
auto  is_login  =  false ;
tpl.assign!"is_login"( is_login) ) ;
if( is_login ) {
tpl.assign!"user"( new User() ) ;
}

auto string switch_user = "new_user_email" ;
if( switch_user !is null ) {
tpl.assign!"user"( new User(switch_user) ) ;
}

tpl.assign!"user"( true )  ; // static assert error
}
---

After think what is done,  a better way is put the 
Template_parameter on the annotation data section.


some things like this:
class Template_Engine(string name) {
 static this_ti =  typeid( typeof(this) ) ;
 void assign(string name, T)(ref T t){
static const parameter = new Template_parameter!(T, 
name) ;
ti.createAnnotation("Template_Engine_Parameter", 
parameter);

parameter.assign(t);
  }
  void render(){
   auto parameters =  
this_ti.getParametersByName("Template_Engine_Parameter") ;
   // compile template to dynamic link library by 
template file and parameters

 }
}



Re: Add compile time mutable variable type

2012-06-04 Thread Ali Çehreli

On 06/04/2012 06:22 PM, Chang Long wrote:

> The previous two example is not correct, please see this one:

Your post sounds interesting but there are lots of errors:

> size_t line l;  <-- ERROR

> void this(string name) { <-- ERROR

etc. Can you actually compile that code?

It would be better if you can present your question with less code.

Ali



Re: Add compile time mutable variable type

2012-06-04 Thread Chang Long

On Tuesday, 5 June 2012 at 01:01:07 UTC, Chang Long wrote:
 I need a type can be change on compile time,  it can be 
immutable or mutable at run time.


For example :
---
abstract class Template_parameter_Base{
TypeInto ti;
string file ;
size_t  line l;
string name ;

   this(TypeInto ti, string file, size_t line, string name){
this.ti = ti ;
this.file = file ;
   this.line = line ;
   this.name = name ;
}
}

class Template_parameter(T) : Template_parameter_Base {
   T   value ;
   alias T this;
void assign(ref T t){
value = t ;
}
}

class Template {
 static 
compile_time_mutable(string[Template_parameter_Base])  
template_vars ;


	void assign(string name, string __file__ = __FILE__, size_t 
__line__ =__LINE__, T)(T t) {

static if( name in template_vars ){
static parameter = template_vars[name] ;
} else {
			static parameter = template_vars[name] =  new 
Template_parameter(typeid(T),  __file__, __line__ );

}
parameter.assign(t);
}

string render(){
		// use template_vars comiplate a dynamic link lib ,  and load 
it,  and put the template_vars to it, and run it ,
		// if  dynamic link lib  already exists,  or the templte file 
is not changed, just run it .

}
}

void main(){
static tpl = new Template;
auto  is_login  =  false ;
tpl.assign!"is_login"( is_login) ) ;
if( is_login ) {
tpl.assign!"user"( new User() ) ;
}
}

---

Why I need this is because I need to know all parameters at 
first time call Template.render,  but a lot parameter will not 
be call at run time. so I need a type can be changed at compile 
time.

the new type is just like mutable type at CTFE.



The previous two example is not correct, please see this one:





abstract class Template_parameter_Base{
TypeInto ti;
string file ;
size_t  line l;
string name ;

   this(TypeInto ti, string file, size_t line, string name){
this.ti = ti ;
this.file = file ;
this.line = line ;
this.name = name ;
}
}

class Template_parameter(T) : Template_parameter_Base {
   T   value ;
   alias T this;
void assign(ref T t){
value = t ;
}
}

class Template_Engine {
string name ;
Template_parameter_Base[string] parameters ;
void this(string name) {
this.name = name ;
}
}


class Template (string name) {

	static compile_time_mutable(Template_Engine)  engine = new 
Template_Engine(name) ;


	void assign(string name, string __file__ = __FILE__, size_t 
__line__ =__LINE__, T)(T t) {

static if( name in engine.parameters ){
			static compile_time_mutable(parameter) = 
engine.parameters[name] ;
			static assert( parameter.ti == typeid(T),  "assign var at " ~ 
__file__ ~ " line" ~ __line__ " with type " ~ T.stringof " ~ 
conflict with old parameter at file " ~ parameter.file  ~ " line 
" ~ parameter.line );

} else {
			static compile_time_mutable(parameter) = 
engine.parameters[name] =  new Template_parameter(typeid(T),  
__file__, __line__ , name );

}
// put the value to parameter at run time
parameter.assign(t);
}

string render(){
		// use the engine.parameters can know all parameter type 
information
		// use template_vars comiplate a dynamic link lib ,  and load 
it,  and put the template_vars to it, and run it ,
		// if  dynamic link lib  already exists,  or the templte file 
is not changed, just run it .

}
}

void main(){
static tpl = new Template!"home_page" ;
auto  is_login  =  false ;
tpl.assign!"is_login"( is_login) ) ;
if( is_login ) {
tpl.assign!"user"( new User() ) ;
}

auto string switch_user = "new_user_email" ;
if( switch_user !is null ) {
tpl.assign!"user"( new User(switch_user) ) ;
}

tpl.assign!"user"( true )  ; // static assert error
}



Re: Add compile time mutable variable type

2012-06-04 Thread Chang Long

On Tuesday, 5 June 2012 at 01:01:07 UTC, Chang Long wrote:
 I need a type can be change on compile time,  it can be 
immutable or mutable at run time.


For example :
---
abstract class Template_parameter_Base{
TypeInto ti;
string file ;
size_t  line l;
string name ;

   this(TypeInto ti, string file, size_t line, string name){
this.ti = ti ;
this.file = file ;
   this.line = line ;
   this.name = name ;
}
}

class Template_parameter(T) : Template_parameter_Base {
   T   value ;
   alias T this;
void assign(ref T t){
value = t ;
}
}

class Template {
 static 
compile_time_mutable(string[Template_parameter_Base])  
template_vars ;


	void assign(string name, string __file__ = __FILE__, size_t 
__line__ =__LINE__, T)(T t) {

static if( name in template_vars ){
static parameter = template_vars[name] ;
} else {
			static parameter = template_vars[name] =  new 
Template_parameter(typeid(T),  __file__, __line__ );

}
parameter.assign(t);
}

string render(){
		// use template_vars comiplate a dynamic link lib ,  and load 
it,  and put the template_vars to it, and run it ,
		// if  dynamic link lib  already exists,  or the templte file 
is not changed, just run it .

}
}

void main(){
static tpl = new Template;
auto  is_login  =  false ;
tpl.assign!"is_login"( is_login) ) ;
if( is_login ) {
tpl.assign!"user"( new User() ) ;
}
}

---

Why I need this is because I need to know all parameters at 
first time call Template.render,  but a lot parameter will not 
be call at run time. so I need a type can be changed at compile 
time.

the new type is just like mutable type at CTFE.


this example is more convincing:




abstract class Template_parameter_Base{
TypeInto ti;
string file ;
size_t  line l;
string name ;

   this(TypeInto ti, string file, size_t line, string name){
this.ti = ti ;
this.file = file ;
this.line = line ;
this.name = name ;
}
}

class Template_parameter(T) : Template_parameter_Base {
   T   value ;
   alias T this;
void assign(ref T t){
value = t ;
}
}

class Template {
 static 
compile_time_mutable(Template_parameter_Base[string])  
template_vars ;


	void assign(string name, string __file__ = __FILE__, size_t 
__line__ =__LINE__, T)(T t) {

static if( name in template_vars ){
static compile_time_mutable(parameter) = 
template_vars[name] ;
			static assert( parameter.ti == typeid(T),  "assign var at " ~ 
__file__ ~ " line" ~ __line__ " with type " ~ T.stringof " ~ 
conflict with old parameter at file " ~ parameter.file  ~ " line 
" ~ parameter.line );

} else {
			static compile_time_mutable(parameter) = template_vars[name] = 
 new Template_parameter(typeid(T),  __file__, __line__ , name );

}
// put the value to parameter at run time
parameter.assign(t);
}

string render(){
		// use template_vars comiplate a dynamic link lib ,  and load 
it,  and put the template_vars to it, and run it ,
		// if  dynamic link lib  already exists,  or the templte file 
is not changed, just run it .

}
}

void main(){
static tpl = new Template;
auto  is_login  =  false ;
tpl.assign!"is_login"( is_login) ) ;
if( is_login ) {
tpl.assign!"user"( new User() ) ;
}

auto string switch_user = "new_user_email" ;
if( switch_user !is null ) {
tpl.assign!"user"( new User(switch_user) ) ;
}

tpl.assign!"user"( true )  ; // static assert error
}



Add compile time mutable variable type

2012-06-04 Thread Chang Long
 I need a type can be change on compile time,  it can be 
immutable or mutable at run time.


For example :
---
abstract class Template_parameter_Base{
TypeInto ti;
string file ;
size_t  line l;
string name ;

   this(TypeInto ti, string file, size_t line, string name){
this.ti = ti ;
this.file = file ;
   this.line = line ;
   this.name = name ;
}
}

class Template_parameter(T) : Template_parameter_Base {
   T   value ;
   alias T this;
void assign(ref T t){
value = t ;
}
}

class Template {
 static 
compile_time_mutable(string[Template_parameter_Base])  
template_vars ;


	void assign(string name, string __file__ = __FILE__, size_t 
__line__ =__LINE__, T)(T t) {

static if( name in template_vars ){
static parameter = template_vars[name] ;
} else {
			static parameter = template_vars[name] =  new 
Template_parameter(typeid(T),  __file__, __line__ );

}
parameter.assign(t);
}

string render(){
		// use template_vars comiplate a dynamic link lib ,  and load 
it,  and put the template_vars to it, and run it ,
		// if  dynamic link lib  already exists,  or the templte file 
is not changed, just run it .

}
}

void main(){
static tpl = new Template;
auto  is_login  =  false ;
tpl.assign!"is_login"( is_login) ) ;
if( is_login ) {
tpl.assign!"user"( new User() ) ;
}
}

---

Why I need this is because I need to know all parameters at first 
time call Template.render,  but a lot parameter will not be call 
at run time. so I need a type can be changed at compile time.

the new type is just like mutable type at CTFE.





Re: How mutable is immutable?

2012-01-01 Thread Timon Gehr

On 01/01/2012 10:40 AM, Denis Shelomovskij wrote:

So, I'm a function `f`, I have an `immutable(type)[]` argument and I
want to store it for my friend `g` in an TLS variable `v`:
---
string v;
debug string sure;

void f(string s) { v = s; debug sure = s.idup; }
void g() { assert(v == sure); }
---
I also store a copy of `s` into `sure` for my friend to ensure immutable
date hasn't been mutated.
Can my friend's assertion ever fail without breaking a type-system?
Sure. Just consider this:
---
void main() {
auto s = "abba".idup;
f(s);
delete s;
g();
}
---
Is it by-design? Looks like deleting immutable (and const because of
implicit conversion) data should be prohibited.
OK. Let `delete` be fixed. Can we still fail?
---
void h() {
immutable(char)[4] s = "abba";
f(s);
}
void main() {
h();
g();
}
---
Damn! So, what can we do with it? Not sure, but I have a proposal.

Fix it in language:
* disallow `delete` of const/immutable data
* disallow immutable data on the stack

This makes data really immutable if I don't miss something. Anyway, I
want `immutable` qualified data to be immutable without breaking a
type-system (if one do it, its his own responsibility), so some changes
should be made (IMHO).


You are using unsafe language features to break the type system. That is 
not the fault of the type system.


'@safe:' at the top of the program should stop both examples from 
working, it is a bug that it does not.


How mutable is immutable?

2012-01-01 Thread Denis Shelomovskij
So, I'm a function `f`, I have an `immutable(type)[]` argument and I 
want to store it for my friend `g` in an TLS variable `v`:

---
string v;
debug string sure;

void f(string s) { v = s; debug sure = s.idup; }
void g() { assert(v == sure); }
---
I also store a copy of `s` into `sure` for my friend to ensure immutable 
date hasn't been mutated.

Can my friend's assertion ever fail without breaking a type-system?
Sure. Just consider this:
---
void main() {
auto s = "abba".idup;
f(s);
delete s;
g();
}
---
Is it by-design? Looks like deleting immutable (and const because of 
implicit conversion) data should be prohibited.

OK. Let `delete` be fixed. Can we still fail?
---
void h() {
immutable(char)[4] s = "abba";
f(s);
}
void main() {
h();
g();
}
---
Damn! So, what can we do with it? Not sure, but I have a proposal.

Fix it in language:
* disallow `delete` of const/immutable data
* disallow immutable data on the stack

This makes data really immutable if I don't miss something. Anyway, I 
want `immutable` qualified data to be immutable without breaking a 
type-system (if one do it, its his own responsibility), so some changes 
should be made (IMHO).


Re: mutable compile-time data proposal

2011-12-28 Thread Gor Gyolchanyan
You missed the point. The case with dynamic libraries is just too
obvious: they're "dynamic" for a reason. The case of base classes not
knowing their derived classes is also kinda obvious because the
mutable aliases would allow for derived classes to add themselves to
the tuple by mixin in some compile-time stuff. You could do that if
aliases would be compile-time rebindable, but you can't do it
otherwise.

On Thu, Dec 29, 2011 at 11:31 AM, Jonathan M Davis  wrote:
> On Thursday, December 29, 2011 10:23:11 Gor Gyolchanyan wrote:
>> The mutability of compile-time data would essentially enable fully
>> imperative compile-time computation. Right now it's almost purely
>> functional with the small exception of CTFE functions. Sometimes
>> functional style can't do the trick. For instance, you can't make a
>> template which "returns" a TypeTuple of derived classes of the given
>> class.
>
> You can't do that because the compiler doesn't have that information, not
> because of the functional nature of much of the compile time stuff. Classes
> don't know about their derived classes, and with the C linking model (which D
> uses), you can't possibly know what they all are until link time - and with
> dynamically loaded libraries, you won't even know then, because more can be
> loaded and linked in at runtime.
>
> You should be able to do pretty much anything in a functional style that you
> can do with an imperative style. You just have to go about it differently.
>
> - Jonathan M Davis



-- 
Bye,
Gor Gyolchanyan.


Re: mutable compile-time data proposal

2011-12-28 Thread Jonathan M Davis
On Thursday, December 29, 2011 10:23:11 Gor Gyolchanyan wrote:
> The mutability of compile-time data would essentially enable fully
> imperative compile-time computation. Right now it's almost purely
> functional with the small exception of CTFE functions. Sometimes
> functional style can't do the trick. For instance, you can't make a
> template which "returns" a TypeTuple of derived classes of the given
> class.

You can't do that because the compiler doesn't have that information, not 
because of the functional nature of much of the compile time stuff. Classes 
don't know about their derived classes, and with the C linking model (which D 
uses), you can't possibly know what they all are until link time - and with 
dynamically loaded libraries, you won't even know then, because more can be 
loaded and linked in at runtime.

You should be able to do pretty much anything in a functional style that you 
can do with an imperative style. You just have to go about it differently.

- Jonathan M Davis


Re: mutable compile-time data proposal

2011-12-28 Thread Gor Gyolchanyan
The mutability of compile-time data would essentially enable fully
imperative compile-time computation. Right now it's almost purely
functional with the small exception of CTFE functions. Sometimes
functional style can't do the trick. For instance, you can't make a
template which "returns" a TypeTuple of derived classes of the given
class.

2011/12/29 Mariusz Gliwiński :
> David Nadlinger wrote:
>> Could you show a few examples? I'm just curious, because I wrote a
>> sizable chunk of D code, often incorporating some form of compile time
>> magic, and never felt the need for it.
> I'd rather avoid that because code i'm writing isn't a state of art, so you
> might neglect my concrete ideas of solving things (use of tool).
> Furthermore, i'm quite sleepy already so i might forget something, explain
> wrongly. So, i hope i'm not ruining good idea by providing stupid examples.
>
> -- local CT variables, result to standard RT variable.
> 1) Generate UUIDs of types of messages which are being provided and received
> from various parts of application.
>
> -- global CT variables, not sure if we're talking about that now.
> 2) Make sure there is only one provider, and one receiver (in couple of
> cases). More generally, validation of application logic, that can be done
> static, but can't be catched up by compiler itself.
>
> -- local CT variables,
> 3) There are examples, where i'd like to avoid use of classes (i don't need
> to put them in some container, and treat under superclass API), but i would
> still like to share code (traits). So yes, i'm using mixins, but frequently
> this kind of mixin needs initialization/dispose, which has to be called
> manually by consumer. It leads to many initXTrait on initializer. I'd rather
> like to store function pointers and iterate over it (i'm not even talking
> about add something like this to language).
>
> 4) I'd like to generate application interface prototype during compilation
> (serialization of specific parts of AST if i'm not wrong to use this term
> here), and not having to write my own D parser for it. Yeah, i know you
> probably got big WTF in your head while reading this, but these are things
> i'd like to do, and neverthless if it's good or not, those are ideas that
> programmer would like to have a chance to implement.
>
> I'm sure there are more appealing examples, but these are mine, and i'd like
> to just have a possibility to implement them.



-- 
Bye,
Gor Gyolchanyan.


Re: mutable compile-time data proposal

2011-12-28 Thread Mariusz Gliwiński
David Nadlinger wrote:
> Could you show a few examples? I'm just curious, because I wrote a
> sizable chunk of D code, often incorporating some form of compile time
> magic, and never felt the need for it.
I'd rather avoid that because code i'm writing isn't a state of art, so you 
might neglect my concrete ideas of solving things (use of tool). 
Furthermore, i'm quite sleepy already so i might forget something, explain 
wrongly. So, i hope i'm not ruining good idea by providing stupid examples.

-- local CT variables, result to standard RT variable.
1) Generate UUIDs of types of messages which are being provided and received 
from various parts of application.

-- global CT variables, not sure if we're talking about that now.
2) Make sure there is only one provider, and one receiver (in couple of 
cases). More generally, validation of application logic, that can be done 
static, but can't be catched up by compiler itself. 

-- local CT variables,
3) There are examples, where i'd like to avoid use of classes (i don't need 
to put them in some container, and treat under superclass API), but i would 
still like to share code (traits). So yes, i'm using mixins, but frequently 
this kind of mixin needs initialization/dispose, which has to be called 
manually by consumer. It leads to many initXTrait on initializer. I'd rather 
like to store function pointers and iterate over it (i'm not even talking 
about add something like this to language).

4) I'd like to generate application interface prototype during compilation 
(serialization of specific parts of AST if i'm not wrong to use this term 
here), and not having to write my own D parser for it. Yeah, i know you 
probably got big WTF in your head while reading this, but these are things 
i'd like to do, and neverthless if it's good or not, those are ideas that 
programmer would like to have a chance to implement.

I'm sure there are more appealing examples, but these are mine, and i'd like 
to just have a possibility to implement them.


Re: mutable compile-time data proposal

2011-12-28 Thread David Nadlinger

On 12/29/11 6:18 AM, Mariusz Gliwiński wrote:

Andrei Alexandrescu wrote:

I don't think such a feature has a huge potential use. I honestly think
it's a "meh" feature. It's a feature for defining elaborate literals,
and for that we have the shock and awe of mixin and CTFE.


Actually, i already needed it few times in my D project (and still need).


Could you show a few examples? I'm just curious, because I wrote a 
sizable chunk of D code, often incorporating some form of compile time 
magic, and never felt the need for it.


Thanks,
David


Re: mutable compile-time data proposal

2011-12-28 Thread Walter Bright

On 12/28/2011 9:18 PM, Mariusz Gliwiński wrote:

For me, question would be not "if it's useful", but "is it easy to implement
and if it's not hurting compiler performance too much".


I beg to differ. A feature should be "why", not "why not". Otherwise, we wind up 
with a complex boatload of semi-useless features.


Re: mutable compile-time data proposal

2011-12-28 Thread Mariusz Gliwiński
Andrei Alexandrescu wrote:
> I don't think such a feature has a huge potential use. I honestly think
> it's a "meh" feature. It's a feature for defining elaborate literals,
> and for that we have the shock and awe of mixin and CTFE.

Actually, i already needed it few times in my D project (and still need).
I think people are just not used to treat compile-time as just another time 
of execution and they don't see value of it.

While uneducated coder as me (advantage of seeing things with fresh eye) 
sees CTFE as natural thing to do when input data is known, and computation 
power is bigger than memory read && executable growth.
Of course it might be done by preprocessing sources but that's a pain in the 
ass.

For me, question would be not "if it's useful", but "is it easy to implement 
and if it's not hurting compiler performance too much".


Re: mutable compile-time data proposal

2011-12-28 Thread Andrei Alexandrescu

On 12/28/11 4:54 PM, Gor Gyolchanyan wrote:

I think you are, because this depends on syntax; blank lines between
them would break it. Still there would be a huge potential use for
that feature.


I don't think such a feature has a huge potential use. I honestly think 
it's a "meh" feature. It's a feature for defining elaborate literals, 
and for that we have the shock and awe of mixin and CTFE.


Iota is present in Go, and I don't think it's gone anywhere past 
"meh"iness, even in Go which lacks better code generation features.



Andrei


Re: mutable compile-time data proposal

2011-12-28 Thread Martin Nowak
On Wed, 28 Dec 2011 19:51:42 +0100, Andrei Alexandrescu  
 wrote:



On 12/28/11 12:22 PM, Martin Nowak wrote:

On Wed, 28 Dec 2011 15:00:10 +0100, Gor Gyolchanyan
 wrote:


This is something I was thinking about for a long time now.

There seems to be absolutely no difference between T, const(T) and
immutable(T) if T is a compile-time value (a enum or a local in CTFE).
The possibility to mutate compile-time values (at compile time, of
course) would allow very convenient techniques to be used for a number
of purposes.
And since in my hypothetical D compile-time data can be mutated, then
a compile-time static this is required (especially for the next
example).
For instance, here's something I'd love to be able to do:

class Base
{
mixin template Register()
{
ctStaticThis() // a placeholder for the real compile-time static this
{
Derived = TypeTuple!(Derived, typeof(this));
}
}

enum Derived = TypeTuple!();
}

class Derived1: Base
{
mixin Register;
}

class Derived2: Base
{
mixin Register;
}

static assert(is(Base.Derived == TypeTuple!(Base, Derived1,  
Derived2)));


Similar things would allow to quickly build extremely powerful and
useful compile-time information, which is currently not possible to
build.
If mutable compile-time data is implemented, the entire compile-time
computation in D would become just like the run-time one.



I'd really like to see such a construct.

enum __iota;

enum Masks
{
A = (1 << __iota++),
B = (1 << __iota++),
C = (1 << __iota++),

DMask = (0b11 << __iota),
D0 = (1 << __iota++),
D1 = (1 << __iota++),
}

static assert(__iota <= 32);

Now this would depend on the order of semantic so it's not feasible.


enum Masks
{
 __iota = __LINE__, A = (1 << 0),
 B = (1 << __LINE__ - __iota),
 C = (1 << __LINE__ - __iota),
 DMask = (0b11 << __LINE__ - __iota), D0 = (1 << __LINE__ - __iota),
 D1 = (1 << __LINE__ - __iota),
}

Yeah, I'm jesting. Or am I???


Andrei
:), but seriously using __LINE__ or __FILE__ to create unique ids just  
doesn't cut it.


Re: mutable compile-time data proposal

2011-12-28 Thread Gor Gyolchanyan
I think you are, because this depends on syntax; blank lines between
them would break it. Still there would be a huge potential use for
that feature.

On Wed, Dec 28, 2011 at 10:51 PM, Andrei Alexandrescu
 wrote:
> On 12/28/11 12:22 PM, Martin Nowak wrote:
>>
>> On Wed, 28 Dec 2011 15:00:10 +0100, Gor Gyolchanyan
>>  wrote:
>>
>>> This is something I was thinking about for a long time now.
>>>
>>> There seems to be absolutely no difference between T, const(T) and
>>> immutable(T) if T is a compile-time value (a enum or a local in CTFE).
>>> The possibility to mutate compile-time values (at compile time, of
>>> course) would allow very convenient techniques to be used for a number
>>> of purposes.
>>> And since in my hypothetical D compile-time data can be mutated, then
>>> a compile-time static this is required (especially for the next
>>> example).
>>> For instance, here's something I'd love to be able to do:
>>>
>>> class Base
>>> {
>>> mixin template Register()
>>> {
>>> ctStaticThis() // a placeholder for the real compile-time static this
>>> {
>>> Derived = TypeTuple!(Derived, typeof(this));
>>> }
>>> }
>>>
>>> enum Derived = TypeTuple!();
>>> }
>>>
>>> class Derived1: Base
>>> {
>>> mixin Register;
>>> }
>>>
>>> class Derived2: Base
>>> {
>>> mixin Register;
>>> }
>>>
>>> static assert(is(Base.Derived == TypeTuple!(Base, Derived1, Derived2)));
>>>
>>> Similar things would allow to quickly build extremely powerful and
>>> useful compile-time information, which is currently not possible to
>>> build.
>>> If mutable compile-time data is implemented, the entire compile-time
>>> computation in D would become just like the run-time one.
>>>
>>
>> I'd really like to see such a construct.
>>
>> enum __iota;
>>
>> enum Masks
>> {
>> A = (1 << __iota++),
>> B = (1 << __iota++),
>> C = (1 << __iota++),
>>
>> DMask = (0b11 << __iota),
>> D0 = (1 << __iota++),
>> D1 = (1 << __iota++),
>> }
>>
>> static assert(__iota <= 32);
>>
>> Now this would depend on the order of semantic so it's not feasible.
>
>
> enum Masks
> {
>    __iota = __LINE__, A = (1 << 0),
>    B = (1 << __LINE__ - __iota),
>    C = (1 << __LINE__ - __iota),
>    DMask = (0b11 << __LINE__ - __iota), D0 = (1 << __LINE__ - __iota),
>    D1 = (1 << __LINE__ - __iota),
> }
>
> Yeah, I'm jesting. Or am I???
>
>
> Andrei



-- 
Bye,
Gor Gyolchanyan.


Re: mutable compile-time data proposal

2011-12-28 Thread Andrei Alexandrescu

On 12/28/11 12:22 PM, Martin Nowak wrote:

On Wed, 28 Dec 2011 15:00:10 +0100, Gor Gyolchanyan
 wrote:


This is something I was thinking about for a long time now.

There seems to be absolutely no difference between T, const(T) and
immutable(T) if T is a compile-time value (a enum or a local in CTFE).
The possibility to mutate compile-time values (at compile time, of
course) would allow very convenient techniques to be used for a number
of purposes.
And since in my hypothetical D compile-time data can be mutated, then
a compile-time static this is required (especially for the next
example).
For instance, here's something I'd love to be able to do:

class Base
{
mixin template Register()
{
ctStaticThis() // a placeholder for the real compile-time static this
{
Derived = TypeTuple!(Derived, typeof(this));
}
}

enum Derived = TypeTuple!();
}

class Derived1: Base
{
mixin Register;
}

class Derived2: Base
{
mixin Register;
}

static assert(is(Base.Derived == TypeTuple!(Base, Derived1, Derived2)));

Similar things would allow to quickly build extremely powerful and
useful compile-time information, which is currently not possible to
build.
If mutable compile-time data is implemented, the entire compile-time
computation in D would become just like the run-time one.



I'd really like to see such a construct.

enum __iota;

enum Masks
{
A = (1 << __iota++),
B = (1 << __iota++),
C = (1 << __iota++),

DMask = (0b11 << __iota),
D0 = (1 << __iota++),
D1 = (1 << __iota++),
}

static assert(__iota <= 32);

Now this would depend on the order of semantic so it's not feasible.


enum Masks
{
__iota = __LINE__, A = (1 << 0),
B = (1 << __LINE__ - __iota),
C = (1 << __LINE__ - __iota),
DMask = (0b11 << __LINE__ - __iota), D0 = (1 << __LINE__ - __iota),
D1 = (1 << __LINE__ - __iota),
}

Yeah, I'm jesting. Or am I???


Andrei


Re: mutable compile-time data proposal

2011-12-28 Thread Martin Nowak
On Wed, 28 Dec 2011 15:00:10 +0100, Gor Gyolchanyan  
 wrote:



This is something I was thinking about for a long time now.

There seems to be absolutely no difference between T, const(T) and
immutable(T) if T is a compile-time value (a enum or a local in CTFE).
The possibility to mutate compile-time values (at compile time, of
course) would allow very convenient techniques to be used for a number
of purposes.
And since in my hypothetical D compile-time data can be mutated, then
a compile-time static this is required (especially for the next
example).
For instance, here's something I'd love to be able to do:

class Base
{
mixin template Register()
{
ctStaticThis() // a placeholder for the real compile-time static  
this

{
Derived = TypeTuple!(Derived, typeof(this));
}
}

enum Derived = TypeTuple!();
}

class Derived1: Base
{
mixin Register;
}

class Derived2: Base
{
mixin Register;
}

static assert(is(Base.Derived == TypeTuple!(Base, Derived1, Derived2)));

Similar things would allow to quickly build extremely powerful and
useful compile-time information, which is currently not possible to
build.
If mutable compile-time data is implemented, the entire compile-time
computation in D would become just like the run-time one.



I'd really like to see such a construct.

enum __iota;

enum Masks
{
A = (1 << __iota++),
B = (1 << __iota++),
C = (1 << __iota++),

DMask = (0b11 << __iota),
D0 = (1 << __iota++),
D1 = (1 << __iota++),
}

static assert(__iota <= 32);

Now this would depend on the order of semantic so it's not feasible.


mutable compile-time data proposal

2011-12-28 Thread Gor Gyolchanyan
This is something I was thinking about for a long time now.

There seems to be absolutely no difference between T, const(T) and
immutable(T) if T is a compile-time value (a enum or a local in CTFE).
The possibility to mutate compile-time values (at compile time, of
course) would allow very convenient techniques to be used for a number
of purposes.
And since in my hypothetical D compile-time data can be mutated, then
a compile-time static this is required (especially for the next
example).
For instance, here's something I'd love to be able to do:

class Base
{
mixin template Register()
{
ctStaticThis() // a placeholder for the real compile-time static this
{
Derived = TypeTuple!(Derived, typeof(this));
}
}

enum Derived = TypeTuple!();
}

class Derived1: Base
{
mixin Register;
}

class Derived2: Base
{
mixin Register;
}

static assert(is(Base.Derived == TypeTuple!(Base, Derived1, Derived2)));

Similar things would allow to quickly build extremely powerful and
useful compile-time information, which is currently not possible to
build.
If mutable compile-time data is implemented, the entire compile-time
computation in D would become just like the run-time one.

-- 
Bye,
Gor Gyolchanyan.


Re: std.string.reverse() for mutable array of chars

2011-12-09 Thread bearophile
Jonathan M Davis:

> Well, it looks like Andrei had some free time this morning and figured it 
> out. 
> He has a pull request for it:

Thanks you Andrei Alexandrescu and Jonathan :-)

Bye,
bearophile


Re: std.string.reverse() for mutable array of chars

2011-12-09 Thread Jonathan M Davis
On Friday, December 09, 2011 13:27:01 Jonathan M Davis wrote:
> On Friday, December 09, 2011 12:44:37 bearophile wrote:
> > Jonathan M Davis:
> > > It sounded like you were,
> > 
> > Right, I was :-) But you have changed my mind when you have explained me
> > that nothing in std.algorithm is grapheme-aware. So I have reduced the
> > amount of what I am asking for.
> 
> So, now you're asking that char and wchar arrays be reversible with reverse
> such that their code points are reversed (i.e. the result is the same as if
> you reversed an array of dchar). Well, I'm not sure that you can actually do
> that with the same efficiency. I'd have to think about it more. Regardless,
> the implementation would be _really_ complicated in comparison to how
> reverse works right now. char[] and wchar[] don't work with reverse,
> because their elements aren't swappable. So, you can't just swap elements
> as you iterate in from both ends. You'd have to be moving stuff off into
> temporaries as you swapped them, because the code point on one side
> wouldn't necessarily fit where the code point on the other side was, and in
> the worst case (i.e. all of the code points on one half of the string are
> multiple code units and all of those on the other side are single code
> units), you'd pretty much end up having to copy half the array while you
> waited for enough space to open up on one side to fit the characters from
> the other side. So, regardless of whether it has the same computational
> complexity as the current reverse, its memory requirements would be far
> more.
> 
> I don't think that the request is completely unreasonable, but also I'm not
> sure it's acceptable for reverse to change its performance characteristics
> as much as would be required for it to work with arrays of char or wchar -
> particularly with regards to how much memory would be required. In general,
> the performance characteristics of the algorithms in Phobos don't vary much
> with regards to the type that that's used. I'm pretty sure that in terms of
> big-o notation, the memory complexity wouldn't match (though I don't recall
> exactly how big-o notation works with memory rather than computational
> complexity).

Well, it looks like Andrei had some free time this morning and figured it out. 
He has a pull request for it:

https://github.com/D-Programming-Language/phobos/pull/359

- Jonathan M Davis


Re: std.string.reverse() for mutable array of chars

2011-12-09 Thread Jonathan M Davis
On Friday, December 09, 2011 12:44:37 bearophile wrote:
> Jonathan M Davis:
> > It sounded like you were,
> 
> Right, I was :-) But you have changed my mind when you have explained me
> that nothing in std.algorithm is grapheme-aware. So I have reduced the
> amount of what I am asking for.

So, now you're asking that char and wchar arrays be reversible with reverse 
such that their code points are reversed (i.e. the result is the same as if 
you reversed an array of dchar). Well, I'm not sure that you can actually do 
that with the same efficiency. I'd have to think about it more. Regardless, the 
implementation would be _really_ complicated in comparison to how reverse 
works right now. char[] and wchar[] don't work with reverse, because their 
elements aren't swappable. So, you can't just swap elements as you iterate in 
from both ends. You'd have to be moving stuff off into temporaries as you 
swapped them, because the code point on one side wouldn't necessarily fit where 
the code point on the other side was, and in the worst case (i.e. all of the 
code points on one half of the string are multiple code units and all of those 
on the other side are single code units), you'd pretty much end up having to 
copy half the array while you waited for enough space to open up on one side 
to fit the characters from the other side. So, regardless of whether it has the 
same computational complexity as the current reverse, its memory requirements 
would be far more.

I don't think that the request is completely unreasonable, but also I'm not 
sure it's acceptable for reverse to change its performance characteristics as 
much as would be required for it to work with arrays of char or wchar - 
particularly with regards to how much memory would be required. In general, 
the performance characteristics of the algorithms in Phobos don't vary much 
with regards to the type that that's used. I'm pretty sure that in terms of 
big-o notation, the memory complexity wouldn't match (though I don't recall 
exactly how big-o notation works with memory rather than computational 
complexity).

- Jonathan M Davis


Re: std.string.reverse() for mutable array of chars

2011-12-09 Thread bearophile
Jonathan M Davis:

> It sounded like you were,

Right, I was :-) But you have changed my mind when you have explained me that 
nothing in std.algorithm is grapheme-aware. So I have reduced the amount of 
what I am asking for.

Bye,
bearophile


Re: std.string.reverse() for mutable array of chars

2011-12-09 Thread Jonathan M Davis
On Friday, December 09, 2011 06:15:04 bearophile wrote:
> Jonathan M Davis:
> > I don't expect that std.string will _ever_ be grapheme-aware or be
> > processed by default as a range of graphemes.
> 
> OK, let's forget about graphemes in this discussion. Now I am not asking for
> a grapheme-aware reverse.

It sounded like you were, because you were complaining about how dchar did an 
exact reversal of the code points rather than taking combining code points 
into account.

- Jonathan M Davis


Re: std.string.reverse() for mutable array of chars

2011-12-09 Thread bearophile
Jonathan M Davis:

> I don't expect that std.string will _ever_ be grapheme-aware or be processed 
> by default as a range of graphemes.

OK, let's forget about graphemes in this discussion. Now I am not asking for a 
grapheme-aware reverse.

Bye,
bearophile


Re: std.string.reverse() for mutable array of chars

2011-12-09 Thread Jonathan M Davis
On Friday, December 09, 2011 05:58:40 bearophile wrote:
> Jonathan M Davis:
> > And as I explained in bug# 7085, reverse's behavior with regards to
> > dchar[] is completely correct. It's reversing the code points, _not_
> > the graphemes.
> OK. Maybe I will open a differently worded enhancement request, for a
> grapheme-aware std.string.
> > If you want to reverse a char[], then cast it to ubyte[] and reverse
> > that. If you want to reverse a wchar[], then cast it to ushort[] and
> > reverse that. In Phobos, strings are ranges of dchar, so reverse is
> > going to reverse code points. If you want it to reverse code units
> > instead, then you just use the appropriate cast. There's no reason to
> > have it reverse the code units and completely mess up unicode strings.
> 
> I am not interested in reversing code units. Sorry if my post has led to
> this wrong idea. For this specific problem I am not going to cast to
> ubyte[] or ushort[] because it gives very wrong results.
> 
> It's possible to write a "correct" (that doesn't take into account
> graphemes) reverse even if you do not use casts, keeping the array as
> char[] or wchar[], reversing the bytes, and then reversing the bytes of
> each variable-length codepoint. This is what I was asking to an in-place
> reverse().

I don't expect that std.string will _ever_ be grapheme-aware or be processed 
by default as a range of graphemes. That's far too expensive as far as 
performance goes. Rather, we're likely to have a wrapper and/or separate 
range-type which handles graphemes. Then if you want the extra correctness and 
are willing to pay the cost, you use that. As I understand it, std.regex does 
have the beginnings of such, but we do still need to have a range type of some 
variety (probably in std.utf) which fully supports graphemes.

- Jonathan M Davis


Re: std.string.reverse() for mutable array of chars

2011-12-09 Thread bearophile
Jonathan M Davis:

> And as I explained in bug# 7085, reverse's behavior with regards to dchar[] 
> is 
> completely correct. It's reversing the code points, _not_ the graphemes.

OK. Maybe I will open a differently worded enhancement request, for a 
grapheme-aware std.string.


> If you want to reverse a char[], then cast it to ubyte[] and reverse that. If 
> you want to reverse a wchar[], then cast it to ushort[] and reverse that. In 
> Phobos, strings are ranges of dchar, so reverse is going to reverse code 
> points. If you want it to reverse code units instead, then you just use the 
> appropriate cast. There's no reason to have it reverse the code units and 
> completely mess up unicode strings.

I am not interested in reversing code units. Sorry if my post has led to this 
wrong idea. For this specific problem I am not going to cast to ubyte[] or 
ushort[] because it gives very wrong results.

It's possible to write a "correct" (that doesn't take into account graphemes) 
reverse even if you do not use casts, keeping the array as char[] or wchar[], 
reversing the bytes, and then reversing the bytes of each variable-length 
codepoint. This is what I was asking to an in-place reverse().

Bye,
bearophile


Re: std.string.reverse() for mutable array of chars

2011-12-09 Thread Jonathan M Davis
On Friday, December 09, 2011 04:46:35 bearophile wrote:
> Reversing an array of chars/wchars is a common enough operation (mutable
> arrays often come from precedent operations that have built it). Currently
> std.algorithm.reverse() can't be used:
> 
> 
> import std.algorithm;
> void main() {
> dchar[] s1 = "hello"d.dup;
> s1.reverse(); // OK
> wchar[] s2 = "hello"w.dup;
> s2.reverse(); // error
> char[] s3 = "hello".dup;
> s3.reverse(); // error
> }
> 
> 
> I suggest to add a char[]/wchar[] specialization to std.algorithm.reverse()
> (or to add a std.string.reverse()), to make it work on those types too.
> Generally std.algorithms don't work on UTF8/UTF16 because of the variable
> length of its items, but for this specific algorithm I think this is not a
> problem because:
> 
> 1) Reversing an array is an O(n) operation, and decoding UTF adds a constant
> overhead, so the computational complexity of reverse doesn't change. 2) If
> you reverse an char[] or wchar[] the result will fit in the input array (is
> this always true? Please tell me if this isn't true). It "just" needs to
> correctly swap the bytes of multi-byte chars, and swap if there are
> combined codepoints too.
> 
> - - - - - - - - - - - - - - - - - -
> 
> And I think std.algorithm.reverse() is sometimes buggy on a dchar[] (UTF32):
> 
> 
> import std.algorithm: reverse;
> void main() {
> dchar[] txt = "\U0041\U0308\U0042"d.dup;
> txt.reverse();
> assert(txt == "\U0042\U0308\U0041"d);
> }
> 
> 
> txt contains LATIN CAPITAL LETTER A, COMBINING DIAERESIS, LATIN CAPITAL
> LETTER B (see bug 7084 for more details).
> 
> A correct output for reversing txt is (LATIN CAPITAL LETTER B, LATIN CAPITAL
> LETTER A, COMBINING DIAERESIS):
> 
> "\U0042\U0041\U0308"d
> 
> 
> See for some code:
> http://stackoverflow.com/questions/199260/how-do-i-reverse-a-utf-8-string-in
> -place
> 
> See also:
> http://d.puremagic.com/issues/show_bug.cgi?id=7085
> 
> Regarding the printing of unicode strings see also:
> http://d.puremagic.com/issues/show_bug.cgi?id=7084

If you want to reverse a char[], then cast it to ubyte[] and reverse that. If 
you want to reverse a wchar[], then cast it to ushort[] and reverse that. In 
Phobos, strings are ranges of dchar, so reverse is going to reverse code 
points. If you want it to reverse code units instead, then you just use the 
appropriate cast. There's no reason to have it reverse the code units and 
completely mess up unicode strings.

And as I explained in bug# 7085, reverse's behavior with regards to dchar[] is 
completely correct. It's reversing the code points, _not_ the graphemes. If 
you want to operate on graphemes, you need a range of graphemes, which Phobos 
does not yet support. Once it does (or if you implement it yourself), you can 
reverse a string based on graphemes if that's what you want to do. But as it 
stands, ranges of code points are the most advanced unicode construct that 
Phobos currently supports, so that's what its functions are going to operate 
on.

- Jonathan M Davis


std.string.reverse() for mutable array of chars

2011-12-09 Thread bearophile
Reversing an array of chars/wchars is a common enough operation (mutable arrays 
often come from precedent operations that have built it). Currently 
std.algorithm.reverse() can't be used:


import std.algorithm;
void main() {
dchar[] s1 = "hello"d.dup;
s1.reverse(); // OK
wchar[] s2 = "hello"w.dup;
s2.reverse(); // error
char[] s3 = "hello".dup;
s3.reverse(); // error
}


I suggest to add a char[]/wchar[] specialization to std.algorithm.reverse() (or 
to add a std.string.reverse()), to make it work on those types too. Generally 
std.algorithms don't work on UTF8/UTF16 because of the variable length of its 
items, but for this specific algorithm I think this is not a problem because:

1) Reversing an array is an O(n) operation, and decoding UTF adds a constant 
overhead, so the computational complexity of reverse doesn't change.
2) If you reverse an char[] or wchar[] the result will fit in the input array 
(is this always true? Please tell me if this isn't true). It "just" needs to 
correctly swap the bytes of multi-byte chars, and swap if there are combined 
codepoints too.

- - - - - - - - - - - - - - - - - -

And I think std.algorithm.reverse() is sometimes buggy on a dchar[] (UTF32):


import std.algorithm: reverse;
void main() {
dchar[] txt = "\U0041\U0308\U0042"d.dup;
txt.reverse();
assert(txt == "\U0042\U0308\U0041"d);
}


txt contains LATIN CAPITAL LETTER A, COMBINING DIAERESIS, LATIN CAPITAL LETTER 
B (see bug 7084 for more details).

A correct output for reversing txt is (LATIN CAPITAL LETTER B, LATIN CAPITAL 
LETTER A, COMBINING DIAERESIS):

"\U0042\U0041\U0308"d


See for some code:
http://stackoverflow.com/questions/199260/how-do-i-reverse-a-utf-8-string-in-place

See also:
http://d.puremagic.com/issues/show_bug.cgi?id=7085

Regarding the printing of unicode strings see also:
http://d.puremagic.com/issues/show_bug.cgi?id=7084

Bye,
bearophile


Re: " is not mutable" when using ref return type

2011-05-22 Thread Steven Schveighoffer
On Fri, 20 May 2011 14:42:57 -0400, Jonathan M Davis   
wrote:


On Thu, 19 May 2011 00:22:42 -0400, Jonathan M Davis  



wrote:
> On 2011-05-18 20:55, %u wrote:
>> Hi!
>>
>> Is this a bug, or is it intentional that this fails? I can't come up
>> with any case where it would cause a problem, but the compiler  
doesn't

>>
>> like the fact that there's a const in the structure:
>> struct Temp { const int a; int b; }
>>
>> auto ref foo(Temp* t) { return *t; } //Error
>
> As soon as you do *t, you're copying the value.

That's not true, if it's ref, it just copies the reference.


Well, I wasn't sure either way, and when I tested it by creating a  
postblit
which printed, it printed. So, either I ran into a bug (quite possible),  
or I

definitely misunderstood what was going on.


It depends on the example, if you are assigning the result to another  
variable, that is where the copy may occur.


But if you do something like just take the address of the return, or pass  
it to something else that accepts ref, it should not call the postblit.


Most certainly it's not within the function.

-Steve


Re: " is not mutable" when using ref return type

2011-05-20 Thread Jonathan M Davis
> On Thu, 19 May 2011 00:22:42 -0400, Jonathan M Davis 
> 
> wrote:
> > On 2011-05-18 20:55, %u wrote:
> >> Hi!
> >> 
> >> Is this a bug, or is it intentional that this fails? I can't come up
> >> with any case where it would cause a problem, but the compiler doesn't
> >> 
> >> like the fact that there's a const in the structure:
> >> struct Temp { const int a; int b; }
> >> 
> >> auto ref foo(Temp* t) { return *t; } //Error
> > 
> > As soon as you do *t, you're copying the value.
> 
> That's not true, if it's ref, it just copies the reference.

Well, I wasn't sure either way, and when I tested it by creating a postblit 
which printed, it printed. So, either I ran into a bug (quite possible), or I 
definitely misunderstood what was going on.

- Jonathan M Davis


Re: " is not mutable" when using ref return type

2011-05-19 Thread Muffin

On 19/05/11 1:25 PM, %u wrote:

Hi!

Is this a bug, or is it intentional that this fails? I can't come up
with any case where it would cause a problem, but the compiler doesn't
like the fact that there's a const in the structure:

 struct Temp { const int a; int b; }

 auto ref foo(Temp* t) { return *t; } //Error


Just about all D type modifier keywords like const, shared, immutable 
and friends are completely broken semantically (i.e. TFBR**) and so 
there is very little hope that there will ever be a fix for these type 
system issue problems.


(** TFBR Totally fucked beyond repair)

Muffin's tip on the programming languages stocks (aka the PLS-2011 
index) is to stay with your current investment in D2 for as long as the 
proprietary digitalmars implementation serves your purpose and to short 
sell otherwise.  This is code for saying that the open source world is 
unlikely to ever provide any alternative to the currently available 
bug-ridden proprietary implementation of D2 which is itself, as a 
language specification, is riddled with bugs.


Unfortunately there is no options market on D stock so that those of you 
that might be thinking of doing a PUT or CALL on D will be as bitterly 
disappointed as others that have tried to measure temperature in a vaccuum.


xxx


Re: " is not mutable" when using ref return type

2011-05-19 Thread Steven Schveighoffer
On Thu, 19 May 2011 00:22:42 -0400, Jonathan M Davis   
wrote:



On 2011-05-18 20:55, %u wrote:

Hi!

Is this a bug, or is it intentional that this fails? I can't come up
with any case where it would cause a problem, but the compiler doesn't
like the fact that there's a const in the structure:

struct Temp { const int a; int b; }

auto ref foo(Temp* t) { return *t; } //Error


As soon as you do *t, you're copying the value.


That's not true, if it's ref, it just copies the reference.

example:

void foo(ref int i) { i = 5; }

void main()
{
   int i;
   int *p = &i;
   foo(*p);
   assert(i == 5);
}

To further drive home the point, this actually compiles:


Temp foo(Temp* t) { return *t; } // no error

There should be no restrictions on returning ref there, no matter what's  
inside Temp.


Definitely a bug with the original, please file with bugzilla.

-Steve


Re: " is not mutable" when using ref return type

2011-05-18 Thread Jonathan M Davis
On 2011-05-18 21:52, Mehrdad wrote:
> On 5/18/2011 9:22 PM, Jonathan M Davis wrote:
> > On 2011-05-18 20:55, %u wrote:
> >> Hi!
> >> 
> >> Is this a bug, or is it intentional that this fails? I can't come up
> >> with any case where it would cause a problem, but the compiler doesn't
> >> 
> >> like the fact that there's a const in the structure:
> >>  struct Temp { const int a; int b; }
> >>  
> >>  auto ref foo(Temp* t) { return *t; } //Error
> > 
> > As soon as you do *t, you're copying the value. As such, I don't know why
> > the ref is working at all. And it's impossible to assign to a struct
> > with a const or immutable member, so the struct is not mutable. Why
> > that's a problem here... My guess would be that it's a bug relating to
> > copying from or assigning to const. If you declare this(this), you'll
> > notice that it doesn't currently work with const, and if declared,
> > this(this) would be called upon copying the struct. Still, something
> > like
> > 
> > auto t = Temp();
> > auto u = t;
> > 
> > works with your definition of Temp, so just copying a non-mutable struct
> > works as long as it doesn't declare this(this). It's probably treating
> > auto ref as if it must be mutable or something like that, and Temp
> > isn't. But I don't know what the problem is exactly.
> > 
> > In any case, I would definitely advise that you _not_ create structs with
> > const or immutable values, because you can never reassign to them, which
> > causes all kinds of fun problems - including making it very hard to use
> > them in arrays (_any_ place that would use Temp.init is stuck with
> > Temp.init). It's generally better to just make the variables private and
> > provide @property functions for getting the variables but not provide
> > any for setting them. That way, they're read-only and you can still
> > re-assign the whole struct if need be.
> > 
> > - Jonathan M davis
> 
> By the way, it doesn't matter if I use auto or not. It does the same
> thing if I say "ref Temp".
> 
> Interesting notes about postblit and everything, I'll keep those in
> mind, thanks!

If I wasn't clear enough, postblit is _supposed_ to work with const but 
currently doesn't. I wasn't saying that it won't ever, just that it's 
currently broken.

http://d.puremagic.com/issues/show_bug.cgi?id=4867

- Jonathan M Davis


Re: " is not mutable" when using ref return type

2011-05-18 Thread Mehrdad

On 5/18/2011 9:22 PM, Jonathan M Davis wrote:

On 2011-05-18 20:55, %u wrote:

Hi!

Is this a bug, or is it intentional that this fails? I can't come up
with any case where it would cause a problem, but the compiler doesn't
like the fact that there's a const in the structure:

 struct Temp { const int a; int b; }

 auto ref foo(Temp* t) { return *t; } //Error

As soon as you do *t, you're copying the value. As such, I don't know why the
ref is working at all. And it's impossible to assign to a struct with a const
or immutable member, so the struct is not mutable. Why that's a problem
here... My guess would be that it's a bug relating to copying from or
assigning to const. If you declare this(this), you'll notice that it doesn't
currently work with const, and if declared, this(this) would be called upon
copying the struct. Still, something like

auto t = Temp();
auto u = t;

works with your definition of Temp, so just copying a non-mutable struct works
as long as it doesn't declare this(this). It's probably treating auto ref as
if it must be mutable or something like that, and Temp isn't. But I don't know
what the problem is exactly.

In any case, I would definitely advise that you _not_ create structs with
const or immutable values, because you can never reassign to them, which
causes all kinds of fun problems - including making it very hard to use them
in arrays (_any_ place that would use Temp.init is stuck with Temp.init). It's
generally better to just make the variables private and provide @property
functions for getting the variables but not provide any for setting them. That
way, they're read-only and you can still re-assign the whole struct if need
be.

- Jonathan M davis


By the way, it doesn't matter if I use auto or not. It does the same 
thing if I say "ref Temp".


Interesting notes about postblit and everything, I'll keep those in 
mind, thanks!


Re: " is not mutable" when using ref return type

2011-05-18 Thread Jonathan M Davis
On 2011-05-18 20:55, %u wrote:
> Hi!
> 
> Is this a bug, or is it intentional that this fails? I can't come up
> with any case where it would cause a problem, but the compiler doesn't
> like the fact that there's a const in the structure:
> 
> struct Temp { const int a; int b; }
> 
> auto ref foo(Temp* t) { return *t; } //Error

As soon as you do *t, you're copying the value. As such, I don't know why the 
ref is working at all. And it's impossible to assign to a struct with a const 
or immutable member, so the struct is not mutable. Why that's a problem 
here... My guess would be that it's a bug relating to copying from or 
assigning to const. If you declare this(this), you'll notice that it doesn't 
currently work with const, and if declared, this(this) would be called upon 
copying the struct. Still, something like

auto t = Temp();
auto u = t;

works with your definition of Temp, so just copying a non-mutable struct works 
as long as it doesn't declare this(this). It's probably treating auto ref as 
if it must be mutable or something like that, and Temp isn't. But I don't know 
what the problem is exactly.

In any case, I would definitely advise that you _not_ create structs with 
const or immutable values, because you can never reassign to them, which 
causes all kinds of fun problems - including making it very hard to use them 
in arrays (_any_ place that would use Temp.init is stuck with Temp.init). It's 
generally better to just make the variables private and provide @property 
functions for getting the variables but not provide any for setting them. That 
way, they're read-only and you can still re-assign the whole struct if need 
be.

- Jonathan M davis


" is not mutable" when using ref return type

2011-05-18 Thread %u
Hi!

Is this a bug, or is it intentional that this fails? I can't come up
with any case where it would cause a problem, but the compiler doesn't
like the fact that there's a const in the structure:

struct Temp { const int a; int b; }

auto ref foo(Temp* t) { return *t; } //Error


Re: Should conversion of mutable return value to immutable allowed?

2011-02-24 Thread Tomek Sowiński
Ali Çehreli napisał:

> Implicit conversions to immutable in the following two functions feel 
> harmless. Has this been discussed before?
> 
> string foo()
> {
>  char[] s;
>  return s; // Error: cannot implicitly convert expression
>//(s) of type char[] to string
> }
> 
> string bar()
> {
>  char[] s;
>  return s ~ s; // Error: cannot implicitly convert expression
>//(s ~ s) of type char[] to string
> }
> 
> Is there a reason why that's not possible? I am sure there must be other 
> cases that at least I would find harmless. :)

Indeed. The returned object can be safely set to stone when its only aliases to 
the outside world point to immutable data. Such a guarantee is expressed in 
today's language by marking the function pure and all its arguments immutable. 
The conversion is currently not allowed as the above virtue of immutably pure 
functions was discovered not too long ago.

If you want it, vote up:
http://d.puremagic.com/issues/show_bug.cgi?id=5081

-- 
Tomek



Re: Should conversion of mutable return value to immutable allowed?

2011-02-24 Thread Jesse Phillips
Also there is std.exception.assumUnique()



Re: Should conversion of mutable return value to immutable allowed?

2011-02-24 Thread Jesse Phillips
Ali Çehreli Wrote:

> I have another question: Does calling .idup copy any data below?
> 
> string foo()
> {
>  char[] s;
>  return s.idup;  // Is the content copied?
> }
> 
> Ali
> 

Yes, dup stands for duplicate and is a property of arrays.

There was discussion for allowing immutable objects to be created and return 
from pure functions.



Re: Should conversion of mutable return value to immutable allowed?

2011-02-24 Thread Simon Buerger

On 24.02.2011 19:08, Ali Çehreli wrote:

Implicit conversions to immutable in the following two functions feel
harmless. Has this been discussed before?

string foo()
{
char[] s;
return s; // Error: cannot implicitly convert expression
// (s) of type char[] to string
}

string bar()
{
char[] s;
return s ~ s; // Error: cannot implicitly convert expression
// (s ~ s) of type char[] to string
}

Is there a reason why that's not possible? I am sure there must be
other cases that at least I would find harmless. :)

Ali


Currently, the correct way to do it is to use the phobos function 
assumeUnique, like:


string bar()
{
char[] s;
return assumeUnique(s);
}

Note that this does only little more than casting to immutable, so you 
have to ensure there is no mutable reference left behind.


Anyway, it might be nice if the compiler could detect some trivial 
cases and insert the cast appropriately. But on the other hand, the 
compiler will never to be able to auto-detect all cases, and so its 
cleaner to use assumeUnique explicitly.


- Krox


Re: Should conversion of mutable return value to immutable allowed?

2011-02-24 Thread Ali Çehreli

On 02/24/2011 10:28 AM, spir wrote:
> On 02/24/2011 07:08 PM, Ali Çehreli wrote:
>> Implicit conversions to immutable in the following two functions feel
>> harmless.
>> Has this been discussed before?
>>
>> string foo()
>> {
>> char[] s;
>> return s; // Error: cannot implicitly convert expression
>> // (s) of type char[] to string
>> }
>>
>> string bar()
>> {
>> char[] s;
>> return s ~ s; // Error: cannot implicitly convert expression
>> // (s ~ s) of type char[] to string
>> }
>>
>> Is there a reason why that's not possible? I am sure there must be
>> other cases
>> that at least I would find harmless. :)
>>
>> Ali
>
> I'm all for that. Can hardly how auto conversion in the sense mutable
> --> immutable could be harmful, but may miss a meaningful point.

It shouldn't be allowed if a reference to that char[] is left behind. 
Otherwise although the receiver would think that the data wouldn't 
change; it could be changed by that other reference.


struct S
{
char[] s;

string foo()
{
return s;// <-- Must not be allowed
}
}

But when the object in question is about to go out of scope? I don't 
know. On the other hand, reducing some implicit behavior is also good.


> This
> would esp be nice for strings, since we regularly need to use char
> arrays to construct textual content.
>
> Denis

I have another question: Does calling .idup copy any data below?

string foo()
{
char[] s;
return s.idup;  // Is the content copied?
}

Ali



Re: Should conversion of mutable return value to immutable allowed?

2011-02-24 Thread spir

On 02/24/2011 07:08 PM, Ali Çehreli wrote:

Implicit conversions to immutable in the following two functions feel harmless.
Has this been discussed before?

string foo()
{
char[] s;
return s; // Error: cannot implicitly convert expression
// (s) of type char[] to string
}

string bar()
{
char[] s;
return s ~ s; // Error: cannot implicitly convert expression
// (s ~ s) of type char[] to string
}

Is there a reason why that's not possible? I am sure there must be other cases
that at least I would find harmless. :)

Ali


I'm all for that. Can hardly how auto conversion in the sense mutable --> 
immutable could be harmful, but may miss a meaningful point. This would esp be 
nice for strings, since we regularly need to use char arrays to construct 
textual content.


Denis
--
_
vita es estrany
spir.wikidot.com



Should conversion of mutable return value to immutable allowed?

2011-02-24 Thread Ali Çehreli
Implicit conversions to immutable in the following two functions feel 
harmless. Has this been discussed before?


string foo()
{
char[] s;
return s; // Error: cannot implicitly convert expression
  //(s) of type char[] to string
}

string bar()
{
char[] s;
return s ~ s; // Error: cannot implicitly convert expression
  //(s ~ s) of type char[] to string
}

Is there a reason why that's not possible? I am sure there must be other 
cases that at least I would find harmless. :)


Ali


Re: Logical Const using a Mutable template

2010-11-30 Thread Jesse Phillips
Jesse Phillips Wrote:

> The rules for this are:
> 
> * Only mutable data can be assigned to a Mutable
> * Modification of referenced fields can be modified (inner class fields, 
> pointer targets)
> 
> I'll be back to finish this in a bit.

* Value types can be modified if the encapsulating class
  is not declared const/immutable

And I have come up with 2 major concerns related to immutable classes. Would an 
inner class be placed in read-only memory  in instantiating an immutable class:

class A {
Mutable!(Inner) innerclass;
this() { innerclass = new Inner; } // Is innerclass placed in read-only 
memory
}

new immutable(A);

And what about when an immutable instance is passed to a thread or network. 
Would the innerclass be placed in read-only memory for the new thread/machine.

And looking over it again, I found that I wasn't using the opAssign const 
functions, they didn't meet the requirements. So I think a working alias this 
would allow the template to be: (The important check being that Mutables are 
unqualified)

struct Mutable( T ) if ( is( T : Unqual!T ) ) {
 private T _payload;

 this( T t ) {
 _payload = t;
 }

 @trusted @property ref T get( )( ) const {
 T* p = cast( T* )&_payload;
 return *p;
 }
 alias get this;
}

https://gist.github.com/721066


Re: Logical Const using a Mutable template

2010-11-30 Thread Jesse Phillips
Max Samukha Wrote:

> On 11/30/2010 09:30 AM, Jesse Phillips wrote:
> > This came up in discussion and I think the behavior is safe and usable when 
> > wanting to change class data in a const function.
> >
> > http://article.gmane.org/gmane.comp.lang.d.general/43476
> >
> > One limitation is that value types declared as Mutable (Mutable!(int)) can 
> > not be changed if the encapsulating class is declared immutable. For this 
> > reason a Mutable value can not be changed inside a const function. I think 
> > this is acceptable.
> >
> > Another limitation appears to be an issue with alias this. It is commented 
> > as a //FIXME in the code.
> >
> > https://gist.github.com/721066
> 
> It is not enough to forward opAssign and opEquals. Any operator should 
> be handled. For example, change the implementation of A.foo to
> 
> n2 += 1;
> 
> and you will get a segfault during compilation.
> 
> You could add more kludge with operator overloads but I don't think it 
> is worth the effort. It makes more sense to wait until "alias this" bugs 
> are fixed. On the other hand, we may wait forever since the way "alias 
> this" should handle operators has never been specified.
> 

The intent isn't to work around alias this bugs. It is to provide mutation in a 
const function, but with the guarantee that it will not result in undefined 
behavior. (I should have stated that first, but it was getting late). 
Concurrency shouldn't be any different from having a reference in a class you 
are sharing. Sharing immutable objects should be fine as they still can not 
have their state changed.

The rules for this are:

* Only mutable data can be assigned to a Mutable
* Modification of referenced fields can be modified (inner class fields, 
pointer targets)

I'll be back to finish this in a bit.


Re: Logical Const using a Mutable template

2010-11-30 Thread Max Samukha

On 11/30/2010 09:30 AM, Jesse Phillips wrote:

This came up in discussion and I think the behavior is safe and usable when 
wanting to change class data in a const function.

http://article.gmane.org/gmane.comp.lang.d.general/43476

One limitation is that value types declared as Mutable (Mutable!(int)) can not 
be changed if the encapsulating class is declared immutable. For this reason a 
Mutable value can not be changed inside a const function. I think this is 
acceptable.

Another limitation appears to be an issue with alias this. It is commented as a 
//FIXME in the code.

https://gist.github.com/721066

An example usage looks like:

 class Inner { int n; }

 class A {
 Mutable!(int*) n;
 Mutable!(int)  n2;
 Mutable!(Inner) innerClass;
 this() { n = new int; innerClass = new Inner; }

 void foo( int num ) {
 n2 = num;
 }

 void bar( int num ) const {
 innerClass.n = num;
 }
 }

 auto aImmu = new immutable(A);
 auto aMu   = new A;
 int i = 8;

 *aImmu.n = i,
 aImmu.bar(6),
 *aMu.n = i,
 aMu.n =&i,
 aMu.n2 = i,
 aMu.bar(6),
 aMu.foo(6),



It is not enough to forward opAssign and opEquals. Any operator should 
be handled. For example, change the implementation of A.foo to


n2 += 1;

and you will get a segfault during compilation.

You could add more kludge with operator overloads but I don't think it 
is worth the effort. It makes more sense to wait until "alias this" bugs 
are fixed. On the other hand, we may wait forever since the way "alias 
this" should handle operators has never been specified.




Logical Const using a Mutable template

2010-11-29 Thread Jesse Phillips
This came up in discussion and I think the behavior is safe and usable when 
wanting to change class data in a const function.

http://article.gmane.org/gmane.comp.lang.d.general/43476

One limitation is that value types declared as Mutable (Mutable!(int)) can not 
be changed if the encapsulating class is declared immutable. For this reason a 
Mutable value can not be changed inside a const function. I think this is 
acceptable.

Another limitation appears to be an issue with alias this. It is commented as a 
//FIXME in the code.

https://gist.github.com/721066

An example usage looks like:

class Inner { int n; }

class A {
Mutable!(int*) n;
Mutable!(int)  n2;
Mutable!(Inner) innerClass;
this() { n = new int; innerClass = new Inner; }

void foo( int num ) {
n2 = num;
}

void bar( int num ) const {
innerClass.n = num;
}
}

auto aImmu = new immutable(A);
auto aMu   = new A;
int i = 8;

*aImmu.n = i,
aImmu.bar(6),
*aMu.n = i,
aMu.n = &i,
aMu.n2 = i,
aMu.bar(6),
aMu.foo(6),



Re: main.d(61): Error: temp_[i_] isn't mutable

2010-06-21 Thread Andrei Alexandrescu

On 06/21/2010 03:37 AM, Ben Hanson wrote:

I'm currently using strings for the regex strings themselves. In lexertl, I use
templated free functions what work with iterators, which means input can come
from different sources. This sounds like the kind of thing you are talking
about?

Regards,

Ben


Sounds about right!

Andrei


Re: main.d(61): Error: temp_[i_] isn't mutable

2010-06-21 Thread Ben Hanson
Hi Andrei,

== Quote from Andrei Alexandrescu (seewebsiteforem...@erdani.org)'s article
> On 06/20/2010 12:56 PM, Ali Çehreli wrote:
> > Ben Hanson wrote:
> >> == Quote from Justin Spahr-Summers (justin.spahrsumm...@gmail.com)'s
> >>> "string" is actually an alias for "immutable(char)[]" (and
> >> similarly for
> >>> the other string types), so its contents are not modifiable, though
> >> its
> >>> length can be adjusted and contents appended. If you need to be
> >> able to
> >>> modify the characters, just use char[] instead. You can then use the
> >>> .idup property to get a string afterward.
> >>
> >> I'm converted temp_ to CharT[] as suggested, but the conversion back
> >> to a string is failing:
> >>
> >> _charset = temp_.idup;
> >>
> >> main.d(76): Error: cannot implicitly convert expression (_adDupT((&
> >> D58TypeInfo_AT4main14__T5regexTAyaZ18basic_string_token5CharT6__initZ),cast
> >>
> >> (string)temp_)) of type immutable(CharT)[] to string
> >
> >
> > Would it work for you if the regex template took the character type
> > instead of the string type?
> >
> > The relevant lines:
> >
> > template regex(CharT)
> > {
> > // ...
> > alias CharT[] StringT;
> > StringT _charset;
> > enum size_t MAX_CHARS = CharT.max + 1;
> > // ...
> > _charset = squeeze(_charset.idup).dup;
> >
> > And then, in main:
> >
> > regex!(char).basic_string_token token_;
> >
> > Ali
> IMHO it's more general if the regexp took the string type as a
> parameter. This is because later that is easier generalizable to
> accepting a range that's different from an array.
> My dream: to have a compile-time-generated regex engine that can operate
> on any input stream.
> Andrei

I'm currently using strings for the regex strings themselves. In lexertl, I use
templated free functions what work with iterators, which means input can come
from different sources. This sounds like the kind of thing you are talking
about?

Regards,

Ben


Re: main.d(61): Error: temp_[i_] isn't mutable

2010-06-20 Thread Andrei Alexandrescu

On 06/20/2010 02:29 PM, Ali Çehreli wrote:

Andrei Alexandrescu wrote:

 > IMHO it's more general if the regexp took the string type as a
 > parameter. This is because later that is easier generalizable to
 > accepting a range that's different from an array.

Agreed.

Given T which may be an immutable type, what is the cleanest way of
creating a mutable copy of that type? typeof(array.dup) works on arrays
but what if T is a value type or any type where .dup doesn't exist?

Ali


std.conv.to should work with most sensible combinations.

Andrei


Re: main.d(61): Error: temp_[i_] isn't mutable

2010-06-20 Thread Ali Çehreli

Andrei Alexandrescu wrote:

> IMHO it's more general if the regexp took the string type as a
> parameter. This is because later that is easier generalizable to
> accepting a range that's different from an array.

Agreed.

Given T which may be an immutable type, what is the cleanest way of 
creating a mutable copy of that type? typeof(array.dup) works on arrays 
but what if T is a value type or any type where .dup doesn't exist?


Ali


Re: main.d(61): Error: temp_[i_] isn't mutable

2010-06-20 Thread Andrei Alexandrescu

On 06/20/2010 07:01 AM, Ben Hanson wrote:

== Quote from Justin Spahr-Summers (justin.spahrsumm...@gmail.com)'s

"string" is actually an alias for "immutable(char)[]" (and

similarly for

the other string types), so its contents are not modifiable, though

its

length can be adjusted and contents appended. If you need to be

able to

modify the characters, just use char[] instead. You can then use the
.idup property to get a string afterward.


I'm converted temp_ to CharT[] as suggested, but the conversion back
to a string is failing:

_charset = temp_.idup;

main.d(76): Error: cannot implicitly convert expression (_adDupT((&
D58TypeInfo_AT4main14__T5regexTAyaZ18basic_string_token5CharT6__initZ),cast
(string)temp_)) of type immutable(CharT)[] to string


import std.conv;
...
_charset = to!(typeof(_charset))(temp_);

"to" converts strings of any width and mutability to strings of any 
width and mutability.



Andrei


Re: main.d(61): Error: temp_[i_] isn't mutable

2010-06-20 Thread Justin Spahr-Summers
On Sun, 20 Jun 2010 12:01:31 + (UTC), Ben Hanson 
 wrote:
> 
> == Quote from Justin Spahr-Summers (justin.spahrsumm...@gmail.com)'s
> > "string" is actually an alias for "immutable(char)[]" (and
> similarly for
> > the other string types), so its contents are not modifiable, though
> its
> > length can be adjusted and contents appended. If you need to be
> able to
> > modify the characters, just use char[] instead. You can then use the
> > .idup property to get a string afterward.
> 
> I'm converted temp_ to CharT[] as suggested, but the conversion back
> to a string is failing:
> 
> _charset = temp_.idup;
> 
> main.d(76): Error: cannot implicitly convert expression (_adDupT((&
> D58TypeInfo_AT4main14__T5regexTAyaZ18basic_string_token5CharT6__initZ),cast
> (string)temp_)) of type immutable(CharT)[] to string

Sorry I missed this on the first run through. Since you're using typedef 
to create your CharT type, it will create a type independent from all 
the others, meaning no implicit casts to or from it. "alias" is the 
equivalent to a C/C++ "typedef", and that should fix the compilation 
error.


Re: main.d(61): Error: temp_[i_] isn't mutable

2010-06-20 Thread Andrei Alexandrescu

On 06/20/2010 12:56 PM, Ali Çehreli wrote:

Ben Hanson wrote:

== Quote from Justin Spahr-Summers (justin.spahrsumm...@gmail.com)'s

"string" is actually an alias for "immutable(char)[]" (and

similarly for

the other string types), so its contents are not modifiable, though

its

length can be adjusted and contents appended. If you need to be

able to

modify the characters, just use char[] instead. You can then use the
.idup property to get a string afterward.


I'm converted temp_ to CharT[] as suggested, but the conversion back
to a string is failing:

_charset = temp_.idup;

main.d(76): Error: cannot implicitly convert expression (_adDupT((&
D58TypeInfo_AT4main14__T5regexTAyaZ18basic_string_token5CharT6__initZ),cast

(string)temp_)) of type immutable(CharT)[] to string



Would it work for you if the regex template took the character type
instead of the string type?

The relevant lines:

template regex(CharT)
{
// ...
alias CharT[] StringT;
StringT _charset;
enum size_t MAX_CHARS = CharT.max + 1;
// ...
_charset = squeeze(_charset.idup).dup;

And then, in main:

regex!(char).basic_string_token token_;

Ali


IMHO it's more general if the regexp took the string type as a 
parameter. This is because later that is easier generalizable to 
accepting a range that's different from an array.


My dream: to have a compile-time-generated regex engine that can operate 
on any input stream.



Andrei


  1   2   >