Scheme learning

1. Description

  • This is my own learning doc for scheme lisp, and further on guile, GNUs scheme system for integration into their programs

2. Recources

3. first small example

3.1. hello world

(newline)
(display "Hello, World!")
(newline)

Display takes the argument given and display on the screen, like echo or printf newline is newline, like \n the action is always first, so after a (, you cant do (deisplay "Hello" newline), because for newline to do newline it needs to be ran, and that only happends if its first so (action => argument) ) to close it again

3.2. basic math

(newline)
(display (+ 3 3) ) (newline)
(display (* 3 3) ) (newline)
(display (- 3 3) ) (newline)
(display (/ 3 3) ) (newline)

-, *, / and + are as they reprecent, simple math opperators (here i did display and newline to easily show what it does) you can also nest it

(newline)
(display (* (/ 20 4)(- 7 2)))(newline)

4. variables

4.1. define

(newline)
(define variable_name "variable content")

(display variable_name)(newline)

Here we define the variable variablename to have the value "variable content" and print it just to check that it is indeed just that. to define a variable you start with define, then the variable name and then the content of the variable.

(newline)
(define root
  (* 3 3))
(display "root is: ")(display root)
(newline)

defina also let you do stuff and set the outcome of that as the var value then you can later do an if, cond … to set it too

now let us define and use later

(newline)
(define (rooter r)
    (* r r))
(display "Square is: ")
(display (rooter 6))
(newline)

here i said rooter accepts an value, r then use that in a math expression, r * r

4.2. let

(newline)
(let ((total 200))
  (let ((tenth (/ total 10)))
    (display "Tenth of total is: ")
    (display tenth)))
(newline)
;; the variable tenth doesnt exist here, because we escaped the block

