Jump to page: 1 2
Thread overview
More useful fixed-size array literals
May 30, 2014
bearophile
May 30, 2014
Meta
May 30, 2014
bearophile
May 31, 2014
Mason McGill
May 31, 2014
Benjamin Thaut
May 31, 2014
bearophile
May 31, 2014
bearophile
May 31, 2014
Benjamin Thaut
May 31, 2014
bearophile
May 31, 2014
Namespace
Jun 03, 2014
bearophile
May 30, 2014
Code similar to this is not uncommon. Currently it's refused:


immutable data = [1, 5, 3, 1, 5, 1, 5];
void main() @nogc {
    import std.algorithm: count;
    assert(data.count([1, 5]) == 3);
}


test.d(4,23): Error: array literal in @nogc function main may cause GC allocation


The current workaround is not handy when you have conditionals, etc:

immutable data = [1, 5, 3, 1, 5, 1, 5];
void main() @nogc {
    import std.algorithm: count;
    immutable static part = [1, 5];
    assert(data.count(part) == 3);
}


A language solution is a literal syntax for fixed-sized arrays (here I slice it again because unfortunately count doesn't accept fixed-sized arrays):


immutable data = [1, 5, 3, 1, 5, 1, 5];
void main() @nogc {
    import std.algorithm: count;
    assert(data.count([1, 5]s[]) == 3);
}


I remember Kenji is not fond of this []s syntax, for reasons I don't remember. Do you think there are other better/different solutions?

Bye,
bearophile
May 30, 2014
On Friday, 30 May 2014 at 22:19:51 UTC, bearophile wrote:
> Code similar to this is not uncommon. Currently it's refused:
>
>
> immutable data = [1, 5, 3, 1, 5, 1, 5];
> void main() @nogc {
>     import std.algorithm: count;
>     assert(data.count([1, 5]) == 3);
> }
>
>
> test.d(4,23): Error: array literal in @nogc function main may cause GC allocation
>
>
> The current workaround is not handy when you have conditionals, etc:
>
> immutable data = [1, 5, 3, 1, 5, 1, 5];
> void main() @nogc {
>     import std.algorithm: count;
>     immutable static part = [1, 5];
>     assert(data.count(part) == 3);
> }
>
>
> A language solution is a literal syntax for fixed-sized arrays (here I slice it again because unfortunately count doesn't accept fixed-sized arrays):
>
>
> immutable data = [1, 5, 3, 1, 5, 1, 5];
> void main() @nogc {
>     import std.algorithm: count;
>     assert(data.count([1, 5]s[]) == 3);
> }
>
>
> I remember Kenji is not fond of this []s syntax, for reasons I don't remember. Do you think there are other better/different solutions?
>
> Bye,
> bearophile

What about prepending the word static?

immutable data = [1, 5, 3, 1, 5, 1, 5];
void main() @nogc {
    import std.algorithm: count;
    assert(data.count(static[1, 5]) == 3);
}

Or variadic template arguments. Aren't they allocated on the stack like static arrays?

immutable data = [1, 5, 3, 1, 5, 1, 5];
void main() @nogc {
    import std.algorithm: count;
    //Assume count has a variadic template implementation
    assert(data.count(1, 5) == 3);
}
May 30, 2014
Meta:

> What about prepending the word static?
>
> immutable data = [1, 5, 3, 1, 5, 1, 5];
> void main() @nogc {
>     import std.algorithm: count;
>     assert(data.count(static[1, 5]) == 3);
> }

This is about the same as appending the char 's'.


> Or variadic template arguments. Aren't they allocated on the stack like static arrays?
>
> immutable data = [1, 5, 3, 1, 5, 1, 5];
> void main() @nogc {
>     import std.algorithm: count;
>     //Assume count has a variadic template implementation
>     assert(data.count(1, 5) == 3);
> }

Currently they are allocated on the stack. But "count" doesn't work like that. And I think this feature of D is bug-prone, and in bugzilla I've asked to change it (allocating on the heap on default).

Bye,
bearophile
May 31, 2014
On Friday, 30 May 2014 at 22:19:51 UTC, bearophile wrote:
> A language solution is a literal syntax for fixed-sized arrays (here I slice it again because unfortunately count doesn't accept fixed-sized arrays):
>
>
> immutable data = [1, 5, 3, 1, 5, 1, 5];
> void main() @nogc {
>     import std.algorithm: count;
>     assert(data.count([1, 5]s[]) == 3);
> }

I would use this often. It's always seemed strange to me that static arrays are one of the few built-in data structures that don't have a dedicated literal form. `[1, 2, 3]s` nicely parallels the syntax for string and number literals.
May 31, 2014
Am 31.05.2014 00:19, schrieb bearophile:
> Code similar to this is not uncommon. Currently it's refused:
>
>
> immutable data = [1, 5, 3, 1, 5, 1, 5];
> void main() @nogc {
>      import std.algorithm: count;
>      assert(data.count([1, 5]) == 3);
> }
>
>
> test.d(4,23): Error: array literal in @nogc function main may cause GC
> allocation
>
>
> The current workaround is not handy when you have conditionals, etc:
>
> immutable data = [1, 5, 3, 1, 5, 1, 5];
> void main() @nogc {
>      import std.algorithm: count;
>      immutable static part = [1, 5];
>      assert(data.count(part) == 3);
> }
>
>
> A language solution is a literal syntax for fixed-sized arrays (here I
> slice it again because unfortunately count doesn't accept fixed-sized
> arrays):
>
>
> immutable data = [1, 5, 3, 1, 5, 1, 5];
> void main() @nogc {
>      import std.algorithm: count;
>      assert(data.count([1, 5]s[]) == 3);
> }
>
>
> I remember Kenji is not fond of this []s syntax, for reasons I don't
> remember. Do you think there are other better/different solutions?
>
> Bye,
> bearophile


give "scope" a meaning for function arguments other then lambdas E.g:

size_t count(scope int[] heystack, scope int[] needle);

Now the compiler can allocate the literal [1, 5] on the stack without any special syntax because it knows that the array literal will not be escaped.

Kind Regards
Benjamin Thaut
May 31, 2014
> I remember Kenji is not fond of this []s syntax, for reasons I don't remember. Do you think there are other better/different solutions?
>
> Bye,
> bearophile

Read it on my closed Pull Request:
https://github.com/D-Programming-Language/dmd/pull/2952

Another attempt was also closed:
https://github.com/D-Programming-Language/dmd/pull/2958
May 31, 2014
Benjamin Thaut:

> give "scope" a meaning for function arguments other then lambdas E.g:
>
> size_t count(scope int[] heystack, scope int[] needle);
>
> Now the compiler can allocate the literal [1, 5] on the stack without any special syntax because it knows that the array literal will not be escaped.


With your suggestion this code should be accepted:

int foo(scope int[] items) @nogc {
    int total = 0;
    foreach (immutable x; items)
        total += x;
    return total;
}
void main() @nogc {
    assert(foo([1, 5, 3, 1, 5, 1, 5]) == 21);
}



While this can't be accepted because 'items' escapes the body of 'foo', so 'scope' forbids some valid code:

import std.algorithm: sum;
int foo(scope int[] items) @nogc {
    return foo.sum;
}
void main() @nogc {
    assert(foo([1, 5, 3, 1, 5, 1, 5]) == 21);
}



The []s syntax moves the control to the calling point, allowing more valid code to compile:

import std.algorithm: sum;
int foo(int[] items) @nogc {
    return foo.sum;
}
void main() @nogc {
    assert(foo([1, 5, 3, 1, 5, 1, 5]s) == 21);
}



A disadvantage of the []s syntax is that it's less safe than scope:

int[] global;
void foo() @nogc {
    bar([1, 5, 3, 1, 5, 1, 5]s);
}
void bar(int[] b) @nogc {
    global = b;
}
void main() {
    import std.stdio;
    foo();
    writeln(global);
}



But that usage of []s is not much worse than this currently accepted code, the difference is that the []s syntax makes this problem a bit less visible:

int[] global;
void foo() @nogc {
    int[7] a = [1, 5, 3, 1, 5, 1, 5];
    bar(a); // Implicit slicing.
}
void bar(int[] b) @nogc {
    global = b;
}
void main() {
    import std.stdio;
    foo();
    writeln(global);
}


(I think Jonathan M Davis suggested to disallow such implicit slicing, and require a "bar(a[]);".)


A possible way to increase the number of functions allowed by 'scope' is to allow a reference to escape if it goes into another 'scope':

int sum(scope int[] items) @nogc {
    int total = 0;
    foreach (immutable x; items)
        total += x;
    return total;
}
int foo(scope int[] items) @nogc {
    return sum(items); // Allowed.
}
void main() @nogc {
    assert(foo([1, 5, 3, 1, 5, 1, 5]) == 21); // Allowed.
}



(The problem with Scott Meyers' suggestion in the "The Last Thing D Needs" keynote is that to design a language/library feature that takes in account every other language/library part, you need a mind significantly larger than the average human one :-) ).

Bye,
bearophile
May 31, 2014
> int foo(scope int[] items) @nogc {
>     return foo.sum;
> }

That was:

return items.sum;

Bye,
bearophile
May 31, 2014
Am 31.05.2014 11:08, schrieb bearophile:
>> int foo(scope int[] items) @nogc {
>>     return foo.sum;
>> }
>
> That was:
>
> return items.sum;
>
> Bye,
> bearophile

Well obviously the std.algorithm sum would also be annoted with scope. Because it doesn't escape it either. I don't see the problem here. And in case you really want to escape it, you need to .dup it.

A additional advantage of my solution is, that the compiler can prove it to be @safe. Your solution does not allow that.

Kind Regards
Benjamin Thaut
May 31, 2014
Benjamin Thaut:

> Well obviously the std.algorithm sum would also be annoted with scope. Because it doesn't escape it either. I don't see the problem here. And in case you really want to escape it, you need to .dup it.
>
> A additional advantage of my solution is, that the compiler can prove it to be @safe. Your solution does not allow that.

You can see that the contents of this answer of yours are a strict subset of the contents of my last post :-)

A problem with that use of "scope" to solve this problem is that such feature interacts with several other things (like ownership), so it's a complex topic, so nearly everyone is afraid of touching and implementing it, so nothing will happen.

This phenomenon has happened even for more contained features the "old" (prestate) of contract programming, for built-in D tuple syntax, etc. And we keep having a language with holes, that lacks such basic features.

This means that sometimes designing a language in a less coherent way (in Scott Meyers' words) is better than having a language that lacks certain basic features.

I hope Walter or others will figure out this topic of ownership, etc.

Bye,
bearophile
« First   ‹ Prev
1 2