www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - std.range.put?

reply simendsjo <simendsjo gmail.com> writes:
Shouldn't the following work?

import std.range;
import std.stdio;

void main() {
     int[] a;
     a.reserve(10);
     //a.put(1); // Attempting to fetch the front of an empty array of int
     a.length = 1;
     writeln(a.length); // 1
     a.put(2);
     writeln(a.length); // 0 - what?
     writeln(a); // [] - come on!

     char[] b;
     //b.put('a'); // range.d(615): Error: static assert  "Cannot put a  
char into a char[]"
}
May 21 2012
next sibling parent reply "jerro" <a a.com> writes:
On Monday, 21 May 2012 at 11:26:33 UTC, simendsjo wrote:
 Shouldn't the following work?

 import std.range;
 import std.stdio;

 void main() {
     int[] a;
     a.reserve(10);
     //a.put(1); // Attempting to fetch the front of an empty 
 array of int
     a.length = 1;
     writeln(a.length); // 1
     a.put(2);
     writeln(a.length); // 0 - what?
     writeln(a); // [] - come on!

     char[] b;
     //b.put('a'); // range.d(615): Error: static assert  
 "Cannot put a char into a char[]"
 }
Input ranges are supposed to work like that when use as output range. You could change that by also defining a put member for them, but I don't think doing that would be a good idea. The current behavior allows you to fill an input range using a function that takes an output range. For example you can do the following with an array: auto a = [4, 3, 2, 1, 0]; copy([0,1,2], a); writeln(a); // prints [0, 1, 2, 1, 0] If an array had a put member that would append to it, this would print [4, 3, 2, 1, 0, 0, 1, 2]. I think it is better to have to explicitly state that you want to append to an array. It should be possible to use RefAppender for that: copy([0, 1, 2], appender(&a)); // error This currently doesn't work (I think that because RefAppender implements put through opDispatch and constraint for range.put checks for put member using hasMember). You could write your own function to work around that: auto output(T)(ref T[] arr) { static struct R { T[]* arr; void put(int v){ arr ~= v; } } return R(&arr); } auto a = [4, 3, 2, 1, 0]; copy([0,1,2], output(a)); writeln(a); // prints [4, 3, 2, 1, 0, 0, 1, 2]
May 21 2012
parent "jerro" <a a.com> writes:
 void put(int v){ arr ~= v; }
should be void put(T v){ *arr ~= v; }
May 21 2012
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 21 May 2012 07:26:32 -0400, simendsjo <simendsjo gmail.com> wrote:

 Shouldn't the following work?

 import std.range;
 import std.stdio;

 void main() {
      int[] a;
      a.reserve(10);
      //a.put(1); // Attempting to fetch the front of an empty array of  
 int
      a.length = 1;
      writeln(a.length); // 1
      a.put(2);
      writeln(a.length); // 0 - what?
      writeln(a); // [] - come on!
OK, here is why: put(R, v) has three modus operandi: 1. R is an input range with an lvalue front(). 2. R is a function/delegate that accepts a v 3. R implements the method put(v) slices fit into category one. In this case, guess what happens? R.front = v; R.popFront(); Why? Think of R as a *buffer* that is *pre-allocated* and needs to be filled. This is what put is trying to do. What you want is std.array.Appender, which defines the method put, which *appends* data to the end instead of overwriting it.
      char[] b;
      //b.put('a'); // range.d(615): Error: static assert  "Cannot put a  
 char into a char[]"
 }
This is just phobos being its usual nasty self claiming that char[] is not an array of char, but actually a range of dchar. If I only had a nickel every time someone ran into this "feature"... I'd probably have about $5 by now ;) It's one of the worst designs of Phobos. -Steve
May 23 2012