Having a standard set ofwell documented things ready to go as if they were part of the core language, all with a single snazzy name, is soo important. I love this; Maybe it can become the new standard target. All it needs now is a good mascot or logo.
Follow-up: apparently there is a sidebar. In my defense, on mobile, the sidebar is closed by default, and you have to click the tiny hamburger menu in the very bottom left of the screen. I did not see this.
Another tip: hamburger menus are customarily at the top left: it would never occur to me to look for one in the bottom. It's more convenient to use where you put it, but convention trumps convenience when the convention is as strong as this.
It still looks weird to me at I'm not used to it, but the bottom is kinda better as it's easier to reach on a sizeable phone without resting the phone on some surface or using an additional hand.
Yeah, the other option is to leave it there but draw more attention to it (maybe make it a blue circle with white bars). The subtle menu only works in the right place, though.
Using an iPhone with rounded display corners, a few pixels of the last line of the “hamburger” are even off screen. I would never have seen it without the discussion in this thread.
Love the approach! I was ready to see "yet another Lisp", which is cool, but not something I'd readily use. Expanding and improving things that already exist can be harder and less fun than starting a fresh thing, but it's infinitely more valuable. I already use Common Lisp (it's quirky, but also incredibly robust, productive and fast), and this seems to make it a little less quirky, especially for newcomers and smaller projects.
Watching it on Safari gives me the same Javascript warning. No extensions loaded. Otherwise, checked with chrome, that looks like exactly what I wanna use.
The CL sodlib is a bit overloaded already, but if you wanna go batteries included, it was definitely missing stuff like Alexandria and Bordeaux etc, so I dig this choice. Brings a sense of "best practices" or standardization to the slightly fractured CL ecosystem.
I personally have an image with Alexandria, Serapeum, Dexador, Bordeaux Threads, some JSON stuff, but it might be handy to have something others use as a similar target.
Probably stands a better chance of success than the over-pontificated CDR proposals, and CL21 which preceded it.
Curious if there’s a bunch of reader macros set up by default?
It's enabled by default for the terminal repl, but not in the ciel-user package, that we would use on our editor's REPL. In that case we can enable it with
CIEL-USER> (enable-shell-passthrough
#<NAMED-READTABLE CLESH:SYNTAX {1003EE7F13}>
CIEL-USER> ! ls
Could this get a wrapper for building ncurses & sdl cores so that maybe one day lem could run right on top of ciel and a true lisp environment could emerge? https://news.ycombinator.com/item?id=41357409
Users who want an advanced lisp shell for the terminal, where they can mix & match shell and lisp code, would turn to lish: https://github.com/nibbula/lish/ (not considered "ready" or "good enough" by the author, but well advanced).
Forgive me if I'm wrong but I thought that was a fairly standard thing? The Ipython kernel uses exactly the same format, or you can go for a full shell and use xonsh.
Or is python the odd one out in its REPL implementations here? I'm only familiar with python and e-lisp for REPL's.
You are right but let's put things in order: CL's REPL is outstandingly more interactive than Python's. Specially with Emacs & Slime (or the others coming close: Pulsar with SLIMA, vim, VSCode, Intellij, Sublime…) We have an interactive debugger, restarts, we can resume a failed computation from anywhere in the stack, we don't loose state, the Lisp program actually never restarts, we compile a function against a live image and get immediate feedback… (it's an internal and difficult explanation on forums)
However, neither the built-in SBCL terminal REPL nor Slime offer a shell pass-through or ipython-like commands. We add one (by using the Clesh library).
The doc doesn't mention it yet, we can enable the shell passthrough in Slime's REPL (or any other editor):
Hi o/ Hopefully the goal of CIEL is well explained. I use it daily (with the core image, in my editor), I ship products with it. It saves me a load of time, when I start a new project, when I need to interact with the outside world, when I want to write a little something and ship it on the server without Python's mess, etc. Speaking of which, Django is of course difficult to replace, but I started an automatic DB dashboard for CRUD operations, something's on the way (unreleased).
I integrated CL step by step for my clients' work, and CIEL is another means to this end. To use CL, for real. None of my projects need CL's superpowers, but I want them for development, deployment and monitoring!
---
Today I fixed a few issues and released a v0.2: https://github.com/ciel-lang/CIEL/releases/tag/v02 The key point is that CIEL should be much easier to install, specially on Mac. We now rely on many less system dependencies.
If you find out that CIEL is still difficult to install on your platform, don't hesitate to send details on an issue. Thanks in advance.
---
TLDR; May CIEL ease and soften your CL journey.
ps: you have no idea how much time it took me to discover certain things! Now you have them here, ready, packaged :-]
Yes I do, of course, and I actually use it nearly exclusively for multi-file projects: I don't write short scripts everyday, but I have bigger projects that need more features. The one I am on: extract data from an existing DB, format it, save it to a csv, send it with SFTP. I build a binary and send it to my servers.
For this I use :ciel as a dependency, I use a typical project structure: a system definition in an .asd file (that :depends-on (:ciel)), and sources. I also start my editor with CIEL's core image. I build a binary the usual way out of this, I don't run this app as a script, specially if I added a couple dependencies. But that's OK, I benefited from CIEL during development.
I recommend to start with a file packages.lisp that defines 1 (one) package for the whole application, to use it across multiple files, until it makes sense to create a second package. Otherwise, one can easily loose oneself into export & import symbols hell, specially when we are new at it. So I don't recommend the "one-package-per-file" approach.
Hopefully the Cookbook gets you covered if you need examples.
(You can put this in ~/.sbclrc or your implementation's equivalent dot file!)
(Tangentially: I've encountered Common Lisp libraries in that wild that actually break if you do this, highly surprising bugs where the author was doing something too-clever with symbols and compared their representation against hard-coded strings, such that changing your *IDE's default print case* had the effect of breaking a very low-level library. This isn't important to anyone else here; I just wanted to vent. I have so much programming pain that only I know about and no one else in the world shares).
CL is case-sensitive, but it handles things so you typically don't have to be aware of it. I don't think I'm smart enough to try to do something clever on top of that, so I hope I can avoid your pain.
Since everyone likes something just a wee bit different, I'd also like to see something where most of the functions in :COMMON-LISP are made generic, so you can overload '+, etc. to work on vectors, etc.. Obviously you can do it yourself on a per-project basis.
This feature is based on generic-cl, a high quality library. To be franc, I didn't test much the integration with generic-cl, it's on the todo list. When I started out, I was carving for a library like this. Now, I don't feel the need anymore.
I think https://github.com/CodyReichert/awesome-cl with a bit more trimming/tagging and interactivity (e.g. show all "stars") to empower users to explore the ecosystem and build their own image is a better way.
There should also be a large disclaimer saying "Consider disregarding portability in favour of SBCL to get a more modern experience".
I wrote Lisp (Clojure) professionally for several years. It was the most fun I ever had.
My only problem was it was an ongoing battle to convince people - especially management - that I wasn't crazy.
Sure, I was crazy-productive, but they also thought that there was some nutjob in the corner that was quietly adding risk to the business.
If someone could give me the ergonomics of Clojure, but without the JVM and the ability to easily target 1/ native (incl easy bidirectional C iterop), 2/ wasm, and 3/ support both in aot and runtime + JIT modes, I would switch in a heartbeat.
>If someone could give me the ergonomics of Clojure, but without the JVM and the ability to easily target 1/ native (incl easy bidirectional C iterop), 2/ wasm, and 3/ support both in aot and runtime + JIT modes, I would switch in a heartbeat.
The name might be hard to push to management, but I love that it is s-expr based.
I'll definitely check it out, but if you don't mind me asking: how good is the REPL side on Jank? If it is remotely close to SBCL, then I might become a fan.
jank will have full nREPL support, so the REPL story should be at parity with Clojure. I'm working on the nREPL server now We're JIT compiling C++ code, so there are indeed more dragons.
Late to the party, do you think you could give me a comparison of Jank vs Janet ? I'm just starting to look at janet, and just found out about jank at this point.
How usable is Jank for greenfield projects, The comparison page isnt that useful as I don't know what I'm missing.
In terms of design, Janet is Clojure-inspired, but very much does its own thing. jank is a Clojure, such that any existing Clojure code you have will work. Largely speaking, only Java intorop needs to be ported, using a reader conditonal.
Beyond that, jank is built on a C++ host and interops with C++. This means you qan use C++ features, such as templates, in your jank code. Janet has a C runtime and any C++ interop will need to be through C's ABI.
Lastly, Janet is usable today while jank is still under heavy development.
I agree that the JVM is an amazing piece of technology.
But the ecosystem that exists around the JVM also comes with both a bunch of awesome libraries, and a whole bunch of cruft and ceremony.
If, like Clojure, you're trying to pull in compatibility with JVM libraries, then you pull all that in. So now if you want a little C in your Clojure, you have to go through JNA or something.
I would like the option of going native with a Clojure dialect, without passing through either JVM (Clojure) or JS (ClojureScript).
Speaking as someone who was using Clojure pre-1.0 through... 1.2? because I was so interested in Lisps and one with access to a modern library ecosystem excited me, I did not enjoy my time with Maven at all. It felt very janky. A second issue that I hear they finally fixed was Clojure still gave all of the low level parts of the error that were basically the guts of Clojure and had nothing to do with my code which I got tired of dealing with. Probably other issues I'm forgetting as I have not used it in a decade or so, but I just did not enjoy my time dealing with the JVM ecosystem.
Smaller ones where you're the sole dev on a given component, there are no cross-language dependencies in your systems (it's a CLI-invoked tool and/or communicates through stdout or JSON data, etc.), and your boss has had such poor experiences with freelancers and Microsoft lock-in in the past that he's open to you choosing the best tool for the job within reason.
What made it more productive than the usual mainstream languages?
I'm coming from 10 years of OOP leaning C++/Java/Python, and have been seeing the beauty of functional programming in the latter half of that time. It's just far easier to test than OOP in my experience.
off-topic: is there anything that aims to be a 'universal stdlib'? Something that lets you write eg some small spec about how your language operates and then it lets you add a fullblown polyglot batteries-included stdlib to your language? Would be a dream for language devs I imagine. I guess you could go pretty far by just linking to some C library probably though.
CL is better than Python for very short scripts that will be called repeatedly (e.g. from a makefile), since a python already has a slower startup time than a CL binary, and for every import you add it gets even slower.
I don't consider it an extended Lisp, rather I just consider it a "batteries included", bundled library distribution of Lisp.
Common Lisp is still Common Lisp.
And I know it's a slippery slope.
Someone posted (here?) a list of the language changes to Java over the years.
And for something like Java, you "have" to "change the language" to get the results they wanted. Much of these changes could not have been done with just more classes in the JRE distributions. Whereas with CL, most of those things could have been done natively with just macros and functions, rather than having to update the core.
Of course, this is the Scheme story from day one, just with a much smaller core. But CL, due to the happenstance of the time of uniting several commercial efforts under one banner, has a larger core, but also, by definition, more opportunity for the actual compiler to be "better" with the higher level constructs it works with.
Contrived example being that Lisp "knows" about Structs and CLOS, whereas while you can add Structs (records) to Scheme, at a Scheme level you can only reduce them to the given Scheme primitives (vectors or lists), when the compiler finally sees the result, all it will see is a vector or list, with no knowledge of it actually being a struct (and thus can't potentially optimized for it).
If you want "native" structs, you need to actually extend the particular Scheme compiler.
So, anyway, the point being this is a nice package of libraries (it is, really, quite nice), all bundled into a single image. Batteries included.
But it's still CL at its core, there's nothing necessarily new there.
> Contrived example being that Lisp "knows" about Structs and CLOS, whereas while you can add Structs (records) to Scheme, at a Scheme level you can only reduce them to the given Scheme primitives (vectors or lists), when the compiler finally sees the result, all it will see is a vector or list, with no knowledge of it actually being a struct (and thus can't potentially optimized for it).
I don't know every single implementation of Scheme, but at least the Chez Scheme compiler has a lot of special code for records. The compiler sees them as records, tries to inline as many getters and setters as possible, and has low level support for the tree of subrecords and I may be missing a few more tricks. You can go to https://github.com/cisco/ChezScheme/blob/main/s/cp0.ss and Ctr+F record . For example https://github.com/cisco/ChezScheme/blob/main/s/cp0.ss#L3816...
The old implementation of Racket also had some tricks, but now the structs are transformed to Chez Scheme records.
Maybe that's why Chez is the most performant scheme.
I've heard people suggest that a more expanded scheme would become a ~lisp. "Common" lisp was formed as a moderately expansive standard for lisps of its time.