digitalmars.D - String mixin syntax sugar
- Mantis <mail.mantis.88 gmail.com> Mar 20 2012
- Dmitry Olshansky <dmitry.olsh gmail.com> Mar 20 2012
- Jacob Carlborg <doob me.com> Mar 20 2012
- "Tove" <tove fransson.se> Mar 20 2012
- d coder <dlang.coder gmail.com> Mar 20 2012
- bcs <bcs example.com> Mar 20 2012
- kennytm <kennytm gmail.com> Mar 21 2012
- dennis luehring <dl.soluz gmx.net> Mar 21 2012
- Mantis <mail.mantis.88 gmail.com> Mar 21 2012
- kennytm <kennytm gmail.com> Mar 21 2012
- "RivenTheMage" <riven-mage id.ru> Mar 21 2012
Hello,
since people discussed a lot about user-defined attributes recently,
I've been thinking about a way to implement it with a string mixins. The
problem with them is their syntax - it's far from what we want to use in
everyday job. I understand, they should be easily distinguished at use
site, but perhaps this may be accomplished in other ways as well. My
idea is to translate this kind of statements:
# identifier statement
into this:
mixin( identifier( q{ statement } ) );
where an identifier is a, possibly templated, function that accepts one
string argument and returns a string. Here are some possible use cases:
#serialize int a; // marked to be serializable
#serialize!not int b; // -.- non-serializable
#readonly float c; // generate trivial private setter and public getter
#handles!Events.Foo void handler(); // event handler
#attribute!"Foo" void foo(); // function with additional compile-time info
Most of these examples require some D parser, but, since it is planned
to add parser-generation into Phobos, this shouldn't be a problem.
What do you think, does it have some value for the language, and, if
yes, is it possible to implement?
Mar 20 2012
On 20.03.2012 22:25, Mantis wrote:Hello, since people discussed a lot about user-defined attributes recently, I've been thinking about a way to implement it with a string mixins. The problem with them is their syntax - it's far from what we want to use in everyday job.
Use template mixins? At least in struct/class area that catches the most attention it should work perfectly. I understand, they should be easily distinguished at usesite, but perhaps this may be accomplished in other ways as well. My idea is to translate this kind of statements: # identifier statement into this: mixin( identifier( q{ statement } ) ); where an identifier is a, possibly templated, function that accepts one string argument and returns a string. Here are some possible use cases: #serialize int a; // marked to be serializable #serialize!not int b; // -.- non-serializable #readonly float c; // generate trivial private setter and public getter
Why not just leave it alone, and (if need comes) turn it into property on demand.#handles!Events.Foo void handler(); // event handler #attribute!"Foo" void foo(); // function with additional compile-time info
It's just voodoo - no guaranties that #attribute can do that given the above rewrite.Most of these examples require some D parser, but, since it is planned to add parser-generation into Phobos, this shouldn't be a problem. What do you think, does it have some value for the language, and, if yes, is it possible to implement?
Looks like throwing nukes to pin down a pesky cockroach. The sugar is more or less nice, but encourages ineffective compile-time wise idiom. -- Dmitry Olshansky
Mar 20 2012
On 2012-03-20 19:25, Mantis wrote:Hello, since people discussed a lot about user-defined attributes recently, I've been thinking about a way to implement it with a string mixins. The problem with them is their syntax - it's far from what we want to use in everyday job. I understand, they should be easily distinguished at use site, but perhaps this may be accomplished in other ways as well. My idea is to translate this kind of statements: # identifier statement into this: mixin( identifier( q{ statement } ) );
I don't like it. I want real user defined attributes. -- /Jacob Carlborg
Mar 20 2012
On Tuesday, 20 March 2012 at 21:28:25 UTC, Jacob Carlborg wrote:On 2012-03-20 19:25, Mantis wrote:Hello, since people discussed a lot about user-defined attributes recently, I've been thinking about a way to implement it with a string mixins. The problem with them is their syntax - it's far from what we want to use in everyday job. I understand, they should be easily distinguished at use site, but perhaps this may be accomplished in other ways as well. My idea is to translate this kind of statements: # identifier statement into this: mixin( identifier( q{ statement } ) );
I don't like it. I want real user defined attributes.
I think the idea has merit, string mixins together with CTFE parsing is the holy grail... because of the current syntax it's not really feasible to use on a per-member basis... but it is possible to use on a struct/class basis... mixin(attr(q{struct Foo { NonSerialized int x; NonSerialized int y; int z; }})); Please disregard my broken parser(it's just a proof of concept) However, consider what we could do with the latest CTFE parser advances, coupled with a tighter compiler/library callback interface. ==================================================================== import std.stdio; import std.array; import std.string; import std.algorithm; string attr(string complex_decl) { string org_struct; string ser_struct; auto lines = splitLines(complex_decl); { auto decl = split(stripLeft(lines[0])); if(decl[0]=="struct") { org_struct = decl[0] ~ " " ~ decl[1]; ser_struct = decl[0] ~ " " ~ decl[1] ~ "_Serializable"; } else return complex_decl; } foreach(line; lines[1..$]) { auto attr = findSplitAfter(stripLeft(line), " NonSerialized "); if(attr[0]==" NonSerialized ") org_struct ~= attr[1]; else { org_struct ~= attr[1]; ser_struct ~= attr[1]; } } return ser_struct ~ "\n" ~ org_struct; } mixin(attr(q{struct Foo { NonSerialized int x; NonSerialized int y; int z; }})); void main() { auto m = [ __traits(allMembers, Foo) ]; writeln("Normal members of Foo:", m); auto n = [ __traits(allMembers, Foo_Serializable) ]; writeln("Serializable members of Foo:", n); }
Mar 20 2012
--f46d0407152b0382e204bbb6e823 Content-Type: text/plain; charset=ISO-8859-1Use template mixins? At least in struct/class area that catches the most attention it should work perfectly.
I believe template mixins are equally ugly. Don't you have to explicitly specify that you are invoking a mixin? Or am I missing something here. Regards - Puneet --f46d0407152b0382e204bbb6e823 Content-Type: text/html; charset=ISO-8859-1 <div class="gmail_quote"><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Use template mixins? At least in struct/class area that catches the most attention it should work perfectly.</blockquote> </div><br><div>I believe template mixins are equally ugly. Don't you have to explicitly specify that you are invoking a mixin? Or am I missing something here.</div><div><br></div><div>Regards</div><div>- Puneet</div> --f46d0407152b0382e204bbb6e823--
Mar 20 2012
On 03/20/2012 11:25 AM, Mantis wrote:Hello, since people discussed a lot about user-defined attributes recently, I've been thinking about a way to implement it with a string mixins. The problem with them is their syntax - it's far from what we want to use in everyday job. I understand, they should be easily distinguished at use site, but perhaps this may be accomplished in other ways as well. My idea is to translate this kind of statements: # identifier statement into this: mixin( identifier( q{ statement } ) );
No no no no, oh the humanity no! String mixins should be a method of LAST resort. Please don't add sugar to make them look nicer. If anything add vinegar and make them look as ugly as they really are.where an identifier is a, possibly templated, function that accepts one string argument and returns a string. Here are some possible use cases: #serialize int a; // marked to be serializable #serialize!not int b; // -.- non-serializable #readonly float c; // generate trivial private setter and public getter #handles!Events.Foo void handler(); // event handler #attribute!"Foo" void foo(); // function with additional compile-time info Most of these examples require some D parser, but, since it is planned to add parser-generation into Phobos, this shouldn't be a problem. What do you think, does it have some value for the language, and, if yes, is it possible to implement?
Mar 20 2012
Mantis <mail.mantis.88 gmail.com> wrote:Hello, since people discussed a lot about user-defined attributes recently, I've been thinking about a way to implement it with a string mixins. The problem with them is their syntax - it's far from what we want to use in everyday job. I understand, they should be easily distinguished at use site, but perhaps this may be accomplished in other ways as well. My idea is to translate this kind of statements: # identifier statement
You mean 'declaration'.into this: mixin( identifier( q{ statement } ) ); where an identifier is a, possibly templated, function that accepts one string argument and returns a string. Here are some possible use cases: #serialize int a; // marked to be serializable #serialize!not int b; // -.- non-serializable #readonly float c; // generate trivial private setter and public getter #handles!Events.Foo void handler(); // event handler #attribute!"Foo" void foo(); // function with additional compile-time info Most of these examples require some D parser, but, since it is planned to add parser-generation into Phobos, this shouldn't be a problem. What do you think, does it have some value for the language, and, if yes, is it possible to implement?
The syntax may conflict with '#line'. What to do where there are multiple attributes? E.g. #license!"BSD" safe #memoize pure nothrow auto invertMatrix(T)(T[] elements) if (isArithmetic!T) { ... } What to do with .di files? // in .di #handler void onLoad(); // in .d #handler void onLoad() { .... } Besides, what's wrong with using ' '? serialize int a;
Mar 21 2012
and what about attribute parameters like serialize(version=2) Am 21.03.2012 13:35, schrieb Mantis:21.03.2012 13:35, kennytm пишет:Mantis<mail.mantis.88 gmail.com> wrote:[...] # identifier statement
Not necessarily, this could be used anywhere a mixin can be.[...]
I didn't know. The choice for the symbol is not that important however.What to do where there are multiple attributes? E.g. #license!"BSD" safe #memoize pure nothrow auto invertMatrix(T)(T[] elements) if (isArithmetic!T) { ... }
Evaluation order stays the same as in this example, the improvement is purely syntactical: // import std.stdio, std.array; string m1( string s ) { return replace( s, "foo", "bar" ); } string m2( string s ) { return replace( s, "bar", "baz" ); } mixin( m1( q{ mixin( m2( q{ void foo( int i ) { writeln( i ); }}));})); void main() { baz( 42 ); } //What to do with .di files? // in .di #handler void onLoad(); // in .d #handler void onLoad() { .... }
Since the function receives a string, it can deal with declarations differently from definitions, it's only a matter of parser.Besides, what's wrong with using ' '? serialize int a;
possible and ambiguous: string safe( string s ); safe void foo(); // what safe stands for?
Mar 21 2012
21.03.2012 13:35, kennytm пишет:Mantis<mail.mantis.88 gmail.com> wrote:[...] # identifier statement
Not necessarily, this could be used anywhere a mixin can be.[...]
I didn't know. The choice for the symbol is not that important however.What to do where there are multiple attributes? E.g. #license!"BSD" safe #memoize pure nothrow auto invertMatrix(T)(T[] elements) if (isArithmetic!T) { ... }
Evaluation order stays the same as in this example, the improvement is purely syntactical: // import std.stdio, std.array; string m1( string s ) { return replace( s, "foo", "bar" ); } string m2( string s ) { return replace( s, "bar", "baz" ); } mixin( m1( q{ mixin( m2( q{ void foo( int i ) { writeln( i ); }}));})); void main() { baz( 42 ); } //What to do with .di files? // in .di #handler void onLoad(); // in .d #handler void onLoad() { .... }
Since the function receives a string, it can deal with declarations differently from definitions, it's only a matter of parser.Besides, what's wrong with using ' '? serialize int a;
possible and ambiguous: string safe( string s ); safe void foo(); // what safe stands for?
Mar 21 2012
Mantis <mail.mantis.88 gmail.com> wrote:21.03.2012 13:35, kennytm пишет:Mantis<mail.mantis.88 gmail.com> wrote:[...] # identifier statement
Not necessarily, this could be used anywhere a mixin can be.[...]
I didn't know. The choice for the symbol is not that important however.What to do where there are multiple attributes? E.g. #license!"BSD" safe #memoize pure nothrow auto invertMatrix(T)(T[] elements) if (isArithmetic!T) { ... }
Evaluation order stays the same as in this example, the improvement is purely syntactical: // import std.stdio, std.array; string m1( string s ) { return replace( s, "foo", "bar" ); } string m2( string s ) { return replace( s, "bar", "baz" ); } mixin( m1( q{ mixin( m2( q{ void foo( int i ) { writeln( i ); }}));})); void main() { baz( 42 ); } //What to do with .di files? // in .di #handler void onLoad(); // in .d #handler void onLoad() { .... }
Since the function receives a string, it can deal with declarations differently from definitions, it's only a matter of parser.Besides, what's wrong with using ' '? serialize int a;
possible and ambiguous: string safe( string s ); safe void foo(); // what safe stands for?
They could be contextual keywords, just like the 'exit' in scope(exit). Your # has the same problem. So we have AttributeIdentifier: any Identifier except 'safe', 'system', 'trusted', 'disable' and 'property'. (Alternatively, implement these 5 things using the CTFE method. )
Mar 21 2012
On Wednesday, 21 March 2012 at 12:37:50 UTC, Mantis wrote:Builtin annotations' names are not reserved keywords, so this would be possible and ambiguous: string safe( string s ); safe void foo(); // what safe stands for?
What about " " for built-in annotations and " !" for user-defined? !license("BSD") safe !memoize pure nothrow auto invertMatrix(T)(T[] elements) if (isArithmetic!T) { ... }
Mar 21 2012









Dmitry Olshansky <dmitry.olsh gmail.com> 