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.