www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - opMixin or mixin function templates with convenience operator?

reply aliak <something something.com> writes:
So the interpolated dip thread got me thinking, and wondering if 
any time there's been a proposal for an opMixin? It can possibly 
be the hash tag symbol? And opMixin does what mixin does, and 
mixes the code in the spot.

struct interpolator {
   void opMixin!(string)() {
   }
}

// globally declared interpolator
interpolator i;

--- code.d

import interpolation;



Advantages over template mixins include that this has a return 
type so it can be used to create things out of the current 
context and give you something back.

auto html = json#q{ // compile error if invalid json
   "hello": "${variable}",
   "another: "${a + b}",
};

Another one is function mixin templates? So maybe that can be 
done with eponymous mixin templates?

mixin template i(string str) {
     string i() {
         return str;
     }
}



If it can't be done eponymously then how about:

mixin string s(string str)() {
   // parse str
   return mixin(stuff);
}


And this enables string interpolation libraries that have the 
syntax that any or all of the dips that are being propose have.

- ali
Dec 12 2019
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 12 December 2019 at 10:33:21 UTC, aliak wrote:
 struct interpolator {
   void opMixin!(string)() {
   }
 }

 // globally declared interpolator
 interpolator i;
Ok, so this is interesting, in the sense that you can have a runtime configured interpolator that can take localization for various countries into account. But opMixin should take any parameter, not just string. so you could do:
 Advantages over template mixins include that this has a return 
 type so it can be used to create things out of the current 
 context and give you something back.
Yes. It could be used for composition at runtime. But how do you type check the resulting code? This is getting close to AST macros... but you should be able to put constraint on the resulting AST.
Dec 12 2019
next sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 12 December 2019 at 11:39:46 UTC, Ola Fosheim 
Grøstad wrote:
 [snip]

 This is getting close to AST macros... but you should be able 
 to put constraint on the resulting AST.
If it is anything like AST macros, then I wouldn't expect Walter to be that supportive of it...
Dec 12 2019
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 12 December 2019 at 14:28:52 UTC, jmh530 wrote:
 If it is anything like AST macros, then I wouldn't expect 
 Walter to be that supportive of it...
It isn't. Just typing constraints. A string mixin that is type checked after construction.
Dec 12 2019
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On Thursday, 12 December 2019 at 14:28:52 UTC, jmh530 wrote:

 If it is anything like AST macros, then I wouldn't expect 
 Walter to be that supportive of it...
I think one of the reasons AST macros are not liked and that this idea will not be liked either is because there's basically no visual indication on the calling side that some code will be mixed in. -- /Jacob Carlborg
Dec 13 2019
parent reply Aliak <something something.com> writes:
On Friday, 13 December 2019 at 13:15:12 UTC, Jacob Carlborg wrote:
 On Thursday, 12 December 2019 at 14:28:52 UTC, jmh530 wrote:

 If it is anything like AST macros, then I wouldn't expect 
 Walter to be that supportive of it...
I think one of the reasons AST macros are not liked and that this idea will not be liked either is because there's basically no visual indication on the calling side that some code will be mixed in. -- /Jacob Carlborg
Won’t the pound symbol denote that from the calling side?
Dec 13 2019
parent Jacob Carlborg <doob me.com> writes:
On 2019-12-14 00:23, Aliak wrote:

 Won’t the pound symbol denote that from the calling side?
I'm not sure it's enough. -- /Jacob Carlborg
Dec 14 2019
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On Thursday, 12 December 2019 at 11:39:46 UTC, Ola Fosheim 
Grøstad wrote:

 This is getting close to AST macros... but you should be able 
 to put constraint on the resulting AST.
I agree. Therefore I think it would be much better to implement AST macros. Yet again we have an issue that AST macros can solve but Walter and company prefers to have specialized features instead of generic ones. -- /Jacob Carlborg
Dec 13 2019
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 13 December 2019 at 13:17:24 UTC, Jacob Carlborg wrote:
 On Thursday, 12 December 2019 at 11:39:46 UTC, Ola Fosheim 
 Grøstad wrote:

 This is getting close to AST macros... but you should be able 
 to put constraint on the resulting AST.
I agree. Therefore I think it would be much better to implement AST macros.
Since D is not changing much anymore it could be the right time to introduce AST macros. Although I think it should follow this route: 1. refactor the compiler so that as much as possible is done as lowerings 2. create a minimal IR that (1.) can lower to 3. implement the lowerings as AST macros to the IR 4. add AST macro features to the language So it cannot happen over night...
Dec 13 2019
prev sibling next sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 14/12/2019 2:17 AM, Jacob Carlborg wrote:
 On Thursday, 12 December 2019 at 11:39:46 UTC, Ola Fosheim Grøstad wrote:
 
 This is getting close to AST macros... but you should be able to put 
 constraint on the resulting AST.
