Jump to page: 1 2
Thread overview
Lazy functions, lazy arrays
Mar 20, 2015
Dennis Ritchie
Mar 20, 2015
Dennis Ritchie
Mar 20, 2015
John Colvin
Mar 20, 2015
Dennis Ritchie
Mar 20, 2015
Tobias Pankrath
Mar 20, 2015
Dennis Ritchie
Mar 20, 2015
Tobias Pankrath
Mar 20, 2015
John Colvin
Mar 20, 2015
John Colvin
Mar 20, 2015
Dennis Ritchie
Mar 20, 2015
John Colvin
Mar 20, 2015
Adam D. Ruppe
March 20, 2015
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?
March 20, 2015
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.
March 20, 2015
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!()
March 20, 2015
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.
March 20, 2015
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?
March 20, 2015
> 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]);
}
March 20, 2015
Now I am totally confused. lazy and eager evaluation are unrelated to compile time  and run time.
March 20, 2015
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.
March 20, 2015
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.
March 20, 2015
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.
« First   ‹ Prev
1 2