Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
CIEL Is an Extended Lisp (ciel-lang.org)
401 points by todsacerdoti on Aug 30, 2024 | hide | past | favorite | 98 comments


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.


Given the name, it probably has to be a chibi seal.


Could also use the face of the character from Tsukihime/Melty Blood.


the name means sky in French


Give the seal wings then


How do we make the wings look French?


Give them pencil mustaches and a cigarette.


Where is this documentation? Honestly I don't see much here. I'd call this a readme, not documentation.


How so?? You should have a sidebar with menu entries. Try on http://ciel-lang.org/#/libraries

oh, the sidebar disappears quickly when we scroll and it disappears when we click on "show me"… not great.


I was on mobile when I looked and I never saw the sidebar. Might be something that needs fixing. Love the project regardless.


There's a hamburger menu on the bottom left.


Hey vindarel, I don't get it:

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)


so, that's in the terminal REPL. Thanks for the report.

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.


Thanks! So it is a bug :-).


hey this bug is fixed! thanks


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.


thank you (both) for the feedback. I added links to the documentation at the end of the landing page.


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.


It's linked on the GitHub front page, for some reason it's not in this link at all.


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.


I like to bring up Joker (https://github.com/candid82/joker) whenever there is a discussion of some lisp that is fast and convenient.

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.


Nice to see that the approach taken by Babashka (https://babashka.org/) is now also available in the CommonLisp world. Good stuff!


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.


This is great.

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?


Only one is enabled in the terminal repl, but none when we use ciel as a regular Lisp library. We don't want to mess with the readtables by default.

(see below to enable the shell passthrough in your editor's REPL)


I did a quick search of the code, and only clesh[1] seems to be enabled by default for shelling out from the REPL.

1: https://github.com/Neronus/Clesh


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


Looks different than Ciel, another Lisp from 2010 (https://pldb.io/concepts/ciel.html), by Ron Garret, rocket scientist (https://flownet.com/ron/).


Everyone has their own paradis.


Can you easily compile a binary?

(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.


It is very handy.

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...


> Can you easily compile a binary? (I assume you just use standard CL methods?)

ATM you use standard methods, by using CIEL as a library.

I'd like to add a `ciel build` command.


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):

    CIEL-USER> (enable-shell-passthrough)


> CIEL's REPL is more user friendly than the default SBCL one. In particular:

> ...

> * 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.


What's wrong with Ctrl+Z?


You cannot use lisp expressions and functions as arguments in bash.


so it wouldn't require a shell that supports job control?


That's a pretty low bar. What's the Venn diagram of (systems which can run this) & (systems with only terrible shells)?


Looks like SBCL plus libraries. The author, vindarel, is here on HN.


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 :-]


I absolutely love this and will be using it extensively for scripts.

I was wondering - do you also use it for larger (multi-file) projects? Any recommendations on how to structure those when using CIEL?


Awesome, thanks for the feedback.

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'd love to see one of these revitalizations of CL that gets rid of the ALLCAPS. I know it's a small aesthetic thing but it drives me crazy.

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.


You're looking for (setq *print-case* :downcase), no need to mess with the reader.


(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.


> compared their representation against hard-coded strings

Ah, used string= instead of string-equal, did they? Simple mistake to make, not keeping CL being case-insensitive in mind.


I always liked it. I type lowercase, the computer speaks back uppercase. We know who said what. It's also nostalgia for BASIC. ;-)


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.


That's part of Ciel!


That's great! Is that described in the documentation? I can't seem to find it.


good catch! It is only mentioned at the end of the install section: http://ciel-lang.org/#/install?id=use-in-the-repl-and-in-new...

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.


You mean something like generic-cl? https://github.com/alex-gutev/generic-cl


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".


"Ciel" means "sky", in French language.


In Slovak, it means "destination". :)


surely not a coincidence


Ahh, the siren song of Lisp

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?


>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.

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!


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.


Hi,

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.


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.


Will check it out!


The JVM is exactly why Clojure is one of the most successful Lisp variants since the AI Winter.


I agree! And I still love it because it's what allowed me to sneak a Lisp into not just a Java shop, but the Java shop: Oracle.


What is wrong with the JVM? The JVM is utterly amazing and you know very well that you can target native, even with Clojure.


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).


Have you seen Jank? It’s a Clojure dialect being written in C++ and designed for interop with C++ instead of the JVM.

https://jank-lang.org/


It's almost perfect.

If it were strict C in stead of C++ I would probably be in love.


Now there is Panama, and then GraalVM as well.

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.


Not to mention that you can

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.


Yeah, for a reason I have always wandered around JVM, and its counterpart CLR, unless requested otherwise, since 2002.


You should meet this nice https://github.com/babashka/babashka !

It is Clojure written in Clojure compiled to native via GraalVM.


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.


Nim.

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".


Just curious, what kind of companies do you find that are open to using Nim professionally? It's always hard with more niche languages.


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.


I'll check it out, thanks!


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.


Take a look at Gerbil Scheme

https://cons.io/


you might like https://janet-lang.org/ !


Some good progress on Jank lately:

https://jank-lang.org/


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.


It looks fun to learn it for scripting. I often use Python to manipulate JSON and YAML and with Python requests library, this seems like a fit


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.


How come Ironclad is not included?


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.


Modern Scheme standards (R6RS and R7RS) have native record types.


This seems really useful! Good work


Thanks! Encouraging feedback is my nectar.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: