Scheme notes

Notes

  • tinyscheme has some functions missing unless init.scm is added to the current directory. (*) means that implementation needs init.scm.

First item of a list

Scheme

(car list)

Clojure

(first list)

All items except the first

Scheme

(cdr list)

Clojure

(rest list)

Prepend item to list

Scheme

(cons '(1 2 3 4))

Clojure

(first [1 2 3 4])

Scheme

(display "Hello, world!\n")

Clojure

(println "Hello, world!\n")

Open REPL

Scheme

chezscheme [FILE]

Clojure

lein repl

Run file

Scheme

chezscheme --script [FILE]

Clojure

lein run

Compile a

Scheme

csc [FILE]

Clojure

lein uberjar

Apply a function to all elements of list

Scheme

(map add1 '(1 2 3 4))
; => (2 3 4 5)

Clojure

(map inc [1 2 3 4])
; => [2 3 4 5]

Apply a function for all the items in pairs

Scheme

(define reduce
  (lambda (fn list)
	((null? list) '())))
 
(reduce + '(1 2 3 4 5))
;; => 15

Clojure

(reduce + [1 2 3 4 5])
;; => 15

Check for empty list

Scheme

(null? list)

Clojure

(empty? list)

Combine strings

Scheme

(string-append "hello" "world")
; => "helloworld"

Clojure

(str "hello" "world")
; => "helloworld"

If statement

Scheme

(cond
 ((> 1 2) #t)
 (else #f))

or (*)

(if (> 1 2)
	#t
	#f)

Clojure

(if (> 1 2)
	true
	false)

Do one operation after the other

Scheme

(begin
 (+ 1 2)
 (+ 2 3))

Clojure

(do
 (+ 1 2)
 (+ 2 3))

If statement with multiple operations

Scheme

(when #t
	(+ 1 2)
	(+ 3 4))

Clojure

(when true
	(+ 1 2)
	(+ 3 4))

Check for equality

(equal? 1 "Hello")
;; => #f

Clojure

(= 1 "Hello")
;; => false

Assign variable

(define name "Michael")
name
; => Michael
(def name "Michael")
name
; => Michael

Define function

(define add1
  (lambda (x)
	(+ 1 x)))

(add1 7)
; => 8
(defn add1
	[x]
	(+ 1 x))

(add1 7)
; => 8

Hash tables/maps

Scheme

R5RS doesn't really include hash tables (it was included in R6RS). Some Scheme implentations have them by adding SRFI 69 but the most basic Schemes don't have it. A (less efficient) alternative are (improper) association lists:

(define person
  '((first-name . "John")
  (last-name . "Smith")))

person
; => (("first-name" . "John") ("last-name" . "Smith"))

Clojure

(def person
  {:first-name "John"
  :last-name "Smith"})

person
; => {:first-name "John", :last-name "Smith"}

Create hash-map

Scheme

Equivalent with association lists:

(define alist
 (lambda args
   (cond
    ((null? args) '())
    (else
     (cons (cons (car args) (cadr args))
           (apply alist (cddr args)))))))

(alist 'a '1 'b '2)

Clojure

(hash-map :a 1 :b 2)

Pass list as arguments

Scheme

(apply + '(1 2 3))

Clojure

(apply + [1 2 3])

Nested hash maps

Scheme

'(name ((first . "John") (middle . "Jacob") (last . "Smith"))

Clojure

"{:name {:first "John" :middle "Jacob" :last "Smith"}}"

Create hash map accepting nested hash maps

Scheme

(define alist
 (lambda args
   (cond
    ((null? args) '())
    ((list? (cadr args))
     (cons (cons (car args) (list (cadr args)))
           (apply alist (cddr args))))
    (else
     (cons (cons (car args) (cadr args))
           (apply alist (cddr args)))))))


(alist 'name '((first . "John") (middle . "Jacob") (last . "Smith")))

Clojure

(hash-map :name {:first "John" :middle "Jacob" :last "Smith"})

Equivalences

Scheme*

If comparing… then use…
numbers =
non numeric eqv?
strings string=?(*)
lists equal?
don't use eq?

Look up values

Scheme

(define get
  (lambda (alist key)
    (cdr (assoc key alist))))

(get '((a . 0) (b . ((c . "ho hum")))) 'b)
; => ((c . ho hum))

technically, Scheme also accepts:

(get '((:a . 0) (:b . ((:c . "ho hum")))) 'b)

but

  • 'a in Scheme is a symbol
  • Clojure has symbols and keywords
    • :a in Clojure is a keyword, not a symbol

Clojure

(get {:a 0 :b {:c "ho hum"}} :b)
; => {:c "ho hum"}

Write to file

Scheme(*)

(call-with-output-file "out.txt"
  (lambda (p)
    (begin
      (write "Hello, world!" p)
      (newline p))))

Check if file exists

Scheme

Not the most elegant but I think should work.

(define file-exists?
  (lambda (file)
    (let ((port (open-input-file file)))
          (if (port? port)
            (close-input-port port)
            #f))))

(file-exists? "/bin/bash")
; => #t
(file-exists? "/bin/bosh")
; => #f