Quote:
Original post by Nathan Baum
Quote:
Original post by jdh30
Quote:
Original post by flangazor
What have we learned here?
I think Lisp should be evaluated in the context of modern, high-level programming languages like ML, rather than comparing it to C++.
I'd compare it to modern, high-level programming languages like Java, or Python.
Python makes me cringe. I'd probably prefer Lisp to Java because it is roughly as fast but more expressive, and probably not much more verbose.
Quote:
Quote:
However, Lisp does not statically check code as much as languages like ML and Haskell,
Of course that's neither true nor false. Languages don't check anything; implementations do. Some implementations of Lisp perform more checking than others.
The best you can say is that ML requires ML implementations to perform more static type checking than Common Lisp. That's true, but it also imposes limitations.
Yes. In the case of OCaml, the implementation implicitly defines the language.
Quote:
The relaxed attitude of the Lisp standard towards compile-time checking allows simple implementations to remain simple, but also allows for efficiency-oriented implementations to provide comprehensive static checks.
Unfortunately, it is so difficult for a Lisp compiler to optimise Lisp code to be as fast as many other languages that none of the free Lisp compilers are capable of doing that.
Stalin can do it for Scheme code. However, it takes 1,000x longer to compile than ocamlopt.
Quote:
Additionally, some of the checks that ML performs don't make sense from the perspective of Lisp. Many 'type errors' that ML detects simply aren't errors in Lisp.
Yes. Static type checking is definitely a trade-off.
Quote:
Quote:
it is harder to optimise,
I don't know about that.
I'm a Lisp novice who knows next-to-nothing about raytracing or writing efficient Lisp code (or writing efficient code in general for that matter), and I optimised the ray tracer in several hours spread over just over a week.
I think we should "compare time spent to optimise the code to run at a given speed". I can well believe that it is just as easy to apply any given optimisation to Lisp code as it is to any other program. Indeed, it is probably easier thanks to macros.
However, people optimise code to make it run fast enough. So we need to compare the performances of the different implementations.
First working Lisp implementations were 10-100x slower than my first working OCaml implementation.
I applied a few low-level optimisations to the OCaml to get it into its current state. I manually unboxed a sphere type, inlining "vec * float" into the variant type constructors "Sphere" and "Group". I used records instead of 3-tuples to represent vectors as I know ocamlopt will unbox float records but not tuples.
Of the Lisp implementations, only 2 (both Juho Snellman's, one of the authors of the SBCL compiler) are faster than my first OCaml on either of my machines.
Given that only a compiler writer has been able to write a Lisp implementation as fast as the (basically unoptimised) OCaml, I'd say it is a lot harder to optimise Lisp to achieve a given speed than it is to optimise OCaml.
Quote:
And the final optimisations that actually had an effect (inlining and using scratch variables) are simple rule-of-thumb optimisations which, had I any formal training in Lisp, I would certainly already have known about.
I've made similar optimisations to the OCaml and it can be made a lot faster as well.
Quote:
Quote:
arguably harder to read
It's only harder to read for someone who finds ML easier to read. I find myself in the opposite situation.
Ok. Lisp has prefix operators but OCaml has separate "+" and "+." operators.
Quote:
Additionally, it's inarguably harder to modify ML's syntax if you find it doesn't intuitively fit the particular program you're trying to write.
True.
Quote:
Quote:
and it is considerably more verbose (particularly for code of comparable performance).
My final tracer has only 1.1 as many words in it as the equivalent OCaml tracer, and if I follow the same hideous code layout policy as you observed in your code, only 1.6 as many lines.
What about bytes?
Quote:
Furthermore, it is well known that Lisp's conciseness wins out for large programs.
I believe Lisp and OCaml both have this advantage over C. That doesn't make for a clear winner between Lisp and OCaml though.
Quote:
This is precisely because of macros. Functions compress certain expressions into (generally) far shorter expressions, without (usually) sacrificing clarity. Macros may be viewed as generalisations of this principle. They can be applied to a wider class of expressions. In particular, macros can be applied to factor out expressions which are dependent upon context.
Higher-order functions do that in OCaml. I don't know why Lisp programmers prefer macros to HOFs but I've heard that the vast majority of uses of macros are equivalent to HOFs.
Macros can do more than HOFs, of course. But I'd bet you write functions vastly more often than you define new syntaxes.
The only data point I have for long Lisp vs OCaml programs is a pair of Mathematica implementations.
Richard Fateman wrote a Mathematica implementation (MockMMA) in 20kLOC of Lisp. It was roughly 10x less code and 10x faster than the real Mathematica.
I wrote one in OCaml. The first working version (a simple interpreter) was only 800LOC but it was 5x slower than the real Mathematica. I then wrote a 2kLOC JIT compiler than is 600x faster than the real Mathematica.
The functionality of my code is roughly the same as that of Richards but mine is 10x shorter (in lines) and vastly faster.
So I see no evidence that Lisp is asymptotically more concise than OCaml, as you imply.