Re: functional way doing array stuff/ lambda functions

2015-12-14 Thread Namal via Digitalmars-d-learn

On Sunday, 13 December 2015 at 01:01:07 UTC, cym13 wrote:

That's because you want to modify it in product passing it by 
ref.


Hmm, that seems different to c++.


On Sunday, 13 December 2015 at 11:37:50 UTC, cym13 wrote:



As cryptic as it is this means that the range you passed to 
reduce is empty. Reduce needs it not to be because as I said it 
needs a seed and as you didn't pass one explicitely as argument 
it tries to take the first element of the range (and fails 
obviously). You can either pass it a seed explicitely or add a 
non-empty check before the return.



Here is the full code, where I changed the product function. 
Sorry, I don't understand what the difference now and why it 
crashes.


import std.stdio, std.array, std.algorithm;


int product(const ref int[] arr){

/*int p = 1;
foreach(i;arr)
p*=i;
return p;*/

return arr.reduce!((a, b) => a*b)();

}


int [] prim_sieve(int n){

bool [] T;
T.length = n;
T[0] = true;
T[1] = true;

for(int i = 2; i*i <= T.length-1;++i){
for(int j = i*i;j1)
v~=n;

return v.dup.sort.uniq.array;

}


void bubblesort(ref int[2][] v){

size_t n = v.length;
do{
int newn = 1;
for(int i = 0;iv[i+1][1]){
auto temp = v[i];
v[i] = v[i+1];
v[i+1] = temp;
newn = i+1;
}
}
n=newn; 
}
while(n>1);
}



void main(){

int[] P = prim_sieve(500);

int[2][] v;

foreach(k;1..11){
auto t = prim_factors(k,P);
v~= [k,product(t)];
}

bubblesort(v);

writeln(v[][0]);
}


Re: functional way doing array stuff/ lambda functions

2015-12-14 Thread visitor via Digitalmars-d-learn

On Monday, 14 December 2015 at 11:45:50 UTC, Namal wrote:


foreach(k;1..11){
auto t = prim_factors(k,P);
v~= [k,product(t)];
}


it crashes because your first t in the loop is an empty array

because 1 is not a prime ( in "prim_sieve" : T[1] = true)
later when you loop starting with k = 1, prim_factors(1,P) gives 
you back an empty array.

so either loop through 2..11 or guard against the empty array
if (!t.empty) v~= [k, product(t)];

i don't think you need any ref in your functions parameters, as a 
slice is already a reference

http://dlang.org/spec/arrays.html#slicing


Re: functional way doing array stuff/ lambda functions

2015-12-13 Thread cym13 via Digitalmars-d-learn

On Sunday, 13 December 2015 at 03:08:33 UTC, Namal wrote:

On Saturday, 12 December 2015 at 23:50:55 UTC, Xinok wrote:

[...]



I tried this, it compiles, but crashes when I try to run it:

object.Exception@/usr/include/dmd/phobos/std/algorithm/iteration.d(2481): 
Enforcement failed

??:? pure @safe void 
std.exception.bailOut!(Exception).bailOut(immutable(char)[], 
ulong, const(char[])) [0x43a547]
??:? pure @safe bool std.exception.enforce!(Exception, 
bool).enforce(bool, lazy const(char)[], immutable(char)[], 
ulong) [0x43a4c4]
??:? pure @safe int 
std.algorithm.iteration.__T6reduceS305ep1247productFKxAiZ9__lambda2Z.reduce!(const(int)[]).reduce(const(int)[]) [0x43a2ed]

??:? int ep124.product(ref const(int[])) [0x439d49]
??:? _Dmain [0x43a229]
??:? 
_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv 
[0x448b9a]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).tryExec(scope void delegate()) [0x448af0]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).runAll() [0x448b56]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).tryExec(scope void delegate()) [0x448af0]

??:? _d_run_main [0x448a4d]
??:? main [0x4447ad]
??:? __libc_start_main [0xd9f09ec4]


As cryptic as it is this means that the range you passed to 
reduce is empty. Reduce needs it not to be because as I said it 
needs a seed and as you didn't pass one explicitely as argument 
it tries to take the first element of the range (and fails 
obviously). You can either pass it a seed explicitely or add a 
non-empty check before the return.


Re: functional way doing array stuff/ lambda functions

2015-12-13 Thread visitor via Digitalmars-d-learn

On Sunday, 13 December 2015 at 03:08:33 UTC, Namal wrote:



This works for me :

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

int[] prim_factors(int n, const int[] P) {
int[] v;

P.filter!( x => x*x <= n).each!( (i) {
while (n % i == 0) {
v ~= i;
n /= i;
if (i == 1) break; // infinite loop otherwise !
}
} );

if (n > 1) v ~= n;

return v.sort.uniq.array;
}

void main(string[] args) {
int[] P = [1,2,3,4,5];
writeln( prim_factors(10, P).reduce!((r, i) => r*i)() );
}




Re: functional way doing array stuff/ lambda functions

2015-12-12 Thread Namal via Digitalmars-d-learn

