Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 6207 - Mixin template evaluated to string can convert to string mixin expression implicitly #459

Closed
wants to merge 1 commit into from

Conversation

9rnsr
Copy link
Contributor

@9rnsr 9rnsr commented Oct 17, 2011

http://d.puremagic.com/issues/show_bug.cgi?id=6207

If mixin template instantiation makes manifest constant string and it appears in expression context, the compiler converts it implicitly to string mixin expression.

@dnadlinger
Copy link
Member

First, thanks Kenji for your tireless work on fixing DMD bugs and filling little language holes. However, contrary to many of your other fixes, I don't think this pull request is a change to the better:

Yes, string mixins and mixin templates in D are limited in the sense that you explicitly need to »embed« them using mixin at some point, and I am well aware of the consequences for metaprogramming stuff. But in my opinion, this is a feature rather than a defect, in that it allows one to reason about the code without knowing the details about all the entities involved. For example, if you write

void main() {
  auto a = "some funky value";
  foo(3);
}

you can be sure that the invocation of foo(3) is in no way related to the contents of a, without knowing what exactly foo is.

Your proposal would break this fundamental guarantees about the semantics of D code, and in my opinion, we should not allow developers to open this Pandora's box. After all, this kind of uncontrollable semantics is one of the reasons why preprocessor macros are generally avoided in C++ if possible.

If you want, I can put together a more detailed account on why I think this would not be a wise addition to the language, but right now, I'm really curious what possible applications for the feature you have been thinking of – besides introducing template access to the instantiation scope »though the back door«.

@9rnsr
Copy link
Contributor Author

9rnsr commented Oct 18, 2011

you can be sure that the invocation of foo(3) is in no way related to the contents of a, without knowing what exactly foo is.

This feature is supposed to work only if given an explicit template arguments. In the example, foo is not eligible for replacement. But if you write foo!(tiargs)(), foo!(tiargs) is eligible.

Your proposal would break this fundamental guarantees about the semantics of D code, ...

In addition, this feature generates just only an expression as a result of string mixin. Please see the following example.

mixin template Inj(string s) { enum Inj = s; }
void func() {}
void main()
{
//  Inj!("auto a = 10;");   // NG, cannot inject statement/declaration.
    Inj!("func()");         // OK, `func()` is expression.
}

Yes, I acknowledge that it can be used as a macro. But I think it is useful for DSL, and enough hygienic to accept it.

@WalterBright
Copy link
Member

I share Klickverbot's reservations about this. It's a major change, and I fear it may blow up in our faces.

… mixin expression implicitly

If mixin template instantiation makes manifest constant string and it appears in expression context, the compiler converts it implicitly to string mixin expression.
@andralex
Copy link
Member

I think this work is pertinent barring some issues. Today if anyone writes or sees sees mixin(stuff) they are well warned that arbitrary code generation is taking place and are ready to deal with the consequences. This proposal makes that assumption go away.

One aspect of hygiene is that arbitrary stuff from the context may be caught. For example, writing fun!(stuff) may capture names in the enclosing scope even though they don't occur inside stuff at all. HOWEVER sometimes that is exactly what's needed. Consider interpolation! writeln(interp!"a is $a and b is $b my friends") is all about capturing the actual values of a and b by transforming the expression into writeln("a is ", a, " and b is ", b, " my friends"). So Kenji's work would allow interpolation. Currently we'd need to write writeln(mixin(interp!"a is $a and b is $b my friends")) which is seriously reducing the impetus for the whole feature as the scaffolding is about as unwieldy as expanding the thing by hand.

Another aspect is that the mixin may define its own symbol, which would spill into the enclosing scope. But wait, an expression can't introduce symbols, so that's taken care of by design. Nice.

The last aspect is integrating these mixin subexpressions into larger expressions. Consider e.g.

int a, b;
auto x = func!("a + b")() * c;

How does the expansion occur? Would that be (a + b) * c or a + b * c? In the latter case, we're looking at the some of the unpleasantness created by C expression macros. @9rnsr please let us know

To summarize: I think this has its uses but we need to really think it through. For example, more use cases would be great. I mentioned string interpolation. What are others?

braddr pushed a commit to braddr/dmd that referenced this pull request Oct 22, 2012
Improve documentation in std.stdio
@9rnsr 9rnsr closed this Jan 22, 2013
@9rnsr
Copy link
Contributor Author

9rnsr commented Jan 22, 2013

This enhancement will not be merged in the near future, so I close it.

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.

4 participants