digitalmars.D.learn - cannot use local f as parameter to non-global template
- aliak (34/34) Dec 08 2018 Hi, I'm wondering about why this happens in a certain situation
- Paul Backus (12/20) Dec 08 2018 The "de-sugared" version of your second `match` function looks
- aliak (14/36) Dec 10 2018 Ah, that's a good way of breaking it down. But ok, so then the
- Paul Backus (8/21) Dec 10 2018 Holder!f is a type, not a delegate, so passing it as a parameter
Hi, I'm wondering about why this happens in a certain situation
and not another. I have the following code:
struct Holder(alias fun) {
alias T = typeof(fun());
T get() { return fun(); }
alias get this;
}
template match(handlers...) {
auto match(T)(T holder) {
return handlers[0](holder);
}
}
void main() {
int f() { return i7 }
auto value = Holder!f().match!(
(int a) => f()
);
}
This compiles fine. However, if I change the match template to:
template match(handlers...) {
auto match(alias f)(Holder!f holder) {
return handlers[0](holder);
}
}
Notice the template parameter of the eponymous match is an alias
now, and the function parameter is typed as a Holder.
The error you get is basically because of bug 5710 [0] I guess.
But I'm confused as to why the same thing doesn't then happen
when using match(T) as opposed to match(alias f)?
I can work around it by have a template constraint on match of
course. But still curious why one version works and the other
not, they both have to access the same frame+context data at the
end of the day.
[0]: https://issues.dlang.org/show_bug.cgi?id=5710
Dec 08 2018
On Saturday, 8 December 2018 at 09:57:29 UTC, aliak wrote:
This compiles fine. However, if I change the match template to:
template match(handlers...) {
auto match(alias f)(Holder!f holder) {
return handlers[0](holder);
}
}
Notice the template parameter of the eponymous match is an
alias now, and the function parameter is typed as a Holder.
The "de-sugared" version of your second `match` function looks
like this:
template match(handlers...) {
template match(alias f) {
auto match(Holder!f holder) {
return handlers[0](holder);
}
}
}
Notice the second template nested inside the first. That's the
"non-gloal template" the error is complaining about.
Dec 08 2018
On Saturday, 8 December 2018 at 14:21:01 UTC, Paul Backus wrote:On Saturday, 8 December 2018 at 09:57:29 UTC, aliak wrote:Ah, that's a good way of breaking it down. But ok, so then the other version would be lowered to: template match(handlers...) { template match(T) { auto match(T holder) { return handlers[0](holder); } } } So now the second template is accessing a T, which is actually a Holder!f right? But doing that makes it "work". Even though the number of "contexts" needed to execute "handlers[0](holder)" is the same, right?This compiles fine. However, if I change the match template to: template match(handlers...) { auto match(alias f)(Holder!f holder) { return handlers[0](holder); } } Notice the template parameter of the eponymous match is an alias now, and the function parameter is typed as a Holder.The "de-sugared" version of your second `match` function looks like this: template match(handlers...) { template match(alias f) { auto match(Holder!f holder) { return handlers[0](holder); } } } Notice the second template nested inside the first. That's the "non-gloal template" the error is complaining about.
Dec 10 2018
On Monday, 10 December 2018 at 16:15:36 UTC, aliak wrote:
Ah, that's a good way of breaking it down. But ok, so then the
other version would be lowered to:
template match(handlers...) {
template match(T) {
auto match(T holder) {
return handlers[0](holder);
}
}
}
So now the second template is accessing a T, which is actually
a Holder!f right? But doing that makes it "work". Even though
the number of "contexts" needed to execute
"handlers[0](holder)" is the same, right?
Holder!f is a type, not a delegate, so passing it as a parameter
to a non-global template is fine. Issue 5710 only applies to
delegates passed directly as parameters.
Trying to reason about the "number of contexts" required is a
waste of time. There's no logical, principled reason why one
works and the other doesn't. It's purely an artifact of details
in the compiler implementation.
Dec 10 2018








Paul Backus <snarwin gmail.com>