Skip to content

Instantly share code, notes, and snippets.

@jacob-carlborg
Last active September 13, 2018 07:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jacob-carlborg/b3c91a94f306564158b2a6ac58a57d50 to your computer and use it in GitHub Desktop.
Save jacob-carlborg/b3c91a94f306564158b2a6ac58a57d50 to your computer and use it in GitHub Desktop.
Go 2 draft D corrections

The examples for D while they will most likley compile, it's not really how one would write D templates today. I also provide usage examples showing that everything compiles as expected.

Set example:

// no need to use the template keyword
struct Set(T) if(is(typeof(T.init == T.init))) // Verify T has equlity
{
    void add(T o) {}
}

Sum example. Since D supports operator overloading and + does not necessarly need to be the same as += we're checking for += since that's what is used in the implementation.

enum hasAddAssign(T) = __traits(compiles, { T a; a += a; }); // Verify T supports +=

T sum(T)(T[] x) if (hasAddAssign!T) // only for arrays
{
    T s;
    foreach (e; x)
        s += e;
    return s;
}

The above example only supports arrays. Usually one would implement a function like sum to take a range instead of an array. The range version handles bascilly anything that is iteratable:

enum hasAddAssign(T) = __traits(compiles, { T a; a += a; }); // Verify T supports +=

import std.array : front;
import std.range : isInputRange, ElementType;

auto sum(Range)(Range x)
    if (isInputRange!Range && hasAddAssign!(ElementType!Range))
{
    ElementType!Range s;
    foreach (e; x)
        s += e;
    return s;
}

ShortestPath example:

import std.traits : ReturnType;

enum isGraph(Node, Edge) =
    is(ReturnType!(Node.Edges) == Edge[]) &&
    is(ReturnType!(Edge.Nodes) == Node[]);

Edge[] shortestPath(Edge, Node)(Node src, Node dest) if (isGraph!(Node, Edge))
{
    return null;
}

Usage:

struct Node
{
    Edge[] Edges()
    {
        return null;
    }
}

struct Edge
{
    Node[] Nodes()
    {
        return null;
    }
}

void main()
{
    shortestPath!(Edge)(Node(), Node()); // implicit function template instantiation for the second type
    [1, 2, 3].sum(); // implicit function template instantiation
                     // UFCS, Uniform Function Call Syntax. That is, a free function can be called like a member function

    Set!int a; // template instantiations without parentheses if the type is a single symbol
    a.add(3);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment