CIEL Is an Extended Lisp
ciel-lang.org
ciel-lang.org
oh, the sidebar disappears quickly when we scroll and it disappears when we click on "show me"… not great.
ciel-user> (disassemble #'(lambda (x) (+ x 2)))
Error: Missing closing quotation in string (line 1):
(disassemble #'(lambda (x) (+ x 2)))
ciel-user> (disassemble (lambda (x) (+ x 2)))
; disassembly for (LAMBDA (X))
; Size: 35 bytes. Origin: #x54354A64
; (LAMBDA (X)
Meanwhile, you can use CIEL in your editor (as a library or with the core image), where you'll have a normal REPL and this will work.
Clojure syntax implemented in Go.
I'm not affiliated I just think it's brilliant.
CEIL's example in Joker:
(prn {:a 1 :b 2 :c 3})
Gist for downloading, installing and executing the above example: https://gist.github.com/lsh-0/f7df23777ef35a8cc3d85e1dcbf0eb...Executing script took 2.1s overall. Execution of example took 0.007s.
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?
CIEL-USER> (enable-shell-passthrough
#<NAMED-READTABLE CLESH:SYNTAX {1003EE7F13}>
CIEL-USER> ! ls(see below to enable the shell passthrough in your editor's REPL)
(I assume you just use standard CL methods?)
> [CIEL custom REPL ] has a shell pass-through: try !ls (available in the ciel-user package)
That's a kickass feature.
Or is python the odd one out in its REPL implementations here? I'm only familiar with python and e-lisp for REPL's.
> ...
> * it has a shell pass-through: try !ls (available in the ciel-user package)
It was specifically mentioned as a reason why CIEL is better. But I don't use enough languages to know overall, sorry.
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):
CIEL-USER> (enable-shell-passthrough)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).
also https://github.com/bradleyjensen/shcl, a POSIX shell.
As always: see more on https://github.com/CodyReichert/awesome-cl#shells-shells-int...
ATM you use standard methods, by using CIEL as a library.
I'd like to add a `ciel build` command.
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 :-]
I was wondering - do you also use it for larger (multi-file) projects? Any recommendations on how to structure those when using CIEL?
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.
Happy real-world lisping!
I found a snippet somewhere that messes with string interning and so symbols don't instantly get capitalized, but there's still way too much shouting.
(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).
Ah, used string= instead of string-equal, did they? Simple mistake to make, not keeping CL being case-insensitive in mind.
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.
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.
Is that too much to ask?
Might want to look at Jank (https://jank-lang.org/, https://github.com/jank-lang/jank). It's still in it's early stages but it's basically all you're hoping for!
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.
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.
Thanks in advance.
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.
Not joking. I use it at work. Former Clojure crazy. All the referential transparency/immutable data you could want from a non-Clojure language.
Super easy bidirectional C interop.
Native compiled but does have a compile-time script engine. Is the absolute most powerful compile-time evaluation I've seen outside of Lisp.
Creator calls it a "quirky Lisp".
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).
Plus OpenJ9, PTC, Aicas, Azul, and even the Java like MicroEJ and ART.
Many don't have an idea of breath and depth of Java ecosystem, and what guest languages can profit from.
Compile JVM bytecode to Wasm https://github.com/cretz/asmble
or
Run the JVM on Wasm https://cheerpj.com/docs/overview
Now is always the great time to be using JVM tech.
If it were strict C in stead of C++ I would probably be in love.
It is Clojure written in Clojure compiled to native via GraalVM.
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.
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.
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.
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.