September 23, 2014
On Monday, 22 September 2014 at 17:21:50 UTC, Andrei Alexandrescu wrote:
>
> I would agree with that. If I'd do it over again I'd probably make the string the second argument with no default.
>
That's not the problem though.

>> You can make the argument that it's not that much of a burden. And on a cursory read, sure, that makes enough sense.
>
> It's a good argument. At some point some RTFM is necessary; I think it's reasonable to assume that whoever is in the market for using Typedef would spend a minute with the documentation.
>
Even just reading this thread, I can see that the people in the market for using Typedef also want to use it _often_ (a sentiment I echo) because trivial type safety is such a compelling feature.  The fact that it's documented is beside the point. (I thought you or Walter talked before about how "RTFM" isn't a shining endorsement of your API?)  The fact that its primary use isn't the default presents a usability problem.  For one thing, no one likes writing boilerplate.  It's annoying.  When things are annoying, people find some other way.  But there's another aspect that makes this even worse (below).

> Type safety is not the problem here. I do agree that surprising behavior for those who don't RTFM is possible.
>
I beg to differ.  Type safety is the entire goal.  Surprising behaviour shouldn't be the default when the "Surprise!" part is that it doesn't break until later.  That surprises should explode spectacularly at their earliest convenience is a lesson you taught me with e.g. the rationale behind using NaN as the floating point init value.  By failing to detonate, errors can manifest in the implementation subtly after appearing to work for an extended period.  This is bad.

You said earlier it's reasonable to assume people would read the docs, and I agree to an extent.  But I think it's reasonable to want APIs in the standard library that are resistant to misreading, skimming, and misunderstanding.  That very sort of confusion is why this thread even started, after all!  And the solution in this case is conceptually simple.

> I'd agree with that. (Again if I could do things over again there'd be no default for the cookie.) But my understanding is

Generating a unique cookie if one isn't given is the correct behaviour from the _user's_ perspective.  I believe it also addresses the concerns Timon raised regarding Typedef in templates.

> that there's quite a bit of blowing this out of proportion.
>
I agree some of the discussion has been hyperbolic, but I also agree there's a real problem with the current situation that goes beyond simply "this is moderately annoying".

