I've been hearing claims my entire programming career about how Lisp is supposedly "superior" to mainstream programming languages, but I've never seen a concise code example that actually demonstrates this. For instance, it's easy to demonstrate how Rust is superior to C: Just show a short piece of code where an array is returned from a function. In C, this will involve raw pointers and manual memory management with…
Considering Lisp was here first, shouldn't the real question be "why use Rust/C++/Python when there's Lisp?" You can't even create a real closure in Rust. I'd love to see 10 lines of Rust that showed me something that: 1. I can't easily do in Lisp. 2. Actually matters in practice.
#![allow(arithmetic_overflow)]
fn main() {
let x = 1073741823;
println!("x = {}", x*3);
}
# cargo build && cargo run
thread 'main' panicked at 'attempt to multiply with overflow', src/main.rs:4:24
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
To be fair, Rust is improving over time, as of I think last year you now have to explicitly have that first line to allow the overflow? This behavior is somewhat annoying to replicate in Lisp if you aren't familiar with type declarations and suppressing the debugger: (defun main ()
(let ((x 1073741823))
(declare (type (signed-byte 32) x))
(format t "x = ~a~%" (the (signed-byte 32) (* x 32)))))
(handler-case
(main)
(simple-type-error (e)
(format *error-output* "Panicking because of ~a~%" e)
(uiop:quit 1)))
# sbcl --script main.lisp
; file: /tmp/main.lisp
; in: DEFUN MAIN
; (THE (SIGNED-BYTE 32) (* X 32))
;
; caught WARNING:
; Derived type of (* COMMON-LISP-USER::X 32) is
; (VALUES (INTEGER 34359738336 34359738336) &OPTIONAL),
; conflicting with its asserted type
; (SIGNED-BYTE 32).
; See also:
; The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
; caught 1 WARNING condition
Panicking because of Value of (* X 32) in
(THE (SIGNED-BYTE 32) (* X 32))
is
34359738336,
not a
(SIGNED-BYTE 32).
A bit more work and you could muffle the compilation time warning too. As for how important this is, I'unno, personally I prefer to have my math Just Work by default -- (expt (expt 2 64) 64) or #I((2^^64)^^64) -- and I like by default being given the chance to fix things and continue/restart via the debugger rather than panic.