View mode: basic / threaded / horizontal-split · Log in · Help
April 11, 2012
foreach and filter
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
Re: foreach and filter
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
Re: foreach and filter
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
Re: foreach and filter
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
Re: foreach and filter
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
Re: foreach and filter
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
Re: foreach and filter
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
Re: foreach and filter
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
Re: foreach and filter
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
Re: foreach and filter
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
Top | Discussion index | About this forum | D home