As far as I know, the CL spec hasn’t been updated for 30+ years, and most of its design is far older.
(defmethod join ((a String) (b String))
(concatenate 'String a b))
;; example: (join "abc" "def") => "abcdef"
(defmethod join ((a Integer) (b Integer))
(parse-integer (format nil "~D~D" a b)))
;; example: (join 123 456) => 123456
And rudimentary support for ADTs: (deftype Low-Score ()
'(Integer 0 20))
(deftype Normal-Score ()
'(Integer 21 79))
(deftype High-Score ()
'(Integer 80 100))
(deftype Score ()
'(or Low-Score Normal-Score High-Score))
(But note that deftypes aren't allowed to recurse.)CL also has first-class support for debugging with things like describe, step, and trace built-in.
EDIT: Yeah, the CL spec dates from 1994 and a bunch of things which we would expect nowadays (networking, POSIX,...) are provided by external libraries rather than being part of the spec, but in various ways CL is way ahead of its time.
Which goes to show how many lessons the industry failed to learn on those 30+ years.
CL has a more-or-less frozen standard, in the sense that it's unlikely to have an update. Scheme gets updated standards, but they seem to focus on refining Scheme rather than adding "modern" features. Both are very extensible and people do add modern features as implementation extras or libraries.
I can't comment about Racket. As an outsider, it appears to be a playground for hardcore CS types to experiment with different programming language features, which suggests it's the most "modern." That's just the impression I get, though - feel free to correct me on that.
(macroexpand '(when-let (foo (frob bar))
(jib foo)))
;; (let ((foo (frob bar)))
;; (when foo
;; (jib foo)))Racket improves on Scheme: its macros are fully hygienic whilst not being limited to template -> pattern transforms. See https://docs.racket-lang.org/guide/macro-transformers.html
EDIT: syntax-case -> syntax-rules; R6RS specifies the latter—I believe the former is a Racket construct equivalent in power to `syntax-rules`.
It does not have the same power as `defmacro`: you cannot define general procedural macros with `syntax-rules`, as you are limited to the pattern-matching language to compute over and construct syntax objects.
[1]: https://docs.racket-lang.org/reference/stx-patterns.html#%28...
R6 having `syntax-case` macros is one of the more controversial things about it; a surprising number of implementers don't care for them.
Scheme R5RS, R6RS and R7RS all have macro systems. In R5RS has a pattern/template based system (syntax-rules). In R6RS the system has both patterns, templates and procedural macros.
The most modern system is Racket though. See `syntax-parse`.
Wait, r6rs has proc macros? Where is that in the spec? I've only seen the `syntax-rules` bit.
Look for `define-syntax`.
https://www.r6rs.org/final/html/r6rs/r6rs-Z-H-14.html#node_i... https://www.r6rs.org/final/html/r6rs/r6rs-Z-H-13.html