Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
March 31, 2016 Units of Measurement Library: units-d | ||||
---|---|---|---|---|
| ||||
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. |
April 01, 2016 Re: Units of Measurement Library: units-d | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | On 01.04.2016 01:58, Nordlöw wrote: > https://github.com/nordlow/units-d From 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))); ---- |
April 01, 2016 Re: Units of Measurement Library: units-d | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | 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.
|
April 01, 2016 Re: Units of Measurement Library: units-d | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | 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 |
April 01, 2016 Re: Units of Measurement Library: units-d | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjaeraas | 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?
|
April 01, 2016 Re: Units of Measurement Library: units-d | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | On Friday, 1 April 2016 at 21:46:35 UTC, ag0aep6g wrote: > 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? 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. -- Simen |
April 02, 2016 Re: Units of Measurement Library: units-d | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjaeraas | 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:
>> 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?
>
> 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.
>
> --
> Simen
What is needed is Lisp's gensym construct.
|
April 02, 2016 Re: Units of Measurement Library: units-d | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjaeraas | 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.
|
April 04, 2016 Re: Units of Measurement Library: units-d | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | 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, and spits out a string on the form MANGLE_#, with # being a 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
|
Copyright © 1999-2021 by the D Language Foundation