let is a temp variable, so using (define defines it globally, but (let is locally lice "local var=value" in bash

4.3. list

(newline)
(define name-list '(Nusse Sigster Hanne HH))
(define (print-lines values)
  (cond
   ((null? values)
    (display "list empty")
    (newline))
   (else
    (display "value: ")
    (display (car values))
    (newline)
    (print-lines (cdr values)))))

(print-lines name-list)
  1. make a list, the ' before () tells it to treat the conetnt as is
  2. make a function to display lines
  3. if no lines say so
  4. else, so if lines
    • display current value
    • call itself and tell it to use next value
  1. cdr return rest of a list
  2. car return first value of list

5. conditions

5.1. If condition

(if test-condition then-result else-result)

(newline)
(let ((var 3))
  (if (= var 3)
      (display "Hi!")
      (display "Goodbye!")))
(newline)

Here is an simple if condition First i make a variable var and set it to the value 3 Then i check (if var is equal to 3 If it is 3 then say hi Else say Goodbye One can also say (display (if condition …)) then it displays the output #t = true #f = false, 0 is not false

  (newline)
(let (
      (var1 2)
      (var2 6)
      (var3 4))

  (display (if (= var2 var3)
               (+ var1 var3)
               (- 1 1))))
(newline)

Here it will return unspecified, because newline returns an nil value, and then the display try to display that because display returns no value, just prints one

5.2. cond (case statements++)

  (newline)
(let (
      (varcond1 1)
      (varcond2 2))
  (cond
   ((= varcond1 1)(display "cond 1 = 1")(newline))
   ((= varcond2 2)(display "cond 2 = 2")(newline))
   (else          (display "weird")     (newline))))

If condition then… here i check if the variable is equal to a number, or value then display based on that If none of the conditions are met it's else, display weird

(newline)
(let ((temp 1))

  (display
   (cond ((> temp 20)  "It's too hot"           )
         ((> temp 10)  "It's perfect"           )
         ((< temp -10) "It's perfect and better")
         ((even? temp) "It's alright and even " )
         (else         "idk!"                   ))))
(newline)

here i check and display the resoult if temp is over 20 then… same with between 10 and 20 then if temp is under -10 … even? checks if the number is even, so 2 return #t and 3 return #f if none of the conditions are met then idk

  • (odd? x),Is it an odd number?
  • (zero? x),Is it exactly 0?
  • (positive? x),Is it greater than 0?
  • (integer? x),Is it a whole number (no decimals)?
  • (number? x),Is this thing even a number at all?

you need to pass a number value to these to get #t

6. Read, not just write

6.1. Now get user input

(newline)
(display "What's your name: ")
(let ((name (read)))
  (display name))
(newline)

Here i first ask something with display then create a temp variable asign name to the user input, read just does what it says display the name

6.2. combining some things to do a simple opperation

(newline)
(define (ask-it) ; make the function
  (display "number to square: ")
  (force-output) ; sometimes it buffers text to use later, so this forces its use now
  (let ((valg (read))) ;get user input
    (cond
     ((number? valg) ;if number then square, defined this function earlier
      (display "result: ")
      (display (rooter valg))
      (newline))
     (else (display "Hey, that wasn't a number!\n"))) ;if not number tell so
  (newline)))
(ask-it) ;use the function
(newline)
  1. here i:
    1. define a global function
    2. make a temp variable
    3. cond statement
    4. if number then square the user input
    5. if not number say so
    6. call the function

6.3. recursion over list

Now let us use this with a list

(newline)
(define (use-numbers list-number-use)
  (cond
   ((null? list-number-use)(display "no more numbers")(newline)) ;if no numb/val then...
   (else
    (display "num: ")
    (display (car list-number-use)) ;if num display first val of list
    (newline)
    (use-numbers (cdr list-number-use))))) ;set list to all remioaning val

(display "prints list")
(display "Type a list of things inside brackets like (1 2 3): ")
(force-output)
(let ((list-number-use (read))) ;temp var red user input
  (use-numbers list-number-use)) ;tell it to use the function with the var

Here i do a few diffrent things, first i:

  1. make a function
  2. check if the list is empty
  3. if list has stuff then display first
  4. remove first value of the list from the list
  5. let var read, temp val user input
  6. use function with list given

Fast math on list

(newline)
(define (fun-list-math var)
  (if (null? var) ; if passed liust is empty then exit
      (begin ;just to show can be more
        0)
      (+ (car var) ; if not then add first from value
         (fun-list-math (cdr var))))) ; remove used

(display "add numbers")
(display "Type a list of things inside brackets like (1 2 3): ")
(force-output)
(let ((list-number-use (read))) ;temp var red user input
  (display (fun-list-math list-number-use))) ;tell it to use the function with the var

Here we simply add all numbers in list recursivly, and so we can also do other actions like modifying the list as we go

But as you saw here you need (then the list) insted of just typing the list, and thats because read would read it bas a string if we didnt include the parantecies

7. filtering

(newline)
(define (only-evens var)
  (cond
   ((null? var) '())  ;if empty break
   ((even? (car var)) ;if even add to list
    (cons (car var) (only-evens (cdr var)))) ;add first to list and rst of list
   (else
    (only-evens (cdr var))))) ;if not even skip

(display "filter even numbers")
(display "Type a list of things inside brackets like (1 2 3): ")
(force-output)
(let ((list-number-use (read))) ;temp var red user input
  (display (only-evens list-number-use))) ;tell it to use the function with the var

If empty break from loop If number is even remian in list and add rest back to list If not even skip and add rest to list Display end list

(let
    ((lists
      '(1 4 2 6 4 8))) ; make list
  (display ; display output
   (filter ; filter
    (lambda
        (nummer) ; nummer is local var to indicate what it uses
      (> nummer 3)) ; if number is greater than 3 than pass
    lists))) ; what list to filter

Simple list filtering using the filter function

8. simple note app

The goal here is to read notes, add notes, remove notes

(define (my-read-line)
  (let loop ((chars '()))  ; temp var loop thats an empty list char by char
    (let ((charachter (read-char))) ; reads it charachter by charachter
      (cond
       ((eof-object? charachter)
        (if (null? chars) charachter (list->string (reverse chars)))) ; if no mor char then done
       ((char=? charachter #\newline)                                 ; if newline
        (list->string (reverse chars)))                      ; combine chars into a string
       (else
        (loop (cons charachter chars))))))) ; if not done continue

(if (not (file-exists? "note"))    ; if file doesnt exist create it
    (with-output-to-file "note" (lambda () (display ""))))

(define (get-all-notes)          ; turn each line into a string
  (with-input-from-file "note"   ; get from file named note
    (lambda ()
      (let loop ((line (my-read-line)) (acc '())) ; add line by line to a list, with the charchter by charachter reader from above
        (if (eof-object? line)                    ; if no more lines/end of file then reverse list (as scheme adds in reverse, not "correct" order)
            (reverse acc)
            (loop (my-read-line) (cons line acc)))))))

(define (show-notes)                  ; prints notes in list
  (let ((notes (get-all-notes)))      ; make var notes with each note line from dunc above
    (newline)
    (display "--- CURRENT NOTES ---") (newline)
    (if (null? notes)                 ; if notes = 0 then no
        (display "(No notes found.)")
        (let loop ((lst notes) (i 1)) ; for every string
          (if (not (null? lst))       ; !=0
              (begin
                (display i) (display ". ")    ; print number.
                (display (car lst)) (newline) ; print note line
                (loop (cdr lst) (+ i 1))))))  ; add 1 to the i counter
    (display "----------------------") (newline)))

(define (save-note)
  (read-char)                   ; read char
  (display "Enter your note: ")
  (let ((new-note (my-read-line)))         ; temp var new note with my read line
    (let ((current-list (get-all-notes)))  ; set current list to all note lines
      (with-output-to-file "note"          ; select file to output to
        (lambda ()
          (for-each (lambda (notat) (display notat) (newline))       ; for each line display and go newline
                    (append current-list (list new-note))))) ; take current list and add new note
      (display "Success: Note saved.") (newline))))

(define (clear-all-notes) ; just deletes old note file and makes new
  (delete-file "note")
  (with-output-to-file "note" (lambda () (display "")))
  (display "All notes deleted.") (newline))

(define (remove-at-index lst index) ; remove file at numbered line
  (let loop ((current-list lst) ; list
             (current-index 1)  ; index (line + num in front)
             (acc '()))
    (cond
     ((null? current-list) (reverse acc))
     ((= current-index index)            ; if line same index as user input skip it
      (loop (cdr current-list) (+ current-index 1) acc))
     (else
      (loop (cdr current-list) (+ current-index 1) (cons (car current-list) acc)))))) ; otherwise add

(define (delete-note) ; delete selected note
  (show-notes)
  (display "Enter the number of the note to delete: ")
  (let ((num (read))) ; read num
    (let* ((old-notes (get-all-notes)) ;gets notes and list
           (new-notes (remove-at-index old-notes num)))
      (with-output-to-file "note" ; write new list to file
        (lambda ()
          (for-each (lambda (notat) (display notat) (newline)) ; for each line in file display num with line
                    new-notes)))
      (display "Note ") (display num) (display " deleted.") (newline)))) ; when done tell so


(define (startup) ; function to pick which option to use
  (newline)(newline)
  (display "--- CuteNote Menu ---") (newline)
  (display "1: show notes")         (newline)
  (display "2: new note")           (newline)
  (display "3: remove note")        (newline)
  (display "4: remove all notes")   (newline)
  (display "5: exit")               (newline)
  (display "---------------------") (newline)
  (display "> ")

  (let ((valg (read))) ; if the option is picked call the function
    (cond
     ((= valg 1) (begin (show-notes)      (startup)))
     ((= valg 2) (begin (save-note)       (startup)))
     ((= valg 3) (begin (delete-note)     (startup)))
     ((= valg 4) (begin (clear-all-notes) (startup)))
     ((= valg 5)        (display "Goodbye!"        ))
     (else
      (display "Invalid choice, try again.")
      (startup))))                         )

(startup) ; calls startup

I explained it in comments

9. End notes

LISP WILL ONCE AGAIN RULE THE WORLD, DOWN WITH THE TYRANICAL DICTATOR AND OPPERSIVE C, RUST AND PYTHON!

9.1. This is just learning notes++

Author: Alice (trondelagcutie@yahoo.com)

Date: 2025

Emacs 30.1 (Org mode 9.7.11)

Validate