> It's an anecdote. How you explained matters matters a lot :o). I find the requirement for the cookie perfect.
>
Something like, "Look how cool it is that we can do typedefs as a template!" and a link to the docs.  Just an anecdote from a non-D user that ended up being relevant. (I'm trying to score converts! ;)

-Wyatt
September 23, 2014
On 9/23/14, 7:43 AM, Don wrote:
> On Monday, 22 September 2014 at 14:56:26 UTC, Andrei Alexandrescu wrote:
>> On 9/22/14, 2:39 AM, Don wrote:
>>> Yes, but you're advocating a hack.
>>
>> Oh but I very much disagree.
>
> Now you are scaring me. It worries me that this kind of "solution" can
> be viewed as acceptable. It's the kind of hacky code I left C++ to
> escape from.

Hmm... doesn't strike me as similar to C++-specific hacks, but I understand the sentiment.

> People in this thread said it was "ugly" and you dismissed that.

Nononononono. I totally agree some may find it ugly! It's "unusable" I have a problem with.

> But
> this isn't just a matter of personal aesthetics.
> If you want something objective, it's not DRY, and it's verbose in a
> non-trivial way. The hacky design leads to error-prone code.
> eg you can easily get a copy-paste bug because it's not DRY.
>
> alias HMENU = Typedef!(void*, __MODULE__ ~ ".HMENU");
> alias HFONT = Typedef!(void*, __MODULE__ ~ ".HMENU"); // oops

mixin(makeTypedef!("HMENU", void*));
mixin(makeTypedef!("HFONT", void*));

I said and I repeat: I do agree it's less convenient than a baked-in facility. Even with the proper default arguments and all. But I stand by Typedef as an adequate abstraction.

>> How many libraries did you use that came with no idioms for their usage?
>
> Describing this as an "idiom" is extremely generous. My standards are
> higher.

Well "extremely generous" is not "deluded" so I'll take that :o).

>>> And it does seem to me, that because it isn't possible to do a proper
>>> library typedef, you've attempted to redefine what a Typedef is supposed
>>> to do. And sure, it you remove the requirement to create a unique type,
>>> Typedef isn't broken.
>>
>> You're two paragraphs away from "library Typedefs are fundamentally
>> broken". Now which one is it?
>
> Phobos' Typedef is fundamentally broken, and that your claim that it is
> not, relies on moving the goalposts.

I disagree. I'm not one to dismiss good arguments. But there aren't many here. There's gotta be a point at which you'll agree the whole argument against Typedef has no legs. It's working as designed (I forgot who designed it), the design fits the purpose, the semantics never surprised me, and when people now come with the pitchforks that it's broken, all I can do is send them to the manual. IT WORKS.

>>> But then it isn't very useful, either. You can't,
>>> for example, use it to define the various Windows HANDLEs (HMENU, etc),
>>> which was one of the most successful use cases for D1's typedef.
>>
>> alias HMENU = Typedef!(void*, __MODULE__ ~ ".HMENU");
>>
>> So please s/can't/can't the same exact way built-in typedef would have
>> done it/.
>
> No. You can hammer nails in using a rock, but I'm not prepared to accept
> a rock as a kind of hammer. It's not a tool that belongs in any toolbox.
>
> My assertion is, there are no use cases for Phobos's Typedef.
> You're always better off doing something else.

But your evidence destroys your own assertion. Let me explain.

You bring the typo example as the smoking gun. So I take it it's a biggie that, if fixed, would make you happy. But there are a number of trivial fixes to it, such as my defineTypedef above. So it looks like (a) Typedef can be used as long as you are careful to not type the wrong name, (b) with only trivial work, Typedef can be used without even the slightest repetition.

So how come Typedef is unusable when it's usable by your own testimony?


Andrei

September 23, 2014
On Monday, 22 September 2014 at 09:39:29 UTC, Don wrote:
> Having said that, though, the success of 'alias this' does raise some interesting questions about how useful the concept of a typedef is. Certainly it's much less useful than when Typedef was created.
>
> My feeling is that almost every time when you want to create a new type from an existing one, you actually want to restrict the operations which can be performed on it. (Eg if you have  typedef money = double; then money*money doesn't make much sense). For most typedefs I think you're better off with 'alias this'.

If you have a look at our transition.d it does exactly that right now - mixes in the struct with the same name as typedef had and does `alias this` for its value field ;)
September 23, 2014
On Tuesday, 23 September 2014 at 16:01:35 UTC, Andrei Alexandrescu wrote:
> mixin(makeTypedef!("HMENU", void*));

struct HMENU { void* _; alias _ this; }

Don't even have to import a Phobos module for it!
September 23, 2014
On 9/23/14, 9:05 AM, Dicebot wrote:
> On Monday, 22 September 2014 at 09:39:29 UTC, Don wrote:
>> Having said that, though, the success of 'alias this' does raise some
>> interesting questions about how useful the concept of a typedef is.
>> Certainly it's much less useful than when Typedef was created.
>>
>> My feeling is that almost every time when you want to create a new
>> type from an existing one, you actually want to restrict the
>> operations which can be performed on it. (Eg if you have typedef money
>> = double; then money*money doesn't make much sense). For most typedefs
>> I think you're better off with 'alias this'.
>
> If you have a look at our transition.d it does exactly that right now -
> mixes in the struct with the same name as typedef had and does `alias
> this` for its value field ;)

So why not mix in Typedef? -- Andrei
September 23, 2014
On 9/23/14, 9:15 AM, Adam D. Ruppe wrote:
> On Tuesday, 23 September 2014 at 16:01:35 UTC, Andrei Alexandrescu wrote:
>> mixin(makeTypedef!("HMENU", void*));
>
> struct HMENU { void* _; alias _ this; }
>
> Don't even have to import a Phobos module for it!

Even better. I love good idioms! -- Andrei

September 23, 2014
On 9/23/14, 8:10 AM, Wyatt wrote:
> On Monday, 22 September 2014 at 17:21:50 UTC, Andrei Alexandrescu wrote:
>>
>> I would agree with that. If I'd do it over again I'd probably make the
>> string the second argument with no default.
>>
> That's not the problem though.
>
>>> You can make the argument that it's not that much of a burden. And on
>>> a cursory read, sure, that makes enough sense.
>>
>> It's a good argument. At some point some RTFM is necessary; I think
>> it's reasonable to assume that whoever is in the market for using
>> Typedef would spend a minute with the documentation.
>>
> Even just reading this thread, I can see that the people in the market
> for using Typedef also want to use it _often_ (a sentiment I echo)
> because trivial type safety is such a compelling feature.

I'm not buying this. Yah, there's batteries of types a la Windows' definitions, but it's not like casual use everywhere.

> The fact that
> it's documented is beside the point. (I thought you or Walter talked
> before about how "RTFM" isn't a shining endorsement of your API?)

Sure, the lesser the better. But it's a continuum, not beside the point.

> The
> fact that its primary use isn't the default presents a usability
> problem.  For one thing, no one likes writing boilerplate.  It's
> annoying.  When things are annoying, people find some other way.  But
> there's another aspect that makes this even worse (below).

Then define and use defineTypedef. Clearly there's an imbalance between the desire of getting work done with Typedef and that of ildly arguing that Typedef is useless.

People who need to get work done won't be stopped by Typedef. They'll type it twice and if they need it a third time then they'll figure how to simplify its usage. Or they use Adam's idiom (Adam makes this point in his epic slideless talk: just get into it and make it work! I've never seem Adam working himself to a foam over minutia.)

>> Type safety is not the problem here. I do agree that surprising
>> behavior for those who don't RTFM is possible.
>>
> I beg to differ.  Type safety is the entire goal.

That's a loose use of the term.

> Surprising behaviour
> shouldn't be the default when the "Surprise!" part is that it doesn't
> break until later.  That surprises should explode spectacularly at their
> earliest convenience is a lesson you taught me with e.g. the rationale
> behind using NaN as the floating point init value.  By failing to
> detonate, errors can manifest in the implementation subtly after
> appearing to work for an extended period.  This is bad.

Not buying all this, sorry.

> You said earlier it's reasonable to assume people would read the docs,
> and I agree to an extent.  But I think it's reasonable to want APIs in
> the standard library that are resistant to misreading, skimming, and
> misunderstanding.  That very sort of confusion is why this thread even
> started, after all!

The guy who started this thread was explained what to do, replied with "Sorry, my mistake" and went on his way getting stuff done.

> And the solution in this case is conceptually simple.

What would that be?

>> I'd agree with that. (Again if I could do things over again there'd be
>> no default for the cookie.) But my understanding is
>
> Generating a unique cookie if one isn't given is the correct behaviour
> from the _user's_ perspective.  I believe it also addresses the concerns
> Timon raised regarding Typedef in templates.

I'd be fine with improving Typedef. In fact part of the rationale for replacing the built-in with a library type is that we have more flexibility in library space.

>> that there's quite a bit of blowing this out of proportion.
>>
> I agree some of the discussion has been hyperbolic, but I also agree
> there's a real problem with the current situation that goes beyond
> simply "this is moderately annoying".
>
>> It's an anecdote. How you explained matters matters a lot :o). I find
>> the requirement for the cookie perfect.
>>
> Something like, "Look how cool it is that we can do typedefs as a
> template!" and a link to the docs.  Just an anecdote from a non-D user
> that ended up being relevant. (I'm trying to score converts! ;)

That's great.


Andrei

September 23, 2014
On Tue, Sep 23, 2014 at 09:26:51AM -0700, Andrei Alexandrescu via Digitalmars-d wrote:
> On 9/23/14, 9:15 AM, Adam D. Ruppe wrote:
> >On Tuesday, 23 September 2014 at 16:01:35 UTC, Andrei Alexandrescu wrote:
> >>mixin(makeTypedef!("HMENU", void*));
> >
> >struct HMENU { void* _; alias _ this; }
> >
> >Don't even have to import a Phobos module for it!
> 
> Even better. I love good idioms! -- Andrei

To me, this is a big reason for Typedef being of little use. It's just so easy to use struct + alias this to achieve what you want (and to do so without tricky issues or hacks like counters or whatnot, plus you get to control exactly how it should behave without bothering with template parameters -- you can even do things like overload operators / methods, that Typedef can't do), that I find myself wondering what Typedef is actually good for, if anything!


T

-- 
Talk is cheap. Whining is actually free. -- Lars Wirzenius
September 23, 2014
On Tuesday, 23 September 2014 at 16:19:00 UTC, Andrei Alexandrescu wrote:
> So why not mix in Typedef? -- Andrei

Why would I ever want it? Plain struct is absolutely superior to it.
September 23, 2014
On 9/23/14, 9:37 AM, H. S. Teoh via Digitalmars-d wrote:
> On Tue, Sep 23, 2014 at 09:26:51AM -0700, Andrei Alexandrescu via Digitalmars-d wrote:
>> On 9/23/14, 9:15 AM, Adam D. Ruppe wrote:
>>> On Tuesday, 23 September 2014 at 16:01:35 UTC, Andrei Alexandrescu wrote:
>>>> mixin(makeTypedef!("HMENU", void*));
>>>
>>> struct HMENU { void* _; alias _ this; }
>>>
>>> Don't even have to import a Phobos module for it!
>>
>> Even better. I love good idioms! -- Andrei
>
> To me, this is a big reason for Typedef being of little use. It's just
> so easy to use struct + alias this to achieve what you want (and to do
> so without tricky issues or hacks like counters or whatnot, plus you get
> to control exactly how it should behave without bothering with template
> parameters -- you can even do things like overload operators / methods,
> that Typedef can't do), that I find myself wondering what Typedef is
> actually good for, if anything!

If language progress has gotten to the point where Typedef is obsolete (I recall there were a bunch of issues with alias this at the time we introduced Typedef), so much the better. I'm totally fine with "Typedef is obsolete". It's the poetic injustice of "Typedef is broken/unusable" I have a problem with. -- Andrei