Added lisp along with some study work

This commit is contained in:
Logen Kain 2017-06-23 02:16:42 -07:00
parent 0523d93916
commit 0d49347cb7
10 changed files with 496 additions and 0 deletions

View File

@ -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)))

View File

@ -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))

View File

@ -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

View File

@ -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

39
lisp/fuckery/what.lisp Normal file
View File

@ -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)

View File

@ -0,0 +1,5 @@
(defun hello-world ()
(format t "hello, world"))
;Run function
(hello-world)

Binary file not shown.

View File

@ -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))

View File

@ -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

View File

@ -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"