diff --git a/lisp/ansi_lisp/ch2/dunno_yet.lisp b/lisp/ansi_lisp/ch2/dunno_yet.lisp new file mode 100644 index 0000000..e6aa242 --- /dev/null +++ b/lisp/ansi_lisp/ch2/dunno_yet.lisp @@ -0,0 +1,118 @@ +;example of printing proper + +;t indicates that the output is to be sent to the default place +; normally this will be toplevel +; ~% indcates newline +; it's like printf +;(format t "~A plus ~A equals ~A.~%" 2 3 (+ 2 3)) + + +;user-input + +(defun askem (string) + (format t "~A" string) + (read)) + +;example +;(format t "You wrote: ~A ~%" (askem "What is you????? ")) + +;user-input plus variables +(defun ask-number () + (format t "Please enter a number. ") +;;;create a variable "val" to store read (first two arguments of let) + (let ((val (read))) +;;;;Now after asigning values in let, we can do expressions +;;;;Note that the variables are local to the let block +;;;;Test if val is number + (if (numberp val) + val + (ask-number)))) +;example +;(format t "~A~%" (ask-number)) + +;global variables +;The asterisks are simply a standard to show that the variable is global +(defparameter *glob* 99) + +;global constants can be declared as such +;They don't need special names because if they share the name of a variable +;it'll throw an error +(defconstant limit (+ *glob* 1)) + +;We can check if a symbol is the name of a global variable/constant like this +;(format t "~A~%" (boundp '*glob*)) +;(format t "~A~%" (boundp 'limit)) + +;The most general assignment operator is setf +(setf *glob* 98) + +(format t "~A~%" (let ((n 10)) + (setf n 2) + n)) + +;If the first arg to setf is a symbol that is not a local variable, it is +;taken to be global and thus creates one if it didn't exist already + +;Note that this is bad practice because it pisses off my linter +;also, implicit declarations are weird. +;(setf x (list 'a 'b 'c)) +;(format t "~A~%" x) + +; we could also do something like (assuming the above code has also happened) +;We can use an expression instead of a variable. In these cases the second +;argument is inserted in the place refered by the first arg +;So here: +;(setf (car x) 'n) +;We would be replacing the A in (A B C) with an N + +;You can also give any even about of arguments to setf... so...: +;(setf a b +; c d +; e f) + +;Would be equivalnt to doing three seperate setf statements + +;print out the square of the integer from start to end +;do works as (variable inital update) +;So here we have the first arg: +;;;i is set to start and then updates by 1 +;The next argumen to (do) is when the test should end and +;;;what happens after end +;The third and last argument is what's actually happening (the format list) +(defun show-squares (start end) + (do ((i start (+ i 1))) + ((> i end) 'done) + (format t "~A ~A~%" i (* i i)))) + +;Recursive version +;progn can take any number of expressions, it evaluates them in order, and +;returns the value of the last +(defun show-square-rec (i end) + (if (> i end) + 'done + (progn + (format t "~A ~A~%" i (* i i)) + (show-squares (+ i 1) end)))) + +;function that iterates through a list +;dolist takes an argument as (variable expression) followed +;by a body of expressions +(defun our-length (lst) + (let ((len 0)) + (dolist (obj lst) + (setf len (+ len 1))) + len)) + +;rec version +(defun our-length-rec (lst) + (if (null lst) + 0 + (+ (our-length (cdr lst)) 1))) + +;define function tha takes two arguments and returns the greater + +(defun is-greater (arg1 arg2) + (if (> arg1 arg2) + (format t "~A~%" arg1) + (format t "~A~%" arg2))) + diff --git a/lisp/ansi_lisp/ch2/problem_8/print_dots.lisp b/lisp/ansi_lisp/ch2/problem_8/print_dots.lisp new file mode 100644 index 0000000..b105bd3 --- /dev/null +++ b/lisp/ansi_lisp/ch2/problem_8/print_dots.lisp @@ -0,0 +1,26 @@ +;; Take a positive int and print that many dots + +;; repetition +(defun print-dots(num-of-dots) + (do ((i 0 (+ i 1))) + ((= i num-of-dots) 'done) + (format t ". "))) +;; recursion +(defun print-dots-rec(num-of-dots) + ;plusp checks if it's a positivie integer above 0.0 + (if (plusp num-of-dots) + (progn + (format t ". ") + (print-dots-rec(- num-of-dots 1))))) + +;; Take a list and return the number of times the symbol "a" occurs in it +(defun count-a-symbols(lst) + (do ((new-lst lst (cdr new-lst)) + (n 0 (+ n (if (eq (car new-lst) 'a) 1 0)))) + ((not new-lst) n))) + +;; Now do a recursive version (which is probably easier) +(defun count-a-symbols-rec(lst) + (if lst + (+ (if (eq (car lst) 'a)1 0) (count-a-symbols-rec(cdr lst))) + 1)) diff --git a/lisp/ansi_lisp/ch3/notes.txt b/lisp/ansi_lisp/ch3/notes.txt new file mode 100644 index 0000000..61c8fd6 --- /dev/null +++ b/lisp/ansi_lisp/ch3/notes.txt @@ -0,0 +1,85 @@ +(eql x y) -- Tests of it's the same object + +(setf x '(a b c)) +(setf y x) -- This will copy the poiner, so any changes to either will affect the other. + +(setf x '(a b c) + y (copy-list x)) -- This will actually create a new list (eql x y) will return nil + +(append '(a b) '(c d) '(e)) -- append lists together. Will result in a single combined list. + +(nth 0 '(a b c)) -- Find the nth element. In this cas 'A' +(nthcdr 1 '(a b c)) -- Find the nth cdr. In this case (B C) + +(zerop n) -- Checks if value is 0 +(last '(a b c)) -- Returns last cons in a list. So it'll return "(C) here +(car(last '(a b c))) -- Returns last element of a list. In this case "C" + +--first - tenth are defined as functions that are not zero indexed so for example: +(fifth '(a b c d e f g h i)) -- Will return "E" (the element, not the cons) + +(mapcar #'(lambda (x) (+ x 10)) + '(1 2 3)) -- Takes a function and applies everything in the list to it. In this case it will return (11 12 13) + +(mapcar #'list + '(a b c) + '(1 2 3 4)) -- Would return: + ((A1) (B2) (C 3)) + +(member 'b '(a b c d e)) -- (member) finds what it's looking for, and returns it as well as the cdr from that point. So here we would see "b" - "e" + +-- Keywords are a symbol preceded by a colon... so ":test" for example +-- Member defaults to testing with eql, perhaps we want equal instead: +-- NOTE: Equal is less strict than eql. Equal returns true if it's arguemnts print the same. +-- EQL only if they are the same object +(member '(a) '((a) (z)) :test #'equal) -- Will result in ((A) (Z)) + +--There is also :key +(member 'a '((a b) (c d)) :key #'car) -- will return ((A B) (C D)) -- We asked if there was an element whose car was a +-- keywords are always at the end, and multiple are acceptable. + +If we want to find an element satisfying an arbitrary predicate, like oddp, which returns true for odd ints, we can use member-if + +(member-if #'oddp '(2 3 4)) -- This will find the first odd number, 3 in this case, and return it along with the rest of the list + +(adjoin) -- conses an object into a list if it's not already a member +(adjoin 'b '(a b c)) -- (A B C) +(adjoin 'z '(a b c)) -- (Z A B C) + +(union '(a b c) '(c b s)) -- (A C B S) +(intersection '(a b c) '(b b c)) -- (B C) +(set-difference '(a b c d e) '(b e)) -- (A C D) -- So, expected stuff +-- The above creates sets, and as we know, sets have no specific order + +(length ' (a b c)) -- 3 + +-- Grab a part of a list +-- Think python slices, third argument (second number) is optional. +(subseq '(a b c d) 1 2) -- (B) +(subseq '(a b c d) 1) -- (B C D) + +(reverse '(a b c)) -- Obvious, returns (A B C) + +(subseq(reverse '(a b c)) 0 2) -- (C B) -- A way to grab the last two +(subseq(reverse '(a b c)) 1) -- (B A) -- Start with second to last and go backwards. Basically cut off the last (or however many ) element + +(sort '(0 2 1 3 8) #'>) -- (8 3 2 1 0) -- Is destructive to the origional list. Of course, < would sort in order + +(every #'oddp '(1 3 5)) -- Are they all odd? -- True +(some #'evenp '(1 2 3)) -- Are some of the even? -- True + +(every #'> '(1 3 5) '(0 2 4)) -- Think math, is every element greater than it's corresponding element so... +-- is 1 > 0? AND is 3 >2 AND is 5>4? True +If sequences are different lengths, the shortests determines how many tests are performed. + +(push x y) push object x onto the front of list y +(pop x) -- remove and return the first element of list x + +(let ((x '(a b))) + (pushnew 'c x) + (pushnew 'a x) + x) -- This will only push to "x" if the object doesn't already exist. + +-- Conses are not just for building lists, an improper list, or dotted list, can be used make a structure with two fields +(setf pair (cons 'a 'b)) -- (A . B) +-- car will return A, while cdr will return B diff --git a/lisp/ansi_lisp/ch4/notes.txt b/lisp/ansi_lisp/ch4/notes.txt new file mode 100644 index 0000000..afb3674 --- /dev/null +++ b/lisp/ansi_lisp/ch4/notes.txt @@ -0,0 +1,7 @@ +(setf arr (make-array '(2 3) :initial-element nil)) -- Makes a 2x3 array -- :initial-element is optional, the whole array is init to this value +(aref arr 0 0) -- Retrieve an array element + +(setf (aref arr 0 0) 'b) -- Set array element 00 to b + +(setf vec (make-array 4 :initial-element nil)) -- Makes a one-dimentional array known as a vector + diff --git a/lisp/fuckery/what.lisp b/lisp/fuckery/what.lisp new file mode 100644 index 0000000..b08856a --- /dev/null +++ b/lisp/fuckery/what.lisp @@ -0,0 +1,39 @@ +(defun menu () + (format t "Press \"1\" to print \"hi\" ~%") + (format t "Press \"2\" to print \"suck\" ~%") + (format t "Press \"3\" to print \"bitch\" ~%") + (format t "Press \"4\" to print \"ass\" ~%") + (format t "Press \"5\" to print \"dog\" ~%") + (format t "Press \"6\" to open htop ~%") + (format t "Press \"q\" to quit \"dog\" ~%")) + +(defun choices () + (format t "~%Please enter a number: ") + (let ((input (read-line))) + (cond + ((string= "1" input) + (format t "Hi! ~%")) + ((string= "2" input) + (format t "You Suck!~%")) + ((string= "3" input) + (format t "use a bish~%")) + ((string= "4" input) + (format t "Ass!~%")) + ((string= "5" input) + (format t "Hey there dog~%" )) + ((string= "6" input) + (shell "htop")) + ((string= "q" input) + (format t "Bye!~%")) + ((string= "menu" input) + (format t "~%") + (menu)) + (t + (format t "You failed! " ))) + (unless (string= "q" input) + (choices)))) + +(defun main () + (menu) + (choices)) +(main) diff --git a/lisp/hello-world/hello-world.lisp b/lisp/hello-world/hello-world.lisp new file mode 100644 index 0000000..ccac937 --- /dev/null +++ b/lisp/hello-world/hello-world.lisp @@ -0,0 +1,5 @@ +(defun hello-world () + (format t "hello, world")) + +;Run function +(hello-world) diff --git a/lisp/land-of-lisp/ch2/Schedule June 2017.xlsx b/lisp/land-of-lisp/ch2/Schedule June 2017.xlsx new file mode 100644 index 0000000..e0073e2 Binary files /dev/null and b/lisp/land-of-lisp/ch2/Schedule June 2017.xlsx differ diff --git a/lisp/land-of-lisp/ch2/guess-my-number-game.lisp b/lisp/land-of-lisp/ch2/guess-my-number-game.lisp new file mode 100644 index 0000000..1df80f9 --- /dev/null +++ b/lisp/land-of-lisp/ch2/guess-my-number-game.lisp @@ -0,0 +1,23 @@ +(defparameter *small* 1) +(defparameter *big* 100) + +(defun guess-my-number () + ;; ash is the artithmetic shift function + ;; Halvs the sum of the limits and shortens the result + ;; ash, here, shifts the binary bits left or right (well, right in this case) + ;; Which leads to the right most binary falling off + ;; This is a binary search + (ash (+ *small* *big*) -1)) + +(defun smaller () + (setf *big* (1- (guess-my-number))) + (guess-my-number)) + +(defun bigger () + (setf *small* (1+ (guess-my-number))) + (guess-my-number)) + +(defun start-over () + (defparameter *small* 1) + (defparameter *big* 100) + (guess-my-number)) diff --git a/lisp/land-of-lisp/ch2/notes.txt b/lisp/land-of-lisp/ch2/notes.txt new file mode 100644 index 0000000..97d9a5b --- /dev/null +++ b/lisp/land-of-lisp/ch2/notes.txt @@ -0,0 +1,30 @@ +;; List of variables that are surrounded by parens + +(let ((a 5) + (b 6)) + (+ a b)) + +;; Local functions +;; It's like let. A list of functions and their descriptions, +;; followed by some stuff to do with them +(flet ((function_name (args) + ...Function Body...)) + body) +;;example +(flet ((f (n) + (+ n 10))) + (f 5)) + +>> 15 + +;; labels -- like flet, but allow functions to call other +;; defined functions or themselves +;; Same basic structure as flet + +(labels ((a (n) + (+ n 5)) + (b (n) + (+ (a n) 6))) + (b 10)) +>> 21 + diff --git a/lisp/land-of-lisp/ch4/notes.txt b/lisp/land-of-lisp/ch4/notes.txt new file mode 100644 index 0000000..94e9776 --- /dev/null +++ b/lisp/land-of-lisp/ch4/notes.txt @@ -0,0 +1,163 @@ +;(if '() +; 'i-am-true +; 'i-am-false) +;>> I-AM-FALSE +; +;(if '(1) +; 'i-am-true +; 'i-am-false) +;>> I-AM-TRUE +; +;This means empty lists are false. This significantly helps with recurison. +; +;We can take items from the front of a list and send the rest back +;(cdr) until the list is empty. + +;example: +; +;(defun my-length (list) +; (if list +; (1+ (my-length (cdr list))) +; 0)) +; +;(my-length '(list with four symbols)) + +;The empty list is the only false value in common lisp. +;Any value not equivalent to an empty list will be considered true. + +(defvar *number-was-odd* nil) + +(if (oddp 5) + (progn (setf *number-was-odd* t) + 'odd-number) + 'even-number) +;progn allows us to do extra commands in a single expression. +;nly the last evaluation in progn is returned as the value. + +;Other conditionals have implicit prgn such as when and unless + +(defvar *number-is-odd* nil) +(when (oddp 5) + (setf *number-is-odd* t) + 'odd-number) + +(unless (oddp 4) + (setf *number-is-odd* nil) + 'even-number) + +;The tradeoff is that there is no "else: with these commands. +;In those cases they just return nil and do nothing. + +;cond is sometimes considered to be the one true Lisp conditional. +;It has been around for long long time. + +(defvar *arch-enemy* nil) +(defun pudding-eater (person) + (cond ((eq person 'henry) (setf *arch-enemy* 'stupid-lisp-alien) + '(curse you lisp alien -- you ate my pudding)) + ((eq person 'johnny (setf *arch-enemy* 'useless-old-johnny) + '(i hope you choked on my pudding johnny)) + (t '(why you eat my pudding stranger ?))))) + +;Note: "eq" and "eql" Ask if the two things being compared is the same thing. +;"equal" checks to see if the two thing return the same thing +;So... something like this: + +(defun bob () + "bob") + +(let ((x "bob")) + (eq x (bob))) + +;Will return False as x's "bob" is different +;from the "bob" returned by the function +;Yet + +(let ((x "bob")) + (equal x (bob))) + +;will return true as they both end up returning the same result "bob" + +(defun pudding-eater (person) + (case person + ((henry) (setf *arch-enemy* 'stupid-lisp-alien) + '(curse you lisp alien -- you ate my pudding)) + ((johnny) (setf *arch-enemy* 'useless-old-johnny) + '(i hope you choked on my pudding johnny)) + (otherwise '(why you eat my puding stranger ?)))) + +;This is how we do cases. +;Unfortunatly, cases are only really useful in the case of matching symbols +;This is because case uses (eq) to do the comparisons. +;As noted earlier, this doesn't work well with strings. + +(and (oddp 5) (oddp 7) (oddp 9)) +;This is how we could use the (and) macro to check of three numbers are odd + +(or (oddp 4) (oddp 7) (oddp 8)) + +;This is how we can check to see if at least one of the numbers is odd. + +(or (oddp 4) (setf *is-it-even* t)) + +;This is a way we can use (or) as a conditional. +;If the first number was odd, it would never make it to the (setf) +;But, it is even so it does. +;This is called "shortcut boolean evaluation" +;This means once Lisp determines that an earlier statement +;in a list of (or) values is true, +;It doesn't bother evaluating the rest. +;Same happens with (AND) +;If a statement returns false, it doesn't bother checking the rest + +;Another example, think about saving a document: +(if *file-modified* + (if (ask-user-about-saving) + (save-file))) + +;could be rewriten as an (and) statement + +(and *file-modified* (ask-user-about-saving) (save-file)) + +;This is like asking the following +;Has the file been modified? If true then... +;Ask the user about saving, did the user's answer return true? If so, then: +; run the (save-file) function + +;And of course, the way I probably would have written it in c or something + +(if (and *file-modified* + (ask-user-about-saving)) + (save-file)) + +So basically, we could use (and) or (or) as a conditional +;and put what we want to happen at the end + +(if (member 1 '(3 4 1 5)) + 'one-is-in-the-list + 'one-is-not-in-the-list) + +>> ONE-IS-IN-THE-LIST + +;Should be obvious, but member checks if an item is in a list or not. +;It then returns that item, plus the rest of the list +;This being a non-empty list returns true, which allows are (if) conditional +;To chose the "if-True" option of the (if) +;Remember, lisp blocks only return the last thing it computes +;That's why it does not return the normal functionality of (member) +;Could be useful for games. + +;back to the (eq)/(equal)/(eql) issue... +;Conra'ds Rule of thumb for compargint Stuff: +;1. use (eq) to compare symbols +;2 use (equal) for everything else + +;Why bother with (eq) at all? Well, apprently it's faster + +;(equalp) can compare things that are mostly the same. So... +(equalp "BoB" "bob") +;will return true and: +(equalp 1 1.0) +;will also return true + +;Oh shit, chapter 5 is exciting. "Building a text game engine"