Thread overview
[Issue 5491] New: filter cannot be used in a function?
Jan 26, 2011
Timofei Bolshakov
Jan 26, 2011
Timofei Bolshakov
Jan 26, 2011
Timofei Bolshakov
Jan 26, 2011
Timofei Bolshakov
Jan 26, 2011
Timofei Bolshakov
Apr 22, 2012
SomeDude
January 26, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5491

           Summary: filter cannot be used in a function?
           Product: D
           Version: D2
          Platform: x86
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Phobos
        AssignedTo: nobody@puremagic.com
        ReportedBy: tbolsh@gmail.com


--- Comment #0 from Timofei Bolshakov <tbolsh@gmail.com> 2011-01-26 10:36:32 PST ---
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[]

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 26, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5491



--- Comment #1 from Timofei Bolshakov <tbolsh@gmail.com> 2011-01-26 10:40:17 PST ---
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[])

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 26, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5491



--- Comment #2 from Timofei Bolshakov <tbolsh@gmail.com> 2011-01-26 10:50:03 PST ---
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

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 26, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5491



--- Comment #3 from Timofei Bolshakov <tbolsh@gmail.com> 2011-01-26 10:53:14 PST ---
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[]

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 26, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5491



--- Comment #4 from Timofei Bolshakov <tbolsh@gmail.com> 2011-01-26 11:05:52 PST ---
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.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 26, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5491


bearophile_hugs@eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs@eml.cc


--- Comment #5 from bearophile_hugs@eml.cc 2011-01-26 11:37:32 PST ---
(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.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
April 22, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=5491


SomeDude <lovelydear@mailmetrash.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |lovelydear@mailmetrash.com


--- Comment #6 from SomeDude <lovelydear@mailmetrash.com> 2012-04-22 15:49:42 PDT ---
I haven't checked the original code, but bearophile's code gives on 2.059:

PS E:\DigitalMars\dmd2\samples> rdmd bug.d
gateway

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
April 25, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=5491


bearophile_hugs@eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |INVALID


--- Comment #7 from bearophile_hugs@eml.cc 2012-04-24 18:55:55 PDT ---
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.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------