Jump to page: 1 2
Thread overview
foreach and filter
Apr 11, 2012
Russel Winder
Apr 11, 2012
Jakob Ovrum
Apr 16, 2012
Russel Winder
Apr 16, 2012
Timon Gehr
Apr 16, 2012
Russel Winder
Apr 11, 2012
Simen Kjaeraas
Apr 11, 2012
Jakob Ovrum
Apr 11, 2012
bearophile
Apr 11, 2012
Jakob Ovrum
Apr 12, 2012
Timon Gehr
Apr 12, 2012
Timon Gehr
Apr 12, 2012
Jonathan M Davis
April 11, 2012
Doing something along the lines of:

	const a = array ( filter! ... ) ;
	foreach ( i ; a ) { ... }

works fine.  Question 1 though is why I can't use immutable here, why I have to use const.  Question 2 is why I can't do:

	const a = filter! ... ;
	foreach ( i ; a ) { ... }

if I try this I get messages along the lines of:

./signatures_sequential.d(33): Error: function signatures_sequential.main.filter!(delegate @system bool(string item)
{
return isDir(cast(const(char[]))item);
}
).filter!(const(immutable(char)[])[]).filter.Result.empty () is not callable using argument types ()
./signatures_sequential.d(33): Error: function signatures_sequential.main.filter!(delegate @system bool(string item)
{
return isDir(cast(const(char[]))item);
}
).filter!(const(immutable(char)[])[]).filter.Result.popFront () is not callable using argument types ()
./signatures_sequential.d(33): Error: function signatures_sequential.main.filter!(delegate @system bool(string item)
{
return isDir(cast(const(char[]))item);
}
).filter!(const(immutable(char)[])[]).filter.Result.front () is not callable using argument types ()

which, it has to be said, isn't exactly informative to the user.

Thanks.

-- 
Russel. ============================================================================= Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder@ekiga.net 41 Buckmaster Road    m: +44 7770 465 077   xmpp: russel@winder.org.uk London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder


April 11, 2012
On Wednesday, 11 April 2012 at 16:08:25 UTC, Russel Winder wrote:
> Doing something along the lines of:
>
> 	const a = array ( filter! ... ) ;
> 	foreach ( i ; a ) { ... }
>
> works fine.  Question 1 though is why I can't use immutable here, why I
> have to use const.

An array/slice has indirection, you can't implicitly convert it to immutable.

(IIRC, there is actually an exception for the return type of strongly pure functions, but your instantiation of 'array' is evidently not pure enough)

> Question 2 is why I can't do:
>
> 	const a = filter! ... ;
> 	foreach ( i ; a ) { ... }
>
> if I try this I get messages along the lines of:
>
> ./signatures_sequential.d(33): Error: function signatures_sequential.main.filter!(delegate @system bool(string item)
> {
> return isDir(cast(const(char[]))item);
> }
> ).filter!(const(immutable(char)[])[]).filter.Result.empty () is not callable using argument types ()
> ./signatures_sequential.d(33): Error: function signatures_sequential.main.filter!(delegate @system bool(string item)
> {
> return isDir(cast(const(char[]))item);
> }
> ).filter!(const(immutable(char)[])[]).filter.Result.popFront () is not callable using argument types ()
> ./signatures_sequential.d(33): Error: function signatures_sequential.main.filter!(delegate @system bool(string item)
> {
> return isDir(cast(const(char[]))item);
> }
> ).filter!(const(immutable(char)[])[]).filter.Result.front () is not callable using argument types ()
>
> which, it has to be said, isn't exactly informative to the user.

Ranges are iterated in-place. You can't mutate a const range, hence you cannot advance it by one (`popFront`), which is required by the lowering of foreach using the range interface.

> Thanks.

You should be using the D.learn group for these questions.
April 11, 2012
On Wed, 11 Apr 2012 18:08:14 +0200, Russel Winder <russel@winder.org.uk> wrote:

> Doing something along the lines of:
>
> 	const a = array ( filter! ... ) ;
> 	foreach ( i ; a ) { ... }
>
> works fine.  Question 1 though is why I can't use immutable here, why I
> have to use const.  Question 2 is why I can't do:
>
> 	const a = filter! ... ;
> 	foreach ( i ; a ) { ... }

The answer to #1 is easy. Nothing is implicitly castable to immutable.

The easy answer to #2 is that anything const cannot be a range, because
popFront cannot be const.

I have (long ago, probably not usable in this day and age), written an
implementation of tail const for ranges, but it is invasive[1].

For now, the solution is simply to not use const/immutable with ranges
other than arrays.


Some solution really should be created for this problem. One simple
solution would be for all ranges to support opSlice with an empty
parameter list, which would return a non-const version of the range.
The problems are:

1. The elements should still be const.

2. If this range wraps another range, that other range should also
be sliced, and so on.


