On 2016-05-23 21:00, Adam D. Ruppe wrote:
Have I gone completely mad?!?!

---
void main() {
         import std.stdio;
         writeln(obj!(
                 foo => "bar",
                 baz => 12
         ));
}
---

Prints out:

{
         foo: bar
         baz: 12
}



A few tweaks would make a whole loose typed hash thing more akin to Ruby
or PHP than D. What's obj? Behold:


string obj(T...)() {
         import std.conv, std.traits;
         string jsonResult = "{";
         foreach(arg; T) {
                 jsonResult ~= "\n\t";

                 // I don't know why the usual is(__parameters) trick
                 // won't work here, but a stringof hack will!
                 string hack = typeof(arg!string).stringof;
                 import std.string;
                 hack = hack[hack.indexOf("function(string ") +
"function(string ".length .. $];
                 hack = hack[0 .. hack.indexOf(")")];

                 jsonResult ~= hack;
                 jsonResult ~= ": ";
                 jsonResult ~= to!string(arg(""));

         }
         jsonResult ~= "\n}";
         return jsonResult;
}

That's pretty cool and pretty ugly :).

As you probably know, D has a couple lambda literal syntaxes. One of
these is the fat arrow, with a valid form of argument => return_expression.

The compiler makes templates out of these when you pass them around....
and those templates contain the parameters, including the name, and are
callable code (if instantiated with a concrete type).

I was disappointed to see the ordinary reflection tools didn't work here
- I know, I'm abusing the language - but the trusty old .stringof hack
did! Combined with the magic knowledge that these things are templates,
I instantiated them (tbh I was a bit surprised it actually let me!) and
extracted the name of the argument.

__parameters doesn't work because an "untyped" lambda is a template and __parameters works with functions, but I guess you already know that. Instantiating the lambda and then using __parameters should work.

There's a PR for DMD which adds support for inspecting template parameters [1] that would help. Unfortunately it's closed.

Here's a version building an associative array mapping strings to variants:

import std.stdio : println = writeln;
import std.variant;

Variant[string] hash(T...)() {
    import std.conv, std.traits;
    Variant[string] aa;
    foreach(arg; T) {
        // I don't know why the usual is(__parameters) trick
        // won't work here, but a stringof hack will!
        string hack = typeof(arg!string).stringof;
        import std.string;
hack = hack[hack.indexOf("function(string ") + "function(string ".length .. $];
        hack = hack[0 .. hack.indexOf(")")];

        aa[hack] = Variant(arg(""));

    }
    return aa;
}

void main() {
    auto h = hash!(
        foo => 3,
        bar => "asd"
    );
    writeln(h);
}

[1] https://github.com/dlang/dmd/pull/5201

--
/Jacob Carlborg

Reply via email to