4 ms·
> Using "let" for this in Clojure results in nested and realatively less readable code. Why would you have to have nested code? Why can't you just do this:
by jhuni 14y ago
> Using "let" for this in Clojure results in nested and realatively less readable code.
Why would you have to have nested code? Why can't you just do this:
(let [a foo, b bar, c (combine foo bar)])
> Are macros such a nice feature that they justify S-expressions?
I'd say S-expressions are the nicest looking syntax, which justifies them regardless of their considerable practical advantages. The only reason you might think that need to be "justified" is that you are still to used to C syntax. Try using S-expressions for a few years first to get used to them.
> When working on non-trivial projects, I find static typing and OOP really useful.
Again, I think you are just used to mainstream static OOP languages like Java and C++. If you try Clojure for long enough you can get used to its way of programming, which is arguably nicer then the mainstream static OOP way.
- RivieraKid 14y agoWhat I meant was this: (let [x (math/sqrt (+ 256 (* a a))) y (math/log (- (+ a b) (/ 1 (+ a (* b b b))))] (* 2 (+ x y))) In other languages I would do something like this: x = math/sqrt(256 + a * a) y = math/log((a + b) - (1 / (a + (b * b * b)))) 2 * (x + y) As for static typing - in combination with IDE support, it's really useful in larger projects.
- saurik 14y agoI made a reader macro (not technically supported by Clojure, but I don't care) for these situations that provides something I call the "scoping operator". #>a 6 #>(let [b 7]) #>(while true) ... Using this operator, the above code is then equivalent to the below code, which I find much easier to deal with for code that is strictly linear in execution semantics. (let [a 6] (let [b 7] (while true ...))) I don't use it for most functions, however, only those where I find myself otherwise ending up in nested expression hell. When I do, however, it works perfectly with other language features (example: doing a syntax quote on a #> works exactly as one would hope; it is conceptually just a fancy macro). (...and where breaking up the logic into smaller functions would just obfuscate the process, as the steps fundamentally could only be called from a single place anyway, turning the nesting into an even-worse problem of broken apart logic.)
- jhuni 14y agoIn the C-based languages that you apparently familiar with there are several control statements that aren't expressions like for, if, while, and do. For example, here is how you can use the if statement in C: if (a >= 0) { printf("Positive"); } else { printf("Negative"); } The if control statement in C can only be used to induce side effects, such as printing to stdout, it can not be used for functional programming. On the other hand, Lisp is an expression oriented language, so expressions such as if can be used as values for functional programming: (if (<= 0 a) "Positive" "Negative") The same principle applies to the let statement. It is an expression so that you can use it without ever resorting to creating mutable state or inducing side effects. If you allow emacs to automatically handle the nesting involved with your statements, then there it shouldn't really be an inconvience. However, when you need global mutable state use def: (def x (Math/sqrt (+ 256 (* a a))) (def y (Math/log (- (+ a b) (/ 1 (+ (* b b b)))) (prn (* 2 (+ x y))) Clojure encourages good practices like avoiding local mutable state. That said, if you want to you can always create your own local environment to declare local mutable state: (defmacro defun [name args & code] `(defn ~name ~args (with-local-vars [~(symbol 'e) {}] (let [~(symbol 'def*!) (fn [p# v#] (var-set ~(symbol 'e) (assoc (deref ~(symbol 'e)) p# v#)))] ~@code)))) Here is an example of code like yours using this macro and a local environment called e: (defun func [] (def*! 'x (Math/sqrt (+ 256 (* a a)))) (def*! 'y (Math/log (- (+ a b) (/ (+ a (* b b b)))))) (* 2 (+ (@e 'x) (@e 'y)))) You could probably make that look nicer using macrolet and by definining other new macros and operations.