www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Lazy functions, lazy arrays

reply "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
Hi,
Is it possible for D to create lazy functions, lazy arrays? Or in 
addition to the function arguments can't be lazy in D?
Mar 19 2015
parent reply "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
For example,

lazy int sum(int a = 3, int b = 5) {
	return a + b;
}

That is, if the function is not invoked, it should not be 
calculated at compile time.
Mar 20 2015
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 20 March 2015 at 10:02:27 UTC, Dennis Ritchie wrote:
 For example,

 lazy int sum(int a = 3, int b = 5) {
 	return a + b;
 }

 That is, if the function is not invoked, it should not be 
 calculated at compile time.
I don't understand what you mean. You mean a function that isn't compiled if it isn't used anywhere? Template functions that are only compiled if instantiated, so you could write int sum()(int a, int b) { return a+b; } /\ empty braces for a 0-arg template. Can be called just like a normal function, the only time it would be necessary to explicitly write sum!() would be if you wanted to take it's address: &sum!()
Mar 20 2015
parent reply "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
On Friday, 20 March 2015 at 10:38:17 UTC, John Colvin wrote:
 I don't understand what you mean. You mean a function that 
 isn't compiled if it isn't used anywhere?
Yes. That's exactly what I mean.
Mar 20 2015
parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
On Friday, 20 March 2015 at 12:15:22 UTC, Dennis Ritchie wrote:
 On Friday, 20 March 2015 at 10:38:17 UTC, John Colvin wrote:
 I don't understand what you mean. You mean a function that 
 isn't compiled if it isn't used anywhere?
Yes. That's exactly what I mean.
Use case?
Mar 20 2015
next sibling parent reply "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
 Use case?
No. I need to be able to make an array "factorials" is not evaluated, if I don't. import std.stdio; enum N = 15; static int[] factorials = memoizeFactorials(N); // lazy array? :) int[] memoizeFactorials(int n) { if (!__ctfe) { // Make sure that this function is never called at run time assert(false); } int[] result = new int[n]; result[0] = 1; foreach (i; 1 .. n) { result[i] = result[i - 1] * i; } return result; } void main() { writeln(factorials[10]); }
Mar 20 2015
next sibling parent "Tobias Pankrath" <tobias pankrath.net> writes:
Now I am totally confused. lazy and eager evaluation are 
unrelated to compile time  and run time.
Mar 20 2015
prev sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 20 March 2015 at 13:35:10 UTC, Dennis Ritchie wrote:
 Use case?
No. I need to be able to make an array "factorials" is not evaluated, if I don't. import std.stdio; enum N = 15; static int[] factorials = memoizeFactorials(N); // lazy array? :) int[] memoizeFactorials(int n) { if (!__ctfe) { // Make sure that this function is never called at run time assert(false); } int[] result = new int[n]; result[0] = 1; foreach (i; 1 .. n) { result[i] = result[i - 1] * i; } return result; } void main() { writeln(factorials[10]); }
Why? To make a smaller executable? For faster compilation? This can work auto factorials()() property { //if we're here, factorials are used somewhere //generate them at compile-time. enum int[N] resultsE = memoizeFactorials(N); //put them in thread-local array on first access static resultsS = resultsE; return resultsS[]; } void main() { writeln(factorials[10]); } or much easier and simpler, but different: auto factorials()(int n) { //generate them at compile-time. enum int[N] results = memoizeFactorials(N); return results[n]; } void main() { writeln(factorials(10)); } However, none of this is a good idea at all. There are only 13 factorials (0 through 12) that fit in an int, so it's such a small array that you might as well write enum int[N] factorials = memoizeFactorials(N); and be done.
Mar 20 2015
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 20 March 2015 at 14:20:16 UTC, John Colvin wrote:
 On Friday, 20 March 2015 at 13:35:10 UTC, Dennis Ritchie wrote:
 Use case?
No. I need to be able to make an array "factorials" is not evaluated, if I don't. import std.stdio; enum N = 15; static int[] factorials = memoizeFactorials(N); // lazy array? :) int[] memoizeFactorials(int n) { if (!__ctfe) { // Make sure that this function is never called at run time assert(false); } int[] result = new int[n]; result[0] = 1; foreach (i; 1 .. n) { result[i] = result[i - 1] * i; } return result; } void main() { writeln(factorials[10]); }
Why? To make a smaller executable? For faster compilation? This can work auto factorials()() property { //if we're here, factorials are used somewhere //generate them at compile-time. enum int[N] resultsE = memoizeFactorials(N); //put them in thread-local array on first access static resultsS = resultsE; return resultsS[]; } void main() { writeln(factorials[10]); } or much easier and simpler, but different: auto factorials()(int n) { //generate them at compile-time. enum int[N] results = memoizeFactorials(N); return results[n]; } void main() { writeln(factorials(10)); } However, none of this is a good idea at all. There are only 13 factorials (0 through 12) that fit in an int, so it's such a small array that you might as well write enum int[N] factorials = memoizeFactorials(N); and be done.
I made a mistake about the static variable and thread-local storage. immutable(int)[] factorials()() property { static immutable int[N] results = memoizeFactorials(N); return results[]; } is the correct way to do it if you have to. Still, it's totally not worth doing for such a short array.
Mar 20 2015
parent reply "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
On Friday, 20 March 2015 at 14:27:06 UTC, John Colvin wrote:
 I made a mistake about the static variable and thread-local 
 storage.

 immutable(int)[] factorials()()  property
 {
     static immutable int[N] results = memoizeFactorials(N);
     return results[];
 }

 is the correct way to do it if you have to.

 Still, it's totally not worth doing for such a short array.
Thank you, but I can not figure out how I do this: import std.stdio; enum N = 12; immutable(int)[] factorials()() property { static immutable int[N] results = memoizeFactorials(N); return results[]; } int[] memoizeFactorials(int n) { if (!__ctfe) // Make sure that this function is never called at run time assert(false); int[] result = new int[n]; result[0] = 1; foreach (i; 1 .. n) result[i] = result[i - 1] * i; return result; } void main() { bool flag; if (flag) { factorials(); writeln(factorials[10]); // 3628800 } else writeln(factorials[10]); // range violation(35) }
Mar 20 2015
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 20 March 2015 at 16:01:51 UTC, Dennis Ritchie wrote:
 On Friday, 20 March 2015 at 14:27:06 UTC, John Colvin wrote:
 I made a mistake about the static variable and thread-local 
 storage.

 immutable(int)[] factorials()()  property
 {
    static immutable int[N] results = memoizeFactorials(N);
    return results[];
 }

 is the correct way to do it if you have to.

 Still, it's totally not worth doing for such a short array.
Thank you, but I can not figure out how I do this: import std.stdio; enum N = 12; immutable(int)[] factorials()() property { static immutable int[N] results = memoizeFactorials(N); return results[]; } int[] memoizeFactorials(int n) { if (!__ctfe) // Make sure that this function is never called at run time assert(false); int[] result = new int[n]; result[0] = 1; foreach (i; 1 .. n) result[i] = result[i - 1] * i; return result; } void main() { bool flag; if (flag) { factorials(); writeln(factorials[10]); // 3628800 } else writeln(factorials[10]); // range violation(35) }
Both of those work for me on multiple dmd versions including git HEAD.
Mar 20 2015
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 20 March 2015 at 12:52:16 UTC, Tobias Pankrath wrote:
 Use case?
I do this with local imports so a module works without dependencies unless you use the specific functions that need the additional module.
Mar 20 2015