digitalmars.D - proposal: mixin functions to auto-mixin at call site
- Timothee Cour (31/31) Sep 02 2013 I'd like to be able to declare a function with a special @mixin property
- monarch_dodra (13/20) Sep 02 2013 Kenji had apparently implemented this:
- Jacob Carlborg (4/11) Sep 03 2013 Yes, this seems to be another workaround for some kind of AST macros.
- Timothee Cour (22/41) Sep 03 2013 The last comment from Andrei in
- monarch_dodra (8/29) Sep 03 2013 But that sill implies knowing exactly *what* is called, eg
- Ary Borenszweig (7/25) Sep 03 2013 "Today if anyone writes or sees sees mixin(stuff) they are well warned
- monarch_dodra (5/42) Sep 03 2013 But "import" is also explicit. Do you think it would be a good
- Andrej Mitrovic (6/7) Sep 03 2013 You are importing symbols. And when you do "foo()" you know you're
- Jacob Carlborg (6/11) Sep 03 2013 With properties you never know if you're invoking a method or accessing
- Dicebot (4/17) Sep 03 2013 Which is exactly why parens-less calls and properties with side
- Timothee Cour (4/22) Sep 03 2013 that's the whole point, it allows to transparently replace a field acces...
- Dicebot (7/12) Sep 04 2013 You can't replace field access with function call transparently
- Timothee Cour (8/17) Sep 04 2013 IIRC, &foo.x with x a property should take address of return value of x(...
- Dicebot (13/24) Sep 05 2013 It is not possible because getters are not guaranteed to return
- Andrej Mitrovic (8/11) Sep 03 2013 Yeah but it does something with data on its own side. If this becomes
- Ary Borenszweig (10/22) Sep 04 2013 Why would anyone do that?
- Dicebot (11/18) Sep 04 2013 By an accident - mixins are not hygienic.
- Ary Borenszweig (4/15) Sep 04 2013 So the problem is not that implicit mixin is unsafe. The problem is that...
- Dicebot (7/10) Sep 04 2013 This is the same problem. The key property of mixin is that it is
- Timothee Cour (5/15) Sep 04 2013 frankly, UFCS mixin would make the use case in the OT bearable.
- Timothee Cour (5/17) Sep 03 2013 the other part of my post was about UFCS syntax for mixin:
- Ary Borenszweig (3/10) Sep 04 2013 I know, I'm just trying to defend this point of view.
- Dicebot (7/18) Sep 04 2013 You don't do it for _every single symbol_. Good good matches
- Dicebot (2/2) Sep 03 2013 Was objecting in previous thread and have not changed my mind -
I'd like to be able to declare a function with a special mixin property that will auto-mixin at call site: mixin string foo(){return some_string;} void main(){ foo; //behaves as mixin(foo()); if mixin weren't provided } This is purely syntax sugar, as it could be done with a mixin at call site, but is very useful in a number of scenarios: Example 1: I wrote a string parsing function 'embed' that allows to embed variables in current scope in a string: void main(){ int x1=11; double x2=2.3; assert(mixin("variables: x1=$x1, x2=$x2, sum=$(x1+x2)".embed) == "variables: x1=11, x2=2.3, sum=13.3"); } The 'embed' function parses the input string, extracts the '$' tokens (with a proper escape mechanism) and return a string of the form 'std.conv.text( ...)' with appropriate arguments so that the string can be mixed in at call site as above. Without the mixin property we have: mixin("variables: x1=$x1, x2=$x2, sum=$(x1+x2)".embed) With the proposed mixin property this would simplify to: "variables: x1=$x1, x2=$x2, sum=$(x1+x2)".embed Which is simpler and easier to read than: text("variables: x1=",x1,", x2=",x2,", sum=",x1+x2); There are many other use cases. If for some reason we can't have mixin special property, can we at least have UFCS for mixin, so that we could write: "variables: x1=$x1, x2=$x2, sum=$(x1+x2)".embed.mixin
Sep 02 2013
On Tuesday, 3 September 2013 at 04:15:17 UTC, Timothee Cour wrote:I'd like to be able to declare a function with a special mixin property that will auto-mixin at call siteKenji had apparently implemented this: https://github.com/D-Programming-Language/dmd/pull/459 But pulled out. This recent thread should sum it up: http://forum.dlang.org/thread/yaasjclvyobpeftgwmke forum.dlang.org Long story short, you are basically asking for macro. If we allowed this, than anything could actually be code injection, and mean anything.If for some reason we can't have mixin special property, can we at least have UFCS for mixin, so that we could write: "variables: x1=$x1, x2=$x2, sum=$(x1+x2)".embed.mixinI'm not sure this us very interesting (why not though), since nothing would ever come after the mixin. I'd still rather have "typeof" be UFCS-able: 5.typeof.stringof.writeln(); If we only got to choose 1 that is ;)
Sep 02 2013
On 2013-09-03 07:11, monarch_dodra wrote:Kenji had apparently implemented this: https://github.com/D-Programming-Language/dmd/pull/459 But pulled out. This recent thread should sum it up: http://forum.dlang.org/thread/yaasjclvyobpeftgwmke forum.dlang.org Long story short, you are basically asking for macro. If we allowed this, than anything could actually be code injection, and mean anything.Yes, this seems to be another workaround for some kind of AST macros. -- /Jacob Carlborg
Sep 03 2013
On Mon, Sep 2, 2013 at 10:11 PM, monarch_dodra <monarchdodra gmail.com>wrote:On Tuesday, 3 September 2013 at 04:15:17 UTC, Timothee Cour wrote:The last comment from Andrei in https://github.com/D-Programming-Language/dmd/pull/459 is actually rather supportive of such feature, and seemed to encourage a more thorough discussion which never happened (AFAIK). And unlike what is said in the thread above (last comment), the feature indeed was implemented already, but not merged.I'd like to be able to declare a function with a special mixin property that will auto-mixin at call siteKenji had apparently implemented this: https://github.com/D-**Programming-Language/dmd/pull/**459<https://github.com/D-Programming-Language/dmd/pull/459> But pulled out. This recent thread should sum it up: http://forum.dlang.org/thread/**yaasjclvyobpeftgwmke forum.**dlang.org<http://forum.dlang.org/thread/yaasjclvyobpeftgwmke forum.dlang.org>Long story short, you are basically asking for macro. If we allowed this, than anything could actually be code injection, and mean anything.No, only mixin statements and mixin functions. And a regular function calling a mixin function would still be regular, eg not able to access symbols in enclosing scope by name. Given that properties can be queried at compile time, there is no ambiguity. Proper tooling can reveal which statements are mixins if needed (which doesn't imply that the language readability depends on having an IDE).If for some reason we can't have mixin special property, can we at leastWhat do you mean by "nothing would ever come after the mixin" ? You can have: some_string.embed.mixin.writeln; Simple use case: or: assert(foo(x)==bar(y), "error with $(foo(x)) and $(bar(y)) ".embed); I'd still rather have "typeof" be UFCS-able:have UFCS for mixin, so that we could write: "variables: x1=$x1, x2=$x2, sum=$(x1+x2)".embed.mixinI'm not sure this us very interesting (why not though), since nothing would ever come after the mixin.5.typeof.stringof.writeln(); If we only got to choose 1 that is ;)Features should be orthogonal unless there's a good reason not to. IMO, assert, typeof, mixin, etc should all be UFCS-able. But this has been brought up many times before.
Sep 03 2013
On Tuesday, 3 September 2013 at 08:23:57 UTC, Timothee Cour wrote:But that sill implies knowing exactly *what* is called, eg knowing the documentation of everything that is used, as opposed to just knowing "that *looks* like a function call that *does* something or other", but not worrying about it more than that. Allowing implicit mixin adds an entire extra level of "dereference" when reading wode.Long story short, you are basically asking for macro. If we allowed this, than anything could actually be code injection, and mean anything.No, only mixin statements and mixin functions. And a regular function calling a mixin function would still be regular, eg not able to access symbols in enclosing scope by name.Hadn't thought of that.If for some reason we can't have mixin special property, can we at leastWhat do you mean by "nothing would ever come after the mixin" ? You can have: some_string.embed.mixin.writeln;have UFCS for mixin, so that we could write: "variables: x1=$x1, x2=$x2, sum=$(x1+x2)".embed.mixinI'm not sure this us very interesting (why not though), since nothing would ever come after the mixin.
Sep 03 2013
On 9/3/13 2:11 AM, monarch_dodra wrote:On Tuesday, 3 September 2013 at 04:15:17 UTC, Timothee Cour wrote:"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." When you do "import foo.bar" you are importing arbitrary code... If you are not sure what that does, you go look it up. And it's the same for implicit mixins. I don't see the issue at all...I'd like to be able to declare a function with a special mixin property that will auto-mixin at call siteKenji had apparently implemented this: https://github.com/D-Programming-Language/dmd/pull/459 But pulled out. This recent thread should sum it up: http://forum.dlang.org/thread/yaasjclvyobpeftgwmke forum.dlang.org Long story short, you are basically asking for macro. If we allowed this, than anything could actually be code injection, and mean anything.If for some reason we can't have mixin special property, can we at least have UFCS for mixin, so that we could write: "variables: x1=$x1, x2=$x2, sum=$(x1+x2)".embed.mixinI'm not sure this us very interesting (why not though), since nothing would ever come after the mixin. I'd still rather have "typeof" be UFCS-able: 5.typeof.stringof.writeln(); If we only got to choose 1 that is ;)
Sep 03 2013
On Tuesday, 3 September 2013 at 18:26:57 UTC, Ary Borenszweig wrote:On 9/3/13 2:11 AM, monarch_dodra wrote:But "import" is also explicit. Do you think it would be a good idea that a function be allowed to implicitly import things just by calling it? Because that basically what implicit mixin allows.On Tuesday, 3 September 2013 at 04:15:17 UTC, Timothee Cour wrote:"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." When you do "import foo.bar" you are importing arbitrary code... If you are not sure what that does, you go look it up. And it's the same for implicit mixins. I don't see the issue at all...I'd like to be able to declare a function with a special mixin property that will auto-mixin at call siteKenji had apparently implemented this: https://github.com/D-Programming-Language/dmd/pull/459 But pulled out. This recent thread should sum it up: http://forum.dlang.org/thread/yaasjclvyobpeftgwmke forum.dlang.org Long story short, you are basically asking for macro. If we allowed this, than anything could actually be code injection, and mean anything.If for some reason we can't have mixin special property, can we at least have UFCS for mixin, so that we could write: "variables: x1=$x1, x2=$x2, sum=$(x1+x2)".embed.mixinI'm not sure this us very interesting (why not though), since nothing would ever come after the mixin. I'd still rather have "typeof" be UFCS-able: 5.typeof.stringof.writeln(); If we only got to choose 1 that is ;)
Sep 03 2013
On 9/3/13, Ary Borenszweig <ary esperanto.org.ar> wrote:When you do "import foo.bar" you are importing arbitrary code...You are importing symbols. And when you do "foo()" you know you're calling a function. With the change, you'll never know what foo() does. This feature is never going to fly, but people are just going to argue this forever..
Sep 03 2013
On 2013-09-03 21:05, Andrej Mitrovic wrote:You are importing symbols. And when you do "foo()" you know you're calling a function. With the change, you'll never know what foo() does. This feature is never going to fly, but people are just going to argue this forever..With properties you never know if you're invoking a method or accessing a field: foo.data; // call method or access field? -- /Jacob Carlborg
Sep 03 2013
On Tuesday, 3 September 2013 at 19:10:12 UTC, Jacob Carlborg wrote:On 2013-09-03 21:05, Andrej Mitrovic wrote:Which is exactly why parens-less calls and properties with side effects suck.You are importing symbols. And when you do "foo()" you know you're calling a function. With the change, you'll never know what foo() does. This feature is never going to fly, but people are just going to argue this forever..With properties you never know if you're invoking a method or accessing a field: foo.data; // call method or access field?
Sep 03 2013
On Tue, Sep 3, 2013 at 12:13 PM, Dicebot <public dicebot.lv> wrote:On Tuesday, 3 September 2013 at 19:10:12 UTC, Jacob Carlborg wrote:that's the whole point, it allows to transparently replace a field access by a property function call without breaking client code. How else would you do that?On 2013-09-03 21:05, Andrej Mitrovic wrote: You are importing symbols. And when you do "foo()" you know you'reWhich is exactly why parens-less calls and properties with side effects suck.calling a function. With the change, you'll never know what foo() does. This feature is never going to fly, but people are just going to argue this forever..With properties you never know if you're invoking a method or accessing a field: foo.data; // call method or access field?
Sep 03 2013
On Wednesday, 4 September 2013 at 02:26:27 UTC, Timothee Cour wrote:that's the whole point, it allows to transparently replace a field access by a property function call without breaking client code. How else would you do that?You can't replace field access with function call transparently if it has side effects. In the end breakage may be even worse. For me only replacing property fields with property methods makes sense (with former prohibited to be taken address of and latter forced to be weakly pure).'
Sep 04 2013
On Wed, Sep 4, 2013 at 2:23 AM, Dicebot <public dicebot.lv> wrote:On Wednesday, 4 September 2013 at 02:26:27 UTC, Timothee Cour wrote:IIRC, &foo.x with x a property should take address of return value of x(), which will either fail to compile or do the right thing if it returns a lvalue. So there's no undefined behavior as far as taking address of is concerned when replacing field by property. As for side effects, this is the reason one would go from field access to property, eg populating some data upon 1st access to a field x. Sure it can be misused, but I haven't seen a case in practice where it is misused.that's the whole point, it allows to transparently replace a field access by a property function call without breaking client code. How else would you do that?You can't replace field access with function call transparently if it has side effects. In the end breakage may be even worse. For me only replacing property fields with property methods makes sense (with former prohibited to be taken address of and latter forced to be weakly pure).'
Sep 04 2013
On Wednesday, 4 September 2013 at 17:07:33 UTC, Timothee Cour wrote:IIRC, &foo.x with x a property should take address of return value of x(), which will either fail to compile or do the right thing if it returns a lvalue.It is not possible because getters are not guaranteed to return lvalues. There is a quite elegant (in my opinion) proposal hanging around to allow annotating plain fields with property so that compiler will prohibit doing any operation on them that may later break because of transition to actual properties, such as taking address.As for side effects, this is the reason one would go from field access to property, eg populating some data upon 1st access to a field x. Sure it can be misused, but I haven't seen a case in practice where it is misused.I haven't seen a case in practice when using normal method instead of a property was really harmful. Also modifying own members is legal for weakly pure method as far as I remember (it can modify arguments, including hidden `this`), so your case will actually work within my restrictions.
Sep 05 2013
On 9/3/13, Jacob Carlborg <doob me.com> wrote:With properties you never know if you're invoking a method or accessing a field: foo.data; // call method or access field?Yeah but it does something with data on its own side. If this becomes an implicit mixin, it could do something with code at the call site. E.g. auto st = getSecurityToken(...); updateGui(); // what if this becomes a mixin and ends up reading 'st' and displaying it on the screen? It is equivalent to using globals everywhere in your codebase.
Sep 03 2013
On 9/3/13 5:47 PM, Andrej Mitrovic wrote:On 9/3/13, Jacob Carlborg <doob me.com> wrote:Why would anyone do that? Do you use other people's source code without reading the documentation or reading the source code? How would the author of "updateGui()" know that you named your variable "st"? What if "updateGui()" does "rm -rf /" ? What if "updateGui()" always does a null pointer dereference? Ah, the language is too dangerous. I say we should remove function calls from the language.With properties you never know if you're invoking a method or accessing a field: foo.data; // call method or access field?Yeah but it does something with data on its own side. If this becomes an implicit mixin, it could do something with code at the call site. E.g. auto st = getSecurityToken(...); updateGui(); // what if this becomes a mixin and ends up reading 'st' and displaying it on the screen? It is equivalent to using globals everywhere in your codebase.
Sep 04 2013
On Wednesday, 4 September 2013 at 14:44:50 UTC, Ary Borenszweig wrote:Why would anyone do that?By an accident - mixins are not hygienic.Do you use other people's source code without reading the documentation or reading the source code?Yes, all the time. Documentation is always lacking and reading full 10 MLOC code base to tweak a single function is never an option.How would the author of "updateGui()" know that you named your variable "st"?He has no idea how you may name your variables, that is the key point. Thus he has no idea what safe symbol names to use.What if "updateGui()" does "rm -rf /" ? What if "updateGui()" always does a null pointer dereference?You will have a bugged/malicious function in your code base, one very easy to detect and fix. Nothing in common with discussed problem.
Sep 04 2013
On 9/4/13 11:54 AM, Dicebot wrote:On Wednesday, 4 September 2013 at 14:44:50 UTC, Ary Borenszweig wrote:So the problem is not that implicit mixin is unsafe. The problem is that there's no way to declare a new variable that won't conflict with existing variables in the current scope?Why would anyone do that?By an accident - mixins are not hygienic.Do you use other people's source code without reading the documentation or reading the source code?Yes, all the time. Documentation is always lacking and reading full 10 MLOC code base to tweak a single function is never an option.How would the author of "updateGui()" know that you named your variable "st"?He has no idea how you may name your variables, that is the key point. Thus he has no idea what safe symbol names to use.
Sep 04 2013
On Wednesday, 4 September 2013 at 15:18:10 UTC, Ary Borenszweig wrote:So the problem is not that implicit mixin is unsafe. The problem is that there's no way to declare a new variable that won't conflict with existing variables in the current scope?This is the same problem. The key property of mixin is that it is unhygienic and invades the caller scope. It is the only entity in D that is allowed to do it. Allowing implicit unhygienic inclusions is guaranteed to result in accidental symbol clash and/or unexpected modification sooner or later.
Sep 04 2013
frankly, UFCS mixin would make the use case in the OT bearable. fun().mixin.writeln is ok mixin(fun()).writeln is ugly (esp in more complex cases). so, is there anything against it despite requiring one to implement it? On Wed, Sep 4, 2013 at 8:29 AM, Dicebot <public dicebot.lv> wrote:On Wednesday, 4 September 2013 at 15:18:10 UTC, Ary Borenszweig wrote:So the problem is not that implicit mixin is unsafe. The problem is that there's no way to declare a new variable that won't conflict with existing variables in the current scope?This is the same problem. The key property of mixin is that it is unhygienic and invades the caller scope. It is the only entity in D that is allowed to do it. Allowing implicit unhygienic inclusions is guaranteed to result in accidental symbol clash and/or unexpected modification sooner or later.
Sep 04 2013
On Wednesday, 4 September 2013 at 17:10:32 UTC, Timothee Cour wrote:frankly, UFCS mixin would make the use case in the OT bearable. fun().mixin.writeln is ok mixin(fun()).writeln is ugly (esp in more complex cases). so, is there anything against it despite requiring one to implement it?I guess there is nothing terrible but also nothing extremely useful :) For me second snippet is not any uglier.
Sep 05 2013
On Thursday, 5 September 2013 at 10:36:40 UTC, Dicebot wrote:On Wednesday, 4 September 2013 at 17:10:32 UTC, Timothee Cour wrote:Stuff like data validation, or lazy initialization, anything really data oriented usually benefit from that. Also, the dichotomy function call/field access is really not that clear at the end. Accessing some data may require a function call, go through a signal handler, or involve complicated operation by the CPU (potentially 2 round trip to memory). On the other hand, optimizer will remove many function calls making them effectively field access. Even if it isn't inlined, a simple function call could end up being faster than 2 round trip to memory (the stack is hot).frankly, UFCS mixin would make the use case in the OT bearable. fun().mixin.writeln is ok mixin(fun()).writeln is ugly (esp in more complex cases). so, is there anything against it despite requiring one to implement it?I guess there is nothing terrible but also nothing extremely useful :) For me second snippet is not any uglier.
Sep 05 2013
On Thursday, 5 September 2013 at 10:51:19 UTC, deadalnix wrote:Stuff like data validation, or lazy initialization, anything really data oriented usually benefit from that. Also, the dichotomy function call/field access is really not that clear at the end. Accessing some data may require a function call, go through a signal handler, or involve complicated operation by the CPU (potentially 2 round trip to memory). On the other hand, optimizer will remove many function calls making them effectively field access. Even if it isn't inlined, a simple function call could end up being faster than 2 round trip to memory (the stack is hot).I guess it was an answer to earlier property comment. Key concern here is not actually speed but ease to understand the program - it is pretty much the same deal as pure vs non-pure. Non-volatile non-shared field access is extremely unlikely to cause any side-effects in global program state and same is generally expected from something that looks like plain field access.
Sep 05 2013
the other part of my post was about UFCS syntax for mixin: eg: foo.mixin.writeln is there any reason not to allow it? On Tue, Sep 3, 2013 at 1:47 PM, Andrej Mitrovic <andrej.mitrovich gmail.com>wrote:On 9/3/13, Jacob Carlborg <doob me.com> wrote:With properties you never know if you're invoking a method or accessing a field: foo.data; // call method or access field?Yeah but it does something with data on its own side. If this becomes an implicit mixin, it could do something with code at the call site. E.g. auto st = getSecurityToken(...); updateGui(); // what if this becomes a mixin and ends up reading 'st' and displaying it on the screen? It is equivalent to using globals everywhere in your codebase.
Sep 03 2013
On 9/3/13 4:05 PM, Andrej Mitrovic wrote:On 9/3/13, Ary Borenszweig <ary esperanto.org.ar> wrote:Yes you know: you look at the source code, or the documentation.When you do "import foo.bar" you are importing arbitrary code...You are importing symbols. And when you do "foo()" you know you're calling a function. With the change, you'll never know what foo() does.This feature is never going to fly, but people are just going to argue this forever..I know, I'm just trying to defend this point of view.
Sep 04 2013
On Wednesday, 4 September 2013 at 14:42:26 UTC, Ary Borenszweig wrote:On 9/3/13 4:05 PM, Andrej Mitrovic wrote:You don't do it for _every single symbol_. Good good matches naive assumptions, this is exactly what allows to read it fast. Reading code where you can't make assumptions about anything is a transitive (possibly exponential) task. Exactly the hell you get with undisciplined C macro usage.On 9/3/13, Ary Borenszweig <ary esperanto.org.ar> wrote:Yes you know: you look at the source code, or the documentation.When you do "import foo.bar" you are importing arbitrary code...You are importing symbols. And when you do "foo()" you know you're calling a function. With the change, you'll never know what foo() does.
Sep 04 2013
Was objecting in previous thread and have not changed my mind - it is unhygienic and mostly useless.
Sep 03 2013