7 ms·
That's why I like Clojure's philosophy of a few data structures and many functions operating on them. Of course Alan Perlis wrote "It is better to have 100 fun
by Bizarro 9y ago
That's why I like Clojure's philosophy of a few data structures and many functions operating on them.
Of course Alan Perlis wrote "It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures." in 1982.
But pipelining outputs into inputs (you'll see it a lot in F# too) is just a simple, flexible concept.
As Rich Hickey once said, "We're data processors".
I think we somehow took a wrong path when OO got embraced as wholly as it did back in the 90s or so.
- stochastic_monk 9y agoSimilarly, I like Python and C++’s emphasis on duck-typing. I use STL containers often, and provide similar interfaces to my custom data structures for flexible, general, fast code.
- jonathanyc 9y agoI wish there were tools to auto generate documentation on what interface a duck-typed consumer expects, e.g. what std::vector<T> expects of T.
- stochastic_monk 9y agoWell, C++17 concepts enforce requirements, but hopefully metaclasses will do more in 20.
- bstamour 9y agoConcepts are also C++20. They were voted in, however, shortly after 17 shipped.
- stochastic_monk 9y agoGood point. I was thinking of the rudimentary, template-based use of concepts, not the polished, C++20 version.
- bstamour 9y agoAh gotcha. Yes in the current situation we can do nearly everything that the concepts proposal for C++20 does with enable_if, void_t, and a few other helpers. Though concepts have the benefit of letting you "say what you mean", instead of relying on template magic.
- orf 9y agoThis should be more than possible with Pythons type annotations, when done right. I.e 'iterable[str]' can accept a generator, list, tuple, any class with the right __iter__ and of course a string itself.
- wirrbel 9y agoThis is what I like about Rust and Rust's traits. You write a generic and specify the properties of the generic type parameter, for example that it must implement another trait or something.
- simonbyrne 9y ago> I think we somehow took a wrong path when OO got embraced as wholly as it did back in the 90s or so. I think the particular paradigm that was adopted by C++, Java, etc. was a bad one. Having now worked quite a lot in a language with multiple dispatch (Julia), I find it really cumbersome to work in class-based single dispatch languages.
- ZephyrP 9y agoMultiple (virtual) dispatch is a central feature of C++ (and I suspect Java as well).
- groovy2shoes 9y agoVirtual dispatch in C++ and Java is dynamic dispatch, but it is singly so rather than multiply so as found in CLOS, Dylan, Julia, etc. If you want multiple dispatch in C++ and its kin, you need to jump through hoops with visitor patterns and such.
- foota 9y agoThe difference confused me for a bit, but consider the following: Print(Vehicle v){ print("vehicle"); } Print(Car c){ print("car"); } Print(Boat b){ print("boat"); } Vehicle test = Boat(); Print(test); In a language with multi dispatch I believe this prints boat, whereas with single dispatch it prints vehicle.
- lmitchell 9y agoNot quite. Multiple dispatch (as mentioned in sibling comments) is basically 'virtual on both object and argument types', so like: class Vehicle { virtual void Collide(Vehicle other); } class Car { void Collide(Truck other) { /* hit a truck */ } void Collide(Car other) { /* hit another car */ } } class Truck { void Collide(Truck other) { /* hit another truck */ } void Collide(Car other) { /* hit a car */ } } Vehicle c = Car(); Vehicle t = Truck(); c.Collide(t); // with multiple dispatch, calls Car::Collide(Truck)
- skybrian 9y agoIf you want to avoid OO you'll also want to avoid treating functions as first-class values. As soon as you have structs that contain functions, you can build OO.
- deleted 9y ago[deleted]
- skybrian 9y agoSince I'm getting downvoted: Folks, this is Chapter 3 of Structure and Interpretation of Computer Programming. Technically you don't even need a struct; closures and mutability will do. And how do you serialize data that function pointers in it?
- HumanDrivenDev 9y agoI am almost positive Rich Hickey hasn't read that book. The only thing more stunning than his ignorance when he talks about OO is the amount of young programmers who believe everything he says. It blew my mind when I realised I could write objects from scratch in languages with closures, even statically typed ones! Of course each object has its own v-table in the SICP code, so probably not something you should use in production.
- pjmlp 9y agoI always find ironic when such young devs bash OOP, given that Clojure has protocols and multi-methods. Or bashing Java and the JVM, without which Clojure would not exist in first place.
- coldtea 9y agoYou're not downvoted because people ignore that fact. You are downvoted because people disagree that it's important. Yes, you can create objects with closures, but when people talk against OO programming, they mean the paradigm, not merely the possibility that a language can do objects. Forth and C can do object oriented programming just fine too, if one is so inclined.
- sharpercoder 9y agoMaintaining state and mutating state is useful and neatly done in OO. That is, when done right, which is hard. I certainly agree that for processing data, good functional languages reign supreme. They are usually terser while more expressive. It seems that solving problems need their own tool. Compilers typically fit a data processing pipeline. Yet, a use case such as editing an AST (e.g. a text editor showing incomplete syntax state) probably could better use OO as a tool. Most current software then simply uses the wrong tool for the job; they do data processing with OO, and state representation and mutation using functional pure idioms. A problem that is not yet solved very well in the industry is interplay with these idioms. .NET with C# and F# comes to mind, which allows for easy workflows leveraging both OO and functional.
- agumonkey 9y agoThe "best" design in stateful parts of systems has yet to come to my eyes. IMO FP gives you better foundations to start stateless then see where you can group things into private mutable memory. Not that I know how to do it but at least I can reason instead of invoking innate black art or long experience.
- mbrodersen 9y ago> Maintaining state and mutating state is useful and neatly done in OO I started laughing when I read "neatly done". I assume you don't mind long range state mutating effects making your code a lot more complex to reason about than it needs to be. Or the "grab a banana and you grab the whole planet" dependency issues OO almost inevitably introduce. Or ... (I could go on). OO with mutable state is anti-modular.
- marcosdumay 9y agoI remember my undergrad classes where the types of software engineering diagrams were presented. There were some very informative useful data transformation diagrams that were just glossed over in order to reach the useless UML shit. I took a very important lesson from those classes, but not the one the professor was trying to explain.
- mbrodersen 9y ago> That's why I like Clojure's philosophy of a few data structures and many functions operating on them. Which in practice means that a few data structures that are not perfect for solving a specific problem are forced (with repeated hammer blows) to bend to the problem. Like the old style LISP AList's used as a map. Probably the worst possible structure for representing a map. But yeah it kinda works as long as you don't have much data.
- lispm 9y ago> Probably the worst possible structure for representing a map. Not really. But native hashtables had been added to Lisp in the 70s...
- kazinator 9y agoUnder the right circumstances, a lookup table could be worse. In a simple interpreter, I would hate to pass down a vector of pairs for the environment representation; it would have to be wholly duplicated to extend the environment.
- kbp 9y ago> AList's used as a map. Probably the worst possible structure for representing a map. They're more flexible than hash tables and often faster; what makes them so awful? They both have trade-offs that make them better and worse in different contexts, depending what you're optimising for.
- kazinator 9y agoThe assocation list is a poor data structure for representing a map, if the most important requirement is to have fast access to any key of a large map. However, the association list is an excellent data structure if an important requirement is to be able to cheaply extend a map with new keys functionally: without altering the original. It also provides the requirement that duplicate keys added to the front shadow existing ones. It is also very simple; it is easy to verify that operations are correct. With the above properties, association lists, directly provide an easy and correct implementation model for lexical environments. The empty top-level lexical environment is an empty list. Adding a frame with new variables, including ones that shadow existing variables, is just consing pairs onto the list. The assoc operation correctly implements lexical variable lookup. The environment for making a lexical closure is just a copy of the assoc list pointer that you have now. Because the bindings are independent pair objects in the association list, individual bindings can be located and selected, and combined into another association list. A newly created association list environment can trivially capture an arbitrary subset of bindings from another one without mutating it. Even if we don't use this representation in production use, it provides an important reference model. Anything more complicated has to produce the same results; we can start with assoc based environments, build a lot of code, and then use that as regression test cases for going to a different environment representation. It's good enough for pattern matching and logic languages where the number of variables isn't great, but the search has to do things that are complicated enough without a heavy-weight environment structure.
- kazinator 9y agoIt's worth reading all of those Perlis' epigrams: 103. Purely applicative languages are poorly applicable. Give me a hundred functions on one data structure, but make thirteen of them useful mutators. :)