I agree. Therefore I think it would be much better to implement AST macros. Yet again we have an issue that AST macros can solve but Walter and company prefers to have specialized features instead of generic ones. -- /Jacob Carlborg
I've talked about this before with async, but I'm partial towards having a specialized string like q"" that will always be mixed in i.e. [handler.]async { <brace matched text> } expands to: mixin(handler("<brace matched text>")); Or something like that, with a default handler being available based upon scope. It would be preferable to be able to lookup declarations available in the callee's scope to do reflection on it.
Dec 13 2019
parent rikki cattermole <rikki cattermole.co.nz> writes:
On 14/12/2019 2:31 AM, rikki cattermole wrote:
 
 I've talked about this before with async, but I'm partial towards having 
 a specialized string like q"" that will always be mixed in i.e.
That should be q{} of course, damn widget rendering! I'm even forgetting basic tokens.
Dec 13 2019
prev sibling parent reply mipri <mipri minimaltype.com> writes:
On Friday, 13 December 2019 at 13:17:24 UTC, Jacob Carlborg wrote:
 Yet again we have an issue that AST macros can solve but Walter 
 and company prefers to have specialized features instead of 
 generic ones.
This is a valid Forth program: : rotchar ( c -- c' ) dup [char] a [ char m 1+ ] literal within 13 and over [char] A [ char M 1+ ] literal within 13 and + over [char] n [ char z 1+ ] literal within -13 and + over [char] N [ char Z 1+ ] literal within -13 and + + ; : rot13 ( -- ) begin begin 0 parse dup while 2dup bounds do i c rotchar i c! loop evaluate repeat 2drop refill 0= until ; .( hello) rot13 fcnpr .( jbeyq) pe olr Output: hello world Once evaluation hits ROT13, subsequent code is only evaluated after getting rot13'd. So that FCNPR is actually SPACE ,etc. Through PARSE and REFILL , ROT13 takes over compiling the rest of the program. You can even do it recursively, rot13 .( ebg13 jbeyg) pe ebg13 .( rotated all the way back again!) cr Common Lisp has similar capabilities with the rarely used reader macros. Yes, even the "programmable programming language" has features its adherents are loathe to use. So generic solutions are not that hard to think of, and the idea of languages where normal user words can participate in compilation to this degree have been around for a long time. The problem is that nobody wants to even think about touching "other people's code" in the resulting family of languages. I can't deny that you have some legitimate pattern or gripe but I think the stated bias is fine.
Dec 13 2019
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 13 December 2019 at 13:53:00 UTC, mipri wrote:
 So generic solutions are not that hard to think of, and the
 idea of languages where normal user words can participate in
 compilation to this degree have been around for a long time.
 The problem is that nobody wants to even think about touching
 "other people's code" in the resulting family of languages.
That has nothing to do with AST manipulation. Forth was designed for taking minimal space and was edited in non-scrollable screens of ~1000 characters. You can't be more terse. Postscript is very close to Forth though, and you can write clean code in Postscript. Lisp was also designed as an exercise in minimalism. Lisp and Forth are basically the two of the oldest languages still in use. If anything that shows that they got something right... but arcane obviously. If you want to discuss modern "AST" based languages you should take a look at modern Term Rewriting languages: http://maude.cs.illinois.edu/w/index.php/The_Maude_System https://agraef.github.io/pure-lang/
Dec 13 2019
parent reply mipri <mipri minimaltype.com> writes:
On Friday, 13 December 2019 at 14:29:48 UTC, Ola Fosheim Grøstad 
wrote:
 On Friday, 13 December 2019 at 13:53:00 UTC, mipri wrote:
 So generic solutions are not that hard to think of, and the
 idea of languages where normal user words can participate in
 compilation to this degree have been around for a long time.
 The problem is that nobody wants to even think about touching
 "other people's code" in the resulting family of languages.
That has nothing to do with AST manipulation.
"generic solutions" vs. "specific solutions" has everything to do with AST manipulation vs. a specific string interpolation method.
 Forth was designed for taking minimal space and was edited in 
 non-scrollable screens of ~1000 characters. You can't be more 
 terse. Postscript is very close to Forth though, and you can 
 write clean code in Postscript.
What has absolutely nothing to do with anything, is this.
 Lisp was also designed as an exercise in minimalism. Lisp and 
 Forth are basically the two of the oldest languages still in 
 use. If anything that shows that they got something right... 
 but arcane obviously.
And this.
 If you want to discuss modern "AST" based languages you should 
 take a look at modern Term Rewriting languages:

 http://maude.cs.illinois.edu/w/index.php/The_Maude_System

 https://agraef.github.io/pure-lang/
And, amazingly, this. Please try harder to read what people say instead of responding to keywords like 'Forth' and 'Lisp. That's impolite. I think what you've done here is also impolite.
Dec 13 2019
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 13 December 2019 at 14:39:41 UTC, mipri wrote:
 That's impolite. I think what you've done here is also impolite.
What is impolite is to try to shoot down the relevance of having AST macros by pointing to Forth and Lisp. What are you trying to achieve by pointing to ancient languages that use cryptic identifiers for historic reasons? AST macros are no worse than templates. And certainly a lot better than string mixins!
Dec 13 2019
parent reply mipri <mipri minimaltype.com> writes:
On Friday, 13 December 2019 at 14:52:27 UTC, Ola Fosheim Grøstad 
wrote:
 What is impolite is to try to shoot down the relevance of
 having AST macros by pointing to Forth and Lisp.
What I am trying to do is state that a bias towards specialized features rather than generic ones is a very reasonable bias for a language designer to have. That's it. If a metaprogramming DIP came along I wouldn't object that "Lisp tried this and it was bad".
 What are you
 trying to achieve by pointing to ancient languages that use
 cryptic identifiers for historic reasons?
I mentioned PARSE and REFILL from Forth, and reader macros from Common Lisp. The age and identifiers of these languages has nothing to do with the capabilities of those features. What they represent is a kind of 'final DIP'. If any DIP can be objected to with "this can be done in a library", then the final DIP is the one that lets you do anything at all in a library. If you *don't* have a bias towards specific solutions then I think you'll eventually come up with a solution like this, and I propose that it -- not "AST macros" -- is a bad idea.
 AST macros are no worse than templates.
They really are, though. They're invariably much uglier and harder to maintain than templates. I think that if you want to have AST macros, you should certainly have a feature like templates as both A) a stopgap, so that not everything has to be done with AST macros, and B) a destination for AST macros. It's a very different 'template', but consider this Nim: import strutils func maybeQuote(str: string): string = if {' ', ','} in str: '\'' & str & '\'' else: str template `-->`(str: typed, field: untyped): untyped = str & ':' & maybeQuote($field) echo "hi" --> "hi" Output: hi:hi With a macro you could introduce a syntax echo --- hi With the same output of "hi:hi" How should you do that? Well, you can do it entirely in the ugly macro system, or you can have 1-2 lines of code that just emits `"hi" --> "hi"`, using the template. The macro becomes a way of augmenting the template with a stringification power, and the combination of template * macro is much easier to read and understand than would be a macro generating the final Nim. I imagine I'd come to the same conclusions about how best to employ AST macros in D.
 And certainly a lot better than string mixins!
Dec 13 2019
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 13 December 2019 at 15:24:32 UTC, mipri wrote:
 On Friday, 13 December 2019 at 14:52:27 UTC, Ola Fosheim 
 Grøstad wrote:
 What is impolite is to try to shoot down the relevance of
 having AST macros by pointing to Forth and Lisp.
What I am trying to do is state that a bias towards specialized features rather than generic ones is a very reasonable bias for a language designer to have. That's it. If a metaprogramming DIP came along I wouldn't object that "Lisp tried this and it was bad".
It was reasonable for D1, which was a simple language! But when they went full on meta-programming with D2, and stated that this was their focus then they should try to do a lot better than other competing languages in that department. You have to cut down bloat somewhere. So you have to choose: 1. have lots of special features 2. enable libraries to implement it and have lots of meta programing features If you do both, you end up with an umanagable mess that goes nowhere.
 I mentioned PARSE and REFILL from Forth, and reader macros from
 Common Lisp. The age and identifiers of these languages has
 nothing to do with the capabilities of those features. What
Well, it kinda does, but regardless. Nobody has stated what AST manipulation in D would look like, so what outdated languages have done isn't really relevant unless someone propose exactly the same.
 they represent is a kind of 'final DIP'. If any DIP can be
 objected to with "this can be done in a library", then the
 final DIP is the one that lets you do anything at all in a
 library. If you *don't* have a bias towards specific solutions
 then I think you'll eventually come up with a solution like
 this, and I propose that it -- not "AST macros" -- is a bad
 idea.
Golden rule in programming language design: 1. implement it as a library construct first 2. enhance the language so it can be done as a library construct 3. if it still is too heavy on syntax add syntactic sugar for it 4. if it cannot be done at all, then most reluctantly consider a language change, but resist, resist resist… 5. if you find yourself adding more and more features. Freeze the language. Start over from scratch, build a new language, because what you started with has aggregated too much cruft and is in danger of becoming unmanagble. That means there was something insufficient in the language premises.
 How should you do that? Well, you can do it entirely in the
 ugly macro system, or you can have 1-2 lines of code that just
 emits `"hi" --> "hi"`, using the template.
Nobody has suggested that D should add anything ugly. Did you look at Term Rewriting?
 I imagine I'd come to the same conclusions about how best to
 employ AST macros in D.
Why would you imagine anything about a design nobody has even proposed???
Dec 13 2019
parent reply Paul Backus <snarwin gmail.com> writes:
On Friday, 13 December 2019 at 15:38:14 UTC, Ola Fosheim Grøstad 
wrote:
 I mentioned PARSE and REFILL from Forth, and reader macros from
 Common Lisp. The age and identifiers of these languages has
 nothing to do with the capabilities of those features. What
Well, it kinda does, but regardless. Nobody has stated what AST manipulation in D would look like, so what outdated languages have done isn't really relevant unless someone propose exactly the same.
Walter and Andrei's proposal from 2012 [1] looked like this: // definition macro debugPrint(expr) { writefln("%s(%s): %s == %s", __FILE__, __LINE__, expr.stringof, expr) } // usage debugPrint(2 + 2); You'll notice that there's no direct manipulation of the AST--everything is done by substitution. [1] https://www.youtube.com/watch?v=FRfTk44nuWE&t=1h5m37s
Dec 13 2019
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 13 December 2019 at 16:07:01 UTC, Paul Backus wrote:
 You'll notice that there's no direct manipulation of the 
 AST--everything is done by substitution.
Yes, and there are many ways to do substitution. Full term rewriting is extremely powerful, to the extent that it is used for formal proofs and verifiable programming. That is going a bit far. On the other end of the spectrum you have very limited pattern matching languages like XSLT that compensate for the simplicity by providing entrypoints for scripting (javascript). So it is possible that something like XSLT (substitution) with CTFE where XSLT use javascript could work. Pattern matching transforms with some CTFE mixed in can provide elegant AST manipulation. In my experience it leads to code that is relatively easy to read and understand and feels familiar for people with FP background.
Dec 13 2019
parent reply Paul Backus <snarwin gmail.com> writes:
On Friday, 13 December 2019 at 16:44:17 UTC, Ola Fosheim Grøstad 
wrote:
 On Friday, 13 December 2019 at 16:07:01 UTC, Paul Backus wrote:
 You'll notice that there's no direct manipulation of the 
 AST--everything is done by substitution.
Yes, and there are many ways to do substitution.
The youtube link in my previous post has a time code that will bring you directly to the start of the segment on macros. In that segment, Walter explains in detail how macros would be expanded, with worked examples on the whiteboard. Pattern matching is also discussed.
Dec 13 2019
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 13 December 2019 at 17:00:29 UTC, Paul Backus wrote:
 The youtube link in my previous post has a time code that will 
 bring you directly to the start of the segment on macros. In 
 that segment, Walter explains in detail how macros would be 
 expanded, with worked examples on the whiteboard. Pattern 
 matching is also discussed.
I have only time to skim over it, but it looks very basic.
Dec 13 2019
prev sibling next sibling parent reply Zoadian <no no.no> writes:
On Thursday, 12 December 2019 at 10:33:21 UTC, aliak wrote:
 So the interpolated dip thread got me thinking, and wondering 
 if any time there's been a proposal for an opMixin? It can 
 possibly be the hash tag symbol? And opMixin does what mixin 
 does, and mixes the code in the spot.

 struct interpolator {
   void opMixin!(string)() {
   }
 }

 // globally declared interpolator
 interpolator i;

 --- code.d

 import interpolation;



 Advantages over template mixins include that this has a return 
 type so it can be used to create things out of the current 
 context and give you something back.

 auto html = json#q{ // compile error if invalid json
   "hello": "${variable}",
   "another: "${a + b}",
 };

 Another one is function mixin templates? So maybe that can be 
 done with eponymous mixin templates?

 mixin template i(string str) {
     string i() {
         return str;
     }
 }



 If it can't be done eponymously then how about:

 mixin string s(string str)() {
   // parse str
   return mixin(stuff);
 }


 And this enables string interpolation libraries that have the 
 syntax that any or all of the dips that are being propose have.

 - ali
