# Week 1

### Lisp <a href="#lisp" id="lisp"></a>

> Acronym: ***List Processing*** || ***Lots of Irritating Silly Parentheses***

```bash
# To run lisp progran in VS Code:
> rlwrap sbcl           # starts REPL - read-eval-print loop
* (load "file.lisp")    # assume hello()
* (hello)               # calls hello() method in file.lisp
* (+ 2 3)               # prints 5 (quick temp. form)
* (exit)                # either trash the terminal or enter (exit)
```

**Syntax Basics**

**`Atoms`** : basic syntactic units of the language ex:

* **Numbers**
  * Integers (`0, -1, 69`)
  * Ratios (`1/2, 2/3, 4/2`)
  * Floats (`0.0, -1.0, +1.5`)
* **Individual Chars** : `#\a, #\@`
* **Strings** : `"string"`
* **Boolean** : `T (true), NIL (false)`
* **Symbols** - names (made up of strings/numbers/chars) used for naming functions, variables, & other entities:
  * `2021CPS305, symbolName123, +, T, NIL, <>, -+49ers+-, <+==+>`
* **Lists** : sequence of either *atoms* or *other lists* separated by blanks
  * ```lisp
    (1 2 3)
    (a b c d)
    (a "b" T -2.0)
    (a (b c) (d (e f)))
    ()    ; () = NIL
    ```
* **Vectors** : *faster* list-like sequence
  * `#(1 2 3)`, `#(a "b" -2.0)`

**S-Expressions**

*symbolic expressions* (aka *function application: non-empty list are themselves forms*)

> syntax : `( op a1 a2 a3 ... )`
>
> > `op` : ***function*** || **operator**
> >
> > `a1 a2 a3 ...` : ***arguments*** || **operands**

`Forms` : lisp expressions that may be meaningfully evaluated

* `(= (+ 2 3) 5)` : evaluates to `t`
* `(a b c)` : **ERROR** 'a' is not a function (this is a list, not a form)

```lisp
; same as 2 * 8
; evaluates to 6
(* 2 8)

; you can chain operations aswell
; same as doing 2 + (4 * 4)
; evaluates to 18
(+ 2 (* 4 4))

; another ex.
; same as doing (8/2) - (8*4)
(- (/ 8 2) (* 4 8))
; = to -28

; (2 + [4 * 6]) * (3 + 5 + 7)
; = 390
(* (+ 2 (* 4 6)) (+ 3 5 7))


; (2 - [3 - [6 + 4/5]]) ÷ (3 * [6 - 2])
; = 29/60
(/
    (- 2 (- 3 (+ 6 4/5)))     ; numerator
    (* 3 (- 6 2))             ; denominator
)
; evaluates to 29/60
```

**Variables & Constants**

> below ex. are for **global vars/const** ; for **local vars** use `let`>`defvar`

* **Variables**
  * DEFINE =`(defvar varName varValue "var desc.")`
  * SET =`(setq varName newValue)`

    ```lisp
    ; defines a mutable var *total-glasses* and assigns it's value to be 0
    ; u dont need the *sandwich* like below ex's, but it is good practice
    (defvar *total-glasses* 0 "Total glasses so far")

    ; change value to 3
    (setq *total-glasses* 3)

    ; same as += 1
    (setq *total-glasses* (+ *total-glasses* 1))
    ```
* **Constants**
  * DEFINE =`(defparameter constName constValue)`
  * SET =*can't change const value*

    ```lisp
    ; const variable B = 20
    (defparameter B 20)
    ```

**Named Procedures (aka Functions)**

syntax : `(defun [funcName] ([parameters]) ([body]) )`

```lisp
; squares the value of x
(defun square (x) (* x x))

; sum of squares of 2 parameters
(defun sum-of-squares (x y)
    ; calls above square function from inside this function    
    (+ (square x) (square y))    
)
```

**Lambda (Anonymous Functions)**

> much like in other languages, `lambda` fx's are quick one liners that are defined and called in the same line.

syntax : `( (lambda params body) arguments )`

```lisp
; normal (squares 4) vs. lambda function:
( (lambda (x) (* x x)) 4 )

((lambda (x y) (+ x y)) 2 2)    ; => 4
```

**Blocks + Progn**

* Block

  > Blocks allow for contorlled sequential execution.

  * syntax : `(block blockName body)`

    ```lisp
    (block test
        (print "hello")
        (+ 2 2)
    )

    ; evaluates to:
    ; "hello"
    ; 4
    ```
