www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 1835] New: typeof(this) should return the type of object or some other typeof() is needed

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

           Summary: typeof(this) should return the type of object or some
                    other typeof() is needed
           Product: D
           Version: unspecified
          Platform: Other
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: onlystupidspamhere yahoo.se


Consider the following code:

class A {
  A foo() { return this; }
}

class B : A {
  B bar() { return this; }
}

void main() {
  auto b = new B;
  b.foo().bar(); // We would like to chain methods like this
}

Currently this is not possible without CRTP (fugly) / mixins (not a good idea)
/ casts (yucky). Also typeof(this) returns A in class A.. Why can't we allow
this:

class A {
  typeof(this) foo() { return this; } // here the return type would depend on
the actual runtime type of the object
}

class B : A {
  B bar() { return this; }
}

void main() {
  auto b = new B;
  b.foo().bar(); // We would like to chain methods like this
}


Similar problems occur with common graph data structures. E.g. if we have nodes
and edges and inherit from both of them. Now going from SubNode to SubNode
won't be possible without the tricks mentioned above because of the type
system.

This is a very useful feature, see Scala language docs for more info.


-- 
Feb 14 2008
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1835






This proposal has a lot of merit. A better example than chaining is the clone
function:

class Root
{
    abstract typeof(this) clone();
    ...
}

If such a function were defined, then all derived classes would be required to
implement it (which is a Good Thing) and would also be forced to return the
same static type as themselves (which again is a Good Thing).

Unfortunately, this does not port nicely to functions that accept an
equivariant parameter, such as opCmp and opEquals:

class Root
{
    int opCmp(typeof(this) another);
    int opEquals(typeof(this) another);
    ...
}

The intent is to have the comparison operations accept the same type as the
actual static type of the object. But such a signature cannot be checked
statically - a runtime check would have to be inserted.

Nonetheless, I'll bring it up with Walter.


-- 
Feb 14 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1835






Well, I requested it already before... Unfortunately without much luck:

1.
http://www.digitalmars.com/d/archives/digitalmars/D/Covariance_fix_was_Idea_Lazy_upcasting_51296.html
2.
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=51201

It's also mentioned in previous bugzilla reports:
1. http://d.puremagic.com/issues/show_bug.cgi?id=323
2. http://d.puremagic.com/issues/show_bug.cgi?id=1120

The problem solution seems to have even its name: anchored types.

----------------

Additionally in current design you have to overwrite every, even simple
setter/getter method in every derived class.

e.g.
class A {
  typeof(this) setX(int x) {
    this.x = x;
  }
  int x;
}

class B {
        void test() {}
}

When I don't want to redefine setX() in B, below also should work:

B b = new B;
b.setX(5).test;


-- 
Feb 14 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1835






... B derives after A of course:

class A {
  typeof(this) setX(int x) {
    this.x = x;
  }
  int x;
}

class B : A {
        void test() {}
}


-- 
Feb 14 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1835






I understand. Now the problem is that this is a feature of rather modest
utility, while Walter has many much bigger rocks to move right now. I'll bring
it un nonetheless. 

Andrei


-- 
Feb 14 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1835


matti.niemenmaa+dbugzilla iki.fi changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
OtherBugsDependingO|2295                        |
              nThis|                            |
                 CC|                            |fawzi gmx.ch





-------
*** Bug 2295 has been marked as a duplicate of this bug. ***


-- 
Aug 20 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1835


Simen Kjaeraas <simen.kjaras gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |simen.kjaras gmail.com



PDT ---
With template this parameters[1], shouldn't this bug be closed?

[1]: http://www.digitalmars.com/d/2.0/template.html#TemplateThisParameter

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 24 2010
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1835


Christian Kamm <kamm-removethis incasoftware.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |kamm-removethis incasoftwar
                   |                            |e.de
         Resolution|                            |FIXED



09:15:23 PDT ---
Yes, it looks like template this parameters cover this use case. You can even
express the contract of a clone function nicely:

class B {
  T clone(this T)() {
    return (cast(T)this).cloneImpl();
  }
  B cloneImpl() { return new B; }
}

class D {
  override D cloneImpl() { return new D; }
}

If the user forgets to provide cloneImpl or doesn't make it return the correct
type, the compiler will complain. At least as long as clone!(D) gets
instantiated somewhere.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 24 2010
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1835




Yes indeed and Christian showed this templates argument allows one workaround
to achieve this (a wrapper object is another).

{{{
class A {
  void a(...){ ... }
  T aChain(this T)() {
   a();
   return cast(T)this;
  }
}
class B {
  void a(...){ ... }
}
}}}

it might even be cleaner to have also a non chainable version, the return this
is really a convenience, and not strictly part of the operation itself, even if
it implies some duplication.

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