Skip to content

make ApplyLeft/ApplyRight work with deep template#4374

Merged
DmitryOlshansky merged 1 commit intodlang:masterfrom
mogud:master
Jun 8, 2016
Merged

make ApplyLeft/ApplyRight work with deep template#4374
DmitryOlshansky merged 1 commit intodlang:masterfrom
mogud:master

Conversation

@mogud
Copy link
Contributor

@mogud mogud commented May 28, 2016

The added codes in unittest not work before.

std/meta.d Outdated
template ApplyLeft(right...)
{
static if (is(typeof(Template!(args, right))))
static if (is(typeof({ enum _T = Template!(left, args); })))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right?

Copy link
Contributor

@dnadlinger dnadlinger May 28, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the alias ApplyLeft = Id!(Template!(args, right)); trick work here (where Id is a template that does the alias-ing/enum-ing)? (which would leave you with only one branch)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wilzbach I edited it on web. It's a mistake caused by ctrl + c/v. :(

@dnadlinger
Copy link
Contributor

To elaborate on my in-line comment, given this (which certainly exists somehwere in Phobos)

alias Id(T) = T;
alias Id(alias T) = T;

the implementation could simply be

template ApplyLeft(alias Template, args...)
{
    alias ApplyLeft(right...) = Id!(Template!(args, right));
}

template ApplyRight(alias Template, args...)
{
    alias ApplyRight(left...) = Id!(Template!(left, args));
}

I'm not sure why treating the zero-argument case differently would be required. Maybe that's an attempt at (premature?) optimisation; the original PR discussion should hopefully have more information.

static assert(is(Filter!(ApplyRight!(isImplicitlyConvertible, short),
ubyte, string, short, float, int) == AliasSeq!(ubyte, short)));

static assert(is(typeof({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the unit test; as you discovered, the current implementation is not nearly covered as well as it should be. However, I don't think it really makes sense to show this particular case in the documentation, as it looks pretty confusing at first, and users would just expect it to work transparently anyway. Could you move it to a non-DDoc unittest block?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Id -> Alias in meta.d? I tried the new implementation used Alias and all tests passed.

@dnadlinger
Copy link
Contributor

dnadlinger commented May 29, 2016

If you want to go this route instead of the simplified version (which is fair enough for a quick fix), could you please make sure that the unit test actually covers both the cases? It seems like the typo you had previously made in ApplyLeft slipped through the cracks.

@dnadlinger
Copy link
Contributor

The Id template I was looking for is called Alias in Phobos, albeit with slightly different (less elegant? ;P) implementation. I'd suggest using that instead of duplicating its implementation here.

@mogud
Copy link
Contributor Author

mogud commented May 30, 2016

I mentioned Alias in line note previously :). For a more elegant way to implement this, I do not know if we may also reimplement Alias to Id's you write out. As far as I know, alias can also used where an enum is needed. So why an enum case is required? I'm a complete newbie in d for only a few weeks experience.

@dnadlinger
Copy link
Contributor

dnadlinger commented May 30, 2016

@mogucpp: Sorry about that, the GitHub UI makes such comments easy to miss. The basic issue here is that (simplifying a bit) alias can only be used on types and symbols, not values. For example, alias a = 3; would not compile. However, enum a = 3; does, so one way to write these generic templates is to explicitly switch to using enum when required. However, littering all the code with two branches is unsatisfactory. This is where Alias helps – you can use it to transparently "convert" values into symbols. This way, only one case is required.

@mogud
Copy link
Contributor Author

mogud commented May 30, 2016

Sorry for my poor English misleading. I mean the current implement of Alias use static if for enum and alias cases. And in my opinion, it's not necessary.

/**
Tests whether all given items satisfy a template predicate, i.e. evaluates to
$(D F!(T[0]) && F!(T[1]) && ... && F!(T[$ - 1])).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please leave those as a paragraph break.

@dnadlinger
Copy link
Contributor

In this case, you are right. I don't know of a case where that would be required either. That being said, the fact that you can always alias alias parameters is somewhat of a little-known implementation detail, so whoever wrote and reviewed Alias might not have been aware of it. (Or my memory is outdated and there are actually cases now where the simple version doesn't work.)

@mogud
Copy link
Contributor Author

mogud commented May 30, 2016

This PR's commits looks awful. So weak I am. :(

@dnadlinger
Copy link
Contributor

Ah, we've all started out at some point. What would be embarrassing is if I didn't remember any of the old tricks – after all, my name is on that module, too. ;)

Apart from that, we generally ask people to squash their commits into one (or atomic pieces) before merging a PR anyway.

@mogud
Copy link
Contributor Author

mogud commented May 30, 2016

All commits squashed into one now. Thanks for your patience. :)

@DmitryOlshansky
Copy link
Member

DmitryOlshansky commented Jun 2, 2016

This also fixes issue https://issues.dlang.org/show_bug.cgi?id=16070

See also #4352

UPDATE: so this pull seems to be a superset of #4352 - @klickverbot which one to merge? ;)

@dnadlinger
Copy link
Contributor

dnadlinger commented Jun 2, 2016

@DmitryOlshansky: Merge the other one of you are sure that it also works for all value cases, this one to play it safe. ;)

@dnadlinger
Copy link
Contributor

@mogucpp @aG0aep6G: There has been a bit of unfortunate duplication of work going on between this and #4352 – could you guys collaborate on merging the test cases together into one PR?

@mogud
Copy link
Contributor Author

mogud commented Jun 6, 2016

Covered all cases now, i think.

@DmitryOlshansky
Copy link
Member

Just add "fixes Issue 16070" to commit message and it should be good to go.

@aG0aep6G
Copy link
Contributor

aG0aep6G commented Jun 7, 2016

Just add "fixes Issue 16070" to commit message and it should be good to go.

I think @mogucpp forgot to leave a note here. The commit message now contains "fix Issue 16070".

@DmitryOlshansky
Copy link
Member

Auto-merge toggled on

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants