A Common Lisp kernel for Jupyter.
All stream output is captured and displayed in the notebook interface.
(formatt"Hello, World") (format*error-output*"Goodbye, cruel World.")
NIL
NIL
Hello, World
Goodbye, cruel World.
(formatj:*markdown-output*"# Title This is *markdown*!")
NIL
This is markdown!
Evaluation results are displayed directory in the notebook.
(+2345)
14
All Lisp code is value, including calls to quicklisp.
(ql:quickload:shasht)
To load "shasht": Load 1 ASDF system: shasht
(:SHASHT)
; Loading "shasht"
The serialized JSON will represented as a Lisp string.
(shasht:write-json`(:object-plist"foo""bar""quux"1.23)t)
(:OBJECT-PLIST "foo" "bar" "quux" 1.23)
{ "foo": "bar", "quux": 1.23 }
JSON can also be displayed with open/close expanders using json
or json-file
(jupyter:json`(:object-plist"foo""bar""quux"(:object-plist"a"1"b"2)):expandedt:displayt:id"a")
If you use display_data
and assign an id then you can update the result later on.
(jupyter:json`(:object-plist"foo""bar""quux"(:object-plist"a"1"b"2"c"3)):expandedt:displayt:updatet:id"a")
Error conditions will be captured and a backtrace will be sent to *error-output*
(/10)
3: ((FLET "H1" :IN COMMON-LISP-JUPYTER::MY-EVAL) arithmetic error DIVISION-BY-ZERO signalled Operation was (/ 1 0).) 4: (SB-KERNEL::%SIGNAL arithmetic error DIVISION-BY-ZERO signalled Operation was (/ 1 0).) 5: (ERROR DIVISION-BY-ZERO OPERATION / OPERANDS (1 0)) 6: ("DIVISION-BY-ZERO-ERROR" 1 0) 7: (SB-KERNEL:INTERNAL-ERROR #.(SB-SYS:INT-SAP #X7F7B8362DC80) #<unused argument>) 8: ("foreign function: call_into_lisp") 9: ("foreign function: funcall2") 10: ("foreign function: interrupt_internal_error") 11: ("foreign function: #x558902F62993") 12: (SB-KERNEL::INTEGER-/-INTEGER 1 0) 13: (/ 1 0) 14: (SB-INT:SIMPLE-EVAL-IN-LEXENV (/ 1 0) #<NULL-LEXENV>) 15: (EVAL (/ 1 0)) 16: (COMMON-LISP-JUPYTER::MY-EVAL (/ 1 0)) 17: ((:METHOD JUPYTER:EVALUATE-CODE (COMMON-LISP-JUPYTER:KERNEL T)) #<unused argument> (/ 1 0)) 18: (JUPYTER::HANDLE-EXECUTE-REQUEST) 19: (JUPYTER::RUN-SHELL #<KERNEL {1003A22F83}>) 20: ((LAMBDA NIL :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS)) 21: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN)) 22: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-THREAD::RUN)) 23: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN)) 24: ((FLET "WITHOUT-INTERRUPTS-BODY-4" :IN SB-THREAD::RUN)) 25: (SB-THREAD::RUN) 26: ("foreign function: call_into_lisp") 27: ("foreign function: funcall1")
#<ENVIRONMENT {1003A05853}> [Environment of thread #<THREAD "SHELL Thread" RUNNING {10051C8C13}>] arithmetic error DIVISION-BY-ZERO signalled Operation was (/ 1 0). [Condition of type DIVISION-BY-ZERO] Backtrace: 3: ((FLET "H1" :IN COMMON-LISP-JUPYTER::MY-EVAL) arithmetic error DIVISION-BY-ZERO signalled Operation was (/ 1 0).) 4: (SB-KERNEL::%SIGNAL arithmetic error DIVISION-BY-ZERO signalled Operation was (/ 1 0).) 5: (ERROR DIVISION-BY-ZERO OPERATION / OPERANDS (1 0)) 6: ("DIVISION-BY-ZERO-ERROR" 1 0) 7: (SB-KERNEL:INTERNAL-ERROR #.(SB-SYS:INT-SAP #X7F7B8362DC80) #<unused argument>) 8: ("foreign function: call_into_lisp") 9: ("foreign function: funcall2") 10: ("foreign function: interrupt_internal_error") 11: ("foreign function: #x558902F62993") 12: (SB-KERNEL::INTEGER-/-INTEGER 1 0) 13: (/ 1 0) 14: (SB-INT:SIMPLE-EVAL-IN-LEXENV (/ 1 0) #<NULL-LEXENV>) 15: (EVAL (/ 1 0)) 16: (COMMON-LISP-JUPYTER::MY-EVAL (/ 1 0)) 17: ((:METHOD JUPYTER:EVALUATE-CODE (COMMON-LISP-JUPYTER:KERNEL T)) #<unused argument> (/ 1 0)) 18: (JUPYTER::HANDLE-EXECUTE-REQUEST) 19: (JUPYTER::RUN-SHELL #<KERNEL {1003A22F83}>) 20: ((LAMBDA NIL :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS)) 21: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN)) 22: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-THREAD::RUN)) 23: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN)) 24: ((FLET "WITHOUT-INTERRUPTS-BODY-4" :IN SB-THREAD::RUN)) 25: (SB-THREAD::RUN) 26: ("foreign function: call_into_lisp") 27: ("foreign function: funcall1")
New functions can be defined. The default namespace is COMMON-LISP-USER
.
(defunfibonacci(n) (if(<=n1) 1 (+(fibonacci(-n2))(fibonacci(-n1)))))
FIBONACCI
The seventh element of everybody's favorite sequence.
(fibonacci7)
21
S-Expressions will be displayed using pprint
.
(function-lambda-expression#'fibonacci)
(LAMBDA (N) (BLOCK FIBONACCI (IF (<= N 1) 1 (+ (FIBONACCI (- N 2)) (FIBONACCI (- N 1))))))
T
FIBONACCI
Rich text and images can be displayed using inline values using the inline-result
, html
, jpeg
, latex
, markdown
, png
, svg
or text
functions.
(jupyter:markdown"## wibble foo `quux`")
foo quux
(jupyter:latex"$$R_{\\mu \\nu} - \\tfrac{1}{2}R \,円 g_{\\mu \\nu} + \\Lambda g_{\\mu \\nu} = 8 \\pi G c^{-4} T_{\\mu \\nu}$$")
External files can be rendered using the file
, gif-file
, jpeg-file
, png-file
, ps-file
, svg-file
functions.
The MIME type will be automatically determined in the case of a call to file
.
(jupyter:file"lisplogo_alien.svg":displayt)
Calls to yes-or-no-p
will result in a input_request
to the user.
(defparameterlisp-rocks(yes-or-no-p"LISP rocks?"))
LISP-ROCKS
(jupyter:markdown(formatnil"For the record Lisp ~A"(iflisp-rocks"**rocks**!""**does not** rock.")))
For the record Lisp rocks!
Output send to *query-io*
will result also result in an input_request to the user.
(defunask(prompt) (format*query-io*prompt) (finish-output*query-io*) (read-line*query-io*))
ASK
(defvarquest(ask"What is your quest? "))
QUEST
(formatt"Your quest is: ~A"quest)
NIL
Your quest is: wibble
jupyter:clear
will clear the output of the current.
(loop forifrom1to10 do(sleep0.25) do(jupyter:cleart) do(printi) do(finish-output*standard-output*) finally(return(values)))
10
(values)
can be used to suppress the output. Defining a reader macro can make this easier.
(defunno-output-reader(streamchar) (declare(ignorechar)) (list(quoteprogn)(readstreamtnilt)(values))) (set-macro-character#\~#'no-output-reader)
NO-OUTPUT-READER
T
~(formatt"No output returned!")
NIL
No output returned!
Multiple value returns function correctly and previous result/form are set.
(values'a1'a2) 'b (values'c1'c2'c3) (list//////)
A1
A2
B
C1
C2
C3
((C1 C2 C3) (B) (A1 A2))
(values'a1'a2) 'b (values'c1'c2'c3) (list******)
A1
A2
B
C1
C2
C3
(C1 B A1)
(+01) (-42) (/93) (list++++++)
1
2
3
((/ 9 3) (- 4 2) (+ 0 1))