Scheme learning
Table of Contents
Propriatary means malware for the masses
1. Description
- This is my own learning doc for scheme lisp, and further on guile, GNUs scheme system for integration into their programs
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)
- make a list, the ' before () tells it to treat the conetnt as is
- make a function to display lines
- if no lines say so
- else, so if lines
- display current value
- call itself and tell it to use next value
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)
- here i:
- define a global function
- make a temp variable
- cond statement
- if number then square the user input
- if not number say so
- 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:
- make a function
- check if the list is empty
- if list has stuff then display first
- remove first value of the list from the list
- let var read, temp val user input
- 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
8.1. read-line
(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
8.2. Create file
Here it reads the line char by char into a list, reverse the list and sets it as a string This is because it adds the new item to the list first, as that's just faster
(if (not (file-exists? "note")) ; if file doesnt exist create it (with-output-to-file "note" (lambda () (display ""))))
8.3. List notes
If file note does't exist make one
(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)))))))
8.4. show notes
Read from file note Loop over all the lines, where you use my-read-line on each line and add to list If at end of line end Reverse the list Remove line from list to be parsed, go to next
(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)))
8.5. New note
Use previous function to read the notes into a list If no items in list end Display index. then the line string content Go to next item in list and increese index by 1
(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))))
8.6. Delete all notes
Write new note string Get current notes and add to list Add newest note you wrote as a string to the list Write to note, go over and add the lines to the file, one string per line
(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))
8.7. Remove specified note
Delete old file and make new blank file
(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
8.8. Delete indexed note
Get note list and index it If prompted input index number skip that line Otherwise add all index lines to list
(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
8.9. Startupmenu
Take user input and look at notes, skip specified index numbered list memeber Write new list to file
(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
Prints option and index to choose from, Do action connected to indexed number picked before