www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Two easy pieces

reply "bearophile" <bearophileHUGS lycos.com> writes:
This is a way to insert an item in a sorted array:


import std.stdio: writeln;
import std.range: assumeSorted;
import std.array: insertInPlace;
void main() {
     int[] arr = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90];
     int x = 35;
     arr.insertInPlace(arr.assumeSorted.lowerBound(x).length, x);
     arr.writeln;
}


Haskell has the insert/insertBy functions 
(http://zvon.org/other/haskell/Outputlist/insertBy_f.html  
http://zvon.org/other/haskell/Outputlist/insert_f.html ).
Is it worth adding such small function to std.array?

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

Sometimes you want to print something coming out of a UFCS chain 
with a formatting string. In this case you can't append the 
writef/writefln at the end of the chain. The problem is easy to 
solve with two simple functions like this. Are they worth having 
in std.stdio?


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

void ufcsWritef(T)(T data, string format) {
     writef(format, data);
}

void ufcsWritefln(T)(T data, string format) {
     writefln(format, data);
}

void main() {
     // Problem from:
     // reddit.com/r/dailyprogrammer_ideas/comments/15in89
     immutable txt = ["Line one", "Line 2"];
     foreach (i; 0 .. txt.map!q{ a.length }.reduce!max)
         txt.transversal(i).writeln;

     // Or equivalently:
     txt
     .map!q{ a.length }
     .reduce!max
     .iota
     .map!(i => txt.transversal(i))
     .ufcsWritefln("%(%s\n%)");
}


Bye,
bearophile
Apr 01 2013
next sibling parent reply "ixid" <nuaccount gmail.com> writes:
On Tuesday, 2 April 2013 at 00:10:45 UTC, bearophile wrote:
 This is a way to insert an item in a sorted array:


 import std.stdio: writeln;
 import std.range: assumeSorted;
 import std.array: insertInPlace;
 void main() {
     int[] arr = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90];
     int x = 35;
     arr.insertInPlace(arr.assumeSorted.lowerBound(x).length, x);
     arr.writeln;
 }


 Haskell has the insert/insertBy functions 
 (http://zvon.org/other/haskell/Outputlist/insertBy_f.html  
 http://zvon.org/other/haskell/Outputlist/insert_f.html ).
 Is it worth adding such small function to std.array?

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

 Sometimes you want to print something coming out of a UFCS 
 chain with a formatting string. In this case you can't append 
 the writef/writefln at the end of the chain. The problem is 
 easy to solve with two simple functions like this. Are they 
 worth having in std.stdio?


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

 void ufcsWritef(T)(T data, string format) {
     writef(format, data);
 }

 void ufcsWritefln(T)(T data, string format) {
     writefln(format, data);
 }

 void main() {
     // Problem from:
     // reddit.com/r/dailyprogrammer_ideas/comments/15in89
     immutable txt = ["Line one", "Line 2"];
     foreach (i; 0 .. txt.map!q{ a.length }.reduce!max)
         txt.transversal(i).writeln;

     // Or equivalently:
     txt
     .map!q{ a.length }
     .reduce!max
     .iota
     .map!(i => txt.transversal(i))
     .ufcsWritefln("%(%s\n%)");
 }


 Bye,
 bearophile
UFCS also needs its write function to be able to print whatever data it is passed and then pass exactly the data it was passed on so you can drop write statements into UFCS chains and take them out without needing to chop around the chain. auto result = data.dostuff.domorestuff.writeUFCS.morestuff.finalstep;
Apr 01 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
ixid:

 UFCS also needs its write function to be able to print whatever 
 data it is passed and then pass exactly the data it was passed 
 on so you can drop write statements into UFCS chains and take 
 them out without needing to chop around the chain.
Right, second version: import std.stdio, std.range, std.algorithm; auto ufcsWrite(T)(T data) { write(data); return data; } auto ufcsWriteln(T)(T data) { writeln(data); return data; } auto ufcsWritef(T)(T data, string format) { writef(format, data); return data; } auto ufcsWritefln(T)(T data, string format) { writefln(format, data); return data; } void main() { // Problem from: // reddit.com/r/dailyprogrammer_ideas/comments/15in89 immutable txt = ["Line one", "Line 2"]; txt .map!q{ a.length } .ufcsWriteln .reduce!max .iota .map!(i => txt.transversal(i)) .ufcsWritefln("%(%s\n%)"); } Bye, bearophile
Apr 01 2013
parent Timothee Cour <thelastmammoth gmail.com> writes:
There's too little value in those ufcsWritef, ufcsWritefln,
ufcsWriteln, ufcsWritefln to justify adding them. When does it stop??

Why not introduce 'std.range.tap', which is more generic and has been
proposed before:

something like this:

T tap(alias fun,T)(T a){
  fun(a);
  return a;
}

Then:

auto result = data.dostuff.domorestuff.tap!(a=>
writef(fmt,a)).morestuff.finalstep;

of course for non-formatted write it's even simpler:

auto result = data.dostuff.domorestuff.tap!writeln.morestuff.finalstep;


--------

That being said, I believe std.algorithm.reduce DOES deserve it's
counterpart with reversed arguments, more UFCS friendly (which we
could call fold or reduce2), as this is a more common pattern and
std.algorithm.reduce was a design mistake (before ufcs existed).


On Mon, Apr 1, 2013 at 8:20 PM, bearophile <bearophileHUGS lycos.com> wrote:
 ixid:


 UFCS also needs its write function to be able to print whatever data it is
 passed and then pass exactly the data it was passed on so you can drop write
 statements into UFCS chains and take them out without needing to chop around
 the chain.
Right, second version: import std.stdio, std.range, std.algorithm; auto ufcsWrite(T)(T data) { write(data); return data; } auto ufcsWriteln(T)(T data) { writeln(data); return data; } auto ufcsWritef(T)(T data, string format) { writef(format, data); return data; } auto ufcsWritefln(T)(T data, string format) { writefln(format, data); return data; } void main() { // Problem from: // reddit.com/r/dailyprogrammer_ideas/comments/15in89 immutable txt = ["Line one", "Line 2"]; txt .map!q{ a.length } .ufcsWriteln .reduce!max .iota .map!(i => txt.transversal(i)) .ufcsWritefln("%(%s\n%)"); } Bye, bearophile
Apr 01 2013
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 01 Apr 2013 20:10:44 -0400, bearophile <bearophileHUGS lycos.com>  
wrote:

 Sometimes you want to print something coming out of a UFCS chain with a  
 formatting string. In this case you can't append the writef/writefln at  
 the end of the chain. The problem is easy to solve with two simple  
 functions like this. Are they worth having in std.stdio?


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

 void ufcsWritef(T)(T data, string format) {
      writef(format, data);
 }

 void ufcsWritefln(T)(T data, string format) {
      writefln(format, data);
 }

 void main() {
      // Problem from:
      // reddit.com/r/dailyprogrammer_ideas/comments/15in89
      immutable txt = ["Line one", "Line 2"];
      foreach (i; 0 .. txt.map!q{ a.length }.reduce!max)
          txt.transversal(i).writeln;

      // Or equivalently:
      txt
      .map!q{ a.length }
      .reduce!max
      .iota
      .map!(i => txt.transversal(i))
      .ufcsWritefln("%(%s\n%)");
 }
Good idea. I propose fwrite. We're reversing the parameters, so I reversed the function name. Well, sort of :) -Steve
Apr 01 2013
parent reply "timotheecour" <timothee.cour2 gmail.com> writes:
IMO, there's too little value in those ufcsWritef, ufcsWritefln,
ufcsWriteln, ufcsWritefln to justify adding them. When does it 
stop??

Why not introduce 'tap', which is more generic and has been
proposed before:

something like this:

T tap(alias fun,T)(T a){
   fun(a);
   return a;
}

Then:

auto result = data.dostuff.domorestuff.tap!(a=>
writef(fmt,a)).morestuff.finalstep;

of course for non-formatted write it's even simpler:

auto result = 
data.dostuff.domorestuff.tap!writeln.morestuff.finalstep;


--------

That being said, I believe std.algorithm.reduce DOES deserve it's
counterpart with reversed arguments, more UFCS friendly (which we
could call fold or reduce2), as this is a more common pattern and
std.algorithm.reduce was a design mistake (before ufcs existed).
Apr 01 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
timotheecour:

 IMO, there's too little value in those ufcsWritef, ufcsWritefln,
 ufcsWriteln, ufcsWritefln to justify adding them. When does it 
 stop??
I have opened this thread, instead of asking for those functions in Bugzilla rightly because I don't know where it stops.
 Why not introduce 'tap', which is more generic and has been
 proposed before:

 something like this:

 T tap(alias fun,T)(T a){
   fun(a);
   return a;
 }

 Then:

 auto result = data.dostuff.domorestuff.tap!(a=>
 writef(fmt,a)).morestuff.finalstep;

 of course for non-formatted write it's even simpler:

 auto result = 
 data.dostuff.domorestuff.tap!writeln.morestuff.finalstep;
Because tap leads to a bit more verbose syntax, and because I've seen that in most cases what I want to put in tap is a printing :-)
 That being said, I believe std.algorithm.reduce DOES deserve 
 it's counterpart with reversed arguments,
There is a patch and discussions on this in Bugzilla and GitHub. So probably you will see a UFCS-friendly reduce. Bye, bearophile
Apr 02 2013
next sibling parent "Tobias Pankrath" <tobias pankrath.net> writes:
On Tuesday, 2 April 2013 at 11:27:25 UTC, bearophile wrote:
 timotheecour:

 IMO, there's too little value in those ufcsWritef, 
 ufcsWritefln,
 ufcsWriteln, ufcsWritefln to justify adding them. When does it 
 stop??
I have opened this thread, instead of asking for those functions in Bugzilla rightly because I don't know where it stops.
I think the bar for helper/utility functions in phobos is way to high, leading to everyone defining it's own. These functions do useful stuff that is not possible with normal write-family of functions and UFCS-Chains _are_ a major selling point of D syntax.
Apr 02 2013
prev sibling parent "Dicebot" <m.strashun gmail.com> writes:
On Tuesday, 2 April 2013 at 11:27:25 UTC, bearophile wrote:
 Because tap leads to a bit more verbose syntax, and because 
 I've seen that in most cases what I want to put in tap is a 
 printing :-)
Well, a bit more verbose and a lot more generic - exactly the right balance for standard library snippet in my opinion :)
Apr 02 2013
prev sibling parent reply Nick Treleaven <ntrel-public yahoo.co.uk> writes:
On 02/04/2013 01:10, bearophile wrote:
 Sometimes you want to print something coming out of a UFCS chain with a
 formatting string. In this case you can't append the writef/writefln at
 the end of the chain. The problem is easy to solve with two simple
 functions like this. Are they worth having in std.stdio?
I think usually the format string is known statically, so we could have a template overload of writef[ln] with a compile-time format parameter. We can then use that overload for UFCS: 5.writefln!"hi %s!";
Apr 02 2013
parent reply Nick Treleaven <ntrel-public yahoo.co.uk> writes:
On 02/04/2013 14:33, Nick Treleaven wrote:
 On 02/04/2013 01:10, bearophile wrote:
 Sometimes you want to print something coming out of a UFCS chain with a
 formatting string. In this case you can't append the writef/writefln at
 the end of the chain. The problem is easy to solve with two simple
 functions like this. Are they worth having in std.stdio?
I think usually the format string is known statically, so we could have a template overload of writef[ln] with a compile-time format parameter. We can then use that overload for UFCS: 5.writefln!"hi %s!";
Of course, the main point of doing that is to compile-time validate the format string. But UFCS is a nice consequence.
Apr 02 2013
parent Timothee Cour <thelastmammoth gmail.com> writes:
It breaks ufcs chaining so you can't continue the chain, see above.
On Apr 2, 2013 8:45 AM, "Nick Treleaven" <ntrel-public yahoo.co.uk> wrote:

 On 02/04/2013 14:33, Nick Treleaven wrote:

 On 02/04/2013 01:10, bearophile wrote:

 Sometimes you want to print something coming out of a UFCS chain with a
 formatting string. In this case you can't append the writef/writefln at
 the end of the chain. The problem is easy to solve with two simple
 functions like this. Are they worth having in std.stdio?
I think usually the format string is known statically, so we could have a template overload of writef[ln] with a compile-time format parameter. We can then use that overload for UFCS: 5.writefln!"hi %s!";
Of course, the main point of doing that is to compile-time validate the format string. But UFCS is a nice consequence.
Apr 02 2013