On Saturday, 12 December 2015 at 23:50:55 UTC, Xinok wrote:

On Saturday, 12 December 2015 at 23:36:43 UTC, cym13 wrote:

...
So, in your example:

int product(const ref int[] arr) {
import std.array: array;
import std.algorithm: reduce;

arr = arr.reduce!((p, i) => p*i).array;
}


A good post overall but you got reduce wrong. In D, reduce 
computes and returns the result immediately, not a lazy range. 
The following code is correct:


int product(const ref int[] arr) {
import std.array: array;
import std.algorithm: reduce;

return arr.reduce!((p, i) => p*i)();
}

Example: http://dpaste.dzfl.pl/fc2c2eab2d02



I tried this, it compiles, but crashes when I try to run it:

object.Exception@/usr/include/dmd/phobos/std/algorithm/iteration.d(2481): 
Enforcement failed

??:? pure @safe void 
std.exception.bailOut!(Exception).bailOut(immutable(char)[], 
ulong, const(char[])) [0x43a547]
??:? pure @safe bool std.exception.enforce!(Exception, 
bool).enforce(bool, lazy const(char)[], immutable(char)[], ulong) 
[0x43a4c4]
??:? pure @safe int 
std.algorithm.iteration.__T6reduceS305ep1247productFKxAiZ9__lambda2Z.reduce!(const(int)[]).reduce(const(int)[]) [0x43a2ed]

??:? int ep124.product(ref const(int[])) [0x439d49]
??:? _Dmain [0x43a229]
??:? 
_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv 
[0x448b9a]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).tryExec(scope void delegate()) [0x448af0]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).runAll() [0x448b56]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).tryExec(scope void delegate()) [0x448af0]

??:? _d_run_main [0x448a4d]
??:? main [0x4447ad]
??:? __libc_start_main [0xd9f09ec4]




Re: functional way doing array stuff/ lambda functions

2015-12-12 Thread Namal via Digitalmars-d-learn

On Sunday, 13 December 2015 at 00:02:11 UTC, cym13 wrote:

Now that I think about it, it's true that it would make no 
sense whatsoever to return a range as reduce is typically used 
to return a single value... At least it makes perfect sense.


Thanks alot, this helped alot. But I have another question

I have two functions:

int[] prim_factors(int n, const ref int[] P){

int[] v;

for(int i; P[i]*P[i]<=n;++i){
while(n%P[i]==0){
v~=P[i];
n/=P[i];
}
}
if(n>1)
v~=n;

return v.dup.sort.uniq.array;

}


int product(const ref int[] arr){

int p = 1;
foreach(i;arr)
p*=i;
return p;
}

While vector P contains some primes I get with a prime sieve. So 
if I just try to use those functions like:


writeln(product(prim_factors(10,P)));

I get the error:

function prog.product (ref const(int[]) arr) is not callable 
using argument types (int[])


Why do I have to call it like that first:

auto v = prim_factors(10,P);
writeln(product(v));

?



Re: functional way doing array stuff/ lambda functions

2015-12-12 Thread cym13 via Digitalmars-d-learn

On Sunday, 13 December 2015 at 00:36:29 UTC, Namal wrote:

On Sunday, 13 December 2015 at 00:02:11 UTC, cym13 wrote:

Now that I think about it, it's true that it would make no 
sense whatsoever to return a range as reduce is typically used 
to return a single value... At least it makes perfect sense.


Thanks alot, this helped alot. But I have another question

I have two functions:
j
int[] prim_factors(int n, const ref int[] P){

int[] v;

for(int i; P[i]*P[i]<=n;++i){
while(n%P[i]==0){
v~=P[i];
n/=P[i];
}
}
if(n>1)
v~=n;

return v.dup.sort.uniq.array;

}


int product(const ref int[] arr){

int p = 1;
foreach(i;arr)
p*=i;
return p;
}

While vector P contains some primes I get with a prime sieve. 
So if I just try to use those functions like:


writeln(product(prim_factors(10,P)));

I get the error:

function prog.product (ref const(int[]) arr) is not callable 
using argument types (int[])


Why do I have to call it like that first:

auto v = prim_factors(10,P);
writeln(product(v));

?


That's because you want to modify it in product passing it by 
ref. In order for it to have a reference (and hence be modified 
in place) you need it to have some place in memory of which you 
can take a reference to. This is what rvalues and lvalues are: a 
rvalue is any value that you'd find on the right side of a "=" 
like 3. You can't assign a value to 3, it's a rvalue. On the 
contrary a lvalue is something you'd find on the left side of an 
"=" like v in your example. You can assign a value to v.


Your problem is that product need a lvalue (as you assign 
something to it) but you give it a rvalue instead.


The solution is simple: don't ask arr to be passed by reference 
if you don't intend to modify it.


(I somehow feel like I'm forgetting something there but I can't 
point it, feel free to destroy)


functional way doing array stuff/ lambda functions

2015-12-12 Thread Namal via Digitalmars-d-learn

Hello guys,

