Rust updates

Chad J chadjoan at __spam.is.bad__gmail.com
Wed Jul 11 18:51:08 PDT 2012


On 07/11/2012 02:00 PM, David Piepgrass wrote:
>
> I am particularly a fan of structural typing. I don't know if Rust uses
> it but Opa and other functional languages often do. You see, there's a
> problem that pops up in .NET all the time, and probably the same problem
> exists in D.
>
> Any time two libraries want to use the same concept, but the concept is
> not in the standard library, they need to define it. For instance if
> there is no "Point" type in the standard library, but two unrelated
> libraries need points, they will both define their own (amazingly,
> Points are poorly thought out in .NET and tightly bound to GUI
> libraries, so people define their own in some cases):
>
> // JoesLibrary
> struct Point!T { T x, y; /* followed by some manipulation functions */ }
>
> // FunkyLibrary
> struct Point!T { T x, y; /* followed by other manipulation functions */ }
>
> Sadly, the two point types are not compatible with each other. A client
> that wants to use both libraries now has an interoperability problem
> when he wants to pass data between the.
>
> Even a client that uses only one of the library, let's call it
> "JoesLibrary" has to import Point from "JoesLibrary", even if its
> functionality is not quite what the client wants. It would be much nicer
> if the client could define his own Point struct that seamlessly
> interoperates with Joes'. In D this is currently impractical, but I
> would enjoy designing a way to make it work (before you point out that
> "what if x and y are in a different order in the two structs" and "it
> could be T X,Y in one and T x,y in the other", yes, I know, It's on my
> list of problems to cleverly solve)
>
> A similar problem exists with interfaces, where two unrelated libraries
> expose two similar classes with some common functions, but you can't
> cast them to a common type in D. This is a solved problem in Go
> (http://www.airs.com/blog/archives/277) and it's actually pretty easy
> for a compiler to magically cast a class to an interface that the class
> did not declare--if the underlying language is designed for that, anyway.
>
> In fact, in .NET at least, the same problem exists even if the libraries
> DO know about each other and are even written by the same person and use
> identical interfaces. The problem is, if I write two libraries A and B,
> and I want them to be interoperable, then I need to factor out the
> common structs and interfaces to a microscopic third library, I. But
> from the client's perspective, if a client only knows about A or B, he
> will think it's stupid that I require him to use and deploy two
> DLLs/so's (A and I, or B and I) instead of one. In D I guess it's not
> the same, though.
>

I'm pretty sure this interoperability thing is solved in D, at least at 
compile time.

Example:

import std.traits;

/// Returns true if T is a Point type.
template isPoint(T)
{
     enum bool isPoint = is(typeof(
     {
         T point;

         // (x,y) should be numeric.
         static assert ( isNumeric!(typeof(point.x)) );
         static assert ( isNumeric!(typeof(point.y)) );

         auto x = point.x; // x is readable
         point.x = x;      // x is writable

         auto y = point.y; // y is readable
         point.y = y;      // y is writable
     }));
}

struct MyPointType
{
     float x;
     float y;
}

struct AnotherPointType
{
     int x;
     int y;
}

struct NotAPoint
{
     char[] x;
     char[] y;
}

// TODO: are x and y allowed to have differing types?
static assert(isPoint!MyPointType);
static assert(isPoint!AnotherPointType);
static assert(!isPoint!NotAPoint);

auto myPointCalculation(P1,P2)( P1 p1, P2 p2 ) if ( isPoint!P1 && 
isPoint!P2 )
{
     p1.x += p2.x;
     p1.y += p2.y;
     return p1;
}

import std.stdio;
void main()
{
     MyPointType p1;
     AnotherPointType p2;
     p1.x = 3.5;
     p1.y = 5.0;
     p2.x = 2;
     p2.y = 2;
     writefln("(before) p1 == (%s, %s)",p1.x,p1.y);
     p1 = myPointCalculation(p1,p2);
     writefln("(after)  p1 == (%s, %s)",p1.x,p1.y);
}



At the command line:
chad at Hugin ~/dprojects/dtesting/points $ dmd points.d
chad at Hugin ~/dprojects/dtesting/points $ ./points
(before) p1 == (3.5, 5)
(after)  p1 == (5.5, 7)


More information about the Digitalmars-d mailing list