www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - need clarification: will typedef, C struct initialization, etc. go or not?

reply Trass3r <un known.com> writes:
There have been lots of discussions about removing language parts.
I don't want this thread to become yet another one.
I just want to know if (and when) these features will be removed or not.

Especially typedef, which I found quite useful lately.
C-style struct initialization and complex types have also been discussed but are
still in.
May 17 2010
next sibling parent reply Kagamin <spam here.lot> writes:
And this should go into docs.
May 17 2010
parent Trass3r <un known.com> writes:
 And this should go into docs.

True.
May 18 2010
prev sibling next sibling parent reply Trass3r <un known.com> writes:
 I just want to know if (and when) these features will be removed or not.

 Especially typedef, which I found quite useful lately.
 C-style struct initialization and complex types have also been discussed  
 but are still in.

Nobody got an answer?
May 31 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Trass3r:
 Nobody got an answer?

My opinion: - complex types will be removed. And as far as I know complex number literals too will be removed from D (this is less nice). - I am not sure regarding C-style struct initializations. They are useful to save some typing if you have to for example to put a long array of struct literals in your source code. I presume they will be removed. - Typedef has some limitations, but I think it will be kept because it is useful. Bye, bearophile
May 31 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/31/2010 02:14 PM, bearophile wrote:
 Trass3r:
 Nobody got an answer?

My opinion: - complex types will be removed. And as far as I know complex number literals too will be removed from D (this is less nice). - I am not sure regarding C-style struct initializations. They are useful to save some typing if you have to for example to put a long array of struct literals in your source code. I presume they will be removed. - Typedef has some limitations, but I think it will be kept because it is useful.

typedef is gone. Andrei
May 31 2010
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 typedef is gone.

*mewls* I have shown here some examples of typedef usage, and I'll keep posting few more in future. I'd like to pull it back from the grave and keep it :-) Bye, bearophile
May 31 2010
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/31/2010 03:54 PM, bearophile wrote:
 Andrei Alexandrescu:
 typedef is gone.

*mewls* I have shown here some examples of typedef usage, and I'll keep posting few more in future. I'd like to pull it back from the grave and keep it :-)

It's wasted time. typedef is gone. Andrei
May 31 2010
parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
On 1-6-2010 5:38, Andrei Alexandrescu wrote:
 On 05/31/2010 03:54 PM, bearophile wrote:
 Andrei Alexandrescu:
 typedef is gone.

*mewls* I have shown here some examples of typedef usage, and I'll keep posting few more in future. I'd like to pull it back from the grave and keep it :-)

It's wasted time. typedef is gone. Andrei

