3 ms·
What 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
by RivieraKid 14y ago
What 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.