www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Mapping with partial

reply "matovitch" <camille.brugel laposte.net> writes:
Hi again,

I have this simple toy code :

import point;
import std.random;
import std.algorithm;
import std.functional;

void getRandomPoint(R)(R randVar, ref Point p)
{
       p.x = randVar;
       p.y = randVar;
       p.z = randVar;
}

void main()
{
       Point[500] points;
       auto randVar = uniform(0.0f, 1.0f);

       alias test = partial!(getRandomPoint, randVar);

       points.map!(test);
}

And get the following error :

kmeans_example.d(79): Error: template std.algorithm.iteration.map
cannot deduce function from argument types
!(partial)(Point[500]), candidates are:
/usr/include/dmd/phobos/std/algorithm/iteration.d(434):
std.algorithm.iteration.map(fun...) if (fun.length >= 1)

Btw, I don't understand why :

auto test = partial!(getRandomPoint, randVar);

dont work...partial doesnt return a delegate it seems...:/
Mar 30 2015
next sibling parent "matovitch" <camille.brugel laposte.net> writes:
(it's not on line 79 obviously, you got me :D)
Mar 30 2015
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 30 March 2015 at 18:07:18 UTC, matovitch wrote:
 kmeans_example.d(79): Error: template 
 std.algorithm.iteration.map
That error is easy: use points[].map!(test) instead of points.map. Since points is a static array, it isn't a range. Static arrays can't be popped through. But if you slice it, then it yields a usable range for map. The other problem though is the partial!(). It expects a template argument for the thing so it can make a new function right there at compile time... which doesn't work with a runtime variable. The way I'd do it is just with a little hand written delegate. This will compile, for example: auto test = (ref Point p) => getRandomPoint(randVar, p); points[].map!(test); and should do what you need.
Mar 30 2015
parent reply "matovitch" <camille.brugel laposte.net> writes:
On Monday, 30 March 2015 at 18:23:32 UTC, Adam D. Ruppe wrote:
 On Monday, 30 March 2015 at 18:07:18 UTC, matovitch wrote:
 kmeans_example.d(79): Error: template 
 std.algorithm.iteration.map
That error is easy: use points[].map!(test) instead of points.map. Since points is a static array, it isn't a range. Static arrays can't be popped through. But if you slice it, then it yields a usable range for map. The other problem though is the partial!(). It expects a template argument for the thing so it can make a new function right there at compile time... which doesn't work with a runtime variable. The way I'd do it is just with a little hand written delegate. This will compile, for example: auto test = (ref Point p) => getRandomPoint(randVar, p); points[].map!(test); and should do what you need.
Nice ! Thanks for the tip ! I tried importing std.range and points.array works too.
Mar 30 2015
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 30 March 2015 at 18:29:32 UTC, matovitch wrote:
 I tried importing std.range and points.array works too.
Aye, that would work too, but the slice I think is more efficient as I'm pretty sure... not completely sure, but I think .array makes a copy of static arrays, whereas the slice doesn't.
Mar 30 2015
next sibling parent reply "matovitch" <camille.brugel laposte.net> writes:
On Monday, 30 March 2015 at 18:34:19 UTC, Adam D. Ruppe wrote:
 On Monday, 30 March 2015 at 18:29:32 UTC, matovitch wrote:
 I tried importing std.range and points.array works too.
Aye, that would work too, but the slice I think is more efficient as I'm pretty sure... not completely sure, but I think .array makes a copy of static arrays, whereas the slice doesn't.
I was going to ask you the question does it just add the range shell or does it make a copy ? :/ Maybe someone else know.
Mar 30 2015
parent reply "anonymous" <anonymous example.com> writes:
On Monday, 30 March 2015 at 18:37:53 UTC, matovitch wrote:
 On Monday, 30 March 2015 at 18:34:19 UTC, Adam D. Ruppe wrote:
[...]
 Aye, that would work too, but the slice I think is more 
 efficient as I'm pretty sure... not completely sure, but I 
 think .array makes a copy of static arrays, whereas the slice 
 doesn't.
I was going to ask you the question does it just add the range shell or does it make a copy ? :/ Maybe someone else know.
Let's check the documentation. http://dlang.org/phobos/std_array.html#array says: "Allocates an array and initializes it with copies of the elements of range r." Documentation says copy. Let's check the actual behaviour. ---- void main() { int[1] a = [1]; import std.array: array; a.array[0] = 2; import std.stdio: writeln; writeln(a[0]); } ---- (also at <http://dpaste.dzfl.pl/1191144a9acf>) This program prints "1". That's the output we'd expect when `array` makes a copy. Actual behaviour says copy. So, copy.
Mar 30 2015
parent reply "matovitch" <camille.brugel laposte.net> writes:
On Monday, 30 March 2015 at 19:08:24 UTC, anonymous wrote:
 On Monday, 30 March 2015 at 18:37:53 UTC, matovitch wrote:
 On Monday, 30 March 2015 at 18:34:19 UTC, Adam D. Ruppe wrote:
[...]
 Aye, that would work too, but the slice I think is more 
 efficient as I'm pretty sure... not completely sure, but I 
 think .array makes a copy of static arrays, whereas the slice 
 doesn't.
I was going to ask you the question does it just add the range shell or does it make a copy ? :/ Maybe someone else know.
Let's check the documentation. http://dlang.org/phobos/std_array.html#array says: "Allocates an array and initializes it with copies of the elements of range r." Documentation says copy. Let's check the actual behaviour. ---- void main() { int[1] a = [1]; import std.array: array; a.array[0] = 2; import std.stdio: writeln; writeln(a[0]); } ---- (also at <http://dpaste.dzfl.pl/1191144a9acf>) This program prints "1". That's the output we'd expect when `array` makes a copy. Actual behaviour says copy. So, copy.
That settle the point for array as for [] ? I guess the documentation should have something to say about it too. ;)
Mar 30 2015
next sibling parent "anonymous" <anonymous example.com> writes:
On Monday, 30 March 2015 at 19:11:10 UTC, matovitch wrote:
 That settle the point for array as for [] ?
I though that was clear. [] doesn't copy.
 I guess the documentation should have something to say about it 
 too. ;)
hopefully
Mar 30 2015
prev sibling parent reply "matovitch" <camille.brugel laposte.net> writes:
Language ref -> Array -> Slice
     "An array slice does not copy the data, it is only another 
reference to it."

So the total slice of a static array is a range using the 
underlying memory of the static array isnt it ?
Mar 30 2015
parent reply "anonymous" <anonymous example.com> writes:
On Monday, 30 March 2015 at 19:15:25 UTC, matovitch wrote:
 Language ref -> Array -> Slice
     "An array slice does not copy the data, it is only another 
 reference to it."

 So the total slice of a static array is a range using the 
 underlying memory of the static array isnt it ?
yes
Mar 30 2015
parent "matovitch" <camille.brugel laposte.net> writes:
Thanks. On a sader note, I found a respons'less thread about my 
second question :
http://forum.dlang.org/thread/mailman.2247.1353945423.5162.digitalmars-d-learn puremagic.com

"where std.container.Array is concerned: how come I can't use a 
foreach(i, x; myArray) formulation?  I.e. one where the foreach 
can infer the index value as well as the contained value ..."
Mar 30 2015
prev sibling parent reply "matovitch" <camille.brugel laposte.net> writes:
Well I have a bit of a similar problem with foreach.

If I use classic T[] range, I can do :

foreach(int i, auto t, myRange)...

But if I use an Array!T (from std.container) I get :

cannot infer argument types, expected 1 argument, not 2

Even if I add the brackets []. Any idea ? Thanks for your help ! 
:)
Mar 30 2015
parent reply "anonymous" <anonymous example.com> writes:
On Monday, 30 March 2015 at 19:03:05 UTC, matovitch wrote:
 Well I have a bit of a similar problem with foreach.

 If I use classic T[] range, I can do :

 foreach(int i, auto t, myRange)...

 But if I use an Array!T (from std.container) I get :

 cannot infer argument types, expected 1 argument, not 2

 Even if I add the brackets []. Any idea ? Thanks for your help 
 ! :)
