CIEL is an extended CL
Find a file
2020-10-13 10:23:11 +02:00
.github add FUNDING just because. We can put several names. 2020-10-09 13:48:01 +02:00
src (minor tiny detail) :use :cl 2020-10-09 14:30:15 +02:00
.gitignore init 2019-03-23 13:04:03 +01:00
ABOUT.org add FAQ, ABOUT 2020-10-13 10:23:11 +02:00
after-plus.jpeg README: before/after 2020-10-09 14:02:56 +02:00
before.jpeg README: before/after 2020-10-09 14:02:56 +02:00
build-image.lisp Build a core image 2020-10-13 06:01:52 +02:00
ciel.asd REPL++ 2020-10-13 07:22:01 +02:00
FAQ.org add FAQ, ABOUT 2020-10-13 10:23:11 +02:00
Makefile Build a binary with a REPL from sbcli 2020-10-13 07:09:57 +02:00
README.org add FAQ, ABOUT 2020-10-13 10:23:11 +02:00
repl.lisp REPL++ 2020-10-13 07:22:01 +02:00

DISCLAIMER: this is an EARLY DRAFT, but it is usable.

CIEL Is an Extended Lisp

What is this ?

CIEL is a collection of useful Quicklisp libraries.

It's Common Lisp, batteries included.

Questions, doubts? See the FAQ.

TODOs

  • settle on libraries that help newcomers
  • automate the documentation
  • distribute (Quicklisp, Qlot, Quicklisp distribution, Ultralisp, Ultralisp distribution (upcoming)…)
  • ship a core image and a binary
  • optionnal: create a tool that, given a CIEL code base, explains what packages to import in order to switch to "plain CL".

How to procede ?

This is an experiment. I'd be happy to give push rights to more maintainers. We will send pull requests, discuss, and in case we don't find a consensus for what should be on by default, we can create other packages.

Rules

  • don't install libraries that need a Slime helper to work in the REPL (cl-annot).
  • reader syntax changes may not be enabled by default.

Install

With Quicklisp

You need a Lisp implementation and Quicklisp installed.

CIEL is not yet on Quicklisp (but it is on Ultralisp), so clone this repository and load the .asd (with load or C-c C-k in Slime).

git clone https://github.com/ciel-lang/CIEL ~/quicklisp/local-projects/CIEL

Then, quickload it:

(ql:quickload "ciel")

and enter the ciel-user package, instead of the default common-lisp-user (or cl-user):

(in-package :ciel-user)

With a core image

You need a Lisp implementation, but you don't need Quicklisp.

Build a core image for your lisp with all CIEL's dependencies:

sbcl --load build-image.lisp

and use it:

sbcl --core ciel --eval '(in-package :ciel-user)'

TODO: we will distribute ready-to-use core images.

With a binary. Use CIEL's own REPL.

You don't need anything, just download the CIEL executable and run its REPL.

TODO: build it on CI for different platforms.

To build it, clone this repository and run make build.

Start it with ./ciel-repl.

You are dropped into a custom Lisp REPL, freely based on sbcli.

This REPL is more user friendly than the default SBCL one. It handles errors gracefully, it is not too verbose and it has readline capabilities, including multiline input and reset.

Libraries

Data structures

access, generic and nested access to all common datastructures

https://github.com/AccelerationNet/access/

It's always

(access my-structure :elt)

hash-table utilities

str, a string manipulation library

Available with the str prefix.

https://github.com/vindarel/cl-str/

Data formats

JSON

CSV

Pattern matching

Use Trivia, also available with the match local nickname.

Numbers

Parsing numbers, floats, decimals

cl-decimals: parse and format decimal numbers

https://github.com/tlikonen/cl-decimals

The main interface are the functions parse-decimal-number and format-decimal-number. The former is for parsing strings for decimal numbers and the latter for pretty-printing them as strings.

Reading:

DECIMALS> (parse-decimal-number "0.24")
6/25


DECIMALS> (parse-decimal-number "12,345"
                                :decimal-separator #\,
                                :negative-sign #\)
-2469/200

Parsing:

DECIMALS> (format-decimal-number -100/6 :round-magnitude -3)
"-16.667"
("-" "16" "." "667")

DECIMALS> (loop for e from -5 upto 5
                do (print (format-decimal-number
                           (expt 10 e) :round-magnitude -5
                           :decimal-separator ","
                           :integer-minimum-width 7
                           :integer-group-separator " "
                           :fractional-minimum-width 7
                           :fractional-group-separator " ")))

"      0,000 01"
"      0,000 1 "
"      0,001   "
"      0,01    "
"      0,1     "
"      1       "
"     10       "
"    100       "
"  1 000       "
" 10 000       "
"100 000       "
NIL

Regular expressions

Use ppcre.

Threads, monitoring, scheduling

Bordeaux-Threads (bt prefix)

Lparallel

Moira: https://github.com/ruricolist/moira (monitor and restart background threads)

http://quickdocs.org/trivial-monitored-thread/

Trivial Monitored Thread offers a very simple (aka trivial) way of spawning threads and being informed when one any of them crash and die.

cl-cron http://quickdocs.org/cl-cron/api

Web

Imported:

  • Hunchentoot
  • Easy-routes
  • Djula
  • Spinneret
  • Quri

https://lispcookbook.github.io/cl-cookbook/web.html

Syntax extensions

Pythonic triple quotes docstring

https://github.com/smithzvk/pythonic-string-reader

We can use triple quotes for docstrings, and double quotes within them.

(defun foo ()
  """foo "bar"."""
  t)

Lambda shortcuts

You have to enable cl-punch's syntax yourself.

https://github.com/windymelt/cl-punch/ - Scala-like anonymous lambda literal.

(cl-punch:enable-punch-syntax)
;; ^() is converted into (lambda ...) .
;; Each underscore is converted into a lambda argument.

(mapcar ^(* 2 _) '(1 2 3 4 5))
;; => '(2 4 6 8 10)

;; One underscore corresponds one argument.

(^(* _ _) 2 3)
;; => 6

;; <_ reuses last argument.

(mapcar ^(if (oddp _) (* 2 <_) <_) '(1 2 3 4 5))
;; => '(2 2 6 4 10)

;; _! corresponds one argument but it is brought to top of the argument list.
;; It can be useful when you want to change argument order.

(^(cons _ _!) :a :b)
;; => (:b . :a)

(^(list _! _! _!) 1 2 3)
;; => '(3 2 1)

Other utilities

Logging (log4cl)

repl-utilities (readme, summary,…)

repl-utilities:

(repl-utilities:readme repl-utilities)

printv

https://github.com/danlentz/printv

(:printv
(defvar *y*)
(defparameter *x* 2)
(setf *y* (sqrt *x*))
(setf *y* (/ 1 *y*)))

;; This produces the following text to PRINTV's output stream, and still results in the same returned value: 0.70710677.

;;;   (DEFVAR *Y*) => *Y*
;;;   (DEFPARAMETER *X* 2) => *X*
;;;   (SETF *Y* (SQRT *X*)) => 1.4142135
;;;   (SETF *Y* (/ 1 *Y*)) => 0.70710677

Getting a function's arguments list (trivial-arguments)

https://github.com/Shinmera/trivial-arguments

(defun foo (a b c &optional d) nil)
(arglist #'foo)
;; (a b c &optional d)

generic-cl

https://github.com/alex-gutev/generic-cl/

todo:

generic-ciel

Example:

;; with a struct or class "point":
(defmethod equalp ((p1 point) (p2 point))
   ())

Final words

That was your life in CL:

and now: