digitalmars.D - user defined literals
- Trass3r (12/12) Mar 25 2011 Just came across C++0x user defined literals (via user defined suffixes)...
- Steven Schveighoffer (8/28) Mar 25 2011 What is the need for this? Just to replace complex(0, 5) with 5i? I
- Trass3r (9/15) Mar 25 2011 I didn't claim it was of "huge" benefit. It's just some slight syntactic...
- Steven Schveighoffer (30/51) Mar 25 2011 Aside from the parsing issues, which I think would be minor, it's more o...
- Lars T. Kyllingstad (9/22) Mar 25 2011 I believe the plan is to keep complex literals even after the built-in
- Trass3r (4/9) Mar 25 2011 It is indeed capable of doing that :)
- Lars T. Kyllingstad (3/13) Mar 25 2011 Even when you compile with -O?
- Trass3r (7/11) Mar 25 2011 Yep.
- Trass3r (6/24) Mar 25 2011 Well the user defined literals could only be used in places where the mo...
- Steven Schveighoffer (9/13) Mar 25 2011 CTFE is only used when you are defining a compile-time constant, or
- Walter Bright (13/16) Mar 25 2011 One difficulty with the C++0x approach is that the operator"" needed to
- Andrei Alexandrescu (4/20) Mar 25 2011 All good points. I should also add that the user-defined literal syntax
- Trass3r (2/3) Mar 25 2011 Of course the suffix itself is missing:
Just came across C++0x user defined literals (via user defined suffixes): http://en.wikipedia.org/wiki/C%2B%2B0x#User-defined_literals They are implemented via something like: std::complex<double> operator "" i(double d) // cooked form, e.g. 15i { return std::complex(0, d); } Another C++0x typical <nasty syntax> solution for a nice feature. It should be possible to incorporate this into D quite easily via something along the lines of: Complex!T opSuffix(U data) // whatever the name should be where U can be a number type or a string (see the link for cooked vs. raw form) Just like traditional operator overloading in D this would only mean a tiny layer of syntactic sugar on top of standard language features. Given D's CTFE capabilities you could probably even define compile-time literals without further modifications (C++0x needs variadic templates and constexpr for that! :D). My actual question is: are there any non-apparent pitfalls or side effects that might complicate or speak against an implementation?
Mar 25 2011
On Fri, 25 Mar 2011 09:32:12 -0400, Trass3r <un known.com> wrote:Just came across C++0x user defined literals (via user defined suffixes): http://en.wikipedia.org/wiki/C%2B%2B0x#User-defined_literals They are implemented via something like: std::complex<double> operator "" i(double d) // cooked form, e.g. 15i { return std::complex(0, d); } Another C++0x typical <nasty syntax> solution for a nice feature. It should be possible to incorporate this into D quite easily via something along the lines of: Complex!T opSuffix(U data) // whatever the name should be where U can be a number type or a string (see the link for cooked vs. raw form) Just like traditional operator overloading in D this would only mean a tiny layer of syntactic sugar on top of standard language features. Given D's CTFE capabilities you could probably even define compile-time literals without further modifications (C++0x needs variadic templates and constexpr for that! :D). My actual question is: are there any non-apparent pitfalls or side effects that might complicate or speak against an implementation?What is the need for this? Just to replace complex(0, 5) with 5i? I don't see the huge benefit. Also, complex is the clear and obvious beneficiary because it's so widely understood. What are other use cases? BigXXX for sure, but Rational probably cannot be covered by this since you need two numbers. I simply find the complication of the language is not worth the benefits. -Steve
Mar 25 2011
Steven Schveighoffer Wrote:What is the need for this? Just to replace complex(0, 5) with 5i? I don't see the huge benefit.I didn't claim it was of "huge" benefit. It's just some slight syntactic sugar. Furthermore I didn't mean to praise its usefulness. I was actually asking about practical issues that could arise if it _was_ implemented the way I presented.I simply find the complication of the language is not worth the benefits.This is more towards my question. Please elaborate how this complicates the language.Also, complex is the clear and obvious beneficiaryYep, though I think complex literals would still better be handled by the compiler specifically so that 5 + 3i is transformed to Complex(5,3) rather than 5 + Complex(0, 3) But keeping complex literals in dmd as syntactic sugar beyond the grave of complex types is another story.What are other use cases? BigXXX for sure, but Rational probably cannot be covered by this since you need two numbers.Units, I think. auto dist = 1km; sin(90deg);
Mar 25 2011
On Fri, 25 Mar 2011 11:14:26 -0400, Trass3r <un known.com> wrote:Steven Schveighoffer Wrote:OK, I understand.What is the need for this? Just to replace complex(0, 5) with 5i? I don't see the huge benefit.I didn't claim it was of "huge" benefit. It's just some slight syntactic sugar. Furthermore I didn't mean to praise its usefulness. I was actually asking about practical issues that could arise if it _was_ implemented the way I presented.Aside from the parsing issues, which I think would be minor, it's more of a problem with anyone and his mother is allowed to define literal types. That is, someone could have 1fud and I'm not sure what the hell that means, so I have to go find out where that xyz is defined. It must be global, since literals can be used anywhere, so it can be anywhere. I just find that I have very little need for custom literals with all the wealth of features that D has, so I would be hesitant to stray from the f(value) style which is easily understood and readily parsable.I simply find the complication of the language is not worth the benefits.This is more towards my question. Please elaborate how this complicates the language.We have quite powerful mixin abilities such that I think something like: complex!("5 + 3i") could be rewritten as Complex!double(5, 3) without compiler help. And like you said, the feature as proposed does not do the ideal thing.Also, complex is the clear and obvious beneficiaryYep, though I think complex literals would still better be handled by the compiler specifically so that 5 + 3i is transformed to Complex(5,3) rather than 5 + Complex(0, 3)These are good points, but of course, units are open to interpretation. Not every unit has a standard abbreviation, and not every abbreviation is unique. These things are highly context sensitive. For example, I could say: auto mytime = 1h + 3m + 4s; auto mydistance = 15m; Notice that 3 minutes and 15 meters can't really be distinguished by the compiler. I like the idea of having this be more context-sensitive and also allow for the feature without language changes: auto mytime = tstamp!("1h + 3m + 4s"); Not only that, but it's compile-time, meaning there is no actual call to some operator processor to generate the timestamp. I believe we already have this for octal. If we could define a more standard way to create these things, then I think it would be a good step. -SteveWhat are other use cases? BigXXX for sure, but Rational probably cannot be covered by this since you need two numbers.Units, I think. auto dist = 1km; sin(90deg);
Mar 25 2011
On Fri, 25 Mar 2011 11:46:08 -0400, Steven Schveighoffer wrote:On Fri, 25 Mar 2011 11:14:26 -0400, Trass3r <un known.com> wrote:I believe the plan is to keep complex literals even after the built-in complex types are gone, but I don't think this is necessary at all. The following works just fine: enum I = Complex!float(0, 1); auto z = 5.0 + 3*I; The compiler should be able to fold the sum into a single constant at compile time. -LarsSteven Schveighoffer Wrote:We have quite powerful mixin abilities such that I think something like: complex!("5 + 3i") could be rewritten as Complex!double(5, 3) without compiler help. And like you said, the feature as proposed does not do the ideal thing.Also, complex is the clear and obvious beneficiaryYep, though I think complex literals would still better be handled by the compiler specifically so that 5 + 3i is transformed to Complex(5,3) rather than 5 + Complex(0, 3)
Mar 25 2011
Lars T. Kyllingstad Wrote:enum I = Complex!float(0, 1); auto z = 5.0 + 3*I; The compiler should be able to fold the sum into a single constant at compile time.It is indeed capable of doing that :) But it only does it if you force it to (e.g. via enum z). With auto it will perform 2 opBinaryRight calls at runtime.
Mar 25 2011
On Fri, 25 Mar 2011 12:36:11 -0400, Trass3r wrote:Lars T. Kyllingstad Wrote:Even when you compile with -O? -Larsenum I = Complex!float(0, 1); auto z = 5.0 + 3*I; The compiler should be able to fold the sum into a single constant at compile time.It is indeed capable of doing that :) But it only does it if you force it to (e.g. via enum z). With auto it will perform 2 opBinaryRight calls at runtime.
Mar 25 2011
Yep. It doesn't even seem to optimize away an unused variable: void main() { auto z = 5.0 + 3*I; } Or I've done something wrong.It is indeed capable of doing that :) But it only does it if you force it to (e.g. via enum z). With auto it will perform 2 opBinaryRight calls at runtime.Even when you compile with -O?
Mar 25 2011
Steven Schveighoffer Wrote:Aside from the parsing issues, which I think would be minor, it's more of a problem with anyone and his mother is allowed to define literal types.Yeah that's true.That is, someone could have 1fud and I'm not sure what the hell that means, so I have to go find out where that xyz is defined. It must be global, since literals can be used anywhere, so it can be anywhere.Well the user defined literals could only be used in places where the module containing the proper opSuffix implementation is imported. The search for that doesn't really differ from the search for any other poorly named function or type or whatever. I do agree though that suffixes would mostly be very short and could get very cryptic.Probably one of the biggest problems of the whole concept.auto dist = 1km; sin(90deg);These are good points, but of course, units are open to interpretation. Not every unit has a standard abbreviation, and not every abbreviation is unique. These things are highly context sensitive. For example, I could say: auto mytime = 1h + 3m + 4s; auto mydistance = 15m;Not only that, but it's compile-time, meaning there is no actual call to some operator processor to generate the timestamp.You forget CTFE ;)
Mar 25 2011
On Fri, 25 Mar 2011 12:54:46 -0400, Trass3r <un known.com> wrote:Steven Schveighoffer Wrote:CTFE is only used when you are defining a compile-time constant, or creating a static initializer. literals are not CTFE'd. For example, an array literal still calls a runtime function to construct the array. The call could also be optimized out, but when the literal is a generic template (not necessarily a function), you can *force* it to be compile-time, regardless of optimizations or inlining. -SteveNot only that, but it's compile-time, meaning there is no actual call to some operator processor to generate the timestamp.You forget CTFE ;)
Mar 25 2011
On 3/25/2011 8:14 AM, Trass3r wrote:Units, I think. auto dist = 1km; sin(90deg);One difficulty with the C++0x approach is that the operator"" needed to implement it is a global function. Global functions work fine until you wind up with two km functions with different purposes, and then things just don't work anymore. In D, you can have user defined literals of the form: km!1 km!"1" km(1) implemented using CTFE. Adding yet another syntax for it seems to be of marginal utility. C++0x needed to add the new syntax because its CTFE ability is minimal, and C++ template metaprogramming cannot process strings.
Mar 25 2011
On 3/25/11 10:28 AM, Walter Bright wrote:On 3/25/2011 8:14 AM, Trass3r wrote:All good points. I should also add that the user-defined literal syntax is considered an albatross in certain C++ circles. AndreiUnits, I think. auto dist = 1km; sin(90deg);One difficulty with the C++0x approach is that the operator"" needed to implement it is a global function. Global functions work fine until you wind up with two km functions with different purposes, and then things just don't work anymore. In D, you can have user defined literals of the form: km!1 km!"1" km(1) implemented using CTFE. Adding yet another syntax for it seems to be of marginal utility. C++0x needed to add the new syntax because its CTFE ability is minimal, and C++ template metaprogramming cannot process strings.
Mar 25 2011
Complex!T opSuffix(U data) // whatever the name should beOf course the suffix itself is missing: Complex!T opSuffix!(string suffix="i")(U data)
Mar 25 2011