The index is the problem. Generally, foreach doesn't do automatic indices for ranges. You can use std.range.enumerate or count yourself explicitly. foreach(i, t; myRange.enumerate) {...} size_t i = 0; foreach(t; myRange) {... ++i;}
Mar 30 2015
parent reply "matovitch" <camille.brugel laposte.net> writes:
On Monday, 30 March 2015 at 19:31:54 UTC, anonymous wrote:
 On Monday, 30 March 2015 at 19:03:05 UTC, matovitch wrote:
 Well I have a bit of a similar problem with foreach.

 If I use classic T[] range, I can do :

 foreach(int i, auto t, myRange)...

 But if I use an Array!T (from std.container) I get :

 cannot infer argument types, expected 1 argument, not 2

 Even if I add the brackets []. Any idea ? Thanks for your help 
 ! :)
The index is the problem. Generally, foreach doesn't do automatic indices for ranges. You can use std.range.enumerate or count yourself explicitly. foreach(i, t; myRange.enumerate) {...} size_t i = 0; foreach(t; myRange) {... ++i;}
Is it a compiler problem or a language restriction ? Thanks for the workaround btw, I will try it !
Mar 30 2015
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 30 Mar 2015 19:36:49 +0000, matovitch wrote:

 The index is the problem. Generally, foreach doesn't do automatic
 indices for ranges. You can use std.range.enumerate or count yourself
 explicitly.

 foreach(i, t; myRange.enumerate) {...}

 size_t i =3D 0;
 foreach(t; myRange) {... ++i;}
=20 Is it a compiler problem or a language restriction ?
it is by design. `foreach` is not a "fancy for with hidden counter", it's=20 more high-level construct. so if range isn't providing the counter,=20 `foreach` will not guess why, and simply doesn't provide it too.=
Mar 30 2015