this is similar to my idea. for reference: https://forum.dlang.org/post/qqrblbqygugpkkqgttxp forum.dlang.org I'm all in favor of improving D meta programming to the point we can express stuff like string interpolation in library code because it might allow for other new cool stuff we were not able to do before.
Dec 12 2019
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 12 December 2019 at 11:48:47 UTC, Zoadian wrote:
 I'm all in favor of improving D meta programming to the point 
 we can express stuff like string interpolation in library code 
 because it might allow for other new cool stuff we were not 
 able to do before.
Yes, but you also need to reduce the chance of the mixin doing things completely unexpected or being used for weird things. I suggest the following constraints: 1. opMixin should resolve to the executing of an anonymous function with the following constraints: a. the function must return something that can be used in an expression b. the function must be pure c. all parameters given to the function must be const d. all the parameters given to the function must be found in the opMixin input e. parameters should compile (obviously) 2. opMixin can only be used where you have a expression 1d) will be adhoc for strings, basically it requires the opMixin output function parameters to be word-boundary substrings in the opMixin input. function like this: anonfunc(value) anonfunc(My) anonfunc(pony) anonfunc(pony +2) but nothing else (for 1 parameter)
Dec 12 2019
prev sibling next sibling parent jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 12 December 2019 at 11:48:47 UTC, Zoadian wrote:
 [snip]

 this is similar to my idea. for reference:
 https://forum.dlang.org/post/qqrblbqygugpkkqgttxp forum.dlang.org
