digitalmars.D.announce - Units of Measurement Library: units-d
- =?UTF-8?B?Tm9yZGzDtnc=?= (4/4) Mar 31 2016 I've put David Nadlinger work together with my tweaks on top at
- ag0aep6g (42/50) Apr 01 2016 I dislike that the type depends only on the given name. This effectively...
- Simen Kjaeraas (29/33) Apr 01 2016 The usual way to fix it would be to include __FILE__ and __LINE__
- ag0aep6g (12/14) Apr 01 2016 Right, no mixin this way. I wouldn't call this "truly nice", though.
- Simen Kjaeraas (42/59) Apr 01 2016 I kinda agree. And looking at https://dlang.org/spec/traits.html,
- Meta (2/65) Apr 01 2016 What is needed is Lisp's gensym construct.
- Simen Kjaeraas (42/43) Apr 04 2016 That's basically what I said, no? :p
- crimaniak (5/8) Apr 02 2016 I think adding something like __UNIQUE_NAME__ to predefined
- Jack Stouffer (5/9) Apr 01 2016 Nice work.
I've put David Nadlinger work together with my tweaks on top at https://github.com/nordlow/units-d to make it easier to experiment with. PR are very welcome.
Mar 31 2016
On 01.04.2016 01:58, Nordlöw wrote:https://github.com/nordlow/units-dFrom there:* Example: * --- * alias BaseUnit!("Ampere", "A") Ampere; * enum ampere = Ampere.init; * // or * enum ampere = baseUnit!("Ampere", "A"); * ---I dislike that the type depends only on the given name. This effectively means that the names are in a global namespace. For example: ---- import experimental.units; struct A { alias BaseUnit!("Ampere", "A") Ampere; enum ampere = Ampere.init; } struct B { alias BaseUnit!("Ampere", "A") Ampere; enum ampere = Ampere.init; } ---- A.Ampere and B.Ampere are the same type here. I think it would be more useful if they weren't. When two unrelated sources define a new unit with the same name, then they shouldn't be compatible. Think of all the different kinds of pounds and miles there used to be in the world. I can't think of a truly nice way to accomplish this, though. As far as I see, it needs a mixin of some kind. Like this, for example: ---- enum string baseUnit = q{ { static struct BaseUnit {/* ... */} return BaseUnit.init; }() }; struct A { enum ampere = mixin(baseUnit); } struct B { enum ampere = mixin(baseUnit); } static assert(!is(typeof(A.ampere) == typeof(B.ampere))); ----
Apr 01 2016
On Friday, 1 April 2016 at 19:03:03 UTC, ag0aep6g wrote:I dislike that the type depends only on the given name. This effectively means that the names are in a global namespace.[snip]I can't think of a truly nice way to accomplish this, though. As far as I see, it needs a mixin of some kind.The usual way to fix it would be to include __FILE__ and __LINE__ in the template arguments: // In units/package.d: struct BaseUnit(string name, string symbol = null, string file = __FILE__, size_t line = __LINE__) { // ... } // in foo.d: import experimental.units; struct A { // Actual type is BaseUnit!("Ampere", "A", "foo", 5): alias BaseUnit!("Ampere", "A") Ampere; enum ampere = Ampere.init; } struct B { // Actual type is BaseUnit!("Ampere", "A", "foo", 12): alias BaseUnit!("Ampere", "A") Ampere; enum ampere = Ampere.init; } void main() { assert(!is(B.Ampere == A.Ampere)); } -- Simen
Apr 01 2016
On 01.04.2016 22:59, Simen Kjaeraas wrote:The usual way to fix it would be to include __FILE__ and __LINE__ in the template arguments:Right, no mixin this way. I wouldn't call this "truly nice", though. It depends on code formatting to work. Put everything on one line and it breaks. Significant whitespace is a pain when generating code. Though this is not nearly as bad as significant indentation, of course. __FILE__ also kind of breaks separate compilation. All object files have to be compiled from the same directory. Otherwise __FILE__ will be different. __LINE__ has a similar (maybe even more obscure) issue. Add or remove a newline before compiling dependent modules and things break. Usually, one recompiles all dependents when a dependency changes, but a significant newline, really?
Apr 01 2016
On Friday, 1 April 2016 at 21:46:35 UTC, ag0aep6g wrote:On 01.04.2016 22:59, Simen Kjaeraas wrote:I kinda agree. And looking at https://dlang.org/spec/traits.html, I see there's __MODULE__, which would probably be a better choice than __FILE__. As for __LINE__, what we'd want is basically something like __CONTEXT__, which doesn't exist, but might be the .mangleof of the surrounding scope: struct S(string ctx = __CONTEXT__) { pragma(msg, ctx); } S!() a; // "3foo" void bar() { S!() b; // "_D3foo3barFZv" } struct S2 { S!() c; // "S3foo2S2" void baz() { S!() d; // "_D3foo2S23bazMFZv" } } That'd remove the problem of significant whitespace. In fact, it'd also eliminate the need for __MODULE__ in this case. Still though, that's not enough if we want this to work: void foo() { alias a = Foo!(); alias b = Foo!(); assert(!isSame!(a, b)); } We could also add __COLUMN__, which would be the horizontal index of the instantiation's beginning: foo(3, Bar!3.baz); // ^Here. Position 11. Next problem: void main() { pragma(msg, __LINE__); mixin("pragma(msg, __LINE__);\npragma(msg, __LINE__);"); pragma(msg, __LINE__); } That prints '4' twice - once for the actual line 4, the other for the second line of the mixin. However, __FILE__ is different, so I guess __CONTEXT__ could also be. -- SimenThe usual way to fix it would be to include __FILE__ and __LINE__ in the template arguments:Right, no mixin this way. I wouldn't call this "truly nice", though. It depends on code formatting to work. Put everything on one line and it breaks. Significant whitespace is a pain when generating code. Though this is not nearly as bad as significant indentation, of course. __FILE__ also kind of breaks separate compilation. All object files have to be compiled from the same directory. Otherwise __FILE__ will be different. __LINE__ has a similar (maybe even more obscure) issue. Add or remove a newline before compiling dependent modules and things break. Usually, one recompiles all dependents when a dependency changes, but a significant newline, really?
Apr 01 2016
On Friday, 1 April 2016 at 22:54:53 UTC, Simen Kjaeraas wrote:On Friday, 1 April 2016 at 21:46:35 UTC, ag0aep6g wrote:What is needed is Lisp's gensym construct.On 01.04.2016 22:59, Simen Kjaeraas wrote:I kinda agree. And looking at https://dlang.org/spec/traits.html, I see there's __MODULE__, which would probably be a better choice than __FILE__. As for __LINE__, what we'd want is basically something like __CONTEXT__, which doesn't exist, but might be the .mangleof of the surrounding scope: struct S(string ctx = __CONTEXT__) { pragma(msg, ctx); } S!() a; // "3foo" void bar() { S!() b; // "_D3foo3barFZv" } struct S2 { S!() c; // "S3foo2S2" void baz() { S!() d; // "_D3foo2S23bazMFZv" } } That'd remove the problem of significant whitespace. In fact, it'd also eliminate the need for __MODULE__ in this case. Still though, that's not enough if we want this to work: void foo() { alias a = Foo!(); alias b = Foo!(); assert(!isSame!(a, b)); } We could also add __COLUMN__, which would be the horizontal index of the instantiation's beginning: foo(3, Bar!3.baz); // ^Here. Position 11. Next problem: void main() { pragma(msg, __LINE__); mixin("pragma(msg, __LINE__);\npragma(msg, __LINE__);"); pragma(msg, __LINE__); } That prints '4' twice - once for the actual line 4, the other for the second line of the mixin. However, __FILE__ is different, so I guess __CONTEXT__ could also be. -- SimenThe usual way to fix it would be to include __FILE__ and __LINE__ in the template arguments:Right, no mixin this way. I wouldn't call this "truly nice", though. It depends on code formatting to work. Put everything on one line and it breaks. Significant whitespace is a pain when generating code. Though this is not nearly as bad as significant indentation, of course. __FILE__ also kind of breaks separate compilation. All object files have to be compiled from the same directory. Otherwise __FILE__ will be different. __LINE__ has a similar (maybe even more obscure) issue. Add or remove a newline before compiling dependent modules and things break. Usually, one recompiles all dependents when a dependency changes, but a significant newline, really?
Apr 01 2016
On Saturday, 2 April 2016 at 01:19:45 UTC, Meta wrote:What is needed is Lisp's gensym construct.That's basically what I said, no? :p One problem of lisp's gensym (if we were to use it in D) is that it's simply a monotonically increasing number with a global prefix. It's perfect for the language it's in, and all but useless in D. For this very reason, I have made a stab at implementing __GENSYM__ in D. It follows basically the ideas I outlined above, counter for the given mangled name: module bar; struct Ham(string gensym = __GENSYM__) { pragma(msg, gensym); } struct Eggs(string gensym = __GENSYM__) { pragma(msg, gensym); } // =========================== module foo; import bar; pragma(msg, __GENSYM__); // 3foo_1 void main() { pragma(msg, __GENSYM__); // _Dmain_1 Ham!() a; // _Dmain_3bar_1 Ham!() b; // _Dmain_3bar_2 assert(!is(typeof(a) == typeof(b))); Eggs!() c; // _Dmain_3bar_3 S2!() d; // _Dmain_3foo_1 } struct Qux { pragma(msg, __GENSYM__); // 3foo3Qux_1 void baz() { pragma(msg, __GENSYM__); // _D3foo3Qux3bazMFZv_1 Ham!() a; // _D3foo3Qux3bazMFZv_3bar_1 } } struct S2(string gensym = __GENSYM__) { pragma(msg, gensym); } Should I file an enhancement for this? -- Simen
Apr 04 2016
On Friday, 1 April 2016 at 22:54:53 UTC, Simen Kjaeraas wrote: ...I kinda agree. And looking at https://dlang.org/spec/traits.html, I see there's __MODULE__, which would probably be a better choice than __FILE__.I think adding something like __UNIQUE_NAME__ to predefined constants will allow to avoid all these perversions. The only thing to think here about uniqueness scope.
Apr 02 2016
On Thursday, 31 March 2016 at 23:58:54 UTC, Nordlöw wrote:I've put David Nadlinger work together with my tweaks on top at https://github.com/nordlow/units-d to make it easier to experiment with. PR are very welcome.Nice work. I have yet to play around with it, but this is definitely going to need pre-made symbols for the United States customary system like SI has before it goes into Phobos.
Apr 01 2016