Re: restructuring name hiding around the notion of hijacking

2009-10-02 Thread Michel Fortin
On 2009-10-01 23:52:28 -0400, Andrei Alexandrescu 
seewebsiteforem...@erdani.org said:



Michel Fortin wrote:
On 2009-10-01 12:29:39 -0400, Andrei Alexandrescu 
seewebsiteforem...@erdani.org said:


I think it's a good idea, but there should be a way to *override* 
static functions.


That has the same risks. The problem right now is that in order to use 
a class, you must absorb the definition of that class and that of each 
superclass of it, all the way up to Object. With hijacking thwarted, 
you can specify stuff in the base class that you can be sure will 
continue to work the same in derived classes. I believe this makes 
using classes quite a lot easier and safer.


But it breaks one pattern of mine. In the D/Objective-C bridge I have a 
few static functions and variables that must be redefined for each 
subclass defining an Objective-C interface.


I'd say that's a questionable practice (but then I don't know any more 
details).


Well, essencially you can have a D class that act as a wrapper to an 
Objective-C class, or you can also have the reverse: a D class exposing 
itself as an Objective-C class. In all cases, the type hiearchy is 
preserved, so if you have NSString as a subclass of NSObject on the 
Objective-C side, you'll have the same on the D side.


The NSString wrapper must have different static members than NSObject, 
binding it to a different Objective-C class so it can call the right 
methods on it (and so it allocates the right function), but those 
members have the same role (just a different value per class) and must 
be accessible for any class declaring an Objective-C interface (so the 
bridge can swap between the Objective-C and D value when calling a 
function on the other side).


So it turns out that I'm implementing a mechanism somewhat alike 
classinfo for storing Objective-C related class-level data, and for 
that to work I need to reimplement any function accessing this data in 
each subclass that binds to a different Objective-C class.


If I could attach my class-related data to the ClassInfo of a specific 
class (so it could be retrieved at runtime) and if static functions had 
access to the classinfo of the class they're called from (practically 
making them member function of the corresponding ClassInfo) the 
situation might be different though, and much less code would be needed.


--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/



Re: restructuring name hiding around the notion of hijacking

2009-10-02 Thread Max Samukha
On Thu, 01 Oct 2009 22:52:28 -0500, Andrei Alexandrescu
seewebsiteforem...@erdani.org wrote:

Michel Fortin wrote:
 On 2009-10-01 12:29:39 -0400, Andrei Alexandrescu 
 seewebsiteforem...@erdani.org said:
 
 I think it's a good idea, but there should be a way to *override* 
 static functions.

 That has the same risks. The problem right now is that in order to use 
 a class, you must absorb the definition of that class and that of each 
 superclass of it, all the way up to Object. With hijacking thwarted, 
 you can specify stuff in the base class that you can be sure will 
 continue to work the same in derived classes. I believe this makes 
 using classes quite a lot easier and safer.
 
 But it breaks one pattern of mine. In the D/Objective-C bridge I have a 
 few static functions and variables that must be redefined for each 
 subclass defining an Objective-C interface.

I'd say that's a questionable practice (but then I don't know any more 
details).

Andrei

It may be questionable but it is used quite often. The technique can
be illustrated by altering your example of automatic code injection:

class Counted {
 mixin(Derived)
 {
 // Insert here stuff that must be pasted for each subclass
 // of Counted (including Counted itself).
 // Use Derived as the name of the current subtype of
Counter
 private static uint _counter;
 uint staticCounter() { return _counter; } 

 static if (is(Counted == Derived))
 uint getCounter() { return staticCounter; }
 else
 override uint getCounter() { return staticCounter; }
 }
 ...
}

The counter variable is now incapsulated.

If the counter is, for example, an object that should be lazily
created, then you cannot get away without the static function any
more.

BTW, your example shows that 'override' being optional may actually be
a good idea and in this particular case allows to avoid the static
check and code duplication


Re: restructuring name hiding around the notion of hijacking

2009-10-02 Thread Michel Fortin

On 2009-10-02 08:29:09 -0400, Max Samukha spam...@d-coding.com said:


class Counted {
 mixin(Derived)
 {
 // Insert here stuff that must be pasted for each subclass
 // of Counted (including Counted itself).
 // Use Derived as the name of the current subtype of
Counter
 private static uint _counter;
 uint staticCounter() { return _counter; }

 static if (is(Counted == Derived))
 uint getCounter() { return staticCounter; }
 else
 override uint getCounter() { return staticCounter; }
 }
 ...
}