The comment immediately after yours (at least viewing it on the web client) but not directly responding to you is about re-inventing the Lisp reader macro. I don't know much about Lisp, but when I checked it out [1] it looks quite similar to what people are trying to achieve with this idea. One difference would be that in Lisp they can assign the reader macro to something like "`" or "'", which I imagine Walter would be opposed to because he does not favor creating arbitrary DSL's. [1] https://lisper.in/reader-macros
Dec 12 2019
prev sibling parent reply bachmeier <no spam.net> writes:
On Thursday, 12 December 2019 at 11:48:47 UTC, Zoadian wrote:

 I'm all in favor of improving D meta programming to the point 
 we can express stuff like string interpolation in library code 
 because it might allow for other new cool stuff we were not 
 able to do before.
I'm not, because you'll drive away large numbers of potential users. Metaprogramming might be cool, but you need to keep it under control because it can make the complexity of learning and using the language explode.
Dec 12 2019
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Dec 12, 2019 at 04:53:36PM +0000, bachmeier via Digitalmars-d wrote:
 On Thursday, 12 December 2019 at 11:48:47 UTC, Zoadian wrote:
 
 I'm all in favor of improving D meta programming to the point we can
 express stuff like string interpolation in library code because it
 might allow for other new cool stuff we were not able to do before.
