Jump to page: 1 26  
Page
Thread overview
is(x = module) vs. __traits(isModule, x)
Oct 07, 2020
Paul Backus
Oct 07, 2020
H. S. Teoh
Oct 07, 2020
Paul Backus
Oct 07, 2020
H. S. Teoh
Oct 08, 2020
Jacob Carlborg
Oct 08, 2020
Max Samukha
Oct 08, 2020
Stefan Koch
Oct 08, 2020
Max Samukha
Oct 08, 2020
Adam D. Ruppe
Oct 08, 2020
Stefan Koch
Oct 11, 2020
Nick Treleaven
Oct 11, 2020
Stefan Koch
Oct 11, 2020
Nick Treleaven
Oct 11, 2020
Stefan Koch
Oct 08, 2020
Max Samukha
Oct 08, 2020
H. S. Teoh
Oct 10, 2020
Walter Bright
Oct 10, 2020
Stefan Koch
Oct 12, 2020
Q. Schroll
Oct 07, 2020
Stefan Koch
Oct 07, 2020
Paul Backus
Oct 07, 2020
Stefan Koch
Oct 07, 2020
Meta
Oct 07, 2020
Stefan Koch
Oct 07, 2020
Meta
Oct 07, 2020
Paul Backus
Oct 07, 2020
Stefan Koch
Oct 08, 2020
Imperatorn
Oct 08, 2020
Paul Backus
Oct 08, 2020
Paul Backus
Oct 08, 2020
Jacob Carlborg
Oct 08, 2020
Paul Backus
Oct 10, 2020
Walter Bright
Oct 07, 2020
Adam D. Ruppe
Oct 07, 2020
Adam D. Ruppe
Oct 08, 2020
Walter Bright
Oct 07, 2020
Walter Bright
Oct 07, 2020
Stefan Koch
Oct 08, 2020
H. S. Teoh
Oct 08, 2020
RazvanN
Oct 11, 2020
Nick Treleaven
Oct 08, 2020
Kagamin
Oct 08, 2020
Stefan Koch
Oct 10, 2020
Walter Bright
Oct 10, 2020
Stefan Koch
October 07, 2020
Someone on the discord chat brought this up:

We currently have 2 ways to check if a symbol is a module:

import std.stdio;

pragma(msg, is(std.stdio == module)); // true
pragma(msg, __traits(isModule, std.stdio)); // true

Why both? The first thing that struck me is that, std.stdio is NOT a type. `is` specifically says it works with types. So that seems out of place (indeed the documentation does not mention anything special about this).

And then I looked up when they were added, thinking that maybe one predates the other, and there is a reason it didn't handle all cases.

Wrong. They were both added in the *same PR* to mean the *same thing*: https://github.com/dlang/dmd/pull/5290

Is there a reason we want to have both? Why did we want to muddy the `is` waters?

I really think we should remove one of these, I would recommend removing the `is` form, since it's the only exception to the rule that the parameter must be a type.

BTW, same with packages:

is(std == package) == __traits(isPackage, std);

-Steve
October 07, 2020
On Wednesday, 7 October 2020 at 18:46:07 UTC, Steven Schveighoffer wrote:
> Wrong. They were both added in the *same PR* to mean the *same thing*: https://github.com/dlang/dmd/pull/5290
>
> Is there a reason we want to have both? Why did we want to muddy the `is` waters?

I tried reading through the PR discussion to see how things ended up this way.

The original PR includes only the __traits versions. The is() version was first proposed in a comment by Timothee Cour [1], and supported by several others including Andrei [2]. The PR author continues work on an implementation that includes only the is() versions, until a few months later, Nicholas Wilson leaves the following comment [3]:

> It was decided to have both.

The rationale behind this decision is never elaborated on, and the PR is eventually merged with both versions.

