Calysto Scheme is a real Scheme programming language, with full support for continuations, including call/cc. It can also use all Python libraries. Also has some extensions that make it more useful (stepper-debugger, choose/fail, stack traces), or make it better integrated with Python.
In Jupyter notebooks, because Calysto Scheme uses MetaKernel, it has a fully-supported set of "magics"---meta-commands for additional functionality. This includes running Scheme in parallel. See all of the MetaKernel Magics.
Calysto Scheme is written in Scheme, and then translated into Python (and other backends). The entire functionality lies in a single Python file: https://github.com/Calysto/calysto_scheme/blob/master/calysto_scheme/scheme.py However, you can easily install it (see below).
Please see Calysto Scheme Language for more details on the Calysto Scheme language.
You can install Calysto Scheme with Python3:
pip3 install --upgrade calysto-scheme --user -U
python3 -m calysto_kernel install --user
or in the system kernel folder with:
sudo pip3 install --upgrade calysto-scheme -U
sudo python3 -m calysto_kernel install
Change pip3/python3 to use a different pip or Python. The version of Python used will determine how Calysto Scheme is run.
Use it in the console, qtconsole, or notebook with IPython 3:
ipython console --kernel calysto_scheme
ipython qtconsole --kernel calysto_scheme
ipython notebook --kernel calysto_scheme
In addition to all of the following items, Calysto Scheme also has access to all of Python's builtin functions, and all of Python's libraries. For example, you can use (complex 3 2)
to create a complex number by calling Python's complex function.
When you run Calysto Scheme in Jupyter (console, notebook, qtconsole, etc.) you get:
Calysto Scheme allows you to use LaTeX-style variables in code. For example, if you type:
\beta
with the cursor right after the 'a' in beta, and then press TAB, it will turn into the unicode character:
β
There are nearly 1300 different symbols defined (thanks to the Julia language) and documented here:
http://docs.julialang.org/en/release-0.4/manual/unicode-input/#man-unicode-input
Calysto Scheme may not implement all of those. Some useful and suggestive ones:
(define α 67)
α
67
(define i 2)
(define vectorᵢ (vector-ref (vector 0 6 3 2) i))
vectorᵢ
3
(import "calysto.display")
(calysto)
(calysto.display.HTML "This is <b>bold</b>, <i>italics</i>, <u>underlined</u>.")
(import "calysto.graphics")
(calysto)
(define canvas (calysto.graphics.Canvas))
(define ball (calysto.graphics.Circle '(150 150) 100))
(ball.draw canvas)
! ls /tmp
config-err-xKLxlo data.in snap.0_canonical-livepatch_T3qk8v snap.1000_gimp_sWagwQ ssh-CZzILsgWt9Zv systemd-private-42d628edc3bb4937ba24e08da9a82866-bolt.service-MRDb9u systemd-private-42d628edc3bb4937ba24e08da9a82866-colord.service-GxIyqz systemd-private-42d628edc3bb4937ba24e08da9a82866-fwupd.service-uHFZyL systemd-private-42d628edc3bb4937ba24e08da9a82866-iio-sensor-proxy.service-MgIq5B systemd-private-42d628edc3bb4937ba24e08da9a82866-redis-server.service-eDX0r5 systemd-private-42d628edc3bb4937ba24e08da9a82866-rtkit-daemon.service-KzoHbL systemd-private-42d628edc3bb4937ba24e08da9a82866-systemd-resolved.service-M9b7Fe systemd-private-42d628edc3bb4937ba24e08da9a82866-systemd-timesyncd.service-wCU0NV 'Test Dir' www-data-temp-aspnet-0
Here is what the debugger looks like:
It has breakpoints (click in left margin). You must press Stop to exit the debugger.
%%debug
(begin
(define x 1)
(set! x 2)
)
You can import and use any Python library in Calysto Scheme.
In addition, if you wish, you can execute expressions and statements in a Python environment:
(python-eval "1 + 2")
3
(python-exec
"
def mypyfunc(a, b):
return a * b
")
This is a shared environment with Scheme:
(mypyfunc 4 5)
20
You can use func
to turn a Scheme procedure into a Python function, and define!
to put it into the shared enviornment with Python:
(define! mypyfunc2 (func (lambda (n) n)))
(python-eval "mypyfunc2(34)")
34
choose
Calysto Scheme acts as if it has a call stack, for easier debugging. For example:
(define fact
(lambda (n)
(if (= n 1)
q
(* n (fact (- n 1))))))
(fact 5)
Traceback (most recent call last):
File "In [17]", line 1, col 1, in 'fact'
File "In [16]", line 5, col 17, in 'fact'
File "In [16]", line 5, col 17, in 'fact'
File "In [16]", line 5, col 17, in 'fact'
File "In [16]", line 5, col 17, in 'fact'
File "In [16]", line 4, col 12
RunTimeError: unbound variable 'q'
To turn off the stack trace on error:
(use-stack-trace #f)
That will allow infinite recursive loops without keeping track of the "stack".
SCHEMEPATH
("." "/home/dblank/.local/lib/python3.6/site-packages/calysto_scheme/modules")
(set-cdr! (cdr SCHEMEPATH) (list "/var/modules"))
SCHEMEPATH
("." "/home/dblank/.local/lib/python3.6/site-packages/calysto_scheme/modules" "/var/modules")
Note that you can use the word lambda
or \lambda and then press [TAB]
(define factorial
(λ (n)
(cond
((zero? n) 1)
(else (* n (factorial (- n 1)))))))
(factorial 5)
120
(define-syntax NAME RULES): a method for creating macros
(define-syntax time
[(time ?exp) (let ((start (current-time)))
?exp
(- (current-time) start))])
(time (car '(1 2 3 4)))
0.0012819766998291016
;;---------------------------------------------------------------------
;; collect is like list comprehension in Python
(define-syntax collect
[(collect ?exp for ?var in ?list)
(filter-map (lambda (?var) ?exp) (lambda (?var) #t) ?list)]
[(collect ?exp for ?var in ?list if ?condition)
(filter-map (lambda (?var) ?exp) (lambda (?var) ?condition) ?list)])
(define filter-map
(lambda (f pred? values)
(if (null? values)
'()
(if (pred? (car values))
(cons (f (car values)) (filter-map f pred? (cdr values)))
(filter-map f pred? (cdr values))))))
(collect (* n n) for n in (range 10))
(0 1 4 9 16 25 36 49 64 81)
(collect (* n n) for n in (range 5 20 3))
(25 64 121 196 289)
(collect (* n n) for n in (range 10) if (> n 5))
(36 49 64 81)
;;---------------------------------------------------------------------
;; for loops
(define-syntax for
[(for ?exp times do . ?bodies)
(for-repeat ?exp (lambda () . ?bodies))]
[(for ?var in ?exp do . ?bodies)
(for-iterate1 ?exp (lambda (?var) . ?bodies))]
[(for ?var at (?i) in ?exp do . ?bodies)
(for-iterate2 0 ?exp (lambda (?var ?i) . ?bodies))]
[(for ?var at (?i ?j . ?rest) in ?exp do . ?bodies)
(for ?var at (?i) in ?exp do
(for ?var at (?j . ?rest) in ?var do . ?bodies))])
(define for-repeat
(lambda (n f)
(if (< n 1)
'done
(begin
(f)
(for-repeat (- n 1) f)))))
(define for-iterate1
(lambda (values f)
(if (null? values)
'done
(begin
(f (car values))
(for-iterate1 (cdr values) f)))))
(define for-iterate2
(lambda (i values f)
(if (null? values)
'done
(begin
(f (car values) i)
(for-iterate2 (+ i 1) (cdr values) f)))))
(define matrix2d
'((10 20)
(30 40)
(50 60)
(70 80)))
(define matrix3d
'(((10 20 30) (40 50 60))
((70 80 90) (100 110 120))
((130 140 150) (160 170 180))
((190 200 210) (220 230 240))))
(begin
(define hello 0)
(for 5 times do (set! hello (+ hello 1)))
hello
)
5
(for sym in '(a b c d) do (define x 1) (set! x sym) (print x))
a b c d
done
(for n in (range 10 20 2) do (print n))
10 12 14 16 18
done
(for n at (i j) in matrix2d do (print (list n 'coords: i j)))
(10 coords: 0 0) (20 coords: 0 1) (30 coords: 1 0) (40 coords: 1 1) (50 coords: 2 0) (60 coords: 2 1) (70 coords: 3 0) (80 coords: 3 1)
done
(for n at (i j k) in matrix3d do (print (list n 'coords: i j k)))
(10 coords: 0 0 0) (20 coords: 0 0 1) (30 coords: 0 0 2) (40 coords: 0 1 0) (50 coords: 0 1 1) (60 coords: 0 1 2) (70 coords: 1 0 0) (80 coords: 1 0 1) (90 coords: 1 0 2) (100 coords: 1 1 0) (110 coords: 1 1 1) (120 coords: 1 1 2) (130 coords: 2 0 0) (140 coords: 2 0 1) (150 coords: 2 0 2) (160 coords: 2 1 0) (170 coords: 2 1 1) (180 coords: 2 1 2) (190 coords: 3 0 0) (200 coords: 3 0 1) (210 coords: 3 0 2) (220 coords: 3 1 0) (230 coords: 3 1 1) (240 coords: 3 1 2)
done
(define-syntax scons
[(scons ?x ?y) (cons ?x (lambda () ?y))])
(define scar car)
(define scdr
(lambda (s)
(let ((result ((cdr s))))
(set-cdr! s (lambda () result))
result)))
(define first
(lambda (n s)
(if (= n 0)
'()
(cons (scar s) (first (- n 1) (scdr s))))))
(define nth
(lambda (n s)
(if (= n 0)
(scar s)
(nth (- n 1) (scdr s)))))
(define smap
(lambda (f s)
(scons (f (scar s)) (smap f (scdr s)))))
(define ones (scons 1 ones))
(define nats (scons 0 (combine nats + ones)))
(define combine
(lambda (s1 op s2)
(scons (op (scar s1) (scar s2)) (combine (scdr s1) op (scdr s2)))))
(define fibs (scons 1 (scons 1 (combine fibs + (scdr fibs)))))
(define facts (scons 1 (combine facts * (scdr nats))))
(define ! (lambda (n) (nth n facts)))
(! 5)
120
(nth 10 facts)
3628800
(nth 20 fibs)
10946
(first 30 fibs)
(1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040)
(for-each PROCEDURE LIST): apply PROCEDURE to each item in LIST; like map
but don't return results
(for-each (lambda (n) (print n)) '(3 4 5))
3 4 5
(format STRING ITEM ...): format the string with ITEMS as arguments
(format "This uses formatting ~a ~s ~%" 'apple 'apple)
"This uses formatting apple apple \n"
(func (lambda (n) n))
<function dlr_func.<locals>.f at 0x7fc499d3c2f0>
Please see Calysto Scheme Language for more details on the Calysto Scheme language.