5 ms·
> By "functions" here I mean "pure functions". After programming for Clojure for quite a long time (~2 years), I fully share this sentiment. Using pure functio
by m45t3r 6y ago
> By "functions" here I mean "pure functions".
After programming for Clojure for quite a long time (~2 years), I fully share this sentiment. Using pure functions for business logic (and also using simple data structures instead of, say, classes and encapsulation) seems to generally makes the code more simple and maintainable in the long run.
> Of course the qualifier is "mostly": this isn't a dogma. Writing a 100% functional system ("going vegan", if you will) often requires you to jump through a bunch of extra hoops to get all the functionality you need.
Also this. Sometimes going fully functional makes things much more difficult, so a little of "impurity" is also fine.
- eyelidlessness 6y agoI used Clojure (and ClojureScript) in production for several years, and more or less share your sentiments on this. The only strong objection I have is that the lack of types made even simple data structures an occasional nightmare. Especially when most of the composite types can easily be substituted for many functions, it’s trivial to accidentally recurse a string or a keyword where a data structure should be. And the runtime errors (especially in cljs) can be utterly baffling. I’ve taken what I learned in clojure (and I can just say the article, even just its title, adequately sum it up) and use the same approach in TypeScript. And it’s a breath of fresh air.
- m45t3r 6y agoI didn't say anything about types, but we use plumatic/schema as a "type system". It is not ideal (for once, it is checked at runtime instead of build time, so we only check types during tests and requests, otherwise the impact would be too great). It is not ideal, but it works and keeps our sanity.
- eyelidlessness 6y agoYeah something like that is essential in a dynamic language. To be honest though I don’t think I could go back to runtime-only type checking and having to write those tests where a compiler tests so much automatically.
- dragonwriter 6y ago> where a compiler tests so much automatically Compilers don't necessarily check anything. Static analysis tools (including static type checkers) check things, and some compilers also include static analysis tools. But static analysis tools are often available beyond whatever a compiler provides.
- fiddlerwoaroof 6y agoAnd, some compilers (sbcl) can do fairly sophisticated static analysis on dynamically typed code.
- eyelidlessness 6y agoYes, you’re right. It’s often but not always the case that type checking and compilation are part of the same tool and flow. Thanks for adding that.
- nickbauman 6y agoHave you considered Clojure Protocols for this?
- eyelidlessness 6y agoI used them. But they’re still runtime-only.
- nightcracker 6y agoFor years now I've felt the same way about functional v.s. imperative programming, and where functional languages go 'wrong', and what they get right. There are exceptions of course, but I personally feel that there's three main 'kinds' of code: 1. functions that define some input/output relation 2. query methods on data structures 3. modification methods on data structures 4. the bodies of the above functions In a purely functional language all four are purely functional, but this is (IMO) needlessly restrictive. It leads to recursion where iteration is more natural, awkward choices of data structures or even plain impossibility of certain algorithms/data structures (ask a functional programming zealot to implement an O(1) hash map in a pure way—they will usually stammer, try to move goal posts, before finally admitting it's not possible). Personally I feel that 1 & 2 should be 'pure' and not modify (observable) data and have the same results, but 3 & 4 are perfectly fine if not natural to be imperative and have mutable state.
- nightcracker 6y ago(can't edit anymore but s/three/four/)
- m45t3r 6y ago> In a purely functional language all four are purely functional, but this is (IMO) needlessly restrictive. I concur. My two favorite languages nowadays (Elixir and Clojure) are far from being purely functional. They are functional enough that mutating state is awkward, but if you do need it it is there. I also think having immutable data structures by default is a saner choice IMO. > It leads to recursion where iteration is more natural, awkward choices of data structures or even plain impossibility of certain algorithms/data structures Anecdotal, but I rarely use recursion/for loops, opting for defining auxiliary functions that works in one element and using map/reduce instead. Really, I don't remember the last time I needed recursion to solve a problem (for example, I know recur exists in Clojure, but I never saw it in the code that I work everyday).
- nickbauman 6y agoI often write a loop recur that I will later turn into a map reduce as you say.