4 ms·
> In fact, multiple dispatch is best categorized as a generalization of OOP, being more in the domain of generic programming. Kinda like the generic programming
by catnaroek 11y ago
> In fact, multiple dispatch is best categorized as a generalization of OOP, being more in the domain of generic programming. Kinda like the generic programming of C++, just at runtime instead of being limited to compile-time constructs and metaprogramming.
Doing it at compile-time is a feature, because the compiler has more information available for selecting the right specialization. (Technically, this can be done at runtime as well, but only at the price of making dispatch insanely expensive.) For example, in CLOS, how would I do the equivalent of specializing a template for when its argument is a `vector<list<unique_ptr<int>>>`?
- GregBuchholz 11y agoCould you clarify if you are trying to make a comparison between garbage collection and unique_ptr? Or are you saying that you wish CLOS allowed dispatch on types as well as classes (anyone know the historical reason for why this is the case?). Or are you making the point that it would be ugly to create a new class "vector-of-list-of-fixnums"? Or something else?
- catnaroek 11y agoIt has nothing to do with garbage collection. I could've used GHC Haskell with sufficient extensions (MultiParamTypeClasses, FlexibleInstances, perhaps UndecidableInstances too) enabled as an example, instead of C++. The point is that C++ has a much richer type structure on which you can dispatch.
- jorams 11y agoCLOS only allows dispatch on classes and not types, because there is no hierarchy in types. For example, if you have a method specializing on the type (satisfies a) and a method specializing on the type (satisfies b), and you call a generic function with an object that satisfies both a and b, which method should be called first? Or methods specializing on the types (integer 0 8) and (integer 1 9). If the argument is 5, which type is more specific? Classes are a subset of types with a certain hierarchy, so there is always a "correct" order for methods to be called in.
- pjmlp 11y agoJust an idea, most likely with macros.
- catnaroek 11y agoWhich is totally orthogonal to CLOS, though.
- gecko 11y agoThrough things like this library, which, combined with a Sufficiently Smart Compiler (SBCL qualifies as one for this purpose), produces C++-like static dispatch for cases such as the one you're proposing. https://github.com/guicho271828/inlined-generic-function https://github.com/guicho271828/inlined-generic-function
- catnaroek 11y agoIt's not only about speed, it's also about deeply specializing templates.
- eliben 11y agoBut templates are about speed. Clojure-type dispatch can be easily implemented in CLOS (all of CLOS is just a set of Lisp macros and functions), and it's fully general. You can "deeply specialize" to your heart's content, the only issue being speed. As another comment mentioned, some compilers are smart enough to see through things that are known at compile time, or perhaps even JIT-specialze at runtime, but it's all about speed.
- catnaroek 11y agoIt's not only about speed. It's about dispatching on types that themselves are template instantiations. As an exercise, write a CLOS generic function that takes a list, and prints its elements forwards if the elements are ints, but prints them backwards if they are strings. You aren't allowed to use anything other than CLOS multimethods for type dispatch. In C++ this is super simple.
- eliben 11y agoWhy would you want to do that in Common Lisp? To be honest, I think folks imagine the wrong things when looking at CLOS. They think it's Lisp foray into statically-typed OOP like C++. But it isn't. Lisp stays dynamically typed. The task you're proposing is nonsensical "in CLOS". It's just not Lisp-y :-) I think this discussion has gotten fairly far from the main point by now. There's no real use trying to twist one language to achieve every feature of another.
- junke 11y agoLisp has a rich type system and there is no conceptual problem in having both static analysis and dynamic checks. What happens, especially with classes, is that you cannot guarantee that your type hierarchy will not be altered at the time you invoke your generic method (highly dynamic classes are a feature too). But since your whole language is available at compilation time, there is nothing preventing you to define a DSL for a subset of types that are fixed. You could even use compiler macros to deal with trivial cases. Then, you add enough "(declaim (type ...))" directives in your language and augment the optimization settings to allow your implementation to trust declarations without adding dynamic checks. If you need to have access to more type informations, use the implementation-specific tools to walk your code and define custom transformations (http://www.pvk.ca/Blog/2014/08/16/how-to-define-new-intrinsics-in-sbcl/ http://www.pvk.ca/Blog/2014/08/16/how-to-define-new-intrinsi...) when generating assembly. The only thing that prevents doing the same work than in C++ is that by default, you can redefine your class hierarchy at runtime: your server is running, you change your class definition and instances of that class have, for example, a new slot, properly initialized. Or, you change the class of your object (square -> rectangle).
- catnaroek 11y ago> What happens, especially with classes, is that you cannot guarantee that your type hierarchy will not be altered at the time you invoke your generic method (highly dynamic classes are a feature too). In other words, the type system is unsound. Which is exactly as useful as having no type system at all. But, anyway, what I asked for is (0) types parameterized by other types [e.g. "dictionary mapping ints to strings"] and (1) dispatch [e.g ither static or dynamic] on parameterized types. How would you solve this challenge? https://news.ycombinator.com/item?id=11592693 https://news.ycombinator.com/item?id=11592693