I am still uncertain how to do it right when it comes to lambda 
functions. For instance: how do I multiply all the elements in an 
array ?


int product(const ref int[] arr){

int p = 1;
foreach(i;arr)
p*=i;
return p;
}




Re: functional way doing array stuff/ lambda functions

2015-12-12 Thread cym13 via Digitalmars-d-learn

On Saturday, 12 December 2015 at 23:10:21 UTC, Namal wrote:

Hello guys,

I am still uncertain how to do it right when it comes to lambda 
functions.


If you are looking for the functionnal way I'd advise that you 
start by
looking up three functions in a language-agnostic way: filter, 
map and
reduce. The filter/map/reduce pattern is very common and most 
other
functions can be emulated using them. For that reason they exist 
in almost
any high-level language. Once you know how to use them well the 
rest is

easier.

As a rule of thumb:

- If you have a set of data (for example integers) and want a 
smaller set of
  data that match some property (for example odd integers) then 
the function
  to use is "filter". Filter will take a function, use that 
function on each
  element of the set one at a time, and if it returns false drop 
the element
  in order to return a new set of data matching the property. For 
example:


auto oddData = data.filter!(x => x%2 == 1);

- If you have a set of things (say integers) that you want to 
transform into
  another thing without changing the number of elements in your 
set (say you
  want the set of the doubles of each of your integers) then 
"map" is the way
  to go. Map will take a function, apply it to each element of 
the set and

  return the set of the results. For example:

auto doubles = data.map!(x => x*2);

- If you have a set of data that you want to combine together 
using some rule
  (for exemple, to get their product) in order to reduce it to 
one thing then
  "reduce" is the way to go. It's also called accumulate or fold 
in other
  languages. Reduce will take a function and a seed and pass the 
seed and the
  elements of your set in the function, the result becomming the 
next seed.



For instance: how do I multiply all the elements in an array ?

int product(const ref int[] arr){

int p = 1;
foreach(i;arr)
p*=i;
return p;
}


Here is a good case for reduce. In D it returns a lazy range 
(meaning the
result isn't actually computed until you ask for its value), you 
can use

.array to force its evaluation.

So, in your example:

int product(const ref int[] arr) {
import std.array: array;
import std.algorithm: reduce;

arr = arr.reduce!((p, i) => p*i).array;
}



Re: functional way doing array stuff/ lambda functions

2015-12-12 Thread Xinok via Digitalmars-d-learn

On Saturday, 12 December 2015 at 23:36:43 UTC, cym13 wrote:

...
So, in your example:

int product(const ref int[] arr) {
import std.array: array;
import std.algorithm: reduce;

arr = arr.reduce!((p, i) => p*i).array;
}


A good post overall but you got reduce wrong. In D, reduce 
computes and returns the result immediately, not a lazy range. 
The following code is correct:


int product(const ref int[] arr) {
import std.array: array;
import std.algorithm: reduce;

return arr.reduce!((p, i) => p*i)();
}

Example: http://dpaste.dzfl.pl/fc2c2eab2d02


Re: functional way doing array stuff/ lambda functions

2015-12-12 Thread cym13 via Digitalmars-d-learn

On Saturday, 12 December 2015 at 23:50:55 UTC, Xinok wrote:

On Saturday, 12 December 2015 at 23:36:43 UTC, cym13 wrote:

...
So, in your example:

int product(const ref int[] arr) {
import std.array: array;
import std.algorithm: reduce;

arr = arr.reduce!((p, i) => p*i).array;
}


A good post overall but you got reduce wrong. In D, reduce 
computes and returns the result immediately, not a lazy range. 
The following code is correct:


int product(const ref int[] arr) {
import std.array: array;
import std.algorithm: reduce;

return arr.reduce!((p, i) => p*i)();
}

Example: http://dpaste.dzfl.pl/fc2c2eab2d02


Damn, I was certain it acted as the two others of the trio... I 
stand corrected thanks :-)


Re: functional way doing array stuff/ lambda functions

2015-12-12 Thread cym13 via Digitalmars-d-learn

On Saturday, 12 December 2015 at 23:59:01 UTC, cym13 wrote:

On Saturday, 12 December 2015 at 23:50:55 UTC, Xinok wrote:

On Saturday, 12 December 2015 at 23:36:43 UTC, cym13 wrote:

...
So, in your example:

int product(const ref int[] arr) {
import std.array: array;
import std.algorithm: reduce;

arr = arr.reduce!((p, i) => p*i).array;
}


A good post overall but you got reduce wrong. In D, reduce 
computes and returns the result immediately, not a lazy range. 
The following code is correct:


int product(const ref int[] arr) {
import std.array: array;
import std.algorithm: reduce;

return arr.reduce!((p, i) => p*i)();
}

Example: http://dpaste.dzfl.pl/fc2c2eab2d02


Damn, I was certain it acted as the two others of the trio... I 
stand corrected thanks :-)


Now that I think about it, it's true that it would make no sense 
whatsoever to return a range as reduce is typically used to 
return a single value... At least it makes perfect sense.