Jump to page: 1 2
Thread overview
writeln, UFCS and flip
Apr 25, 2013
bearophile
Apr 25, 2013
bearophile
Apr 25, 2013
ixid
Apr 25, 2013
ixid
Apr 25, 2013
bearophile
Apr 25, 2013
Timon Gehr
Apr 26, 2013
bearophile
Apr 26, 2013
ixid
Apr 26, 2013
bearophile
Apr 26, 2013
Tyro[17]
Apr 26, 2013
bearophile
Apr 26, 2013
Timon Gehr
Apr 26, 2013
Tyro[17]
Apr 26, 2013
Tyro[17]
Apr 26, 2013
bearophile
April 25, 2013
writeln is able to write a whole range:


import std.stdio, std.algorithm, std.range;

void main() {
    10.iota.map!(x => x ^^ 2).writeln;
}


Output:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

- - - - - - - - - - - - - - - -

But if you want to format the range in some way you have to change the order of things, this is not nice:


import std.stdio, std.algorithm, std.range;

void main() {
    writefln("%(%d %)", 10
                        .iota
                        .map!(x => x ^^ 2));
}


Output:
0 1 4 9 16 25 36 49 64 81

- - - - - - - - - - - - - - - -

To solve that little problem I suggested to add some new printing functions to Phobos:

http://d.puremagic.com/issues/show_bug.cgi?id=9882


auto uWrite(T)(T data) {
    write(data);
    return data;
}

auto uWriteln(T)(T data) {
    writeln(data);
    return data;
}

auto uWritef(T, TS)(T data, TS format) if (isSomeString!TS) {
    writef(format, data);
    return data;
}

auto uWritefln(T, TS)(T data, TS format) if (isSomeString!TS) {
    writefln(format, data);
    return data;
}

- - - - - - - - - - - - - - - -

Now I have invented a different solution (similar to the "flip" function of Haskell):


import std.stdio, std.algorithm, std.range;

/// flip!foo(a, b) === foo(b, a)
template flip(alias callable) {
    auto flip(T2, T1)(T2 y, T1 x) {
        return callable(x, y);
    }
}

void main() {
    10.iota.map!(x => x ^^ 2).flip!writefln("%(%d %)");
}

You can also write that main() like this:

void main() {
    10
    .iota
    .map!(x => x ^^ 2)
    .flip!writefln("%(%d %)");
}


(I have used a template+function so flip!foo is usable as argument for some algorithms.)

flip is a much more general solution, and it's useful in other situations.

In theory "callable" should have a template constraint like "isCallable!callable", but in practice I think you can't use it for writeln and other templated functions.

- - - - - - - - - - - - - - - -

An alternative design flips the first two arguments of two or more arguments:



import std.stdio, std.algorithm, std.range;

/// flip2!foo(a, b, c...) === foo(b, a, c...)
template flip2(alias callable) {
    auto flip2(T2, T1n...)(T2 y, T1n others)
    if (T1n.length > 0) {
        return callable(others[0], y, others[1 .. $]);
    }
}

void main() {
    10.iota.map!(x => x ^^ 2).flip2!writefln("%(%d %) %s", "good");
}


I have named it flip2 because I expect this to be true:

flip!foo(a, b, c) === foo(c, b, a)

so the name "foo2" reminds me that it flips only the first two arguments.

What do you think?

Bye,
bearophile
April 25, 2013
This is not a real use case because the reduce!() of Phobos will be fixed for UCFS, but sometimes you can't swap the arguments of a function:


import std.stdio, std.algorithm, std.range;

/// flip2!foo(a, b, c...) === foo(b, a, c...)
template flip2(alias callable) {
    auto flip2(T2, T1n...)(T2 y, T1n others)
    if (T1n.length > 0) {
        return callable(others[0], y, others[1 .. $]);
    }
}

void main() {
    reduce!q{a * b}(1, iota(1, 10))
    .writeln;

    iota(1, 10)
    .flip2!(reduce!q{a * b})(1)
    .writeln;
}


Bye,
bearophile
April 25, 2013
Doesn't binaryReverseArgs in std.functional already do this? Flip is a much, much better name though.

April 25, 2013
On Thursday, 25 April 2013 at 16:20:39 UTC, ixid wrote:
> Doesn't binaryReverseArgs in std.functional already do this? Flip is a much, much better name though.

Though I still think write functions passing on the data would be useful, letting you avoid needless temporaries just so you can write the output of a function. It's useful for normal code as well as UFCS.

string temp = myFun();
temp.writeln;
result ~= temp ~ "\n";
April 25, 2013
On Thursday, 25 April 2013 at 16:20:39 UTC, ixid wrote:
> Doesn't binaryReverseArgs in std.functional already do this?

Right, it's the flip I have suggested here. My flip2 is a little different. I will think about this.


> Though I still think write functions passing on the data would be useful, letting you avoid needless temporaries just so you can write the output of a function.

OK.

Bye,
bearophile
April 25, 2013
On 04/25/2013 05:09 PM, bearophile wrote:
> ...
>
> What do you think?
>
> ...

I think what you call flip2 should be called flip.
April 26, 2013
Timon Gehr:

> I think what you call flip2 should be called flip.

Why?

Bye,
bearophile
April 26, 2013
On Friday, 26 April 2013 at 10:52:09 UTC, bearophile wrote:
> Timon Gehr:
>
>> I think what you call flip2 should be called flip.
>
> Why?
>
> Bye,
> bearophile

flip2 is the more general and useful function with new functionality so there's no need for what was flip and we should call the new function 'flip'.

April 26, 2013
ixid:

> flip2 is the more general and useful function with new functionality so there's no need for what was flip and we should call the new function 'flip'.

I don't agree. Maybe you are missing something.

I expect a function named "flip" to do:

flip!foo(a, b, c) === foo(c, b, a)
flip!foo(a, b, c, d) === foo(d, c, b, a)

While flip2 does:

flip2!foo(a, b, c) === foo(b, a, c)
flip2!foo(a, b, c, d) === foo(b, a, c, d)

Bye,
bearophile
April 26, 2013
On 4/26/13 8:59 AM, bearophile wrote:
> ixid:
>
>> flip2 is the more general and useful function with new functionality
>> so there's no need for what was flip and we should call the new
>> function 'flip'.
>
> I don't agree. Maybe you are missing something.
>
> I expect a function named "flip" to do:
>
> flip!foo(a, b, c) === foo(c, b, a)
> flip!foo(a, b, c, d) === foo(d, c, b, a)

I would expect this to be called reverse

> While flip2 does:
>
> flip2!foo(a, b, c) === foo(b, a, c)
> flip2!foo(a, b, c, d) === foo(b, a, c, d)

and this rotate....

Why flip in the first place?

> Bye,
> bearophile

« First   ‹ Prev
1 2