(I’d love to be credibly told I’m completely wrong, because syntax aside, which I could get used to eventually, I rather like the model of Lisps and some of the features that supports.)
(I’d love to be credibly told I’m completely wrong, because syntax aside, which I could get used to eventually, I rather like the model of Lisps and some of the features that supports.)
There was a systems type of Lisp called PreScheme that was closer to what you're envisioning. Carp also aims at no-GC, real-time use. Finally, ZL was C/C++ implemented in Scheme with both their advantages compiled to C. Although done for ABI research, I've always encouraged something like that to be done for production use with tools to automatically make C and C++ library bindings.
https://en.wikipedia.org/wiki/Scheme_48
Tribe 1: You are a poet and a mathematician. Programming is your poetry
Tribe 2: You are a hacker. You make hardware dance to your tune
Tribe 3: You are a maker. You build things for people to use
alfiedotwtf falls in the first tribe. You fall in the 2nd. Different tribes have different values, and hence all the back and forth.I've always strived to write beautiful code - for things people find very useful - in ways that push boundaries for what people think is possible with the machines we use.
I have succeeded in balancing any two of the above, to terrible detriment of the third. Never been able to juggle the 3 at the same time and this bothers me a lot. The upside is this pushes me to learn a lot, downside is I'm never content with my craft.
I'd have loved to solve domain specific important problems with a domain specific language I craft with a LISP and have state of the art performance while doing so.
Programming is my poetry. Damn... that's a nice take
http://www.call-with-current-continuation.org/bones/
README: http://www.call-with-current-continuation.org/bones/bones.ht...
If Rust had the same features as most LISPs have, then using these features would make Rust programs as "slow" as LISP programs. That is generally true for most programming language comparisons. What also matters for final executable speed is the toolchain, of course. Any languages that compile directly using GCC or LLVM and allows for compile-time typing will be roughly in the same ballpark. If they use their own compiler, such as Chez or Racket, then they usually don't match the performance, because there is not enough manpower in their teams to implement all those nifty optimizations GCC and LLVM have. SBCL is probably the fastest LISP with its own compiler. (Or Allegro?)
To give an example, here are some CommonLisp features that Rust lacks: Full object system with inheritance and multiple dynamic dispatch, dynamic typing, hot runtime code reloading/recompilation, garbage collection.
According to "TechEmpower Web Framework Benchmarks" (which might not be perfect but at least give some indication), Clojure is one of the fastest language (in terms of handling responses per second) for building a JSON API with. Take a look at https://metosin.github.io/reitit/performance.html
1. https://www.techempower.com/benchmarks/#section=data-r18&hw=...
I mentioned resource usage, and that includes memory usage. The JVM can be surprisingly fast for some types of code, but it’s never a memory lightweight.
I suppose I might as well mention another feature I value: ease of deployment. In Rust, I can produce a single statically-linked binary which I can drop on a server, or on users’ machines, or whatever as appropriate, and run it. For anything on the JVM… yeah, without extremely good cause I will consider dependency on the JVM to be a blocker, especially for a consumer product.
Startup you can measure, but the optimal tuning for faster general operation may start up slower, so now you might want both figures. And then you’re getting perilously close to development considerations, so once you’re doing that surely you should benchmark any required compilation, and so on.
Warmup is even harder to handle well, because it introduces another dimension; even if you were presenting just a single-dimensional figure (which you’re not quite), you’re now wanting to consider how that varies over time while warming up, so now it’s at least two-dimensional. But unless warmup takes ages, you’ll find it hard to get statistically significant figures, because you have so many fewer samples in each time slice.
Total installed size? Problematic because the number isn’t meaningfully comparable, as this is a minimal test, and a number in that scope gives no indication of how much is due to the environment (e.g. JRE, CPython, &c.), and how much further growth there will be as you add more features. People will also start arguing about what should count; if for example you count the delta from a given base OS installation, then you’re providing an advantage to something that uses the system version of, say, Python, and penalising something that requires a different and extra version of Python.
Memory usage? Suppose you pick two figures: peak memory usage, and idle memory usage after the tests. Both are easy to measure, but neither is particularly useful. Idle memory usage, similar problem to disk usage, and so the numbers aren’t usefully comparable. Peak memory usage is perhaps surprisingly the more useless of the two, because the increase in memory usage is strongly correlated with how many requests are being served at once—and so a slower contestant might artificially use less memory than a faster one; and so if you wanted those numbers to be comparable, you’d need to throttle requests to the lowest common denominator, which could then be argued as penalising light memory usage patterns.
Nowadays you can either chose a Lisp that does compile to a single binary and doesn't require the JVM (like SBCL or something like that), or you could use Clojure but use GraalVM to get the single binary.
Anyways, I agree with your general point, Rust being in general faster. But I don't agree with the whole "Lisps are just generally slower and use more resources" thing, while it's certainly true in some conditions.
So, there's a Lisp on top of Lua―compiled, not interpreted: https://fennel-lang.org
It's deliberately feature-poor, just like Lua: you use libraries for everything aside simple functions and loops. And it suffers somewhat from double unpopularity of Lua and Lisp. But it works fine.
Sure, flag me, but my comment was relevant to the discussion.
There are Common Lisp implementations of both Python and Javascript (ES3) that compile to Common Lisp and then the Common Lisp compiles to machine code: as I said before, whether or not a language is interpreted or compiled is an implementation detail, not part of its spec.
I chose this based off a random search on google of "scripting language." You can do the same and would get the same result.
It's not a rigorous term, because (you are right) its a property of the implementation not the language itself, despite the name.
But I don't think Julia has relevance to discussion of the speeds of interpreted Lisp.
Basically a scripting language interpreter runs source code files, called scripts.
Lisp does that, too. But many Lisp implementations compile the code and often to machine code, since the runtime includes an incremental compiler. The incremental compiler can compile individual expressions to memory.
Thus when you use a Lisp system, running a script just looks like running an interpreter, even though the code gets compiled incrementally.
Lisp uses the function LOAD, which can load a textual source file and which can then read, compile, execute expressions from the file. Typically this is also available via command line arguments.
Like in SBCL one can do:
sbcl --script foo.lisp
and it will read/compile/execute expression by expression from a textual source code file, actually incrementally compiling each expression to machine code.I don't think this is correct. Scripting aren't rigorously defined, of course, but it would be reasonable to say they are defined by practice (i.e. a scripting language is practical for scripting).
Most compiled languages knock themselves out of contention in this definition because the startup and/or compile times are too long to be practical. But I've used luaJit in scripting contexts before, so that at least muddies the waters. Also common lisp (a variant that was always compiled).
I've always understood it to mean interpreted and from a quick google search there are at least a sizeable number of people who agree.
I think now that there are a lot of high level compiled languages, it makes less sense.
It's about as "compiled" as Luajit is.
I will not finish ... I suck at lisp. But it works.
I totally get you with Lisps and performance, but I was more talking about the beauty and elegance of code written in them. Algorithms written in Lisps seem to be pieces of art.
And that's just Lisps... having a look at logic programming languages like Prolog and Mercury, it's amazing to see just how compact yet understandable an algorithm can be. They're beautiful!
But as for performance, take a look at Mercury - its a declarative logic programming language with built in constraint solving, which compiles down to C, and its performance is great. We've rewritten some Mercury in Rust, and yes our Rust is faster, but not by orders of magnitude as you'd think.
You can read it online for free, and clone the github examples repo.
Lisp is for the other 99.5% of programming that doesn't require you to wring every last drop of performance out of your CPU.
Some languages are easier to be made faster, but I think JS almost proves there’s no such thing as a language incompatible with high performance by design.
You’d be hard pressed to conceive a more dynamic language and here we are, with crazy fast performance through many JIT tiers, interpreters, compilers, each of which would take years for a bright engineer to understand.
I’ve read the latest version of the specs of all these languages in detail.
I’ve worked professionally on a team implementing Ruby, the latest version of JavaScript, and Java at the same time, using the same language implementation system, so I can directly compare.
JavaScript is simplest by far. There’s quite a lot of sugar now, but the core semantics are small and simple. The core semantics of a language like Ruby are an order of magnitude more complicated.
I just find your question a little confusing. My house is only two floors, yet meets all my needs. A bigger house would just waste my time in cleaning, cost me more in maintaining, in heating, etc.
It's the same for programs. Target performance at all cost, and for a lot of programs you get a hard to maintain, non scalable, bug ridden, featureless program that took you way too long to build.
That's why for example I use Clojure and Rust. Rust gets the least use, because the programs I tend to write can manage fine with Clojure's performance. In fact, I mostly toy with Rust, because I really never needed to write anything higher performance.
So I'm just not sure what you mean. The world is full of useful programs that meets the needs of their users which aren't high performance. For all these programs, Lisp is a superpower.
- how to make lisp go faster than C: https://www.reddit.com/r/lisp/comments/1udu69/how_to_make_li...
- https://github.com/marcoheisig/Petalisp "Petalisp is an attempt to generate high performance code for parallel computers by JIT-compiling array definitions. It is not a full blown programming language, but rather a carefully crafted extension of Common Lisp that allows for extreme optimization and parallelization."
Might answer your question [0]
On https://benchmarksgame-team.pages.debian.net/benchmarksgame/... at present, the fastest SBCL implementation, which seems to include these optimisations, is at 2.0, with other SBCL implementations being slower, the first one (whatever that means) being 8.0; meanwhile, the Rust implementations range between 1.0 and 1.2. The SBCL implementations all use at least eight times as much memory as the Rust implementations, too.
I think this demonstrates my point pretty well, actually.
I fail to see the reason for you presenting the facts in this manner especially the "stupidly dangerous things part" which is of course totally inaccurate. (safety 0) has its uses (e.g. like Rust unsafe).
Your conclusions are not indicative of real world performance.
What exactly is it designed to attract attention to?
> … should not be taken seriously.
Because?
> … fully memory safe.
Here's the problem, the programs are explicitly required to use function calls but:
;; * redefine eval-A as a macro
By whom?
Maybe there are situations for which it is "realistic" — the point is that we don't know.
What would actually be suitable for comparing language performance?
No, that isn't required.
On the contrary SBCL is quite insistent that the arithmetic be made safe.
I'm not even a Lisp newbie, but with help from SO I've been able to tweak those spectral-norm programs to make the SBCL compiler happy without destroying the performance:
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...