www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Extended Type Design.

reply Reiner Pope <no spam.com> writes:
Andrei Alexandrescu (See Website For Email) Wrote:

 
 We have talked about a design. In short, the intent is to define three 
 flavors of immutability:
 
 a) final - a simple storage class controlling the immutability of the 
 bits allocated for the symbol per se;
 
 b) const - type qualifier meaning an immutable view of an otherwise 
 modifiable data. const does not control the bits of the object, only the 
 storage addressed indirectly by it (transitively);
 
 c) "superconst" - denoted as "const!" or "super const": type qualifier 
 meaning that the data is genuinely unmodifiable.
 

It seems like you could get this quite easily by adding just one more parameter modifier (is this a storage class? I'm not sure) to denote, "any time this function is called, this parameter must be known at compile-time". Effectively, it would just be a conversion from this: RegExpMatch match(static const char[] pattern, char[] text) {...} ... main() { match("gr[ae]y", din.read()); } to this: RegExpMatch match(char[] pattern)(char[] text) {...} ... main() { match!("gr[ae]y")(din.read()); } Any plans this way? Cheers, Reiner
Mar 16 2007
parent reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Reiner Pope wrote:
 Andrei Alexandrescu (See Website For Email) Wrote:
 
 We have talked about a design. In short, the intent is to define three 
 flavors of immutability:

 a) final - a simple storage class controlling the immutability of the 
 bits allocated for the symbol per se;

 b) const - type qualifier meaning an immutable view of an otherwise 
 modifiable data. const does not control the bits of the object, only the 
 storage addressed indirectly by it (transitively);

 c) "superconst" - denoted as "const!" or "super const": type qualifier 
 meaning that the data is genuinely unmodifiable.


I understand this is high on Walter's list. The syntax discussed is: // dispatched when the pattern is known at compile time RegExpMatch match(const char[] p)(const char[] p, char[] text) {...} // dispatched when the pattern is a runtime string RegExpMatch match()(const char[] p, char[] text) {...}
 It seems like you could get this quite easily by adding just one more
parameter modifier (is this a storage class? I'm not sure) to denote, "any time
this function is called, this parameter must be known at compile-time".
Effectively, it would just be a conversion from this:
 
 RegExpMatch match(static const char[] pattern, char[] text) {...}
 ...
 main()
 {
      match("gr[ae]y", din.read());
 }
 
 to this:
 
 RegExpMatch match(char[] pattern)(char[] text) {...}
 ...
 main()
 {
      match!("gr[ae]y")(din.read());
 }
 
 Any plans this way?

The above forces only compile-time constant regexps. What we need is to dispatch depending on compile-time constant vs. run-time string. Combined with macros, this will essentially allow a call to writefln to morph, depending on its arguments, into putch(), fputs(), write(), fprintf() - or execute today's dynamically-checked writefln. Andrei
Mar 16 2007
next sibling parent reply Reiner Pope <reiner none.com> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 Reiner Pope wrote:
 Andrei Alexandrescu (See Website For Email) Wrote:

 We have talked about a design. In short, the intent is to define 
 three flavors of immutability:

 a) final - a simple storage class controlling the immutability of the 
 bits allocated for the symbol per se;

 b) const - type qualifier meaning an immutable view of an otherwise 
 modifiable data. const does not control the bits of the object, only 
 the storage addressed indirectly by it (transitively);

 c) "superconst" - denoted as "const!" or "super const": type 
 qualifier meaning that the data is genuinely unmodifiable.

sort that you need for 'static if', etc) ? You spoke a while ago about improving compile-time evaluation syntax so that there would be no difference at the call site between runtime and compile-time evaluation (like for regexps).

I understand this is high on Walter's list.

The syntax discussed is:
 
 // dispatched when the pattern is known at compile time
 RegExpMatch match(const char[] p)(const char[] p, char[] text) {...}
 // dispatched when the pattern is a runtime string
 RegExpMatch match()(const char[] p, char[] text) {...}

of p in the first instance?" and also, "why does the second instance of match even need to be a template?".
 
 It seems like you could get this quite easily by adding just one more 
 parameter modifier (is this a storage class? I'm not sure) to denote, 
 "any time this function is called, this parameter must be known at 
 compile-time". Effectively, it would just be a conversion from this:

 RegExpMatch match(static const char[] pattern, char[] text) {...}
 ...
 main()
 {
      match("gr[ae]y", din.read());
 }

 to this:

 RegExpMatch match(char[] pattern)(char[] text) {...}
 ...
 main()
 {
      match!("gr[ae]y")(din.read());
 }

 Any plans this way?

The above forces only compile-time constant regexps. What we need is to dispatch depending on compile-time constant vs. run-time string.

allow for overloading by compile-time-constness (with a preference to the compile-time version when there's a choice). So that you could write: RegExpMatch match(static const char[] pattern, char[] text){...} RegExpMatch match(char[] pattern, char[] text) {...}
 
 Combined with macros, this will essentially allow a call to writefln to 
 morph, depending on its arguments, into putch(), fputs(), write(), 
 fprintf() - or execute today's dynamically-checked writefln.

True. I was also interested in another use of this, though: allowing a library-time implementation of tuples (since what kind of feature is one that can't be implemented in the library?). There are basically two reasons that this can't be done at the moment: alias Tuple!(int, double) myTuple; myTuple[0] = 5; // First reason foreach (val; myTuple) // Second reason { writef(val); } I would imagine that you could implement the first feature as: struct MyTupleImpl(TypeList...) { ... TypeList[i] opIndex(static const int i) {...} // We grab the return type based on the parameter, so we must know it at compile time. It makes no sense to have a runtime version of this. } and at a stretch, you could imagine the second feature as working in a similar way: your compile-time representation of the foreach delegate is either a char[] to be mixed in, or an expression alias, when we get that: struct MyTupleImpl(TypeList...) { int opApply(static const char[] code) { // iterate through tuple; this iteration would actually have to be generated with CTFE, but you get the idea { TypeList[i] __special_foreach_key = whatever; mixin(code); } } } Cheers, Reiner
Mar 16 2007
parent reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Reiner Pope wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 Reiner Pope wrote:
 Andrei Alexandrescu (See Website For Email) Wrote:

 We have talked about a design. In short, the intent is to define 
 three flavors of immutability:

 a) final - a simple storage class controlling the immutability of 
 the bits allocated for the symbol per se;

 b) const - type qualifier meaning an immutable view of an otherwise 
 modifiable data. const does not control the bits of the object, only 
 the storage addressed indirectly by it (transitively);

 c) "superconst" - denoted as "const!" or "super const": type 
 qualifier meaning that the data is genuinely unmodifiable.

