5 ms·
This is probably going to be unpopular: My main problem with most functional languages is that they encourage cryptic code. From the tutorials I've read Lisp s
by emsy 13y ago
This is probably going to be unpopular:
My main problem with most functional languages is that they encourage cryptic code.
From the tutorials I've read Lisp seemed somewhat readable, but the tutorials encouraged me to use list comprehension all over the place because it's so convenient. I need to decrypt all the map zip range calls in order to grasp what's happening. Disclaimer: I don't know if Lisp is used like this in a productive environment.
Haskell is often described as "elegant" (Here for instance: http://www.haskell.org/haskellwiki/Why_Haskell_matters#Elegance http://www.haskell.org/haskellwiki/Why_Haskell_matters#Elega...). To me, the examples are far from elegant. They just prove how much functionality one can cramp into an operator. But if I have to decrypt code in order to understand it then the language does it wrong. Math works like that and I never understood why they called variables "x" instead of "potatoes" or "time". It's simply non-descriptive.
I don't know if you can write code that is as descriptive as code from an imperative language, but the FP community doesn't encourage it either.
- throwaway8972d9 13y agoUser-defined, powerful operators are the most important feature that make programming in Haskell feel so foreign. Yet, since they often require the programmer to sort of grasp a model of the thing the program is trying to accomplish, once you understand the operators (e.g. parser combinators) you have a rather deep understanding of the foundation for this particular program and the rest of the code is expressed very concisely and (sometimes) reasoned about easily. Regarding the short variable names in math: They are supposed to be written and, more importantly, manipulated by hand and so short notation is very important.
- emsy 13y agoThis reply goes to axman6 as well: I for one, write code under the assumption that the reader will have to decrypt it in order to understand it. Therefore I postpone implementation details until the very end. This leads to code that outlines the logic in a fairly readable manner. Of course the implementation details are still code, but at that point there is so little code that you will understand it in no time. The Haskell examples of elegance I've seen so far seem to cramp so much responsibilities in so little code, yet nobody seems to bother about the Single Responsibility Principle. I like operator overloading, but I use them for implementation details, not to keep the number of lines small. The downside is that I have a deeply nested programming structure, which can be unfamiliar for people who churn out 500 lines of bare implementation details in one function. My criticism towards math goes further than variable naming. The language of math is non-descriptive and anyone accepts it with the reasons that: a) That's how it's always been. b) It's short and once you get used to it it's easy. But this just keeps people who struggle with the language of math to embrace and love mathematics. I don't say I have a better solution, but I say that we can get in programming right what's wrong in math: a descriptive language with a low entrance barrier.
- axman6 13y agoWhy "x"? It's idiomatic, like using T for a type in C++ templates, argc and argv for the inputs to main in C, making the second returned value in a Go function the error and calling it err and not error or e or er or failed, using the type "t" in OCaml to specify "the" type a particular module is defining (I think...), or anything else. X, y and z in maths are idiomatic; there's no good reason they're used instead of a, b, c, or LR, UD, FB (left-right, up-down, front-back) for coordinates except that that's what people are used to, and sticking to the convention makes code/equations easier to follow because your brain is used to seeing x used a certain way, so you don't need to keep checking to see what it is when you see it in longer code/equations. Many haskell functions operating on lists are described in terms of the first element "x" and the rest of the elements xs (exes or "the rest of the x's"). It's a common convention used because we have no idea what x might be, all we know is that, in this case, elements of the type that x is can be ordered. This means that one function works on lists of numbers, letters, string, lists of numbers, booleans, etc. Basically terse names like that are used because many haskell functions are very general. We could have decided on (hd:tl) or something, but there's something nice about stating that there is one value x and some values which are also x's. You have to remember these are not features of the language, they are the idiomatic styles that are built up by the users of the language. Haskell's community encourages writing short code which is clear once you understand whatever abstractions are being used (Applicatives, Monads, lists, curried functions, type classes and so on). This is in some ways the essence of programming, building abstraction upon abstraction to make beautiful, "obviously correct" code. Haskell allows very (cognitively and syntactically) cheap abstraction, so they're used everywhere. You complained about having to "decrypt code" in order to understand it, but this is true of any language; you may understand the keywords and how to put things together, but you won't get far if you can't get used to the idioms and conventions used by others using the language.
- nostrademons 13y agomap/zip/range isn't cryptic once you get used to it. You start thinking them as additional CS concepts, which you just apply in one "chunk" to problems. This is working-as-intended: it's you learning how to think at a higher level so that you can solve more complicated problems quickly. Once you've done this you can actually "back port" this knowledge to traditional programming languages: I often think of Java or C code in terms of "Oh, this is a map" or "this is a fold over a tree traversal". There are a bunch of other, legit readability problems with typical Haskell style: the fetish on single-character variable names is just nuts (it comes from math, where it's customary because mathematics culture arose before computers and autocomplete), and once you get into point-free style, combinator libraries, and monads/arrows things really get nuts. In general I've found that abstractions should only be used when they're re-used frequently, so you can internalize them, and Haskell tends to encourage rather overzealous abstracting. But map/zip/range show up all the time in typical industrial programming, and learning how to think of it as a unit frees up brainpower to think about higher-level algorithms.
- pekk 13y agoAfter people learn something they don't find it entirely cryptic any more, but that doesn't mean it isn't cryptic. No evidence that using map instead of loops "frees up brainpower."
- porlw 13y agoThere are many common operations in programming, and it's worthwhile building a consistent syntax for them. Over time, as one layer of abstraction solidifies it's possible to see common patterns at the next level up. It saves brainpower because you you don't need to analyse the logic within the structure to understand what the operation is intended to produce. E.g. in the old days: 10 I=1 20 PRINT A[I] 30 I=I+1 40 IF I <= 10 THEN GOTO 20 You need to parse the logic to realise "Ah, this is a for loop". The I variable and the IF statement are bookkeeping code that doesn't have any relevance to the actual effect you're trying to produce. This construct is common enough that the for-loop was developed. Likewise with the if/else construct and others. The old fogeys would say "we don't need this structured programming nonsense, gotos are more flexible. I can easily look at this and understand what's going on". Structured programming is now widespread enough that we don't think of it as anything special, it's just part of "programming" in general. Now there are several common operations that we do when looping over a list of items. Things like maps, folds and gathers are just building another level on top of structured programming, hiding the bookkeeping code and making similar operation similar, so you can concentrate on the unique aspects of the program.
- a-saleh 13y agoYou get used to it, more or less. It is similar to naming your variables i,j,m,n,x,y, or using bash | or > or >> ... you get used to, that in haskell x:xs refers to head and tail of a list.
- mmaldacker 13y agoMathematicians use x for variables simply because it's faster to write. This is less an issue when typing on a keyboard.