I'm not, because you'll drive away large numbers of potential users. Metaprogramming might be cool, but you need to keep it under control because it can make the complexity of learning and using the language explode.
Wut...?! The primary reason I'm using D is *because* of metaprogramming features. It's one of the things about D that stands out above other languages and differentiates it from them. For me, it's one of the important things that make it worth using D in spite of whatever other flaws D may have. Adam is currently working on a Java<->D glue library via JNI, which is turning out to be *extremely* nice: you just declare a class and annotate its methods with Import and Export, and it automagically creates JNI glue code, creates the right mangling, handles type conversions, etc., and you can call Java code from D directly (and vice versa). You don't even need to do anything special (other than link with the JNI interface library of your chosen JVM) to make this work; just "import arsd.jni", derive your class from the provided template base class, and start calling Java methods like they were native D code. The core of this library is some powerful metaprogramming not found in any other language to my knowledge. Compile-time introspection, static foreach, UDAs, and pragma(mangle) all come together in one powerful package that completely automates what in any other language would have required truckloads of boilerplate and awkward external code generation tools. In D, the entire implementation sits in a single .d file. Bring on the metaprogramming, I say. Make string interpolation another powerful tool in the metaprogramming toolbox, and take D to a whole new level of awesome. We should be embracing and honing metaprogramming in D, not shying away from it! T -- "You are a very disagreeable person." "NO."
Dec 12 2019
parent reply bachmeier <no spam.net> writes:
On Thursday, 12 December 2019 at 17:19:35 UTC, H. S. Teoh wrote:

 Wut...?!  The primary reason I'm using D is *because* of 
 metaprogramming features.  It's one of the things about D that 
 stands out above other languages and differentiates it from 
 them.  For me, it's one of the important things that make it 
 worth using D in spite of whatever other flaws D may have.