:(( I also miss typedef. I thought D had a great opportunity to fix it. Take something like the Windows headers. It mostly consists of typedefs for handles and whatnot. Without typedef you'd have to use alias and type safety is out of the windows. So what would be the way to translate those Windows headers? Create a unique struct for each old typedef? With alias this, and a ctor? Well, if that's the way to do it now, why not make typedef a shortcut for exactly that!? IIRC typedef is gone because you and Walter could not agree whether it had to be a subtype or a supertype of the typedef'ed type. For me it's rather simple: I want to introduce a new type in such a way that it helps me prevent mistakes, ie. passing one handle when the function wants another, even though both are based on void*, or whatever. Bring typedef back! L.
May 31 2010
next sibling parent reply Justin Spahr-Summers <Justin.SpahrSummers gmail.com> writes:
On Tue, 01 Jun 2010 06:05:50 +0800, Lionello Lunesu 
<lio lunesu.remove.com> wrote:
 
 On 1-6-2010 5:38, Andrei Alexandrescu wrote:
 On 05/31/2010 03:54 PM, bearophile wrote:
 Andrei Alexandrescu:
 typedef is gone.

*mewls* I have shown here some examples of typedef usage, and I'll keep posting few more in future. I'd like to pull it back from the grave and keep it :-)

It's wasted time. typedef is gone. Andrei

:(( I also miss typedef. I thought D had a great opportunity to fix it. Take something like the Windows headers. It mostly consists of typedefs for handles and whatnot. Without typedef you'd have to use alias and type safety is out of the windows. So what would be the way to translate those Windows headers? Create a unique struct for each old typedef? With alias this, and a ctor? Well, if that's the way to do it now, why not make typedef a shortcut for exactly that!?

I'm a fan of typedef, personally, but the example you mentioned *would* be solved using just an alias. 'alias' provides the same functionality as C/C++'s 'typedef' and more.
May 31 2010
parent reply Justin Spahr-Summers <Justin.SpahrSummers gmail.com> writes:
On Mon, 31 May 2010 23:31:18 -0300, Leandro Lucarella <llucax gmail.com> 
wrote:
 
 Justin Spahr-Summers, el 31 de mayo a las 16:41 me escribiste:
 On Tue, 01 Jun 2010 06:05:50 +0800, Lionello Lunesu 
 <lio lunesu.remove.com> wrote:
 
 On 1-6-2010 5:38, Andrei Alexandrescu wrote:
 On 05/31/2010 03:54 PM, bearophile wrote:
 Andrei Alexandrescu:
 typedef is gone.

*mewls* I have shown here some examples of typedef usage, and I'll keep posting few more in future. I'd like to pull it back from the grave and keep it :-)

It's wasted time. typedef is gone. Andrei

:(( I also miss typedef. I thought D had a great opportunity to fix it. Take something like the Windows headers. It mostly consists of typedefs for handles and whatnot. Without typedef you'd have to use alias and type safety is out of the windows. So what would be the way to translate those Windows headers? Create a unique struct for each old typedef? With alias this, and a ctor? Well, if that's the way to do it now, why not make typedef a shortcut for exactly that!?

I'm a fan of typedef, personally, but the example you mentioned *would* be solved using just an alias. 'alias' provides the same functionality as C/C++'s 'typedef' and more.

I think he talks about this difference: alias int a1; alias int a2; typedef int t1; typedef int t2; void fa(a2 a) {} void ft(t2 t) {} void main() { a1 a = 5; fa(a); // <--- compiles fine t1 t = 10; ft(t); // <--- error

Understood, but he mentioned translating C headers. D's 'typedef' has no ready equivalent in C or C++.
May 31 2010
parent Lionello Lunesu <lio lunesu.remove.com> writes:
On 1-6-2010 12:05, Justin Spahr-Summers wrote:
 On Mon, 31 May 2010 23:31:18 -0300, Leandro Lucarella <llucax gmail.com> 
 wrote:
 Justin Spahr-Summers, el 31 de mayo a las 16:41 me escribiste:
 On Tue, 01 Jun 2010 06:05:50 +0800, Lionello Lunesu 
 <lio lunesu.remove.com> wrote:
 On 1-6-2010 5:38, Andrei Alexandrescu wrote:
 On 05/31/2010 03:54 PM, bearophile wrote:
 Andrei Alexandrescu:
 typedef is gone.

*mewls* I have shown here some examples of typedef usage, and I'll keep posting few more in future. I'd like to pull it back from the grave and keep it :-)

It's wasted time. typedef is gone. Andrei

:(( I also miss typedef. I thought D had a great opportunity to fix it. Take something like the Windows headers. It mostly consists of typedefs for handles and whatnot. Without typedef you'd have to use alias and type safety is out of the windows. So what would be the way to translate those Windows headers? Create a unique struct for each old typedef? With alias this, and a ctor? Well, if that's the way to do it now, why not make typedef a shortcut for exactly that!?

I'm a fan of typedef, personally, but the example you mentioned *would* be solved using just an alias. 'alias' provides the same functionality as C/C++'s 'typedef' and more.

I think he talks about this difference: alias int a1; alias int a2; typedef int t1; typedef int t2; void fa(a2 a) {} void ft(t2 t) {} void main() { a1 a = 5; fa(a); // <--- compiles fine t1 t = 10; ft(t); // <--- error

Understood, but he mentioned translating C headers. D's 'typedef' has no ready equivalent in C or C++.

Where does it say that translated headers cannot be better than the original? :) L.
Jun 01 2010
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/31/2010 10:07 PM, Simen kjaeraas wrote:
 Lionello Lunesu <lio lunesu.remove.com> wrote:

 I also miss typedef. I thought D had a great opportunity to fix it.

 Take something like the Windows headers. It mostly consists of typedefs
 for handles and whatnot. Without typedef you'd have to use alias and
 type safety is out of the windows.

 So what would be the way to translate those Windows headers? Create a
 unique struct for each old typedef? With alias this, and a ctor? Well,
 if that's the way to do it now, why not make typedef a shortcut for
 exactly that!?

 IIRC typedef is gone because you and Walter could not agree whether it
 had to be a subtype or a supertype of the typedef'ed type. For me it's
 rather simple: I want to introduce a new type in such a way that it
 helps me prevent mistakes, ie. passing one handle when the function
 wants another, even though both are based on void*, or whatever.

 Bring typedef back!

struct Typedef( T ) { T payload; alias payload this; } alias Typedef!int myInt; There you go.

Yah, perfect - that would be the subtype. I think we should work on adding a pseudo-supertype as well, and also on a completely independent type. Then we can add these abstractions to std.typecons. Andrei
May 31 2010
next sibling parent Lionello Lunesu <lio lunesu.remove.com> writes:
On 1-6-2010 11:37, Andrei Alexandrescu wrote:
 On 05/31/2010 10:07 PM, Simen kjaeraas wrote:
 Lionello Lunesu <lio lunesu.remove.com> wrote:

 I also miss typedef. I thought D had a great opportunity to fix it.

 Take something like the Windows headers. It mostly consists of typedefs
 for handles and whatnot. Without typedef you'd have to use alias and
 type safety is out of the windows.

 So what would be the way to translate those Windows headers? Create a
 unique struct for each old typedef? With alias this, and a ctor? Well,
 if that's the way to do it now, why not make typedef a shortcut for
 exactly that!?

 IIRC typedef is gone because you and Walter could not agree whether it
 had to be a subtype or a supertype of the typedef'ed type. For me it's
 rather simple: I want to introduce a new type in such a way that it
 helps me prevent mistakes, ie. passing one handle when the function
 wants another, even though both are based on void*, or whatever.

 Bring typedef back!

struct Typedef( T ) { T payload; alias payload this; } alias Typedef!int myInt; There you go.

Yah, perfect - that would be the subtype. I think we should work on adding a pseudo-supertype as well, and also on a completely independent type. Then we can add these abstractions to std.typecons. Andrei

Super/sub is of minor importance. What's important is that siblings are incompatible. That's impossible now with alias and Simen's TypeDef doesn't solve it either. Typedef was the perfect candidate for it. That, and the custom .init! :o) L.
Jun 01 2010
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Simen kjaeraas:
 My code sidesteps that by including instantiation line and file,
 making each instantiation unique (as long as you don't do
 multiple typedefs on one line).

Cute :-) We can also try to add/invent something similar to the CLisp gensym, that generates ever different symbols at compile-time (just a letter plus an ever increasing integer number suffices). Bye, bearophile
Jun 02 2010
prev sibling parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
On 3-6-2010 14:58, Lars T. Kyllingstad wrote:
 On Thu, 03 Jun 2010 00:02:03 +0200, Simen kjaeraas wrote:
 
 On Wed, 02 Jun 2010 23:12:38 +0200, Adam Ruppe
 <destructionator gmail.com> wrote:

 On 6/2/10, Simen kjaeraas <simen.kjaras gmail.com> wrote: *snip*

 I haven't tried your code, but it looks similar to my own code, which
 had this problem:

 alias Typedef!Int Handle;
 alias Typedef!Int OtherHandle;

 void foo(Handle h) { }

 OtherHandle b;

 foo(b); // compiles, but shouldn't. Problem is that Handle and
 OtherHandle are both alias of the same underlying thing, so the
 compiler considers them the same thing! With the old typedef, I'm
 pretty sure it would (correctly IMO) complain here.

My code sidesteps that by including instantiation line and file, making each instantiation unique (as long as you don't do multiple typedefs on one line).

Cool trick! :) -Lars

Cool trick indeed, but why do we need a trick for something so basic!? A few years from now we'll wonder why compiling moderately sized D projects takes a long time. When you can do something, it doesn't mean that you should. L.
Jun 03 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
My suggestion is to just improve the built-in typedef, instead of trying to
implement some hack in D.

Lionello Lunesu:
 Cool trick indeed, but why do we need a trick for something so basic!?

For that a gensym is better than the date/file pair. But a gensym() despite being a simple thing might require compiler support to be implemented. Bye, bearophile
Jun 03 2010
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/03/2010 12:17 PM, Adam Ruppe wrote:
 On 6/3/10, bearophile<bearophileHUGS lycos.com>  wrote:
 My suggestion is to just improve the built-in typedef, instead of trying to
 implement some hack in D.

Do you consider ALL library solutions to be "hacks"? It sure seems that way at times. What we have here is individually useful language features able to completely replace another, specialized feature, and do even more! This strikes me as being a supremely elegant solution, not a hack. Fixing typedef ONLY fixes typedef, whereas fixing the helper components of Typedef can help a variety of things. If the helper templates are slow, improving template performance fixes that, and helps across the board!

Agreed. The reality was that typedef was in fact a hack; its semantics were quite erratic. A library-based solution can use the existing language to devise a principled artifact. Andrei
Jun 03 2010
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Adam Ruppe:
 Do you consider ALL library solutions to be "hacks"? It sure seems
 that way at times.

I have seen some situations where library solutions are not good enough yet: - std.bitmanip.bitfields is a marvel of programming, but it's trash any way: its code can't be maintained, modified, read. It's past the limit of decency. And its syntax is not as good as C bitfields. - The best library "typedef" shown so far can't be used two times in the same line, it uses a line of code and file name as workaround, for me this is a hack. I have suggested a gensym() to improve the situation a bit, but even with it the syntax is not that good and it can produce some template bloat. - The TightArray so far is not good enough for its purposes. Probably it can be improved. - The suggested replacecement for scope seems to have a bit better semantics (it's an expression and maybe it doesn't suffer some of the implementation bugs of "scope" (see my bug report 4214)), but its syntax is borderline awful, so for now it is not an improvement over the current (buggy) situation. - All the proposed library implementations of array comprehensions that I have seen are bad (including the one I have used). Bye, bearophile
Jun 03 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Adam Ruppe:

 When it comes to code accessibility, the compiler is a black box. You
 can't edit it, even in theory, without breaking the language. A
 library's source might be ugly, but it is at least available for you
 to play with while still writing valid D code.

Code that can be mantained inside the compiler is sometimes better than user code that can't be touched (I have tried to improve the error messages of those bitfields for about one hour and I have failed) :-)
But, be honest, have you ever actually put two typedefs on one line?<

I think I have never put two typedefs on one line, but hidden traps are bad.
If CTFE could get to a static variable, that'd be cool.<

Or the gensym can have compiler support ;-) If D3 will have some form of macros then a gensym will probably be even more useful. Bye, bearophile
Jun 03 2010
prev sibling parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
On 4-6-2010 1:17, Adam Ruppe wrote:
....
 This strikes me as being a supremely elegant solution, not a hack.

struct Typedef( T, T init = T.init, Type type = Type.Sub, string _f = __FILE__, int _l = __LINE__ ) { ... Yes, that's a hack. And it's great that we can do sub, super, independent and parallel, but the question is: are they needed? I thought I had found a compelling use case for typedef. Perhaps, instead of throwing it out because it was ill defined, we should define what's it supposed to solve and then make sure that's exactly what it does, and nothing more. L.
Jun 04 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/04/2010 06:38 AM, Lionello Lunesu wrote:
 On 4-6-2010 1:17, Adam Ruppe wrote:
 ....
 This strikes me as being a supremely elegant solution, not a hack.

struct Typedef( T, T init = T.init, Type type = Type.Sub, string _f = __FILE__, int _l = __LINE__ ) { ... Yes, that's a hack. And it's great that we can do sub, super, independent and parallel, but the question is: are they needed? I thought I had found a compelling use case for typedef. Perhaps, instead of throwing it out because it was ill defined, we should define what's it supposed to solve and then make sure that's exactly what it does, and nothing more.

The problem is, there's not only one good use. Walter and I identified at least a gew. The built-in typedef fails all examples below because it was very superficially designed. 1. Something that's just like another type yet "parallel" with it. This is good for abstractions that encode different units of measurement that aren't supposed to be mixed. ParallelTypedef!double Miles; Such a type should accept explicit initialization from a regular double: auto dist = Miles(3.2); However it shouldn't accept initialization from another parallel typedef: ParallelTypedef!double Kms; auto dist1 = Kms(4); auto dist2 = Miles(dist1); // no Arithmetic operations should only work within Miles but not mixing Miles with other types. Here's where things already get complicated - you do want to allow some operations between Miles and double (e.g. "*"), in some others you don't (e.g. "+"). Here's where a library facility would help: ParallelTypdef!(double, "allow_arithmetic", "allow_mixed:*,/,%") Miles; 2. Opaque "handle" types that can be used with overloading. The base type of the typedef is just the storage strategy: OpaqueTypedef!int FileHandle; Such a typedef supports no arithmetic and no implicit conversions. You can explicitly initialize it from an int and you can cast it back to it using an explicit cast. 3. Proper subtype. Create a true subtype of a type that allows explicit initialization from the type and implicit conversion to the type. SubtypeTypedef!Exception MyException; 4. Proper supertype. The base type implicitly converts to the introduced type, but not vice versa. SupertypeTypedef!uint Bits; Andrei
Jun 04 2010
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/31/2010 04:11 PM, Adam Ruppe wrote:
 Doesn't

 struct T { R _payload; }

 accomplish the same thing as

 typedef R T;

 in the majority of useful cases?

Exactly. And with alias this and other mechanisms, you can define several well-defined typedef incarnations that achieve what you want to express. Andrei
May 31 2010
prev sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 05/31/2010 03:54 PM, bearophile wrote:
 Andrei Alexandrescu:
 typedef is gone.

*mewls* I have shown here some examples of typedef usage, and I'll keep posting few more in future. I'd like to pull it back from the grave and keep it :-) Bye, bearophile

user specified T.init?
May 31 2010
parent Lionello Lunesu <lio lunesu.remove.com> writes:
On 1-6-2010 6:25, Ellery Newcomer wrote:
 user specified T.init?

I love(d) that feature!
May 31 2010
prev sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Andrei Alexandrescu wrote:

 On 05/31/2010 02:14 PM, bearophile wrote:
 Trass3r:
 Nobody got an answer?

My opinion: - complex types will be removed. And as far as I know complex number literals too will be removed from D (this is less nice). - I am not sure regarding C-style struct initializations. They are useful to save some typing if you have to for example to put a long array of struct literals in your source code. I presume they will be removed. - Typedef has some limitations, but I think it will be kept because it is useful.

typedef is gone. Andrei

struct initializers are gone too?
Jun 06 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/06/2010 10:23 AM, Lutger wrote:
 Andrei Alexandrescu wrote:

 On 05/31/2010 02:14 PM, bearophile wrote:
 Trass3r:
 Nobody got an answer?

My opinion: - complex types will be removed. And as far as I know complex number literals too will be removed from D (this is less nice). - I am not sure regarding C-style struct initializations. They are useful to save some typing if you have to for example to put a long array of struct literals in your source code. I presume they will be removed. - Typedef has some limitations, but I think it will be kept because it is useful.

typedef is gone. Andrei

struct initializers are gone too?

You mean { }? I seem to remember Walter mentioned they are no longer relevant. Andrei
Jun 06 2010
parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 06/06/2010 10:40 AM, Andrei Alexandrescu wrote:
 On 06/06/2010 10:23 AM, Lutger wrote:
 Andrei Alexandrescu wrote:

 On 05/31/2010 02:14 PM, bearophile wrote:
 Trass3r:
 Nobody got an answer?

My opinion: - complex types will be removed. And as far as I know complex number literals too will be removed from D (this is less nice). - I am not sure regarding C-style struct initializations. They are useful to save some typing if you have to for example to put a long array of struct literals in your source code. I presume they will be removed. - Typedef has some limitations, but I think it will be kept because it is useful.

typedef is gone. Andrei

struct initializers are gone too?

You mean { }? I seem to remember Walter mentioned they are no longer relevant. Andrei

Ooo Ooo Ooo Can we get rid of them? Pretty pretty please?
Jun 06 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Ellery Newcomer:
 Ooo Ooo Ooo Can we get rid of them? Pretty pretty please?

Why are you so eager to remove them? (They are not essential, D has plenty of other ways (maybe even too many) to instantiate a struct. But I have appreciated C-style struct initializers in D because they give a more compact syntax when I have to define many small structs inside an array literal). Bye, bearophile
Jun 06 2010
parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 06/06/2010 10:47 AM, bearophile wrote:
 Ellery Newcomer:
 Ooo Ooo Ooo Can we get rid of them? Pretty pretty please?

Why are you so eager to remove them? (They are not essential, D has plenty of other ways (maybe even too many) to instantiate a struct. But I have appreciated C-style struct initializers in D because they give a more compact syntax when I have to define many small structs inside an array literal). Bye, bearophile

because they're difficult to disambiguate from function literals (at least dmd doesn't do it correctly) because they entail a lot of lookahead (I don't know, but I suspect they are the cause for most of the slowness in my parser) because they're the only reason we have ArrayInitializer and without them we could merge it with ArrayLiteral I won't disagree that it's a nice syntax, though.
Jun 06 2010
prev sibling next sibling parent Adam Ruppe <destructionator gmail.com> writes:
Doesn't

struct T { R _payload; }

accomplish the same thing as

typedef R T;

in the majority of useful cases?

I use typedef void* Some_C_Type; a lot, and rather like it for a
handful of other things, but I'm pretty sure the struct accomplishes
the same thing in those cases. As a template in the stdlib
(std.typecons surely), it could be done easily enough in user code

The immediate differences are casting doesn't work the same* and the
compiler error messages aren't as good**. But these are minor, and
might be caused solely by my poor implementation.

* I used struct Typedef(R) { R _base; } alias Typedef!int Handle;

Casting:  Error: e2ir: cannot cast a of type Typedef!(int) to type
int. Though, Handle a; a._base; would do the trick, just not be
consistent.

** Using the above:
void foo(T) { }

foo(10); // cannot implicitly convert expression (10) of type int to
Typedef!(int)

Might be nice if it showed the alias name. This is something that
might be generally useful if changed, so it could improve other things
unlike the specialized feature.

On 5/31/10, bearophile <bearophileHUGS lycos.com> wrote:
 Andrei Alexandrescu:
 typedef is gone.

*mewls* I have shown here some examples of typedef usage, and I'll keep posting few more in future. I'd like to pull it back from the grave and keep it :-) Bye, bearophile

May 31 2010
prev sibling next sibling parent Trass3r <un known.com> writes:
 So what would be the way to translate those Windows headers? Create a
 unique struct for each old typedef? With alias this, and a ctor? Well,
 if that's the way to do it now, why not make typedef a shortcut for
 exactly that!?

Yeah there must be some short and clean way to define it.
 IIRC typedef is gone because you and Walter could not agree whether it
 had to be a subtype or a supertype of the typedef'ed type. For me it's
 rather simple: I want to introduce a new type in such a way that it
 helps me prevent mistakes, ie. passing one handle when the function
 wants another, even though both are based on void*, or whatever.

Seconded. Using it often for C wrappers.
May 31 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Lionello Lunesu <lio lunesu.remove.com> wrote:

 I also miss typedef. I thought D had a great opportunity to fix it.

 Take something like the Windows headers. It mostly consists of typedefs
 for handles and whatnot. Without typedef you'd have to use alias and
 type safety is out of the windows.

 So what would be the way to translate those Windows headers? Create a
 unique struct for each old typedef? With alias this, and a ctor? Well,
 if that's the way to do it now, why not make typedef a shortcut for
 exactly that!?

 IIRC typedef is gone because you and Walter could not agree whether it
 had to be a subtype or a supertype of the typedef'ed type. For me it's
 rather simple: I want to introduce a new type in such a way that it
 helps me prevent mistakes, ie. passing one handle when the function
 wants another, even though both are based on void*, or whatever.

 Bring typedef back!

struct Typedef( T ) { T payload; alias payload this; } alias Typedef!int myInt; There you go. -- Simen
May 31 2010
prev sibling next sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Justin Spahr-Summers, el 31 de mayo a las 16:41 me escribiste:
 On Tue, 01 Jun 2010 06:05:50 +0800, Lionello Lunesu 
 <lio lunesu.remove.com> wrote:
 
 On 1-6-2010 5:38, Andrei Alexandrescu wrote:
 On 05/31/2010 03:54 PM, bearophile wrote:
 Andrei Alexandrescu:
 typedef is gone.

*mewls* I have shown here some examples of typedef usage, and I'll keep posting few more in future. I'd like to pull it back from the grave and keep it :-)

It's wasted time. typedef is gone. Andrei

:(( I also miss typedef. I thought D had a great opportunity to fix it. Take something like the Windows headers. It mostly consists of typedefs for handles and whatnot. Without typedef you'd have to use alias and type safety is out of the windows. So what would be the way to translate those Windows headers? Create a unique struct for each old typedef? With alias this, and a ctor? Well, if that's the way to do it now, why not make typedef a shortcut for exactly that!?

I'm a fan of typedef, personally, but the example you mentioned *would* be solved using just an alias. 'alias' provides the same functionality as C/C++'s 'typedef' and more.

I think he talks about this difference: alias int a1; alias int a2; typedef int t1; typedef int t2; void fa(a2 a) {} void ft(t2 t) {} void main() { a1 a = 5; fa(a); // <--- compiles fine t1 t = 10; ft(t); // <--- error } function a.ft (t2) does not match parameter types (t1) types (t1) cannot implicitly convert expression (t) of type t1 to t2 Alias does not provide type-safety. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- There is no such thing as right or wrong Only consequences
May 31 2010
parent reply Kagamin <spam here.lot> writes:
Leandro Lucarella Wrote:

 I think he talks about this difference:
 
 alias int a1;
 alias int a2;
 typedef int t1;
 typedef int t2;
 
 void fa(a2 a) {}
 void ft(t2 t) {}
 
 void main() {
 	a1 a = 5;
 	fa(a); // <--- compiles fine
 	t1 t = 10;
 	ft(t); // <--- error
 }

Jun 01 2010
parent Lionello Lunesu <lio lunesu.remove.com> writes:
On 1-6-2010 18:04, Kagamin wrote:
 Leandro Lucarella Wrote:
 
 I think he talks about this difference:

 alias int a1;
 alias int a2;
 typedef int t1;
 typedef int t2;

 void fa(a2 a) {}
 void ft(t2 t) {}

 void main() {
 	a1 a = 5;
 	fa(a); // <--- compiles fine
 	t1 t = 10;
 	ft(t); // <--- error
 }


OK, so I can pass any handle to CloseHandle, but that doesn't mean I can pass any handle like any other handle. And not all typedefs in the Windows headers behave that way, some are not compatible with anything else. Don't focus too much on my Windows header example. It was just that, an example. L.
Jun 01 2010
prev sibling next sibling parent Trass3r <un known.com> writes:
 struct Typedef( T ) {
      T payload;
      alias payload this;
 }

 alias Typedef!int myInt;

 There you go.

The question is if this still works flawlessly for complicated examples.
May 31 2010
prev sibling next sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
On Tue, 01 Jun 2010 05:07:21 +0200, Simen kjaeraas wrote:

 Lionello Lunesu <lio lunesu.remove.com> wrote:
 
 I also miss typedef. I thought D had a great opportunity to fix it.

 Take something like the Windows headers. It mostly consists of typedefs
 for handles and whatnot. Without typedef you'd have to use alias and
 type safety is out of the windows.

 So what would be the way to translate those Windows headers? Create a
 unique struct for each old typedef? With alias this, and a ctor? Well,
 if that's the way to do it now, why not make typedef a shortcut for
 exactly that!?

 IIRC typedef is gone because you and Walter could not agree whether it
 had to be a subtype or a supertype of the typedef'ed type. For me it's
 rather simple: I want to introduce a new type in such a way that it
 helps me prevent mistakes, ie. passing one handle when the function
 wants another, even though both are based on void*, or whatever.

 Bring typedef back!

struct Typedef( T ) { T payload; alias payload this; } alias Typedef!int myInt; There you go.

Nice. :) But it isn't quite a typedef, because if you do alias Typedef!int myInt; alias Typedef!int yourInt; then myInt and yourInt will refer to the same type. How about this instead: mixin template Typedef(T, string name) { mixin("struct "~name~" { T payload; alias payload this; }"); } Then, mixin Typedef!(int, "myInt"); mixin Typedef!(int, "yourInt"); will define two distinct types. If we had Andrei's (or was it Walter's?) "new alias" feature it would be even cooler: mixin template Typedef(T, new alias name) { struct name { T payload; alias payload this; } } mixin Typedef!(int, myInt); mixin Typedef!(int, yourInt); :) -Lars
Jun 01 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:

 struct Typedef( T ) {
 T payload;
 alias payload this;
 }

 alias Typedef!int myInt;

 There you go.

Yah, perfect - that would be the subtype. I think we should work on adding a pseudo-supertype as well, and also on a completely independent type. Then we can add these abstractions to std.typecons.

Actually, alias this makes it more of a parallel type. This code, however, allows for subtypes, supertypes, parallel types, as well as independent types. please critique. enum Type { Independent, Super, Sub, Parallel, } struct Typedef( T, T init = T.init, Type type = Type.Sub, string _f = __FILE__, int _l = __LINE__ ) { T payload = init; static if ( type != Type.Independent ) { this( T value ) { payload = value; } } static if ( type == Type.Sub || type == Type.Parallel ) { alias payload this; } static if ( type == Type.Super ) { typeof( this ) opAssign( T value ) { payload = value; return this; } } else static if ( type == Type.Sub ) { disable void opAssign( T value ); } } unittest { alias Typedef!( int, 1, Type.Super ) superInt; alias Typedef!( int, 2, Type.Sub ) subInt; alias Typedef!( int, 3, Type.Independent ) independentInt; alias Typedef!( int, 3, Type.Parallel ) parallelInt; int i; superInt m1; subInt m2; independentInt m3; parallelInt m4; // Construct static assert( is( typeof({ superInt j = i; }))); static assert( is( typeof({ subInt j = i; }))); static assert( !is( typeof({ IndependentInt j = i; }))); static assert( is( typeof({ parallelInt j = i; }))); // Assign from base static assert( is( typeof({ m1 = i; }))); static assert( !is( typeof({ m2 = i; }))); static assert( !is( typeof({ m3 = i; }))); static assert( is( typeof({ m4 = i; }))); // Assign to base static assert( !is( typeof({ i = m1; }))); static assert( is( typeof({ i = m2; }))); static assert( !is( typeof({ i = m3; }))); static assert( is( typeof({ i = m4; }))); // Assign from other type static assert( is( typeof({ m1 = m2; }))); static assert( !is( typeof({ m2 = m1; }))); static assert( !is( typeof({ m1 = m3; }))); static assert( !is( typeof({ m2 = m3; }))); static assert( !is( typeof({ m3 = m1; }))); static assert( !is( typeof({ m3 = m2; }))); static assert( is( typeof({ m1 = m4; }))); static assert( !is( typeof({ m2 = m4; }))); static assert( !is( typeof({ m3 = m4; }))); static assert( !is( typeof({ m4 = m1; }))); static assert( is( typeof({ m4 = m2; }))); static assert( !is( typeof({ m4 = m3; }))); } -- Simen
Jun 02 2010
prev sibling next sibling parent Adam Ruppe <destructionator gmail.com> writes:
On 6/2/10, Simen kjaeraas <simen.kjaras gmail.com> wrote:
*snip*

I haven't tried your code, but it looks similar to my own code, which
had this problem:

alias Typedef!Int Handle;
alias Typedef!Int OtherHandle;

void foo(Handle h) { }

OtherHandle b;

foo(b); // compiles, but shouldn't. Problem is that Handle and
OtherHandle are both alias of the same underlying thing, so the
compiler considers them the same thing! With the old typedef, I'm
pretty sure it would (correctly IMO) complain here.
Jun 02 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
On Wed, 02 Jun 2010 23:12:38 +0200, Adam Ruppe <destructionator gmail.com>  
wrote:

 On 6/2/10, Simen kjaeraas <simen.kjaras gmail.com> wrote:
 *snip*

 I haven't tried your code, but it looks similar to my own code, which
 had this problem:

 alias Typedef!Int Handle;
 alias Typedef!Int OtherHandle;

 void foo(Handle h) { }

 OtherHandle b;

 foo(b); // compiles, but shouldn't. Problem is that Handle and
 OtherHandle are both alias of the same underlying thing, so the
 compiler considers them the same thing! With the old typedef, I'm
 pretty sure it would (correctly IMO) complain here.

My code sidesteps that by including instantiation line and file, making each instantiation unique (as long as you don't do multiple typedefs on one line). It is possible to sidestep this issue with a mixin template: mixin template typedef( string name, T ) { mixin(q{ struct } ~ name ~ q{ { //stuff } }); } But 'mixin Typedef!("myInt", int);' does not sit well with me. -- Simen
Jun 02 2010
prev sibling next sibling parent Adam Ruppe <destructionator gmail.com> writes:
How cool! I like that a lot.
Jun 02 2010
prev sibling next sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
On Thu, 03 Jun 2010 00:02:03 +0200, Simen kjaeraas wrote:

 On Wed, 02 Jun 2010 23:12:38 +0200, Adam Ruppe
 <destructionator gmail.com> wrote:
 
 On 6/2/10, Simen kjaeraas <simen.kjaras gmail.com> wrote: *snip*

 I haven't tried your code, but it looks similar to my own code, which
 had this problem:

 alias Typedef!Int Handle;
 alias Typedef!Int OtherHandle;

 void foo(Handle h) { }

 OtherHandle b;

 foo(b); // compiles, but shouldn't. Problem is that Handle and
 OtherHandle are both alias of the same underlying thing, so the
 compiler considers them the same thing! With the old typedef, I'm
 pretty sure it would (correctly IMO) complain here.

My code sidesteps that by including instantiation line and file, making each instantiation unique (as long as you don't do multiple typedefs on one line).

Cool trick! :) -Lars
Jun 02 2010
prev sibling next sibling parent Adam Ruppe <destructionator gmail.com> writes:
On 6/3/10, bearophile <bearophileHUGS lycos.com> wrote:
 My suggestion is to just improve the built-in typedef, instead of trying to
 implement some hack in D.

Do you consider ALL library solutions to be "hacks"? It sure seems that way at times. What we have here is individually useful language features able to completely replace another, specialized feature, and do even more! This strikes me as being a supremely elegant solution, not a hack. Fixing typedef ONLY fixes typedef, whereas fixing the helper components of Typedef can help a variety of things. If the helper templates are slow, improving template performance fixes that, and helps across the board!
Jun 03 2010
prev sibling next sibling parent Adam Ruppe <destructionator gmail.com> writes:
On 6/3/10, bearophile <bearophileHUGS lycos.com> wrote:
 I have seen some situations where library solutions are not good enough yet:
 - std.bitmanip.bitfields is a marvel of programming, but it's trash any way:
 its code can't be maintained, modified, read. It's past the limit of
 decency.

When it comes to code accessibility, the compiler is a black box. You can't edit it, even in theory, without breaking the language. A library's source might be ugly, but it is at least available for you to play with while still writing valid D code.
 And its syntax is not as good as C bitfields.

It is very close though.
 - The best library "typedef" shown so far can't be used two times in the
 same line,

Note: you can use it twice on one line under some circumstances still. But, be honest, have you ever actually put two typedefs on one line? If the limitation wasn't explained in the code, would you have ever noticed this? The only place where I can see it being an issue is if you use it inside a larger string mixin. The line numbers get really weird at times with them. But, it still seems like an academic problem.
 it uses a line of code and file name as workaround, for me this
 is a hack.

When I saw the line/file arguments there, I assumed they were for debugging purposes - you can use them to make prettier error messages for the user. The benefit of letting the distinct types work is a cool side effect. I'll agree that it is a bit weird, but it does the job and isn't really evil.
 I have suggested a gensym() to improve the situation a bit, but
 even with it the syntax is not that good and it can produce some template
 bloat.

I think a gensym would be useful. If CTFE could get to a static variable, that'd be cool. string getsym() { static int count = 0; count++; return "_AUTOMATICALLY_GENERATED_SYMBOL_" ~ to!string(count); } Then, mixin(getsym()) on the useage end. This doesn't work right now because the global isn't accessible at compile time....
 - The TightArray so far is not good enough for its purposes. Probably it can
 be improved.

Yes.
 - The suggested replacecement for scope seems to have a bit better semantics
 (it's an expression and maybe it doesn't suffer some of the implementation
 bugs of "scope" (see my bug report 4214)), but its syntax is borderline
 awful, so for now it is not an improvement over the current (buggy)
 situation.

The syntax should be easy to turn into: Scoped!Object obj; since it is basically just a wrapper struct. What I especially like about this situation is how it has potential to do a variety of things, like stack allocation, or malloc(), or just about anything else. I'd like to see the built in new moved to the library too, actually. auto a = new!Object(args...); should be possible even now!
 - All the proposed library implementations of array comprehensions that I
 have seen are bad (including the one I have used).

I haven't used any so I can't say.
Jun 03 2010
prev sibling parent retard <re tard.com.invalid> writes:
Thu, 03 Jun 2010 15:08:08 -0400, Adam Ruppe wrote:

 On 6/3/10, bearophile <bearophileHUGS lycos.com> wrote:
 I have seen some situations where library solutions are not good enough
 yet: - std.bitmanip.bitfields is a marvel of programming, but it's
 trash any way: its code can't be maintained, modified, read. It's past
 the limit of decency.

When it comes to code accessibility, the compiler is a black box. You can't edit it, even in theory, without breaking the language. A library's source might be ugly, but it is at least available for you to play with while still writing valid D code.
 And its syntax is not as good as C bitfields.

It is very close though.
 - The best library "typedef" shown so far can't be used two times in
 the same line,

Note: you can use it twice on one line under some circumstances still. But, be honest, have you ever actually put two typedefs on one line? If the limitation wasn't explained in the code, would you have ever noticed this?

Don't forget machine generated code. E.g. CTFE or parser generators
Jun 03 2010