The counter variable is now incapsulated.


Hum, I think you forgot to make staticCounter static, as in:

static uint staticCounter() { return _counter; }

--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/



Re: restructuring name hiding around the notion of hijacking

2009-10-02 Thread Max Samukha
On Fri, 2 Oct 2009 08:54:49 -0400, Michel Fortin
michel.for...@michelf.com wrote:

On 2009-10-02 08:29:09 -0400, Max Samukha spam...@d-coding.com said:

 class Counted {
  mixin(Derived)
  {
  // Insert here stuff that must be pasted for each subclass
  // of Counted (including Counted itself).
  // Use Derived as the name of the current subtype of
 Counter
  private static uint _counter;
  uint staticCounter() { return _counter; }
 
  static if (is(Counted == Derived))
  uint getCounter() { return staticCounter; }
  else
  override uint getCounter() { return staticCounter; }
  }
  ...
 }
 
 The counter variable is now incapsulated.

Hum, I think you forgot to make staticCounter static, as in:

   static uint staticCounter() { return _counter; }

Yes, I do it all the time. Thanks!


Re: restructuring name hiding around the notion of hijacking

2009-10-02 Thread Andrei Alexandrescu

Michel Fortin wrote:
If I could attach my class-related data to the ClassInfo of a specific 
class (so it could be retrieved at runtime) and if static functions had 
access to the classinfo of the class they're called from (practically 
making them member function of the corresponding ClassInfo) the 
situation might be different though, and much less code would be needed.


It has crossed my mind more than once to put an Object userdata[string] 
member somewhere in TypeInfo or Classinfo (in fact the two will be soon 
merged). That way client code would be able to plant their own arbitrary 
data on a per-class basis.


Andrei


Re: restructuring name hiding around the notion of hijacking

2009-10-01 Thread Andrei Alexandrescu

Michel Fortin wrote:
On 2009-09-30 22:01:54 -0400, Andrei Alexandrescu 
seewebsiteforem...@erdani.org said:


Today's D has a very strong, principled notion of hijacking: for any 
given function call, if the call candidates are found in different 
modules, the call is invalid. I think that works great.


Lately I've been thinking of using the same notion of hijacking as a 
replacement for symbol hiding in inheritance hierarchies. Right now, 
if a derived class defines a symbol, that symbol simply hides whatever 
homonym symbol (unless it overrides it). There are some warnings about 
hiding sometimes, but it's all kind of fuzzy.


How about just using hijacking? The basic idea is that a use of a 
symbol in a class should not hijack a homonym symbol defined in a 
different module.



What do you think?


I think it's a good idea, but there should be a way to *override* static 
functions.


That has the same risks. The problem right now is that in order to use a 
class, you must absorb the definition of that class and that of each 
superclass of it, all the way up to Object. With hijacking thwarted, you 
can specify stuff in the base class that you can be sure will continue 
to work the same in derived classes. I believe this makes using classes 
quite a lot easier and safer.


In fact I sometime wonder if it'd be a good idea to disallow hijacking 
of global variables with local variables inside functions too, but 
that's more triky to do.


I explain in TDPL that that's not a good idea. Let me paste the text:

=
A symbol  defined inside  a scope hides  a homonym symbol  hanging out
outside all scopes:

\begin{D}
uint widgetCount;
...
void main() {
   writeln(widgetCount); // writes the global symbol
   auto widgetCount = getWidgetCount();
   writeln(widgetCount); // writes the local symbol
}
\end{D}

The first call to @writeln@ prints the global @widgetCount@ symbol and
the second accesses the locally-defined @widgetco...@. Should there be
a  need for  accessing the  global symbol  after it  has  been masked,
prefixing it  with a ``.''---as  in @writeln(.widgetCount)@---will do,
as first  mentioned on page~\ref{pg:dotSyntaxForScoping}.  However, it
is illegal to define a symbol that would mask a symbol in an enclosing
compound statement:

\begin{D}
void main() {
   auto widgetCount = getWidgetCount();
   // let's now open a nested block
   {
  auto widgetCount = getWidgetCount(); // error!
   }
}
\end{D}

As long as masking does not occur, it's legal to reuse the same symbol
in different compound statements:

\begin{D}
void main() {
   {
  auto i = 0;
  ...
   }
   {
  auto i = eye; // fine
  ...
   }
   double i = 3.14; // fine too
}
\end{D}