[1] https://github.com/dlang/dmd/pull/5290#issuecomment-366826557
[2] https://github.com/dlang/dmd/pull/5290#issuecomment-462884161
[3] https://github.com/dlang/dmd/pull/5290#issuecomment-491509238
October 07, 2020
On Wed, Oct 07, 2020 at 02:46:07PM -0400, Steven Schveighoffer via Digitalmars-d wrote: [...]
> We currently have 2 ways to check if a symbol is a module:
> 
> import std.stdio;
> 
> pragma(msg, is(std.stdio == module)); // true
> pragma(msg, __traits(isModule, std.stdio)); // true
[...]
> I really think we should remove one of these, I would recommend removing the `is` form, since it's the only exception to the rule that the parameter must be a type.

I'm on the fence about this one. Having to type __traits(isModule,xxx) is painful.  Is it really necessary to make it so hard just to check whether a symbol is a module??  It's not as if it's something we want to discourage.  Typing is(xxx == module) is much easier, and more pleasant on the eyes.

OTOH you have a very good point about is(...) being intended to work
only for types.

So I dunno.


> BTW, same with packages:
> 
> is(std == package) == __traits(isPackage, std);
[...]

Ditto.


T

-- 
Knowledge is that area of ignorance that we arrange and classify. -- Ambrose Bierce
October 07, 2020
On Wednesday, 7 October 2020 at 19:07:34 UTC, H. S. Teoh wrote:
> I'm on the fence about this one. Having to type __traits(isModule,xxx) is painful.  Is it really necessary to make it so hard just to check whether a symbol is a module??  It's not as if it's something we want to discourage.  Typing is(xxx == module) is much easier, and more pleasant on the eyes.

IMO this is one of those situations where your pain is trying to tell you something. If using __traits syntax is so painful that we're willing to add hacky special cases to other language features in order to avoid it, maybe the message we should take from that is "we need to improve __traits syntax."

Here's my strawman proposal: turn all __traits into properties. A few before-and-after examples:

__traits(isModule, foo)
  => foo.__isModule

__traits(getMember, T, "x")
  => T.__member("x")

__traits(compiles, some(kind, of + expression))
  => (some(kind, of + expression)).__compiles
October 07, 2020
On Wednesday, 7 October 2020 at 18:46:07 UTC, Steven Schveighoffer wrote:
> Why both?

Why *either*?

The real WTF is that modules - which are not actually a child member of another module - is returned in listings of __traits(allMembers).

That's the root bug and should be fixed. These were just added to let user code hack around this bug instead of just fixing the bug in the compiler.

If you want to get imports, we should provide an alternate trait for that.

> is(std == package) == __traits(isPackage, std);

And this is broken af right now anyway. As of the newest dmd, trying to actually modules from imports slams into a brick wall.

The status quo is even worse than it was a couple releases ago... and it was already broken. Let's just fix it all.
October 07, 2020
On Wed, Oct 07, 2020 at 07:15:30PM +0000, Paul Backus via Digitalmars-d wrote:
> On Wednesday, 7 October 2020 at 19:07:34 UTC, H. S. Teoh wrote:
> > I'm on the fence about this one. Having to type __traits(isModule,xxx) is painful.  Is it really necessary to make it so hard just to check whether a symbol is a module??  It's not as if it's something we want to discourage.  Typing is(xxx == module) is much easier, and more pleasant on the eyes.
> 
> IMO this is one of those situations where your pain is trying to tell you something. If using __traits syntax is so painful that we're willing to add hacky special cases to other language features in order to avoid it, maybe the message we should take from that is "we need to improve __traits syntax."
[...]

Actually, I think that *was* the original intent of the __traits syntax. It was meant to be a quick-n-dirty way of exposing various compiler internal structures to Phobos so that it can implement various meta-programming primitives. It was intentionally ugly in order to discourage users from using it directly, and to prefer the nicer packaging in Phobos instead.

However, the way things turned out, it appears that __traits has become sorta a de facto standard for metaprogramming primitives, and Phobos has kinda fallen behind on the job.  So perhaps it's time to rethink this decision?


T