* Progn

  > skipped the blockname and can call the block directly

  * syntax : `(progn body)`

    ```lisp
    ; evaluates to same thing above
    (progn
        (print "hello")
        (+ 2 2)
    )
    ```

**Special Forms**

If `op` is 1 of 25 special words, the form is evaluated as a **`special form`**

> Special Forms usually produce values (but not always)

* **quote**
  * `(quote v)` aka `'v` where v=form : returns v as data, w/o evaluating it.

    ```lisp
    (quote (+ 2 3))    ; (+ 2 3) not 5
    '(+ 2 3)           ; (+ 2 3)
    ```
* **and / or**

  > The following objects are interpreted as **NIL** : `()`, `'()`, `NIL`, `'NIL`
  >
  > All other objects are interpreted as **True**

  * `and a1 ... aN`
    * all forms a1...aN are evaluated (L-to-R)
    * if ***any*** form evaluates to NIL, **`and` returns NIL**
    * if ***none*** of the forms are NIL, **`and` returns evaluation of aN**

```lisp
; 3rd form is nil
; returns NIL
(and 0 1 nil (+ 3 4) 3)

; no form is NIL
; returns (* 3 3) = 9
(and 0 1 2 (* 3 3))
```

* `or a1 ... aN`
  * all forms a1...aN are evaluated (L-to-R)
  * if ***any*** form *ai* evaluates to true, **`or` returns evaluation of&#x20;*****ai***
  * if ***all*** forms but aN evaluate to NIL, **`or` returns evaluation of aN**

```lisp
; 3rd form is (< 3 4) (truthy)
; return (< 3 4) = T
(or nil (> 5 6) (< 3 4) (= 1 2))

; 1st form is 0 (truthy)
; returns 0
(or 0 (* 3 3) 2 1)
```

* **if**
  * `(if cond then [else])`
  * if `cond`-form is T, then evaluate `then`-form
  * opt. `[else]`-form is evaluated if `cond`-form is NIL (false)

```lisp
(if (condition)
    (option-1)
    ; else
    (option-2))

; cond=NIL, so else=(* 3 2) =6
(if nil
    4
    (* 3 2)) ; else

; cond=(and 0 1 NIL ..) =NIL, so else=10 =10
(if (and 0 1 nil (+ 3 4) 3)
    3
    10) ; else

; cond=(or 0 ...) =0 (truthy), so then=(+ 5 5) =10
(if (or 0 (* 3 3) 2 1)
    (+ 5 5) ; then
    (* 10 10))
```

* When we want to evaluate several conditions in a row we use `cond` :

  ```lisp
  (cond
       ; if condition 1
       ((= 1 2)
       (print "hello")) 
      ; else if condition 2
      ((= 1 1)
      (print "world")) 
      ; else
      (t ("nothing else worked"))) 
      ; evaluates to:
      ; "world"
  ```
* **let**

  > special form for temporary local variable binding

  * syntax : `(let ((var1 val1) … (varN valN)) <s-expressions>)`
    * `var1, ... varN` : variable names
    * `val1, ... valN` : initial values assigned to respective vars (default=NIL)
    * each **varN** is assigned to their **valN**, and finally the **s-expression** is evaluated.
    * The value of the last expression evaluated is returned

```lisp
; x =4
; s-exp = (* 4 4) =16 is returned
(let ((x 4)) (* x x))

(let ((x 3)    ; x=3
      (y 1))   ; y=1
     (+ (* y x) x))    ; s-exp = (+ (* 1 3) 3) =6 is returned

; ERROR 
(let ((x 3)       ; x=3
     (y (* x x))) ; ERROR 3 hasn't been bound to x yet!
     (+ x y))     
```

**Loops**

* `dotimes` : used to create simple loops that loop from **0 to n-1**

  > analogous to "for i in range(n)" in python
  >
  > * syntax : `(dotimes (i [n] [completed value]))`
  >   * `i` - loop iteration variable
  >   * `n` - loops until n-1
  >   * `completed value` - opt. value that's returned when the loop completes; `NIL` by default.

  ```lisp
  (dotimes (i 3)
       (prnt i))
  ; 0
  ; 1
  ; 2
  ; NIL
  ```

* `do` : more versatile looping
  * syntax :
    * (`do` ((`i` `[start value]` (`[increment by]` `[operation]` `i`)
    * (`[body]`)))
    * ((`[exit condition]`) `i`)
    * (`[body]`))

      ```lisp
      (defvar i 0)
      (do ((i 0 (1+ i))
          (print i))
          ((> i 4) i)
          ((print i)))
      ```

> Note: `i` needs to be initialized prior.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev-patel-1.gitbook.io/notes/cps305/week-1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