(the sort that you need for 'static if', etc) ? You spoke a while ago about improving compile-time evaluation syntax so that there would be no difference at the call site between runtime and compile-time evaluation (like for regexps).

I understand this is high on Walter's list.

The syntax discussed is:
 // dispatched when the pattern is known at compile time
 RegExpMatch match(const char[] p)(const char[] p, char[] text) {...}
 // dispatched when the pattern is a runtime string
 RegExpMatch match()(const char[] p, char[] text) {...}

of p in the first instance?" and also, "why does the second instance of match even need to be a template?".

Good question. It must be a template by the pigeonhole principle: each compile-time regex generates in theory different code, so you must have as many distinct functions as strings.
 It seems like you could get this quite easily by adding just one more 
 parameter modifier (is this a storage class? I'm not sure) to denote, 
 "any time this function is called, this parameter must be known at 
 compile-time". Effectively, it would just be a conversion from this:

 RegExpMatch match(static const char[] pattern, char[] text) {...}
 ...
 main()
 {
      match("gr[ae]y", din.read());
 }

 to this:

 RegExpMatch match(char[] pattern)(char[] text) {...}
 ...
 main()
 {
      match!("gr[ae]y")(din.read());
 }

 Any plans this way?

The above forces only compile-time constant regexps. What we need is to dispatch depending on compile-time constant vs. run-time string.

allow for overloading by compile-time-constness (with a preference to the compile-time version when there's a choice). So that you could write: RegExpMatch match(static const char[] pattern, char[] text){...} RegExpMatch match(char[] pattern, char[] text) {...}
 Combined with macros, this will essentially allow a call to writefln 
 to morph, depending on its arguments, into putch(), fputs(), write(), 
 fprintf() - or execute today's dynamically-checked writefln.

True. I was also interested in another use of this, though: allowing a library-time implementation of tuples (since what kind of feature is one that can't be implemented in the library?). There are basically two reasons that this can't be done at the moment: alias Tuple!(int, double) myTuple; myTuple[0] = 5; // First reason foreach (val; myTuple) // Second reason { writef(val); } I would imagine that you could implement the first feature as: struct MyTupleImpl(TypeList...) { ... TypeList[i] opIndex(static const int i) {...} // We grab the return type based on the parameter, so we must know it at compile time. It makes no sense to have a runtime version of this. } and at a stretch, you could imagine the second feature as working in a similar way: your compile-time representation of the foreach delegate is either a char[] to be mixed in, or an expression alias, when we get that: struct MyTupleImpl(TypeList...) { int opApply(static const char[] code) { // iterate through tuple; this iteration would actually have to be generated with CTFE, but you get the idea { TypeList[i] __special_foreach_key = whatever; mixin(code); } } }

That's not on the list yet. One thing at a time :o). Andrei
Mar 17 2007
parent Reiner Pope <reiner none.com> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 Reiner Pope wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 Reiner Pope wrote:
 Andrei Alexandrescu (See Website For Email) Wrote:

 We have talked about a design. In short, the intent is to define 
 three flavors of immutability:

 a) final - a simple storage class controlling the immutability of 
 the bits allocated for the symbol per se;

 b) const - type qualifier meaning an immutable view of an otherwise 
 modifiable data. const does not control the bits of the object, 
 only the storage addressed indirectly by it (transitively);

 c) "superconst" - denoted as "const!" or "super const": type 
 qualifier meaning that the data is genuinely unmodifiable.

(the sort that you need for 'static if', etc) ? You spoke a while ago about improving compile-time evaluation syntax so that there would be no difference at the call site between runtime and compile-time evaluation (like for regexps).

I understand this is high on Walter's list.

The syntax discussed is:
 // dispatched when the pattern is known at compile time
 RegExpMatch match(const char[] p)(const char[] p, char[] text) {...}
 // dispatched when the pattern is a runtime string
 RegExpMatch match()(const char[] p, char[] text) {...}

double-declaration of p in the first instance?" and also, "why does the second instance of match even need to be a template?".

Good question. It must be a template by the pigeonhole principle: each compile-time regex generates in theory different code, so you must have as many distinct functions as strings.

But how about the runtime implementation of match()? There's no code generation there...
 
 That's not on the list yet. One thing at a time :o).

that I can't help wanting more :o). Cheers, Reiner
Mar 17 2007
prev sibling parent Reiner Pope <reiner none.com> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 Combined with macros, this will essentially allow a call to writefln to 
 morph, depending on its arguments, into putch(), fputs(), write(), 
 fprintf() - or execute today's dynamically-checked writefln.

definition site that the function (or template) produces a compile-time string which is to be mixed into the call site. eg: // The 'mixin' specifies that the result should be mixed into the call site. mixin char[] writefln(/*params*/) { ... // Generate code return generatedCode; } Sounds good. Reiner
Mar 17 2007