On Friday, 11 November 2016 at 16:39:26 UTC, Heisenberg wrote:
What would it take to implement the Uniform Function Call Syntax for a function's argument which is not the first?

Right now it is possible to do the following:

int someNumber(int a, int b)
{
    return a + b;
}

void main()
{
    int n1 = 5;
    int n2 = n1.someNumber(n1 + 1); // Here the `n1` is `a`
}

But it's not possible to use the `n1' as `b`, for UFCS only substitutes the expression before the `.` for the first argument. This limits a little bit the flexibility of UFCS. What would it take to specify the argument in which UFCS is going to put the expression before the `.`? This would make it even more useful.

For instance:

string someStr = "Yohoho!";
// To format and print it, one could use `printf':
writefln("The string is \"%s\".", someStr);
// But since it is not in the first place,
// it is not possible to use UFCS for it:
someStr.writefln("The string is \"%s\"."); // ^ Prints `Yohoho!'
// One could use tuples to pass
// the expanded list of strings:
tuple("The string is \"%s\".", someStr)[].writefln();
// But it would be much easier if there was
// some way to tell the compiler
// to position the argument,
// for example:
someStr&1.writefln("The string is \"%s\".");
//     ^            ^ argument at the position [0]
//     ^ argument to be put at the position [1]
// This could even allow to insert the argument
// at more than one position at once:
someStr&1&3&4.writefln("Say it, lass!\n" ~
"%s\nI'm a pirate!\n" ~ // someStr goes here (1)
                       "%s\nHe's a pirate!\n" ~ // not here (2)
                       "She's a pirate!\n%s" ~  // here (3)
                       "Ale! Rum! %s\n" ~       // and here (4)
                       "Wait.. Why is the rum gone?",
                       "You are a pirate!");    // gets shifted
// to position (2)

I'm sure there are loads of corner cases this doesn't cover, but:

template inPos(uint n, alias f)
{
    auto inPos(Args...)(auto ref Args args)
    {
        return f(args[1 .. n+1], args[0], args[n+1 .. $]);
    }
}

import std.stdio;
alias formatSecond = inPos!(1, writefln);

void main()
{

    1.writeln(2,3,4,5);
    1.inPos!(2, writeln)(2,3,4,5);

    42.formatSecond("The answer is %d");
}

and of course you could easily develop more powerful templates that could do any other order manipulations you like.

Reply via email to