A bit of good news is that the tartc compiler now runs under Windows, although the linker does not yet. Even if I get the linker working, there is still the issue of getting the resulting programs to actually run, which will require a lot of work, especially in the area of exception handling.
I have a new language idea that I have been thinking about:
Phil Gossett was trying to educate me recently as to the difference between "adhoc" polymorphism and "parametric" polymorphism, specifically as regards to my template syntax. (He was also trying to get me to drink the 'strictly functional' kool-aid, but I wasn't having any of it.)
Parametric polymorphism (which is what Phil considers the "good" kind) is where you have some form of generic or parameterized type that has one or more type parameters. An example is List[T], where T is a type parameter. In parametric polymorphism, you have to declare 'T' as having some sort of upper bound type, and you can only call methods which are defined in that upper bound. An example would be, say, List[Number], which could then be specialized to List[int], List[float] and so on, but not List[String].
Adhoc polymorphism (which he considers the "bad" kind - as in "that way leads to madness") is more like duck typing - once you define List[T], T can be anything, and if you call something like T.toString(), that works as long as T has a toString() method. There's no requirement that the type bound to T have any particular base class as long as it conforms to the implicit contract.
C++ "concepts" are somewhere in between these two - that is, you make the contract explicit rather than implicit (by requiring that T have certain methods) but you don't require that T derive from some particular base class.
Now, given my experience with Python, where adhoc polymorphism has historically been the only kind, I think that such fears are overblown. Just like dynamic typing, it's something that scares the "bondage and dominance" school of language designers - when in practice the kinds of disasters they worry about almost never happen. (I'm surprised that no one has yet done a PHd thesis on whether the lack of strict type checking makes dynamic languages less reliable in practice - and more interestingly, if the answer is "it doesn't" then why?)
However, it occurs to me that there's one concrete benefit to parametric polymorphism, and that is avoiding template bloat. You see, if a template parameter must derive from some class, and can only use methods of that class, then the exact same generated code will work for all subclasses, assuming that those classes have binary compatibility (which is true for all reference types, but not for all value types.) Thus, if a template only calls "toString()" then the same exact set of machine instructions can be used for any subclass of Object.
Note that the savings in space can in some cases cause a small loss in speed - by re-using the same template instance for both Object and String, say, it means that some method calls have to be dispatched dynamically, whereas if the compiler generated a template instance for class String only, it would then be able to resolve certain method calls at compile time and thus generate faster code.
So it seems to me that there is perhaps a use for both types of polymorphism. One way to implement this would be to have two versions of the "<:" (issubclass) operator - a 'strict' and a 'relaxed' version. By making it an operator, it allows you to specify the strictness for each template parameter without affecting the other template parameters. It means that programmers can decide on a case-by-case basis whether to optimize for size or speed.
How to specify this in syntax I really haven't thought too deeply about yet.
-- Talin
No comments:
Post a Comment