Lisp: Difference between revisions

From bibbleWiki
Jump to navigation Jump to search
Line 561: Line 561:
Watching a video (don't use the brand haha) [https://www.youtube.com/watch?v=ymSq4wHrqyU&t=2671s Derek Banas] we see his explanation at 45:34<br>
Watching a video (don't use the brand haha) [https://www.youtube.com/watch?v=ymSq4wHrqyU&t=2671s Derek Banas] we see his explanation at 45:34<br>
<br>
<br>
[[File:Flet.png]]
[[File:Flet.png]]<br>
<br>
Here we have defined local functions, double-it, triple-it to a local area
<syntaxhighlight lang="lisp">
<syntaxhighlight lang="lisp">
(flet ((double-it (num)
    (* 2 num))
    (triple-it (num)
    (* 3 num)))
    (format t "Double & Triple 10 = ~d~%" (triple-it(double-it 10))))
</syntaxhighlight>
</syntaxhighlight>

Revision as of 00:38, 8 September 2024

Introduction

This is a quick tour on lisp. I decided to look at this because of the build a compiler youtube by lens_r which made me feel I am missing something. This has been rabbit hole which I have fallen done

Useful Links

Not gonna type forever whilst someone else already has. I remember by typing but here is a more professional approach Lisp Works

Concepts

This is my view and maybe wrong but to me the first thing I noticed was the huge amount of parentheses which are involved. It made the language look really ugly and made me feel don't do this. I think I have touched this in the past because of a gun to my head. That said, like people, you probably need to understand before having a view, and even then, not for you is a better view and it is negative. So here is the half day I spent

I have a lot of trouble reading the manuals for anything. YouTube has been a god send for me along with examples. If there are youtuber out there please make a video on how to read the manual. Probably all me but this is written in greek to me. I probably give up too easily

flet ((function-name lambda-list [[local-declaration* | local-documentation]] local-form*)*) declaration* form*

Comments

;;;; Describe Program 4 semi colons
;;; Comments

;; Indented Comments

#|| Multiline
My Comments
||#

Format to terminal

(format t "Hello World ~%")

Print

(print "Hello World")

Variables

To declare

(defvar *my-variable* "Hello World" )

It is common practice for local variable to have asterixes

We can declare variables for functions too, in this case read-data now is the built-in read function.

(defvar *read-data* (read))

Functions

We can of course define functions. So putting the above together we are prompted for a value and it prints it to the terminal. Not the ~% is the linefeed in list and ~a is a formatter like printf

(defvar *read-data* (read))

(defun read-and-print (name)
  (format t "Read and Print value is ~a ~%" name))

(read-and-print *read-data*)

Changing values of variables

We use setf to change the values of existing variables

(defvar *read-data* (read))
;; You can change a value using setf
(setf *read-data* "Hello World 1")
(read-and-print *read-data*)
(setf *read-data* "Hello World 2")
(read-and-print *read-data*)

Formatting

This is like printf

(format t "PI to 5 characters is ~5f ~%" 3.14159)
(format t "PI to 4 decimal places is ~,4f ~%" 3.14159)

Cells

A Cell, I think is a set of parentheses and we can embed them inside each other. So

(format t "Text with this ~d ~%" (+ 5 4))
; Add a cell within a cell
(format t "Text with this ~d ~%" (+ 5 (+ 4 3)))
;; and again
(format t "Text with this ~d ~%" (+ 5 (+ 4 (+ 100 5))))

Maths Stuff

Just some examples. This is a whirlwind tour not a tutorial

(format t "Modulus of 10/3 is ~d ~%" (mod 10 3))
(format t "Remainder of 10/3 is ~d ~%" (rem 10 3))
;; All work the same way e.g. sqrt
(format t "Square root of 9 is ~d ~%" (sqrt 9))
;; and floor
(format t "Floor of 9.9 is ~d ~%" (floor 9.9))

The blasted quote

I had to read about this because of my stuffed up brain. In lisp there is some referred to as a quote. And they kept mentioning shorthand but they were incredible unclear what for. and it what the function quote. What they meant is ` means quote ()

(format t "Quote is ~a ~%" (+ 1  2)) ; Quote is 3
(format t "Quote is ~a ~%" (quote (+ 1 2))) ; Quote is (+ 1 2) 
(format t "Quote is ~a ~%" `(+ 1 2)) ; Quote is (+ 1 2)

Equality

Equality in Lisp has three approaches

  • For symbols we use eq
  • For numbers we use =
  • For strings we use equal
;; Symbols
(format t "Are 'hello' and 'hello' equal? ~a ~%" (eq 'hello 'hello))

;; Numbers
(format t "Are 1 and 1 equal? ~a ~%" (= 1 1)) ; T
(format t "Are 1 and 2 equal? ~a ~%" (= 1 2)) ; NIL

;; Strings
(format t "Are 'hello' and 'hello' equal? ~a ~%" (equal "hello" "hello"))

We can compare things with the same value but presented differently with equalp

;; equalp is used to compare numbers
(format t "Are 1 and 1.0 equal? ~a ~%" (equalp 1 1.0)) ;T
(format t "Are 1.01 and 1.010 equal? ~a ~%" (equalp 1.01 1.010)) ;T
(format t "Are 1.010 and 1.01 equal? ~a ~%" (equalp 1.010 1.01)) ;T

;; for strings for case insensitive
(format t "Are 'hello' and 'HELLO' equal? ~a ~%" (equalp "hello" "HELLO")) ;T

Lists

Seemed a big deal in Lisp. I guess most of this is self explanatory

Simple Lists

;; Create a list
(defvar *my-list* (list 0 1 2 3 4 5))

;; Print the list
(format t "List is ~a ~%" *my-list*)

;; Get the first element
(format t "First element is ~a ~%" (first *my-list*))

;; Get the rest of the list
(format t "Rest of the list is ~a ~%" (rest *my-list*))

;; Get the second element
(format t "Second element is ~a ~%" (second *my-list*))

;; Get the third element
(format t "Third element is ~a ~%" (third *my-list*))

;; Using nth
(format t "Third element is ~a ~%" (nth 2 *my-list*))
 
;; Using car
(format t "First element is ~a ~%" (car *my-list*))

;; Using cdr
(format t "Rest of the list is ~a ~%" (cdr *my-list*))

;; Using cadr (get first element of rest)
(format t "Second element is ~a ~%" (cadr *my-list*))

;; Using caddr (get second element of rest)
(format t "Third element is ~a ~%" (caddr *my-list*))

;; Using caddr (get third element of rest)
(format t "Fourth element is ~a ~%" (cadddr *my-list*))


;; Are we a list?
(format t "Is a list? ~a ~%" (listp *my-list*))

;; Is value a list?
(format t "Is a list? ~a ~%" (listp 1))

;; Append to a list
(format t "Append to list ~a ~%" (append *my-list* (list 6 7 8 9 10)))

;; Concatenate lists
(format t "Concatenate lists ~a ~%" (concatenate 'list *my-list* (list 6 7 8 9 10)))

;; Reverse a list
(format t "Reverse list ~a ~%" (reverse *my-list*))

;; Sort a list
(format t "Sort list ~a ~%" (sort *my-list* #'<))

;; Create a list of lists
(defvar *my-list-of-lists* '((1 2 3) (4 5 6) (7 8 9)))

;; Remove duplicates
(format t "Remove duplicates ~a ~%" (remove-duplicates (list 1 1 2 2 3 3 4 4 5 5)))

Splicing

Not sure my odds of remembering. The @ after a comma within quote - yes I know, then the form following the at-sign is evaluated to produce a list of objects

;; Create a list
(defvar *my-list* (list 0 1 2 3 4 5))

;; a reminder of rest which mean everything but the first like javascript
(format t "List with rest is ~a ~%" (rest *my-list*))

;; Splice a list

;; List with 0 is (0 1 2 3 4 5) 
(format t "List with 0 is ~a ~%" `(0 ,@(rest *my-list*)))

;; List with 2 is (2 1 2 3 4 5) 
(format t "List with 2 is ~a ~%" `(2 ,@(rest *my-list*)))

Association list or A-list

The minute they use a fancy word I get stuffed and have to google. So I think what they mean is a list with key value having a key and a value. They go on about car and cdr

(defparameter *my-heroes* `( (superman . "Clark Kent")
                             (batman . "Bruce Wayne")
                             (spiderman . "Peter Parker")))

; List is ((SUPERMAN . Clark Kent) (BATMAN . Bruce Wayne) (SPIDERMAN . Peter Parker)) 
(format t "List is ~a ~%" *my-heroes*) 

; Assoc (SUPERMAN . Clark Kent) 
(format t "Assoc ~a ~%" (assoc 'superman *my-heroes*))

Another approach to achieve the same thing

;; second approach wih cons
(defparameter *marks* (list (cons 'kishan 96) (cons 'saksham 92)))

;2 List is ((KISHAN . 96) (SAKSHAM . 92)) 
(format t "2 List is ~a ~%" *marks*)

;2 Assoc (KISHAN . 96) 
(format t "2 Assoc ~a ~%" (assoc 'kishan *marks*))

Functions 2

Here some examples

Simple example

;; Get average
(defun get-average (a b)
  (/ (+ a b) 2))

(format t "Average is ~a ~%" (get-average 10 20))

Multiple Arguments

We can simulate vargs

;; Rest parameters is like varargs
(defun get-average-rest (&rest numbers)
  (/ (apply #'+ numbers) (length numbers)))

(format t "Average is ~a ~%" (get-average-rest 10 20 30 40 50))

Optional Arguments

Here we can either pass b or not

(defun get-average-optional (a &optional b)
  (if b
      (/ (+ a b) 2)
      a))

; Average is with B 15 
(format t "Average is with B ~a ~%" (get-average-optional 10 20))

; Average is without B 10
(format t "Average is without B ~a ~%" (get-average-optional 10))

Return value

By default the return value is the last statement executed. To override this we use the keyword return-from and the function name

(defun get-average-return (a b)
  (return-from get-average-return (/ (+ a b) 2)))

Flow Control

This is why I am doing this because of the word continuation. Here are some lispy controls

If Statements

For if statements Special Forms

Case Statements

(case 1
  (1 (format t "1 ~%"))
  (2 (format t "2 ~%"))
  (3 (format t "3 ~%"))
  (t (format t "Not 1, 2 or 3 ~%")))

When, Unless and Loops

;; When   
(when (= 1 1)
  (format t "1 is equal to 1 ~%"))

;; Unless
(unless (= 1 1)
  (format t "1 is not equal to 1 ~%"))

;; Loops
;; Loop with for
(loop for i from 1 to 10
  do (format t "Hello ~%"))

;; Loop with repeat
(loop repeat 10
  do (format t "Hello ~%"))

;; dotimes
(dotimes (i 10)
  (format t "Hello ~%"))

cond

Like this one

;; Using cond
(cond
  ((= 1 1) (format t "1 is equal to 1 ~%"))
  ((= 2 2) (format t "2 is equal to 2 ~%"))
  (t (format t "Not 1 or 2 ~%")))

Fun with Cars

car

So for car this is simple

(defvar *my-list* (list 0 1 2 3 4 5))
; Returns first element in list i.e. 0
(format t "First element is ~a ~%" (car *my-list*))

cdr (pronounced cudder)

So for cdr is just the rest

(defvar *my-list* (list 0 1 2 3 4 5))
; Returns rest of the elements in list i.e. 1 2 3 4 5
(format t "First element is ~a ~%" (cdr *my-list*))

All the combinations

Found a page which seems to explain the unexplainable. To understand the terms now we need to understand

This place ... Is equivalent to this place ...
(caar x) (car (car x))
(cadr x) (car (cdr x))
(cdar x) (cdr (car x))
(cddr x) (cdr (cdr x))
(caaar x) (car (car (car x)))
(caadr x) (car (car (cdr x)))
(cadar x) (car (cdr (car x)))
(caddr x) (car (cdr (cdr x)))
(cdaar x) (cdr (car (car x)))
(cdadr x) (cdr (car (cdr x)))
(cddar x) (cdr (cdr (car x)))
(cdddr x) (cdr (cdr (cdr x)))
(caaaar x) (car (car (car (car x))))
(caaadr x) (car (car (car (cdr x))))
(caadar x) (car (car (cdr (car x))))
(caaddr x) (car (car (cdr (cdr x))))
(cadaar x) (car (cdr (car (car x))))
(cadadr x) (car (cdr (car (cdr x))))
(caddar x) (car (cdr (cdr (car x))))
(cadddr x) (car (cdr (cdr (cdr x))))
(cdaaar x) (cdr (car (car (car x))))
(cdaadr x) (cdr (car (car (cdr x))))
(cdadar x) (cdr (car (cdr (car x))))
(cdaddr x) (cdr (car (cdr (cdr x))))
(cddaar x) (cdr (cdr (car (car x))))
(cddadr x) (cdr (cdr (car (cdr x))))
(cdddar x) (cdr (cdr (cdr (car x))))
(cddddr x) (cdr (cdr (cdr (cdr x))))

Functions 3

A while ago we did lists and they had this insane thing called caar, cadar, cddar as Car of Car and gets the car of car or the first item in the list

  • caar is (car (car x))
  • cadar is (car (cdr (car x)))
  • cddar is (cdr (cdr (car x)))

caar

(car (car x))
From inside to outside
First item = (superman (6 ft 3 in) ( 230 lbs))
And first item of this = superman

cadar

(car (cdr (car x)))
From inside to outside
First item = (superman (6 ft 3 in) ( 230 lbs))
rest of items = (6 ft 3 in) ( 230 lbs))
first item (6 ft 3 in)

cddar

(cdr (cdr (car x)))
From inside to outside
First item = (superman (6 ft 3 in) ( 230 lbs))
rest of items = (6 ft 3 in) ( 230 lbs))
rest of items = ( 230 lbs))

(defparameter *my-heroes* `( (superman (6 ft 3 in) ( 230 lbs))
                             (batman  (6 ft 0 in) ( 190 lbs))
                             (spiderman (6 ft 2 in) ( 210 lbs))))

(defun get-heroes-data (size) 
    (format t "Heroes ~a ~%" 
        `(,(caar size) is ,(cadar size), (cddar size))))

; Heroes (cdr (cdr (car x)))(Superman Is (6 Ft 3 In) ((230 Lbs)))
(get-heroes-data *my-heroes*)

Mapping over a list

Here we map over a function, in this case numberp

;; mapcar example of using a function
;; mapcar List is (T T T Nil Nil)
(format t "mapcar List is ~a ~%" (mapcar #'numberp  `(1 2 3 g d)))

Special Forms

Here is a list of special forms and where used some detail

block let* return-from
catch load-time-value setq
eval-when locally symbol-macrolet
flet macrolet tagbody
function multiple-value-call the
go multiple-value-prog1 throw
if progn unwind-protect
labels progv
let quote

quote

Quote is a special form which stops the lisp interpreter. So the thing is a value (number, symbol, string) rather than a variable in a function

I had to read about this because of my stuffed up brain. In lisp there is some referred to as a quote. And they kept mentioning shorthand but they were incredible unclear what for. and it what the function quote. What they meant is ` means quote ()

(format t "Quote is ~a ~%" (+ 1  2)) ; Quote is 3
(format t "Quote is ~a ~%" (quote (+ 1 2))) ; Quote is (+ 1 2) 
(format t "Quote is ~a ~%" `(+ 1 2)) ; Quote is (+ 1 2)

setq

This appears to be identical to setf i.e. (setq x y) is exactly equivalent to (setf x y). Maybe legacy?

(defvar *test-data* "Fred")  
(format t "default ~a ~%" *test-data*)
(setq *test-data* "Fredq")
(format t "setq ~a ~%" *test-data*)
(setf *test-data* "Fredf")
(format t "setf ~a ~%" *test-data*)

return-from

By default the return value is the last statement executed. To override this we use the special form return-from and the function name

(defun get-average-return (a b)
  (return-from get-average-return (/ (+ a b) 2)))

if

With lisp the if statement has two lines by default to implement the else. For not we add an not operator

;; If statements are written as follows, if true then do this else do this
(if (= 1 1)
    (format t "1 is equal to 1 ~%")
    (format t "1 is not equal to 1 ~%"))

;; Not equal
(if (not (= 1 1))
    (format t "1 is equal to 1 ~%")
    (format t "1 is not equal to 1 ~%"))    
;; And  
(if (and (= 1 1) (= 2 2))
    (format t "1 is equal to 1 and 2 is equal to 2 ~%")
    (format t "1 is not equal to 1 and 2 is not equal to 2 ~%"))    
;; And or haha
(if (or (= 1 1) (= 2 2))
    (format t "1 is equal to 1 or 2 is equal to 2 ~%")
    (format t "1 is not equal to 1 or 2 is not equal to 2 ~%"))

progn

To allow multiple line blocks we use progn. Here used with if to demonstrate and if-else

(if (and (= 1 1) (= 2 2))
    (progn
      (format t "1 is equal to 1 and 2 is equal to 2 ~%")
      (format t "Hello ~%")
      (format t "World ~%"))
    (format t "1 is not equal to 1 and 2 is not equal to 2 ~%"))

flet

Early I mentioned the manual for lisp and how, for me, it is usable. Here is flet
flet ((function-name lambda-list [[local-declaration* | local-documentation]] local-form*)*) declaration* form*

Watching a video (don't use the brand haha) Derek Banas we see his explanation at 45:34



Here we have defined local functions, double-it, triple-it to a local area

(flet ((double-it (num)
    (* 2 num))
    (triple-it (num)
    (* 3 num)))
    (format t "Double & Triple 10 = ~d~%" (triple-it(double-it 10))))