The rationale of this setup is simple.  Allowing global symbol masking
is necessary  for writing good,  modular code that's assembled  out of
separately-compiled  parts; you don't  want the  addition of  a global
variable to suddenly  render various innocent bystanders uncompilable.
On the other hand, enclosing-scope  masking is useless as a modularity
device (as there's never the  case a compound statement spans multiple
modules in~\dee) and most often indicates either an oversight aspiring
to become a bug, or a cancerous function that's grown out of control.



Andrei


Re: restructuring name hiding around the notion of hijacking

2009-10-01 Thread Michel Fortin
On 2009-10-01 12:29:39 -0400, Andrei Alexandrescu 
seewebsiteforem...@erdani.org said:


I think it's a good idea, but there should be a way to *override* 
static functions.


That has the same risks. The problem right now is that in order to use 
a class, you must absorb the definition of that class and that of each 
superclass of it, all the way up to Object. With hijacking thwarted, 
you can specify stuff in the base class that you can be sure will 
continue to work the same in derived classes. I believe this makes 
using classes quite a lot easier and safer.


But it breaks one pattern of mine. In the D/Objective-C bridge I have a 
few static functions and variables that must be redefined for each 
subclass defining an Objective-C interface. With your proposal I'd have 
to give them a different name for each subclass.


For instance, the objcClass function in:

NSObject.objcClass

will give you a pointer to the Objective-C class NSObject, while in:

NSString.objcClass

it will give you a pointer to the Objective-C class NSString, because 
objcClass has been reimplemented in the D version of the NSString class 
even though it derives from NSObject which has its own.


If you can't override a static function, how do you implement this?

I'd suggest that a static function could be made final which would 
remove the possibility of redefining it in a subclass. But in abscence 
of final, you should still be able to override a static function in 
a subclass (perhaps the override keyword should be required).


--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/



Re: restructuring name hiding around the notion of hijacking

2009-10-01 Thread Andrei Alexandrescu

Michel Fortin wrote:
On 2009-10-01 12:29:39 -0400, Andrei Alexandrescu 
seewebsiteforem...@erdani.org said:


I think it's a good idea, but there should be a way to *override* 
static functions.


That has the same risks. The problem right now is that in order to use 
a class, you must absorb the definition of that class and that of each 
superclass of it, all the way up to Object. With hijacking thwarted, 
you can specify stuff in the base class that you can be sure will 
continue to work the same in derived classes. I believe this makes 
using classes quite a lot easier and safer.


But it breaks one pattern of mine. In the D/Objective-C bridge I have a 
few static functions and variables that must be redefined for each 
subclass defining an Objective-C interface.


I'd say that's a questionable practice (but then I don't know any more 
details).


Andrei


restructuring name hiding around the notion of hijacking

2009-09-30 Thread Andrei Alexandrescu
Today's D has a very strong, principled notion of hijacking: for any 
given function call, if the call candidates are found in different 
modules, the call is invalid. I think that works great.


Lately I've been thinking of using the same notion of hijacking as a 
replacement for symbol hiding in inheritance hierarchies. Right now, if 
a derived class defines a symbol, that symbol simply hides whatever 
homonym symbol (unless it overrides it). There are some warnings about 
hiding sometimes, but it's all kind of fuzzy.


How about just using hijacking? The basic idea is that a use of a symbol 
in a class should not hijack a homonym symbol defined in a different module.



What do you think?

Andrei


Re: restructuring name hiding around the notion of hijacking

2009-09-30 Thread Michel Fortin
On 2009-09-30 22:01:54 -0400, Andrei Alexandrescu 
seewebsiteforem...@erdani.org said:


Today's D has a very strong, principled notion of hijacking: for any 
given function call, if the call candidates are found in different 
modules, the call is invalid. I think that works great.


Lately I've been thinking of using the same notion of hijacking as a 
replacement for symbol hiding in inheritance hierarchies. Right now, if 
a derived class defines a symbol, that symbol simply hides whatever 
homonym symbol (unless it overrides it). There are some warnings about 
hiding sometimes, but it's all kind of fuzzy.


How about just using hijacking? The basic idea is that a use of a 
symbol in a class should not hijack a homonym symbol defined in a 
different module.



What do you think?


I think it's a good idea, but there should be a way to *override* 
static functions.


In fact I sometime wonder if it'd be a good idea to disallow hijacking 
of global variables with local variables inside functions too, but 
that's more triky to do.



--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/