Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
December 02, 2011 Compile time metaprogramming | ||||
---|---|---|---|---|
| ||||
I had a little talk with one of my teachers regarding the culprits of wrong unit assumptions in code (http://mars.jpl.nasa.gov/msp98/news/mco990930.html). We had a little different views on how much pain it would be for developers to code using an SI library, so I hacked together a small proof-of-concept in D to show how D's metaprogramming could make things a lot less painful than, say, Java. I thought I could share it here too even though it's just a small hack with Norwegian comments. import std.traits, std.stdio, std.conv; void main() { auto f = feet(10); auto m = meter(10.0); // kan fint bruke desimaltall // en type til en annen - konvertering // kan gjerne bruke /, * e.l. også - metaprogrammering er en god ting :) auto feetMeter = f + m; assert( feetMeter.siunit == "feet" ); assert( feetMeter >= feet(42.808) && feetMeter <= feet(42.809) ); auto meterFeet = m + f; assert( meterFeet.siunit == "meter" ); assert( meterFeet >= meter(13.0475) && meterFeet <= meter(13.0485) ); // kan også bruke skalarer - og fint mikse floats inn i det assert( m * 2.2 == meter(22) ); // eller konvertere direkte auto f2 = meterFeet.to!"feet"(); assert( f2.siunit == "feet" ); assert( f2 >= feet(42.808) && f2 <= feet(42.809) ); // men kan ikke konvertere uten konverteringsfunksjoner static assert(!__traits(compiles, m.to!"finnes ikke"()) ); // men kan ikke manipulere urelaterte typer static assert(!__traits(compiles, feet(10) + celsius(10)) ); // kan caste til kompatible typer double d = cast(double)m; assert( d == 10.0 ); // eller sammenlikne direkte assert( m == 10 ); assert( m > 9 ); assert( m < 11 ); } auto meter(V)(V value) pure nothrow @safe { return Value!("meter", V)(value); } auto feet(V)(V value) pure nothrow @safe { return Value!("feet", V)(value); } auto celsius(V)(V value) pure nothrow @safe { return Value!("celsius", V)(value); } auto fahrenheit(V)(V value) pure nothrow @safe { return Value!("fahrenheit", V)(value); } auto SIConvert(string S, string D, T)(T value) pure nothrow @safe if(S == "meter" && D == "feet") { return value / 0.3048; } auto SIConvert(string S, string D, T)(T value) pure nothrow @safe if(S == "feet" && D == "meter") { return value * 0.3048; } auto SIConvert(string S, string D, T)(T value) pure nothrow @safe if(S == "celsius" && D == "fahrenheit") { return (value - 32) * (5/9); } auto SIConvert(string S, string D, T)(T value) pure nothrow @safe if(S == "fahrenheit" && D == "celsius") { return value * (9/5) + 32; } template isSIValue(T) { // HACK: Sjekker kun om det har en unit verdi... static if( is(typeof(T.siunit) : string) ) enum isSIValue = true; else enum isSIValue = false; } auto SIConvert(S, D, T)(T value) pure nothrow @safe if(isSIValue!S && isSIValue!D) { static if( S.siunit == D.siunit ) return value; else { static assert(__traits(compiles, SIConvert!(S.siunit, D.siunit, T)(value)), "Cannot convert value of type "~T.stringof~ " from "~S.siunit~" to "~D.siunit); return SIConvert!(S.siunit, D.siunit, T)(value); } } struct Value(string SIUnit, V) if(isNumeric!V) { enum siunit = SIUnit; // finnes kun ved kompilering immutable V value; this(V)(V value) pure nothrow @safe { this.value = value; } auto opBinary(string op, RHS)(RHS r) const nothrow pure @safe if(isSIValue!RHS) { auto converted = SIConvert!(RHS, typeof(this))(r.value); mixin("auto newval = value "~op~" converted;"); return Value!(siunit, typeof(newval))(newval); } auto opBinary(string op, RHS)(const RHS r) const nothrow pure @safe if(isNumeric!RHS) { mixin("auto val = value "~op~" r;"); return Value!(siunit, typeof(val))(val); } auto to(string unit)() { auto val = SIConvert!(siunit, unit, typeof(value))(value); return Value!(unit, typeof(val))(val); } T opCast(T)() const pure nothrow @safe if(is(typeof(value) : T)) { return cast(T)value; } bool opEquals(T)(const T o) const pure nothrow @safe if(isSIValue!T) { return o.siunit == siunit && o.value == value; } bool opEquals(T)(const T o) const pure nothrow @safe if(is(T : typeof(value))) { return value == o; } int opCmp(T)(const T v) const pure nothrow @safe if(isSIValue!T) { static assert(T.siunit == siunit, "Cannot compare "~siunit~" to "~T.siunit~ ". Try converting the value first"); return value < v ? -1 : (value > v ? 1 : 0); } int opCmp(T)(const T o) const pure nothrow @safe if(isNumeric!T) { return value < o ? -1 : (value > o ? 1 : 0); } string toString() const @trusted { return .to!string(value)~" "~siunit; } } |
December 02, 2011 Re: Compile time metaprogramming | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | On Friday, December 02, 2011 22:00:44 simendsjo wrote:
> I had a little talk with one of my teachers regarding the culprits of wrong unit assumptions in code (http://mars.jpl.nasa.gov/msp98/news/mco990930.html).
>
> We had a little different views on how much pain it would be for developers to code using an SI library, so I hacked together a small proof-of-concept in D to show how D's metaprogramming could make things a lot less painful than, say, Java.
>
> I thought I could share it here too even though it's just a small hack with Norwegian comments.
A unit library is definitely a great place for taking advantage of templates - that's what core.time and std.datetime do with time units (e.g. dur!"seconds"(5)). There's also been at least a couple of cases where people have worked on unit libraries and discussed them in the main newsgroup, but so far, nothing has gotten to the point where it's been reviewed for introduction to Phobos, and I don't know if any of those projects is still alive. It would definitely be an asset though.
- Jonathan M Davis
|
December 03, 2011 Re: Compile time metaprogramming | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 02.12.2011 23:28, Jonathan M Davis wrote:
> There's also been at least a couple of cases where people
> have worked on unit libraries and discussed them in the main newsgroup, but so
> far, nothing has gotten to the point where it's been reviewed for introduction
> to Phobos, and I don't know if any of those projects is still alive. It would
> definitely be an asset though.
I seem to remember someone wanting to work on a library for GSoC and that he would work on it even if it wasn't accepted. I might remember wrong, and the person might have left the project.
|
December 03, 2011 Re: Compile time metaprogramming | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | On 12/3/11 1:43 AM, simendsjo wrote: > On 02.12.2011 23:28, Jonathan M Davis wrote: >> There's also been at least a couple of cases where people >> have worked on unit libraries and discussed them in the main >> newsgroup, but so >> far, nothing has gotten to the point where it's been reviewed for >> introduction >> to Phobos, and I don't know if any of those projects is still alive. >> It would >> definitely be an asset though. > > I seem to remember someone wanting to work on a library for GSoC and > that he would work on it even if it wasn't accepted. I might remember > wrong, and the person might have left the project. That was Cristi Cobzarenco, but he then proposed a different project, linear algebra stuff [1], which he ended up working on because I already had a more or less working implementation of an units library lying around: [2]. I posted my project to the NG, and there seemed to actually be two or three people interested in it, but I didn't submit it to formal review yet, because it sometimes breaks in interesting ways due to compiler bugs (issue 3467 [3] and the likes), and I had enough work to do for my own GSoC project anyway. David [1] http://www.google-melange.com/gsoc/project/google/gsoc2011/cristicbz/36001 [2] http://klickverbot.at/code/units/ [3] http://d.puremagic.com/issues/show_bug.cgi?id=3467 |
December 03, 2011 Re: Compile time metaprogramming | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | David, to be frank, your code is already useful! Something is better than *nothing*! I hope you or someone else will continue with these two modules, and include them in Phobos. |
December 03, 2011 Re: Compile time metaprogramming | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | On 03.12.2011 10:26, David Nadlinger wrote: > > I posted my project to the NG, and there seemed to actually be two or > three people interested in it, but I didn't submit it to formal review > yet, because it sometimes breaks in interesting ways due to compiler > bugs (issue 3467 [3] and the likes), and I had enough work to do for my > own GSoC project anyway. Seems one of your bugs recently got a pull request: https://github.com/D-Programming-Language/dmd/pull/449 Gotta love the move to github! |
December 03, 2011 Re: Compile time metaprogramming | ||||
---|---|---|---|---|
| ||||
Posted in reply to simendsjo | On 12/3/11 1:49 PM, simendsjo wrote:
> Seems one of your bugs recently got a pull request:
> https://github.com/D-Programming-Language/dmd/pull/449
I'm aware of that, though Walter apparently still thinks it's okay for foo!3u and foo!3 to be different things given »template foo(uint u)«…
David
|
December 04, 2011 Re: Compile time metaprogramming | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | On Sat, 03 Dec 2011 10:26:09 +0100, David Nadlinger <see@klickverbot.at> wrote:
> On 12/3/11 1:43 AM, simendsjo wrote:
>> On 02.12.2011 23:28, Jonathan M Davis wrote:
>>> There's also been at least a couple of cases where people
>>> have worked on unit libraries and discussed them in the main
>>> newsgroup, but so
>>> far, nothing has gotten to the point where it's been reviewed for
>>> introduction
>>> to Phobos, and I don't know if any of those projects is still alive.
>>> It would
>>> definitely be an asset though.
>>
>> I seem to remember someone wanting to work on a library for GSoC and
>> that he would work on it even if it wasn't accepted. I might remember
>> wrong, and the person might have left the project.
>
> That was Cristi Cobzarenco, but he then proposed a different project, linear algebra stuff [1], which he ended up working on because I already had a more or less working implementation of an units library lying around: [2].
>
> I posted my project to the NG, and there seemed to actually be two or three people interested in it, but I didn't submit it to formal review yet, because it sometimes breaks in interesting ways due to compiler bugs (issue 3467 [3] and the likes), and I had enough work to do for my own GSoC project anyway.
I, for one, wholeheartedly support the inclusion of this in Phobos.
Oh, and Walter's reply to #3467 is scary. I hope he comes around to
seeing he's not making sense.
|
Copyright © 1999-2021 by the D Language Foundation