> is that the standard is stuck in time, lacking stuff like database providers, a common FFI or threading.
You don't need database providers to be integrated in the language spec. Not in CL and not in many other successful languages.
We already have a de facto common, portable FFI: CFFI.
We already have more than one library to do threading in a portable way. Also, threading has been left out of the CL standard on purpose, so each implementation can offer different capabilities and you can choose whatever fits best to your problem.
> The biggest issue I see with Common Lisp is that the standard is stuck in time,
The standard is from 1994 and Lisp is still pretty much one of the most modern and advanced languages around; i would say it's the other languages, like Java, that historically get new 'versions' each few years because they can't be extended using the very same language, unlike in Lisp or other modern languages like Julia or Racket.
> You don't need database providers to be integrated in the language spec. Not in CL and not in many other successful languages.
Many people underestimate how useful Perl DBI, JDBC, ODBC, Python DB-API, ADO.NET are.
Which is why, in spite of all design flaws, even Go has a database interface defined on their core library.
> Lisp is still pretty much one of the most modern and advanced languages around
I agree with this part, and we are still far from the whole Symbolics experience.
Yet using threading as an example, since it is left for each implementation, it means one cannot guarantee portable semantics across implementations.
Exactly the issue we had with writing threads in C before p_threads came to be, and even as portable library there are semantic issues (e.g. signal handling) until C11 finally defined what threads in C are supposed to look like.
> Many people underestimate how useful Perl DBI, JDBC, ODBC, Python DB-API, ADO.NET
JDBC, ODBC, ADO.NET are not part of the language spec; they are separate specifications. Your initial argument was that the language spec ("the standard") is "stuck in time".
And on the other hand, database access is not really an issue on CL.
> Yet using threading as an example, since it is left for each implementation, it means one cannot guarantee portable semantics across implementations.
There does not exist a single, one-size-fits-all, valid-for-all-use-cases approach to concurrent programming.
> There does not exist a single, one-size-fits-all, valid-for-all-use-cases approach to concurrent programming.
And in CL there does not exist a common platform to efficiently build better abstractions in CL. TBF, this is only marginally worse than many other popular languages. Still, it's undeniably worse.
There is a reference implementation, no standard, and a bunch of implementations and/or extensions. Is it really better? What guarantees do you have? If you need to provide an extension, you have to discuss about extensions and push patches to CPython, just like you could push patches to SBCL or ABCL.
But at least (which I do not consider "undeniably worse"), CL is its own platform and offers a standard extension mechanism (e.g. compiler-macros), and implementations offer more specific extensions mechanisms (sb-vm, ...), as well as a standard way of building portability layers across implementations. Those features are used to define and implement new standards. How is that "undeniably worse"?
You can't use compiler-macros to build cross-platform higher order abstractions, so I don't get why they come up. They're exactly as useful as any indirection facility.
So why are they relevant here?
Not that I like Python, mind you. I miss CL, but I wouldn't go back to it. My experience is that way too many of these beloved libraries have an audience of 1 or 2, sometimes a single company. If I'm going to engage with an environment like that, I'd rather do so to access the leading edge of research and compilation results like w/ Haskell. Even Racket is more desirable than CL on this scale.
EDIT: I just wanna repeat I loathe python and carry no water for that standing wave of bad design decisions. Really. Seriously. Worst.
Not sure what you count as higher order abstractions, but lparallel, fset, cl-ppcre and other libraries make use of compiler macros; this is relevant w.r.t. efficiency.
Haxl is modern. Ponylang's concurrency is modern. Rust's concurrency is modern.
lparallel and fset's affordances are not. I'm not sure why a single threaded regular expression compiler is mentioned here.
I'd have to check. Is fset even using the current standard (not the newest stuff) for immutable-friendly data structures? Last time I checked they had used a lot of older stuff from Okasaki's work and much of that has been improved upon substantially now.
Even Clojure is out of date, compared to this year's innovations!
Note that bordeaux-threads, like CLIM-SYS or CFFI-sys, is not only a portability layer, but also a standard:
BORDEAUX-THREADS is a proposed standard for a minimal MP/Threading interface. It is similar to the CLIM-SYS threading and lock support, but for the following broad differences:
Some behaviours are defined in additional detail: attention has been given to special variable interaction, whether and when cleanup forms are run. Some behaviours are defined in less detail: an implementation that does not support multiple threads is not required to use a new list (nil) for a lock, for example.
Many functions which would be difficult, dangerous or inefficient to provide on some implementations have been removed. Chiefly these are functions such as thread-wait which expect for efficiency that the thread scheduler is written in Lisp and 'hookable', which can't sensibly be done if the scheduler is external to the Lisp image, or the system has more than one CPU.
Unbalanced ACQUIRE-LOCK and RELEASE-LOCK functions have been added.
Posix-style condition variables have been added, as it's not otherwise possible to implement them correctly using the other operations that are specified.
Threads may be implemented using whatever applicable techniques are provided by the operating system: user-space scheduling, kernel-based LWPs or anything else that does the job.
Some parts of this specification can also be implemented in a Lisp that does not support multiple threads. Thread creation and some thread inspection operations will not work, but the locking functions are still present (though they may do nothing) so that thread-safe code can be compiled on both multithread and single-thread implementations without need of conditionals.
To avoid conflict with existing MP/threading interfaces in implementations, these symbols live in the BORDEAUX-THREADS package. Implementations and/or users may also make them visible or exported in other more traditionally named packages.")
And so, instead of one standard like C, you have the CL standard, as well as additional standards that are not called annexes but fulfill the same role.
From a practical point of view, I consider portability layers to be sufficient; but having those additional standards offer stronger guarantees across implementations.
Just for showing how Bordeaux-Threads can be considered almost universally portable. This is the list of Lisp implementations supported by Bordeaux Threads:
- Armed Bear Common Lisp (ABCL)
- Allegro Common Lisp (ACL)
- CLISP
- Clozure CL
- CMUCL
- Corman Lisp
- Embeddable Common Lisp (ECL)
- LispWorks
- MCL
- MKCL
- Steel Bank Common Lisp (SBCL)
- Scieneer CL
You don't need database providers to be integrated in the language spec. Not in CL and not in many other successful languages.
We already have a de facto common, portable FFI: CFFI.
We already have more than one library to do threading in a portable way. Also, threading has been left out of the CL standard on purpose, so each implementation can offer different capabilities and you can choose whatever fits best to your problem.
> The biggest issue I see with Common Lisp is that the standard is stuck in time,
The standard is from 1994 and Lisp is still pretty much one of the most modern and advanced languages around; i would say it's the other languages, like Java, that historically get new 'versions' each few years because they can't be extended using the very same language, unlike in Lisp or other modern languages like Julia or Racket.