Thread overview | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
April 25, 2013 writeln, UFCS and flip | ||||
---|---|---|---|---|
| ||||
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 Re: writeln, UFCS and flip | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 Re: writeln, UFCS and flip | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | Doesn't binaryReverseArgs in std.functional already do this? Flip is a much, much better name though. |
April 25, 2013 Re: writeln, UFCS and flip | ||||
---|---|---|---|---|
| ||||
Posted in reply to ixid | 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 Re: writeln, UFCS and flip | ||||
---|---|---|---|---|
| ||||
Posted in reply to ixid | 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 Re: writeln, UFCS and flip | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 Re: writeln, UFCS and flip | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | Timon Gehr:
> I think what you call flip2 should be called flip.
Why?
Bye,
bearophile
|
April 26, 2013 Re: writeln, UFCS and flip | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 Re: writeln, UFCS and flip | ||||
---|---|---|---|---|
| ||||
Posted in reply to ixid | 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 Re: writeln, UFCS and flip | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 |
Copyright © 1999-2021 by the D Language Foundation