[1]http://d.puremagic.com/issues/show_bug.cgi?id=5377
April 11, 2012
On Wednesday, 11 April 2012 at 16:33:42 UTC, Simen Kjaeraas wrote:
> On Wed, 11 Apr 2012 18:08:14 +0200, Russel Winder <russel@winder.org.uk> wrote:
>
>> Doing something along the lines of:
>>
>> 	const a = array ( filter! ... ) ;
>> 	foreach ( i ; a ) { ... }
>>
>> works fine.  Question 1 though is why I can't use immutable here, why I
>> have to use const.  Question 2 is why I can't do:
>>
>> 	const a = filter! ... ;
>> 	foreach ( i ; a ) { ... }
>
> The answer to #1 is easy. Nothing is implicitly castable to immutable.

Value types with no indirection are implicitly convertible to immutable.

-----------
void main()
{
    int a = 2;
    immutable int b = a;
}
-----------


April 11, 2012
Jakob Ovrum:

> Value types with no indirection are implicitly convertible to immutable.
>
> -----------
> void main()
> {
>     int a = 2;
>     immutable int b = a;
> }
> -----------

And far more, even with immutable reference types, in this program 'a' has to be immutable, no just const:


int[] foo(immutable int[] a) pure {
    return a.dup;
}
void main() {
    immutable b = foo([1, 2]);
}


There is the desire to extend this idea a bit more, I think Hara has something on this.

Bye,
bearophile
April 11, 2012
On Wednesday, 11 April 2012 at 17:00:43 UTC, bearophile wrote:
> Jakob Ovrum:
>
>> Value types with no indirection are implicitly convertible to immutable.
>>
>> -----------
>> void main()
>> {
>>    int a = 2;
>>    immutable int b = a;
>> }
>> -----------
>
> And far more, even with immutable reference types, in this program 'a' has to be immutable, no just const:
>
>
> -snip-

I mentioned this as a side-note in my other reply in the thread. It's a truly neat feature which I feel has much potential, I hope to see some compelling use-cases with standard library functions in the future as Phobos becomes more pure-correct.

If the parameter to `array` in the original problem had presented a pure interface, he should have been able to get an immutable result like he tried initially thanks to this feature and pure inference, which is exciting to think about.

Of course, it's useless in this particular case as his parameter to `array` cannot have a pure interface (it's lazily evaluated, right?), and secondly, an immutable range is not usable with foreach.
April 12, 2012
On 04/11/2012 06:08 PM, Russel Winder wrote:
> Doing something along the lines of:
>
> 	const a = array ( filter! ... ) ;
> 	foreach ( i ; a ) { ... }
>
> works fine.  Question 1 though is why I can't use immutable here, why I
> have to use const.

'array' is not pure for some reason. This should be fixed.

>  Question 2 is why I can't do:
>
> 	const a = filter! ... ;
> 	foreach ( i ; a ) { ... }
>

popFront cannot be const. (And Phobos is not very const correct anyways). You can try

auto a = filter!foo(cast(const)data);
foreach( i ; a ) { ... }

(Assuming data is a built-in array slice)
April 12, 2012
On Thu, 12 Apr 2012 13:44:36 -0400, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 04/11/2012 06:08 PM, Russel Winder wrote:
>> Doing something along the lines of:
>>
>> 	const a = array ( filter! ... ) ;
>> 	foreach ( i ; a ) { ... }
>>
>> works fine.  Question 1 though is why I can't use immutable here, why I
>> have to use const.
>
> 'array' is not pure for some reason. This should be fixed.

It's implied pure if filter is pure.  Templates are auto-pure if all the functions they call are pure.  array should not be specifically marked pure.

This may be what you meant (i.e. it's not being implied as pure), but I want to be clear what it *should* be.

-Steve
April 12, 2012
On 04/12/2012 08:08 PM, Steven Schveighoffer wrote:
> On Thu, 12 Apr 2012 13:44:36 -0400, Timon Gehr <timon.gehr@gmx.ch> wrote:
>
>> On 04/11/2012 06:08 PM, Russel Winder wrote:
>>> Doing something along the lines of:
>>>
>>> const a = array ( filter! ... ) ;
>>> foreach ( i ; a ) { ... }
>>>
>>> works fine. Question 1 though is why I can't use immutable here, why I
>>> have to use const.
>>
>> 'array' is not pure for some reason. This should be fixed.
>
> It's implied pure if filter is pure. Templates are auto-pure if all the
> functions they call are pure. array should not be specifically marked pure.
>
> This may be what you meant (i.e. it's not being implied as pure), but I
> want to be clear what it *should* be.
>
> -Steve

Yes, that is what I meant.
April 12, 2012
On Thursday, April 12, 2012 19:44:36 Timon Gehr wrote:
> On 04/11/2012 06:08 PM, Russel Winder wrote:
> > Doing something along the lines of:
> > 	const a = array ( filter! ... ) ;
> > 	foreach ( i ; a ) { ... }
> > 
> > works fine.  Question 1 though is why I can't use immutable here, why I have to use const.
> 
> 'array' is not pure for some reason. This should be fixed.

Probably a result of various array-related stuff which should be pure but isn't (e.g. Appender and some of what's in object_.d), but I'd have to go dig through the implementation to see. We have some pull requests though that should improve that situation for 2.060, and a number of them _must_ be sorted out for 2.060, because we're looking at making toString pure, and too many string-related functions (particularly format, text, and to) can't be pure yet for that to work.

- Jonathan M Davis
« First   ‹ Prev
1 2