-- 
Be in denial for long enough, and one day you'll deny yourself of things you wish you hadn't.
October 07, 2020
On 10/7/20 3:44 PM, Adam D. Ruppe wrote:
> On Wednesday, 7 October 2020 at 18:46:07 UTC, Steven Schveighoffer wrote:
>> Why both?
> 
> Why *either*?

If you want to determine if a given symbol is a module. Is there another way?

> The real WTF is that modules - which are not actually a child member of another module - is returned in listings of __traits(allMembers).

Yeah, that's a problem we should fix. There was an almost-released fix which made __traits(allMembers, mod) return the full name of the modules, which I don't think was right either.

But aside from that, I don't see a problem with allowing someone to introspect whether something is a module or package.

> If you want to get imports, we should provide an alternate trait for that.

Agreed. But still I would think some mechanism to see if a symbol is a module is fine.

>> is(std == package) == __traits(isPackage, std);
> 
> And this is broken af right now anyway. As of the newest dmd, trying to actually modules from imports slams into a brick wall.

Not sure what this was supposed to mean.

-Steve
October 07, 2020
On Wednesday, 7 October 2020 at 19:15:30 UTC, Paul Backus wrote:
> On Wednesday, 7 October 2020 at 19:07:34 UTC, H. S. Teoh wrote:
>> I'm on the fence about this one. Having to type __traits(isModule,xxx) is painful.  Is it really necessary to make it so hard just to check whether a symbol is a module??  It's not as if it's something we want to discourage.  Typing is(xxx == module) is much easier, and more pleasant on the eyes.
>
> IMO this is one of those situations where your pain is trying to tell you something. If using __traits syntax is so painful that we're willing to add hacky special cases to other language features in order to avoid it, maybe the message we should take from that is "we need to improve __traits syntax."
>
> Here's my strawman proposal: turn all __traits into properties. A few before-and-after examples:
>
> __traits(isModule, foo)
>   => foo.__isModule
>
> __traits(getMember, T, "x")
>   => T.__member("x")
>
> __traits(compiles, some(kind, of + expression))
>   => (some(kind, of + expression)).__compiles

I don't think that looks much better.
__traits are actually fine in my eyes.
It's easy on semantic and parser.
Determining whether a trait applies and therefore should be imported into the properties of a given node is more nasty.
(It means you have to change semanticX and semanticY as well as resolvePropertiesX in DMD)
October 07, 2020
On Wednesday, 7 October 2020 at 20:08:02 UTC, Stefan Koch wrote:
> On Wednesday, 7 October 2020 at 19:15:30 UTC, Paul Backus wrote:
>>
>> Here's my strawman proposal: turn all __traits into properties. A few before-and-after examples:
>>
>> __traits(isModule, foo)
>>   => foo.__isModule
>>
>> __traits(getMember, T, "x")
>>   => T.__member("x")
>>
>> __traits(compiles, some(kind, of + expression))
>>   => (some(kind, of + expression)).__compiles
>
> I don't think that looks much better.
> __traits are actually fine in my eyes.
> It's easy on semantic and parser.
> Determining whether a trait applies and therefore should be imported into the properties of a given node is more nasty.
> (It means you have to change semanticX and semanticY as well as resolvePropertiesX in DMD)

Couldn't you unconditionally lower <Node>.__isModule to __traits(isModule, <Node>) regardless of what type of node it is, and rely on the existing error messages for incorrect trait arguments? You don't have to worry about shadowing "real" properties, because anything that starts with "__" is a reserved identifier.
October 07, 2020
On Wednesday, 7 October 2020 at 20:19:57 UTC, Paul Backus wrote:
>
> Couldn't you unconditionally lower <Node>.__isModule to __traits(isModule, <Node>) regardless of what type of node it is, and rely on the existing error messages for incorrect trait arguments? You don't have to worry about shadowing "real" properties, because anything that starts with "__" is a reserved identifier.

I could do that.

« First   ‹ Prev
1 2 3 4 5 6