September 12, 2010 Re: Question about typeof(this) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pelle | On 2010-09-10 16:53, Pelle wrote: > On 09/10/2010 03:20 PM, Jacob Carlborg wrote: >> On 2010-09-07 22:32, Don wrote: >>> Jacob Carlborg wrote: >>>> On 2010-09-07 17:29, Don wrote: >>>>> Jacob Carlborg wrote: >>>>>> I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof >>>>>> where it says: >>>>>> >>>>>> "typeof(this) will generate the type of what this would be in a >>>>>> non-static member function, even if not in a member function. " >>>>>> >>>>>> From that I got the impression that the code below would print the >>>>>> same result, but it doesn't. It prints: >>>>>> >>>>>> main.Bar >>>>>> main.Foo >>>>>> >>>>>> instead of: >>>>>> >>>>>> main.Foo >>>>>> main.Foo >>>>>> >>>>>> Is this a bug or have I misunderstood the docs? >>>>> >>>>> typeof(this) gives the *compile-time* type of this. Inside Bar, it has >>>>> to return 'Bar'. >>>>> typeid(this) gives the *runtime* type of this. So it can work that >>>>> it's >>>>> Bar is actually a Foo. >>>> >>>> I know that typeof(this) is a compile time expression but in this case >>>> I think the compiler has all the necessary information at compile >>>> time. Note that I'm not calling "method" on a base class reference, >>>> I'm calling it on the static type "Foo". In this case I think >>>> typeof(this) would resolve to the type of the receiver, i.e. the type >>>> of"foo". >>> >>> Even though in this instance it could work out which derived class is >>> being used, it's not allowed to use that information while compiling >>> method(). There is only ONE function method(), and it has to work for >>> Bar, and all classes derived from Bar. >> >> I think Scala can handle this problem, the following text is a snippet >> from a paper called "Scalable Component Abstractions" (link at the >> bottom), page 4 "Type selection and singleton types": >> >> class C { >> protected var x = 0; >> def incr: this.type = { x = x + 1; this } >> } >> >> class D extends C { >> def decr: this.type = { x = x - 1; this } >> } >> >> "Then we can chain calls to the incr and decr method, as in >> >> val d = new D; d.incr.decr; >> >> Without the singleton type this.type, this would not have >> been possible, since d.incr would be of type C, which does >> not have a decr member. In that sense, this.type is similar >> to (covariant uses of ) Kim Bruce's mytype construct [5]." >> >> I'm not very familiar with Scala but the above code example seems to >> work as I want typeof(this) to work. >> >> http://www.scala-lang.org/sites/default/files/odersky/ScalableComponent.pdf >> >> > > You can do this in D, but the syntax is clumsy. And it uses templates. > > class C { > int x; > T incr(this T)() { > x += 1; > return cast(T)this; // clumsy, but always works (?) > } > } > class D : C { > T decr(this T)() { > x -= 1; > return cast(T)this; > } > } > > void main() { > D d = new D; > d.decr.incr.decr.incr.incr; > writeln(d.x); > > } I've done some testing with this template parameters and it actually works as I want it to, but I don't understand why it has to be a template. Both templates and typeof are resolved at compile time so I don't understand why it can't work with typeof. I have this example now: module main; import std.stdio; class Base { void foo (this T) () { writeln(T.stringof); writeln(typeof(this).stringof); } } class Foo : Base { } void main() { auto foo = new Foo; foo.foo; } It will print: Foo Base To me this template parameters look unnecessary, typeof should be able to handle this. In the above "foo" method I think T should be equal to typeof(this). -- /Jacob Carlborg |
September 14, 2010 Re: Question about typeof(this) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | Jacob Carlborg wrote:
> On 2010-09-10 16:53, Pelle wrote:
>> On 09/10/2010 03:20 PM, Jacob Carlborg wrote:
>>> On 2010-09-07 22:32, Don wrote:
>>>> Jacob Carlborg wrote:
>>>>> On 2010-09-07 17:29, Don wrote:
>>>>>> Jacob Carlborg wrote:
>>>>>>> I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof
>>>>>>> where it says:
>>>>>>>
>>>>>>> "typeof(this) will generate the type of what this would be in a
>>>>>>> non-static member function, even if not in a member function. "
>>>>>>>
>>>>>>> From that I got the impression that the code below would print the
>>>>>>> same result, but it doesn't. It prints:
>>>>>>>
>>>>>>> main.Bar
>>>>>>> main.Foo
>>>>>>>
>>>>>>> instead of:
>>>>>>>
>>>>>>> main.Foo
>>>>>>> main.Foo
>>>>>>>
>>>>>>> Is this a bug or have I misunderstood the docs?
>>>>>>
>>>>>> typeof(this) gives the *compile-time* type of this. Inside Bar, it has
>>>>>> to return 'Bar'.
>>>>>> typeid(this) gives the *runtime* type of this. So it can work that
>>>>>> it's
>>>>>> Bar is actually a Foo.
>>>>>
>>>>> I know that typeof(this) is a compile time expression but in this case
>>>>> I think the compiler has all the necessary information at compile
>>>>> time. Note that I'm not calling "method" on a base class reference,
>>>>> I'm calling it on the static type "Foo". In this case I think
>>>>> typeof(this) would resolve to the type of the receiver, i.e. the type
>>>>> of"foo".
>>>>
>>>> Even though in this instance it could work out which derived class is
>>>> being used, it's not allowed to use that information while compiling
>>>> method(). There is only ONE function method(), and it has to work for
>>>> Bar, and all classes derived from Bar.
>>>
>>> I think Scala can handle this problem, the following text is a snippet
>>> from a paper called "Scalable Component Abstractions" (link at the
>>> bottom), page 4 "Type selection and singleton types":
>>>
>>> class C {
>>> protected var x = 0;
>>> def incr: this.type = { x = x + 1; this }
>>> }
>>>
>>> class D extends C {
>>> def decr: this.type = { x = x - 1; this }
>>> }
>>>
>>> "Then we can chain calls to the incr and decr method, as in
>>>
>>> val d = new D; d.incr.decr;
>>>
>>> Without the singleton type this.type, this would not have
>>> been possible, since d.incr would be of type C, which does
>>> not have a decr member. In that sense, this.type is similar
>>> to (covariant uses of ) Kim Bruce's mytype construct [5]."
>>>
>>> I'm not very familiar with Scala but the above code example seems to
>>> work as I want typeof(this) to work.
>>>
>>> http://www.scala-lang.org/sites/default/files/odersky/ScalableComponent.pdf
>>>
>>>
>>>
>>
>> You can do this in D, but the syntax is clumsy. And it uses templates.
>>
>> class C {
>> int x;
>> T incr(this T)() {
>> x += 1;
>> return cast(T)this; // clumsy, but always works (?)
>> }
>> }
>> class D : C {
>> T decr(this T)() {
>> x -= 1;
>> return cast(T)this;
>> }
>> }
>>
>> void main() {
>> D d = new D;
>> d.decr.incr.decr.incr.incr;
>> writeln(d.x);
>>
>> }
>
> I've done some testing with this template parameters and it actually works as I want it to, but I don't understand why it has to be a template. Both templates and typeof are resolved at compile time so I don't understand why it can't work with typeof. I have this example now:
>
> module main;
>
> import std.stdio;
>
> class Base
> {
> void foo (this T) ()
> {
> writeln(T.stringof);
> writeln(typeof(this).stringof);
> }
> }
>
> class Foo : Base { }
>
> void main()
> {
> auto foo = new Foo;
> foo.foo;
> }
>
> It will print:
>
> Foo
> Base
>
> To me this template parameters look unnecessary, typeof should be able to handle this. In the above "foo" method I think T should be equal to typeof(this).
>
There are only two ways to have the behaviour you want:
(1) make it a template, so that the function is duplicated for every derived class (that's what this solution is doing); OR
(2) use runtime type information.
Both of these have unacceptable consequences in general.
|
Copyright © 1999-2021 by the D Language Foundation