You're not the average programmer considering using D. You've got years of experience with D, and probably C and C++ as well. Metaprogramming has its place. You can definitely overdo it though, making your code hard to read and driving folks to other languages. Take a look at the use of templates. Do they have a place? Sure. But one person after another also complains about the difficult of learning the standard library because of the incredible overhead. I feel I have to keep bringing this up, because at least around here, there are very few concerns for new users that just want to write code.
Dec 12 2019
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 12 December 2019 at 17:59:25 UTC, bachmeier wrote:
 I feel I have to keep bringing this up, because at least around 
 here, there are very few concerns for new users that just want 
 to write code.
Yes, but I think the solution is to create a language separation between library code and application code. That would force library authors to write APIs that does not require advanced syntax, but could still use advanced features internally.
Dec 12 2019
prev sibling next sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 12 December 2019 at 10:33:21 UTC, aliak wrote:
 [snip]


 And this enables string interpolation libraries that have the 
 syntax that any or all of the dips that are being propose have.

 - ali
The idea for the convenience operator is discussed on the DIP 1027 thread [1] by Paul Backus (though he uses and I'm a bit simple re-write of writeln( interp!"The number ${num} doubled is ${num * 2}!")); to writeln(mixin(interp!"The number ${num} doubled is ${num * 2}!")); I find it an interesting idea, but wonder what the consequences of this are more generally. [1] https://forum.dlang.org/thread/abhpqwxqgiyzgqxmjaky forum.dlang.org?page=7#post-tlyhhcpomntiwoqxsvjj:40forum.dlang.org
Dec 12 2019
parent reply Paul Backus <snarwin gmail.com> writes:
On Thursday, 12 December 2019 at 17:26:19 UTC, jmh530 wrote:
 The idea for the convenience operator is discussed on the DIP 
 1027 thread [1] by Paul Backus (though he uses   and I'm a bit 

 simple re-write of
 writeln( interp!"The number ${num} doubled is ${num * 2}!"));
 to
 writeln(mixin(interp!"The number ${num} doubled is ${num * 
 2}!"));

 I find it an interesting idea, but wonder what the consequences 
 of this are more generally.
I managed to find the source for this idea: it's a Github comment by Nick Treleaven on an earlier string interpolation DIP. https://github.com/dlang/DIPs/pull/140#pullrequestreview-212264577 Personally, I prefer this rewriting approach to something like opMixin because it doesn't require you to declare a struct as boilerplate, and it works "out of the box" for both templates and CTFE, as well as "naked" strings: #foo!(args) => mixin(foo!args) #foo(args) => mixin(foo(args)) #someCode => mixin(someCode)
Dec 12 2019
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 12 December 2019 at 18:24:30 UTC, Paul Backus wrote:
 Personally, I prefer this rewriting approach to something like 
 opMixin because it doesn't require you to declare a struct as 
 boilerplate, and it works "out of the box" for both templates 
 and CTFE, as well as "naked" strings:

     #foo!(args) => mixin(foo!args)
     #foo(args)  => mixin(foo(args))
     #someCode   => mixin(someCode)
It is too noisy for formatting. Also, too hard for newbies to use, they will misapply it and get weird errors. You need a type check on the library type to ensure that it has been designed for mixin. (Mixin should not exist on the application level.)
Dec 12 2019
parent reply Paul Backus <snarwin gmail.com> writes:
On Thursday, 12 December 2019 at 18:35:03 UTC, Ola Fosheim 
Grøstad wrote:
 It is too noisy for formatting. Also, too hard for newbies to 
 use, they will misapply it and get weird errors.
I don't think it's any harder to use than the `mixin` keyword, though I'll concede that it's more cryptic to read and harder to search for in the documentation. On the other hand, I think both of those arguments also apply to opMixin. Newbies are not likely to have an easy time understanding the difference between `foo!(args)` and difference between `foo(args)` and `foo!(args)`.)
 You need a type check on the library type to ensure that it has 
 been designed for mixin. (Mixin should not exist on the 
 application level.)
I'm not sure I understand what you mean. The only type you can mix in is `string`. There's no "library type" involved at all. Even the original "interpolator" example is really just a template function that takes a string as a compile-time argument and returns another string. Are you proposing a language-level distinction between "string that contains D code for mixing in" and "string that contains some other kind of data"? I can see how that would be a useful thing to have, though it strikes me as orthogonal to the discussion in this thread--all uses of string mixins would benefit from it equally.
Dec 12 2019
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 12 December 2019 at 19:08:40 UTC, Paul Backus wrote:
 I don't think it's any harder to use than the `mixin` keyword, 
 though I'll concede that it's more cryptic to read and harder 
 to search for in the documentation.
I think a solution for string interpolation has to be very close to what other languages offer, maybe it would have to be made a special case for strings.
 On the other hand, I think both of those arguments also apply 
 to opMixin. Newbies are not likely to have an easy time 
 understanding the difference between `foo!(args)` and 

 difference between `foo(args)` and `foo!(args)`.)
