www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 12408] New: map does not like inout

reply d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=12408

           Summary: map does not like inout
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: lt.infiltrator gmail.com



PDT ---
http://dpaste.dzfl.pl/cd03223f4472

----------------------------------------------------
import std.algorithm : map;

class L {
   auto fun(const S s) inout nothrow pure  safe {
      if(point[0] is s)
         return point[1];
      else
         return point[0];
   }
   this(S a, S b) {
      point = [a, b];
   }
   S[2] point;
}

class S {
    property auto foo() inout nothrow pure  safe {
      return arr.map!(e => e.fun(this));
   }
   L[] arr;
}

void main() { }
----------------------------------------------------
Fails to compile:
/opt/compilers/dmd2/include/std/algorithm.d(438): Error: variable
f922.S.foo.MapResult!(__lambda1, inout(L)[]).MapResult._input only parameters
or stack based variables can be inout
/opt/compilers/dmd2/include/std/algorithm.d(390): Error: template instance
f922.S.foo.MapResult!(__lambda1, inout(L)[]) error instantiating
/d556/f922.d(18): instantiated from here: map!(inout(L)[]) /d556/f922.d(18):
Error: template instance f922.S.foo.map!((e) => e.fun(this)).map!(inout(L)[])
error instantiating /d556/f922.d(18): Error: template std.algorithm.map cannot
deduce function from argument types !((e) => e.fun(this))(inout(L[])),
candidates are: /opt/compilers/dmd2/include/std/algorithm.d(375):
std.algorithm.map(fun...) if (fun.length >= 1)

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 18 2014
next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=12408




PDT ---


-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 18 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=12408


monarchdodra gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |monarchdodra gmail.com



Seems invalid to me. Take a look at this reduced example:

//----
struct L(T)
{
    T t;
}
auto l(T)(T t)
{
    return L!T();
}

class S 
{
    auto foo() inout
    {
       return l(a);
    }
    int a;
}

void main() { } 
//----

What's basically happening in "foo", is you are creating a type
`L!(inout(int))`, which has a member t with qualifier `inout(int)`. That don't
make no sense.

You need to chose the static type you are returning. The type *itself* may be
marked as inout. However, that's not what you are doing: You are returning a
type that's parameterized on inout, which is not the same at all.

The idea of "inout" (as I have understood it), is that there is a *single*
implementation that is compatible for all of const/immutable/mutable. That's
not quite what you are doing. I think you simply need a const/non-const
overload. Then, they'll return 2 actual different types "map!(L[])" and
"map!(const(L)[])" (and you can even add an immutable overload if you so wish).

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 19 2014
prev sibling next sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=12408




PDT ---
I thought that the whole point of using inout was to avoid having to copy-paste
code between mutable, const, and immutable functions?  As you've described
(unless I'm misunderstanding), I should copy-paste

 property auto foo() inout nothrow pure  safe {
   return arr.map!(e => e.fun(this));
}

as mutable, const, and nothrow.  Shouldn't this be something which should be
fixed with inout and/or templates themselves?

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 19 2014
prev sibling parent d-bugmail puremagic.com writes:
https://d.puremagic.com/issues/show_bug.cgi?id=12408





 I thought that the whole point of using inout was to avoid having to
 copy-paste code between mutable, const, and immutable functions?
Yes, that's it's design, but it's not magic either. It makes it so that a single *implementation* can work as mutable or immutable. What you are asking for is actually 3 different implementations (3 different return types). At least, that's how I understood the issue. Maybe bring it up on learn to see if I'm wrong. That said, please think about your design, and what it means to have const/non-const overloads that return different types.
 As you've described
 (unless I'm misunderstanding), I should copy-paste
 
  property auto foo() inout nothrow pure  safe {
    return arr.map!(e => e.fun(this));
 }
 
 as mutable, const, and nothrow.  Shouldn't this be something which should be
 fixed with inout and/or templates themselves?
Maybe there is a template solution, but (AFAIK) templates don't have the capability of conditionally tagging things as const or not. I'd have thought mixin templates could solve this, like this: //---- mixin template fooImpl() { auto foo() { return l(a); } } mixin fooImpl!(); const mixin fooImpl!(); immutable mixin fooImpl!(); //---- But apparently, the qualifiers are ignored, and this simply creates the same function 3 times. So I don't see anything other than string mixins :/ -- Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 20 2014