Bug 5491 – filter cannot be used in a function?

Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
x86
OS
Linux
Creation time
2011-01-26T10:36:00Z
Last change time
2012-04-24T18:55:55Z
Assigned to
nobody
Creator
tbolsh

Comments

Comment #0 by tbolsh — 2011-01-26T10:36:32Z
The following code: _______________________________________________________________________________ import std.algorithm, std.conv, std.stdio; enum UsbDevType: uint { indifferent = 0, parent_of_checked = 1, hub_dub_7 = 0x2001f103, spider_hub = 0x05e30608, gateway = 0x11A03232 } struct UsbDevice { //{{{ UsbDevType dev_type; // not essential here ... string toString(){ return to!string( dev_type ); } } UsbDevice [] gateways_only( UsbDevice []devices ){ return filter!("a.dev_type == UsbDevType.gateway" )( devices ); } unittest{ auto devices = [ UsbDevice( UsbDevType.gateway ), UsbDevice( UsbDevType.indifferent ), UsbDevice( UsbDevType.hub_dub_7 ) ]; auto gateways = gateways_only( devices ); foreach( UsbDevice dev; gateways ) writeln( dev.toString() ); } ______________________________________________________________________________ does not compile telling: bugs/tbolsh_d2_bug2.d(10): Error: cannot implicitly convert expression (filter(devices)) of type Filter!(result,UsbDevice[]) to UsbDevice[]
Comment #1 by tbolsh — 2011-01-26T10:40:17Z
Following variant do not work either: ______________________________________________________________________________ import std.algorithm, std.conv, std.stdio; enum UsbDevType: uint { indifferent = 0, parent_of_checked = 1, hub_dub_7 = 0x2001f103, spider_hub = 0x05e30608, gateway = 0x11A03232 } struct UsbDevice { //{{{ UsbDevType dev_type; // not essential here ... string toString(){ return to!string( dev_type ); } } unittest{ auto devices = [ UsbDevice( UsbDevType.gateway ), UsbDevice( UsbDevType.indifferent ), UsbDevice( UsbDevType.hub_dub_7 ) ]; auto gateways = filter!( "a.dev_type == UsbDevType.gateway" )( devices ); foreach( UsbDevice dev; gateways ) writeln( dev.toString() ); } ______________________________________________________________________________ compiler tells: tbolshakov@owner-laptop:~/projects/D$ dmd -unittest bugs/tbolsh_d2_bug3.d /usr/include/d/dmd/phobos/std/functional.d(74): Error: static assert "Bad unary function: a.dev_type == UsbDevType.gateway for type UsbDevice" /usr/include/d/dmd/phobos/std/functional.d(87): instantiated from here: Body!(UsbDevice) /usr/include/d/dmd/phobos/std/algorithm.d(857): instantiated from here: result!(UsbDevice) /usr/include/d/dmd/phobos/std/algorithm.d(842): instantiated from here: Filter!(result,UsbDevice[]) bugs/tbolsh_d2_bug3.d(12): instantiated from here: filter!(UsbDevice[])
Comment #2 by tbolsh — 2011-01-26T10:50:03Z
And this one does not compile: __________________________________________________________________________________ import std.algorithm, std.conv, std.stdio; enum UsbDevType: uint { indifferent = 0, parent_of_checked = 1, hub_dub_7 = 0x2001f103, spider_hub = 0x05e30608, gateway = 0x11A03232 } struct UsbDevice { //{{{ UsbDevType dev_type; ubyte usb_id; // not essential here ... string toString(){ return to!string( dev_type ); } } UsbDevice [ ubyte ] associate_devices( UsbDevice []devices ){//{{{ UsbDevice [ubyte] retval; foreach( UsbDevice dev ; devices ) retval[ dev.usb_id ] = dev; return retval; }//}}} unittest{ auto devices = [ UsbDevice( UsbDevType.gateway, 1 ), UsbDevice( UsbDevType.indifferent, 2 ), UsbDevice( UsbDevType.hub_dub_7, 3 ) ]; auto devmap = associate_devices( filter!( delegate bool( UsbDevice a ){ return a.dev_type == UsbDevType.gateway; } )( devices ) ); foreach( UsbDevice dev; gateways ) writeln( dev.toString() ); } void main(){} ______________________________________________________________________________ Telling: tbolshakov@owner-laptop:~/projects/D$ dmd -unittest bugs/tbolsh_d2_bug4.d bugs/tbolsh_d2_bug4.d(18): Error: function tbolsh_d2_bug4.associate_devices (UsbDevice[] devices) is not callable using argument types (Filter!(__dgliteral1,UsbDevice[])) bugs/tbolsh_d2_bug4.d(19): Error: cannot implicitly convert expression (filter(devices)) of type Filter!(__dgliteral1,UsbDevice[]) to UsbDevice[] bugs/tbolsh_d2_bug4.d(20): Error: undefined identifier gateways bugs/tbolsh_d2_bug4.d(20): Error: foreach: _error_ is not an aggregate type
Comment #3 by tbolsh — 2011-01-26T10:53:14Z
I am sorry for the line > UsbDevType.gateway; } )( devices ) ); > foreach( UsbDevice dev; gateways ) writeln( dev.toString() ); > } It is not needed there - cut and paste error. But it will remove only 2 last errors, "filter" related errors will still be there: > tbolshakov@owner-laptop:~/projects/D$ dmd -unittest bugs/tbolsh_d2_bug4.d > bugs/tbolsh_d2_bug4.d(18): Error: function tbolsh_d2_bug4.associate_devices > (UsbDevice[] devices) is not callable using argument types > (Filter!(__dgliteral1,UsbDevice[])) > bugs/tbolsh_d2_bug4.d(19): Error: cannot implicitly convert expression > (filter(devices)) of type Filter!(__dgliteral1,UsbDevice[]) to UsbDevice[]
Comment #4 by tbolsh — 2011-01-26T11:05:52Z
I got several other similar errors in find, like /usr/include/d/dmd/phobos/std/functional.d(74): Error: static assert "Bad unary function: a.parent_id == usb_id for type UsbDevice" /usr/include/d/dmd/phobos/std/functional.d(87): instantiated from here: Body!(UsbDevice) /usr/include/d/dmd/phobos/std/algorithm.d(2699): instantiated from here: result!(UsbDevice) ampt/field_computer/usbmon.d(312): instantiated from here: find!("a.parent_id == usb_id",Filter!(gateways_pred,UsbDevice[])) Or ampt/field_computer/usbmon.d(295): Error: cannot implicitly convert expression (filter(devlist)) of type Filter!(gateways_pred,UsbDevice[]) to UsbDevice[] That all makes functional style marginal - I do not know when and why it break next time.
Comment #5 by bearophile_hugs — 2011-01-26T11:37:32Z
(In reply to comment #0) > import std.algorithm, std.conv, std.stdio; > > enum UsbDevType: uint { indifferent = 0, parent_of_checked = 1, hub_dub_7 = > 0x2001f103, spider_hub = 0x05e30608, gateway = 0x11A03232 } > struct UsbDevice { //{{{ > UsbDevType dev_type; > // not essential here ... > string toString(){ return to!string( dev_type ); } > } > > UsbDevice [] gateways_only( UsbDevice []devices ){ return filter!("a.dev_type > == UsbDevType.gateway" )( devices ); } This works: auto gateways_only(UsbDevice[] devices) { return filter!((a){ return a.dev_type == UsbDevType.gateway; })(devices); }(In reply to comment #0) > The following code: > _______________________________________________________________________________ > import std.algorithm, std.conv, std.stdio; > > enum UsbDevType: uint { indifferent = 0, parent_of_checked = 1, hub_dub_7 = > 0x2001f103, spider_hub = 0x05e30608, gateway = 0x11A03232 } > struct UsbDevice { //{{{ > UsbDevType dev_type; > // not essential here ... > string toString(){ return to!string( dev_type ); } > } > > UsbDevice [] gateways_only( UsbDevice []devices ){ return filter!("a.dev_type > == UsbDevType.gateway" )( devices ); } > > unittest{ > auto devices = [ UsbDevice( UsbDevType.gateway ), UsbDevice( > UsbDevType.indifferent ), UsbDevice( UsbDevType.hub_dub_7 ) ]; > auto gateways = gateways_only( devices ); > foreach( UsbDevice dev; gateways ) writeln( dev.toString() ); > } The formatting of your code is very bad. This works: import std.algorithm, std.conv, std.stdio; enum UsbDevType: uint { indifferent = 0, parent_of_checked = 1, hub_dub_7 = 0x2001f103, spider_hub = 0x05e30608, gateway = 0x11A03232 } struct UsbDevice { UsbDevType dev_type; string toString() { return to!string(dev_type); } } auto gateways_only(UsbDevice[] devices) { return filter!((a){ return a.dev_type == UsbDevType.gateway; })(devices); } void main() { auto devices = [UsbDevice(UsbDevType.gateway), UsbDevice(UsbDevType.indifferent), UsbDevice( UsbDevType.hub_dub_7)]; auto gateways = gateways_only(devices); foreach (UsbDevice dev; gateways) writeln(dev.toString()); } Currently string-defined functions that you give to filter, map, etc, can't use symbol names defined elsewhere, like UsbDevType. So you need to use a lambda template, as I have done here, or a proper delegate.
Comment #6 by lovelydear — 2012-04-22T15:49:42Z
I haven't checked the original code, but bearophile's code gives on 2.059: PS E:\DigitalMars\dmd2\samples> rdmd bug.d gateway
Comment #7 by bearophile_hugs — 2012-04-24T18:55:55Z
This bug report, and the code examples, are rather messy. This code can't work because Phobos filter() returns a range, so if you want a UsbDevice[] you need to attach an ".array()" at the end. UsbDevice [] gateways_only( UsbDevice []devices ){ return filter!("a.dev_type == UsbDevType.gateway" )( devices ); } And because of the way "string lambdas" are defined, they can't work well here. But we have the lambda syntax now. So code like this works: import std.algorithm, std.conv, std.stdio, std.array; enum UsbDevType: uint { indifferent = 0, parent_of_checked = 1, hub_dub_7 = 0x2001f103, spider_hub = 0x05e30608, gateway = 0x11A03232 } struct UsbDevice { //{{{ UsbDevType dev_type; // not essential here ... string toString(){ return to!string( dev_type ); } } UsbDevice [] gateways_only( UsbDevice []devices ){ return filter!(a => a.dev_type == UsbDevType.gateway)( devices ).array(); } void main() { auto devices = [ UsbDevice( UsbDevType.gateway ), UsbDevice( UsbDevType.indifferent ), UsbDevice( UsbDevType.hub_dub_7 ) ]; auto gateways = gateways_only( devices ); foreach( UsbDevice dev; gateways ) writeln( dev.toString() ); } So there is no bug in DMD/Phobos here, closed as INVALID.