|
Re: Refactoring Dynamic Code
|
Posted: Oct 22, 2007 11:08 AM
|
|
> > Using concepts, you could write the above as: > > > > concept SomeConcept > > { > > void init(); > > } > > > > template<SomeConcept T> > > void f1(T t) > > { > > t.init(); > > } > > > > template<SomeConcept T> > > void f2(T t) > > { > > t.init(); > > } > >
> > Changing "init()" to "init2()" in the concept > definition, > > a refactoring tool should also be able to find all > > instances of uses of SomeConcept, and change those > places, > > too. > > That's very nice. > > Note that you can annotate Python 3.0 arguments like > this: > > class SomeConcept: > def init(self): > pass > > def f1(t: SomeConcept): > t.init() > > def f2(t: SomeConcept): > t.init() >
> The language will nevertheless be dynamically typed and > the annotations are optional and their semantics depends > on particular handlers. That says it's not basically an > issue about type systems but about abstraction and the > provisioning of metadata.
Right. However, note that in the C++ case, any violation of the contract (the interface given by the concept) will be caught at compile-time, whereas I assume that the Python annotations - if they are checked - are checked at run-time, so you only find any violation at run-time, if at all.
However, then we get into that static typing vs dynamic typing debate, again. :)
Also note that - for those who may be new to concepts/constrained generics - a "concept" doesn't specify a specific type, only the requirements of the type (at least the compile-time checkable ones), so that instances of both the following classes would match (or "model", in generic programming speak) the concept above:
class A { ... void init() { ... } ... }; class B { ... void init() { ... } ... } A a; B b; f1(a); // Fine f1(b); // Also fine
In the current concept proposal, you can specify whether a concept would match a type implicitly (without declaring a type to match it, as long as it has the necessary requirements as specified by the concept, or explicityly, where you have to specify that a type matches the concept).
"SomeConcept" in itself is not a type (it might be considered a set of all the types satisfying its requirements), but "T" in the function templates is a specific type ("A" or "B", in this case).
As I understand the Python example above, "SomeConcept" is a type, and in that case, the example isn't analogous to the C++ one, but rather a case of optional (specific) typing, as in:
void f1(SomeConcept t) { ... }
Here, the value passed in must be of type (convertible to) SomeConcept.
A more useful example may make the point of concepts clearer:
concept LessThanComparable<typename T> { bool operator<(T,T); } template<LessThanComparable T> const T& min(const T& a, const T& b) { return a<b ? a : b; } int a=..., b=...; int result=min(a,b); // Fine BigInt a=..., b...; // Some user-defined class BigInt result=min(a,b); // Also fine
But (using the "A" class defined above):
A a(...), b(...); A result=min(a,b); // Error, "A" doesn't model the LessThanComparable concept
I also need to correct the syntax for the concept definition in my first posting. The actual syntax should be the following:
concept SomeConcept<typename T> { T t; t.init(); }
Anyway, this is a little off topic, perhaps, but I find "concepts" rather interesting. :)
|
|