Yes, I agree. If you specialcase mixin-providers that only take one string parameter, then it is possible to come up with a protocol, that can provide something that is "fool proof" and simple syntax: The compiler type checks the variable f for satisfying a string-interpolation protocol. And it is only allowed to return a mixin string that generates a pure lambda function with const parameters and some other constraints. Could even constrain the lambda to return a string or tuple.
 Are you proposing a language-level distinction between "string 
 that contains D code for mixing in" and "string that contains 
 some other kind of data"?
Yes, I guess it would be possible to type a mixin-string in such a way that it is only allowed to represent a lambda function that is being called. As in typing the string to a function signature, would be one step. Maybe it can be expressed in D code already. Probably not enough, but one step.
Dec 12 2019
parent reply Paul Backus <snarwin gmail.com> writes:
On Thursday, 12 December 2019 at 19:42:59 UTC, Ola Fosheim 
Grøstad wrote:
 On Thursday, 12 December 2019 at 19:08:40 UTC, Paul Backus 
 wrote:
 I don't think it's any harder to use than the `mixin` keyword, 
 though I'll concede that it's more cryptic to read and harder 
 to search for in the documentation.
I think a solution for string interpolation has to be very close to what other languages offer, maybe it would have to be made a special case for strings.
I agree. Personally, I'm a fan of Adam Ruppe's proposal. A mixin operator would have applications beyond just string interpolation, though. For example, it could make pattern matching a bit more palatable: a[i .. j].match!( #pattern!`[] => false`, #pattern!`[xs...] => search(xs, target)` );
 Are you proposing a language-level distinction between "string 
 that contains D code for mixing in" and "string that contains 
 some other kind of data"?
Yes, I guess it would be possible to type a mixin-string in such a way that it is only allowed to represent a lambda function that is being called. As in typing the string to a function signature, would be one step.
Is there any actual difference between mixing in a bare expression vs. an immediately-called lambda function that evaluates to the same expression? Forcing string mixins to represent lambdas in particular seems needlessly restrictive.
Dec 12 2019
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 12 December 2019 at 21:40:33 UTC, Paul Backus wrote:
 Is there any actual difference between mixing in a bare 
 expression vs. an immediately-called lambda function that 
 evaluates to the same expression? Forcing string mixins to 
 represent lambdas in particular seems needlessly restrictive.
The idea is to prevent writing to variables outside the mixin. So, pure and const params would perhaps be enough to enable that?
Dec 12 2019
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Thursday, 12 December 2019 at 22:02:22 UTC, Ola Fosheim 
Grøstad wrote:
 On Thursday, 12 December 2019 at 21:40:33 UTC, Paul Backus 
 wrote:
 Is there any actual difference between mixing in a bare 
 expression vs. an immediately-called lambda function that 
 evaluates to the same expression? Forcing string mixins to 
 represent lambdas in particular seems needlessly restrictive.
The idea is to prevent writing to variables outside the mixin. So, pure and const params would perhaps be enough to enable that?
Why is that a desirable goal in the first place? The whole point of a string mixin is that it's the same as if you'd typed the code yourself. It's the tool you reach for when you need maximum expressive power, and nothing else will do. If what you actually want is a pure const lambda, there's nothing stopping you from writing one and sticking your mixin inside it.
Dec 12 2019
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 12 December 2019 at 22:17:59 UTC, Paul Backus wrote:
 If what you actually want is a pure const lambda, there's 
 nothing stopping you from writing one and sticking your mixin 
 inside it.
Just basic software engineering. No external entity should be able to access anything in the calling context that has not been explicitly exported. It does not scale well as it can lead to bugs that are hard to locate. So, it is an attempt to mitigate the problematic "macro" aspect of mixins and make the construct hygenic.
Dec 12 2019
parent reply Paul Backus <snarwin gmail.com> writes:
On Thursday, 12 December 2019 at 22:25:25 UTC, Ola Fosheim 
Grøstad wrote:
 On Thursday, 12 December 2019 at 22:17:59 UTC, Paul Backus 
 wrote:
 If what you actually want is a pure const lambda, there's 
 nothing stopping you from writing one and sticking your mixin 
 inside it.
Just basic software engineering. No external entity should be able to access anything in the calling context that has not been explicitly exported. It does not scale well as it can lead to bugs that are hard to locate. So, it is an attempt to mitigate the problematic "macro" aspect of mixins and make the construct hygenic.
I agree, which I why I try to use string mixins in my own code as little as possible. Nevertheless, it is occasionally very useful to be able to do unhygienic macro-like things. If it were up to me, I'd add AST macros to D and use those, but as it is, string mixins are the only available tool for the job. I would very much prefer not to have that tool taken away, sharp though it may be.
Dec 12 2019
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 12 December 2019 at 23:13:42 UTC, Paul Backus wrote:
 only available tool for the job. I would very much prefer not 
 to have that tool taken away, sharp though it may be.
Oh, I only meant it for the string-interpolation interface, not in general.
Dec 12 2019
prev sibling parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Thursday, 12 December 2019 at 22:02:22 UTC, Ola Fosheim 
Grøstad wrote:
 On Thursday, 12 December 2019 at 21:40:33 UTC, Paul Backus 
 wrote:
 Is there any actual difference between mixing in a bare 
 expression vs. an immediately-called lambda function that 
 evaluates to the same expression? Forcing string mixins to 
 represent lambdas in particular seems needlessly restrictive.
The idea is to prevent writing to variables outside the mixin. So, pure and const params would perhaps be enough to enable that?
toString()? I see what you're trying to do, but IMO there are too many cases where the outlined restrictions cause undue problems. -- Simen
Dec 13 2019
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Friday, 13 December 2019 at 12:37:31 UTC, Simen Kjærås wrote:


 toString()?
No, I don't think the first one would fail. It would: mixin("pure_lambda(foo++)") So similar to const tmp = foo++; pure_lambda(tmp); non-const toString() would fail if interpolate builds a string, but not if it builds a tuple.
 I see what you're trying to do, but IMO there are too many 
 cases where the outlined restrictions cause undue problems.
Well, it will not cause a problem for the tuple that Walter's DIP create. So it certainly is no worse than the proposed DIP?
Dec 13 2019
prev sibling parent jmh530 <john.michael.hall gmail.com> writes:
On Thursday, 12 December 2019 at 19:08:40 UTC, Paul Backus wrote:
 On Thursday, 12 December 2019 at 18:35:03 UTC, Ola Fosheim 
 Grøstad wrote:
 It is too noisy for formatting. Also, too hard for newbies to 
 use, they will misapply it and get weird errors.
I don't think it's any harder to use than the `mixin` keyword, though I'll concede that it's more cryptic to read and harder to search for in the documentation.
[snip] One thing I would be worried about is instead of string s = "int y;"; mixin(s); someone would do string s = "int y;"; #s; ... //some point later y++; and then try to debug that if something goes wrong. So would you do this for both mixin expressions and statements? I feel like limiting it to mixin expressions might actually make some of the risk of cryptic stuff happening a little less.
Dec 12 2019
prev sibling next sibling parent Daniel Kozak <kozzi11 gmail.com> writes:
On Thu, Dec 12, 2019 at 7:25 PM Paul Backus via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
onally, I prefer this rewriting approach to something like
 opMixin because it doesn't require you to declare a struct as
 boilerplate, and it works "out of the box" for both templates and
 CTFE, as well as "naked" strings:

      #foo!(args) => mixin(foo!args)
      #foo(args)  => mixin(foo(args))
      #someCode   => mixin(someCode)
AFAIK this is not possible. I have come with something like this many used for something else. So we would need to change it to some other character
Dec 13 2019
prev sibling parent Daniel Kozak <kozzi11 gmail.com> writes:
On Fri, Dec 13, 2019 at 9:33 PM Daniel Kozak <kozzi11 gmail.com> wrote:
 On Thu, Dec 12, 2019 at 7:25 PM Paul Backus via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
onally, I prefer this rewriting approach to something like
 opMixin because it doesn't require you to declare a struct as
 boilerplate, and it works "out of the box" for both templates and
 CTFE, as well as "naked" strings:

      #foo!(args) => mixin(foo!args)
      #foo(args)  => mixin(foo(args))
      #someCode   => mixin(someCode)
AFAIK this is not possible. I have come with something like this many used for something else. So we would need to change it to some other character
https://dlang.org/spec/lex.html#special-token-sequence
Dec 13 2019
prev sibling parent Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Thursday, 12 December 2019 at 10:33:21 UTC, aliak wrote:
 So the interpolated dip thread got me thinking, and wondering 
 if any time there's been a proposal for an opMixin? It can 
 possibly be the hash tag symbol? And opMixin does what mixin 
 does, and mixes the code in the spot.
Maybe (ab)use opDollar?
 auto html = json$q{ // compile error if invalid json
   "hello": "${variable}",
   "another: "${a + b}",
 };
Dec 12 2019