3 ms·
Yes, but that's a dynamically typed language and everything changes when comparing it. There are so many tradeoffs. Clojure is quite quick to write and time to
by hellofunk 10y ago
Yes, but that's a dynamically typed language and everything changes when comparing it. There are so many tradeoffs.
Clojure is quite quick to write and time to market can be very fast, as with most lisps, but you pay the price at debug time. We recently shipped a production app that had a small typo that the compiler would have easily caught, but instead it crashed the site when this one particular task was run.
- kazinator 10y agoYour experience with Clojure might not in fact generalize to "most lisps", which have very good compilers that catch all kinds of errors. Certainly the "low hanging fruit" ones like references to unbound variables or functions and such. What was the typo? > it crashed the site when this one particular task was run. Might that also be because that was the first time the task was run at all, since the code was written or altered? Code that compiles (such that we are confident it is probably free of silly typos, other than those somewhat rare typos which play out in some way that still compiles), might not be correct; it still requires testing.
- hellofunk 10y agoThe typo had to do with accidentally naming a variable in a let binding to the same name as a built-in function. It happily compiled but when that code actually ran in one particular use-case, it crashed due to the way the binding and the scoping worked in that case.
- kazinator 10y ago> accidentally naming a variable in a let binding to the same name as a built-in function. Not even a problem in a Lisp-2 like ANSI CL! (let ((list '(1 2))) (list list list)) -> ((1 2) (1 2)) Facepalm. We could argue you were burned by the stupid Lisp-1 namespacing. Under the separate function and variable namespace of a Lisp-2, you would have to bind a local function in order to shadow a global one. Even without a compiler, we can implement a warning for this. The code walker which expands macros is aware of lexical environments and can issue diagnostics when suspicious-looking shadowing is going on, or unbound variables are referenced and such. Not only is this not the fault of the language being dynamic, but the problem could exist in a static language, like, oh, C: #define DECLARE_MY_PRINTF int (*printf)(const char *, ...) = my_printf; { DECLARE_MY_PRINTF: printf("hello, %s\n", "world"); // goes to my_printf via shadowing local var } ISO C does not require a diagnostic for this. Gcc has -Wshadow. ISTR -Wshadow is not turned on by -Wall or -Wextra; you have to use it explicitly. Of course, the above depends on the local printf pointer actually having the right type so that the call is well-formed. If we just have "int printf" or whatever, the type system will catch it.