;;; Kode fra PVVs Lisp-kurs 2012-10-25.

;;; Vi leker litt med REPL-en

245
(+ 6 15)
(+ 3 5 24 72)
(* 3 4)
(- 20 14)
(+ (* 3 4) (- 20 14))
(sqrt 16)
(sqrt 34)

;;; Vi lager nye funksjoner

(defun square (x) (* x x))

;;; En større funksjon

(defun hypothenuse (side1 side2)
  (sqrt (+ (square side1) (square side2))))

;;; IF og tester

(defun gjett (tall)
  (if (= tall 42)
      "riktig"
      "galt"))

;;; Eksempel: Fakultet

(defun factorial (n)
  (if (= n 0)
      1
      (* n
         (factorial (- n 1)))))

;;; Eksempel: Fibonacci

(defun fib (n)
  (if (< n 2)
      1
      (+ (fib (- n 1))
         (fib (- n 2)))))

;;; Lister

(list 1 2 3)
(list 24)
(list (list 3 5 7) (list 2 3))
(list)

;;; Sitering

(+ 4 38)
'(+ 4 38)
pi
'pi

;;; Formatert utskrift

(format t "Svaret er ~A.  (Men hva er spørsmålet?)~%"
        42)

(format t "Noen objekter: ~A, ~A, ~A.~%"
        '(a b c)
        50
        "foobar")

;;; Lokale variabler: LET

(let ((x 17)
      (y 38))
  (list x y (+ x y) (* x y)))

;;; Endring av variabler: SETF

(let ((x 3)
      (y 5))
  (format t "~A = ~A, ~A = ~A~%"
          'x x 'y y)
  (setf x (+ x y))
  (setf y (list 1 2 3))
  (format t "~A = ~A, ~A = ~A~%"
          'x x 'y y))

;;; Spesielle variabler

(defvar *foo* 42)

(defun print-foo ()
  (format t "foo = ~A~%" *foo*))

(defun dostuff ()
  (let ((*foo* 0))
    (print-foo)
    (setf *foo* 5)
    (print-foo))
  (print-foo))

;;; Mer om SETF

(defvar *the-list* (list 'foo 'bar 'baz))
(setf (first *the-list*) 'flaff)

;;; Vi plukker lister fra hverandre ...

(first '(a b c d))
(rest '(a b c d))
(first (rest '(a b c d)))
(first (rest (rest '(a b c d))))

;;; ... og setter dem sammen igjen

(defvar *list* (list 'a 'b 'c 'd))
(cons (first *list*) (rest *list*))

;;; Den tomme listen: NIL

(cons 'foo nil)
(cons 'foo (cons 'bar nil))

;;; Funksjonen NULL

(null nil)
(null '(a b c))

;;; Eksempel: Sum av en liste med tall

(defun sum (list)
  (if (null list)          ; Hvis listen er tom
      0                    ; er dens sum 0,
      (+ (first list)      ; ellers første tall pluss
         (sum              ; summen av
          (rest list)))))  ; resten av listen.

;;; Eksempel: Kvadratene av alle tall i en liste

(defun list-of-squares (numbers)
  (if (null numbers)
      nil
      (cons (square (first numbers))
            (list-of-squares (rest numbers)))))

;;; En for-løkke

(loop
  for i from 1 to 10
  do (format t "~A~%" i))

;;; En while-løkke

(let ((x 1))
  (loop
     while (> x 0)
     do (format t "Square root: ~A~%" (sqrt x))
     do (format t "New value:~%")
     do (setf x (parse-integer (read-line)))))

;;; En do-while-løkke

(loop
  do (format t "Continue?~%")
  while (string= (read-line) "yes"))

;;; En foreach-løkke

(loop
  for x in '(foo bar baz quux)
  do (format t "Element: ~A~%" x))

;;; Kombinasjon av flere typer løkker

(loop
  for i from 0
  for x in '(foo bar baz quux stop-here moo moo moo)
  while (not (eq x 'stop-here))
  do (format t "Element ~A: ~A~%" i x))

;;; Oppsamling av verdier

(defun iota (n)
  (loop
     for i from 0 to n
     collect i))

;;; Betingelser

(defun divisors (n)
  (loop
     for i from 1 to n
     if (= (mod n i) 0)
     collect i))

;;; Høyereordens funksjoner

(sort (list 5 2 17 8 9 24 12) #'<)
(sort (list 5 2 17 8 9 24 12) #'>)

;;; MAPCAR

(mapcar #'square (list 4 9 32))

;;; REMOVE-IF

(remove-if #'symbolp '(a 5 b 32 c 4))

(mapcar #'square (remove-if #'symbolp '(a 5 b 32 c 4)))

;;; Anonyme funksjoner: LAMBDA

(mapcar (lambda (x) (list x (sqrt x))) (list 16 24 56))