home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / lisp / interpre / apteryx / tutor2.lsp < prev    next >
Lisp/Scheme  |  1993-12-09  |  18KB  |  462 lines

  1. ; Copyright 1993 Apteryx Lisp Ltd
  2.  
  3. ; The following is a file of some expressions/programs. Remember to
  4. ; use F4 (Lisp:Eval) to see what the expressions evaluate to.
  5.  
  6.  
  7. ; Here is a program that adds up the numbers from 1 to 10. It works because
  8. ; + is a function that takes any number of arguments, and adds them all up.
  9.  
  10. (+ 1 2 3 4 5 6 7 8 9 10)
  11.  
  12. ; Here is another program that does the same calculation.
  13.  
  14. (let ( (i 1) (total 0))
  15.   (while (<= i 10)
  16.     (setq total (+ total i))
  17.     (setq i (+ i 1)) )
  18.   total)
  19.  
  20. ; Roughly, it does the following - it makes a variable called "i" and gives
  21. ; it the value 1, and makes a variable total and gives it the value 0. The
  22. ; general idea is that the variable "i" is going to take on each value from
  23. ; 1 to 10 in turn and each of those values will get added to the value of
  24. ; the variable "total", so that the final value of "total" will be the sum
  25. ; of the numbers from 1 to 10.
  26.  
  27. ; The variables i and total are created by the "let" statement.
  28. ; You can think of a variable as a place where you can put one item of
  29. ; data, which is accessed via the name of the variable. The first
  30. ; argument of the let is a list of variable definitions, i.e. 
  31. ;    ( (i 1) (total 0) ). Each variable definition is a list of two
  32. ; elements. The first is the name of the variable, the second is an 
  33. ; expression that is evaluated to give the initial value of the variable.
  34. ; For example the variable i takes on the initial value 1.
  35. ; The variables can be referred to in the expressions that follow the
  36. ; variable definitions and make up the rest of the let statement.
  37. ; They cannot be referred to outside the let statement. This normally 
  38. ; means that they effectively cease to exist once evaluation of the let
  39. ; statement has completed.
  40.  
  41. ; The variables can be referred to in two ways. If they are evaluated as
  42. ; an expression, the return value is their current value. We can use setq
  43. ; (or setf) to change their value. setq takes two arguments - the name of
  44. ; the variable (which is not evaluated) and an expression for the new
  45. ; value (which is evaluated). Here's an example-
  46.  
  47. (let ( (a 2) (b 3))
  48.   (setq a (+ b 1))
  49.   (setq b (+ a 1))
  50.   (* a b) )
  51.  
  52. ; What happens ?
  53. ; First, a gets set to 2 and b gets set to 3.
  54. ; In the first setq, the expression (+ b 1) evaluates to 4 (= 3 + 1),
  55. ; and this becomes the new value of a.
  56. ; In the second setq, the expression (+ a 1) evaluates to 5 (= 4 + 1),
  57. ; and this becomes the new value of b.
  58. ; Then the last expression evaluates to 4 * 5 = 20, which then becomes the
  59. ; result returned from the whole let expression.
  60.  
  61.  
  62. ; Here's the second expression again.
  63.  
  64. (let ( (i 1) (total 0))
  65.   (while (<= i 10)
  66.     (setq total (+ total i))
  67.     (setq i (+ i 1)) )
  68.   total)
  69.  
  70. ; We note that the let contains two expressions after the variable
  71. ; definitions - the first is a list starting with while, the second is
  72. ; just the expression total. Whatever value the variable total has after
  73. ; the while expression has been evaluated will be the return value of the
  74. ; whole let expression.
  75.  
  76. ; while is a special form which evaluates a series of expressions 
  77. ; repeatedly, until something tells it to stop. The thing that tells
  78. ; it to stop is the first argument. This is a test expression that is
  79. ; evaluated before the start of each repetition. If it evaluates to nil
  80. ; (i.e. false) then the while finishes, otherwise the remaining arguments
  81. ; to the while are evaluated as expressions in order. Then the test 
  82. ; expression is evaluated again and so on, until the test expression
  83. ; evaluates to false.
  84.  
  85. ; What happens if the test expression never evaluates to nil ? Then the
  86. ; while expression will never finish evaluating. This sort of thing is
  87. ; called an infinite loop. It is inevitable that sometimes you will 
  88. ; evaluate an expression that takes either forever or a very long time
  89. ; to evaluate, so you'll want to know how you can abort such an evaluation
  90. ; prematurely. The key for this is the F12 key (there is no menu choice 
  91. ; because the menus cannot operate while an expression is being 
  92. ; evaluated).
  93.  
  94. (while t (print "This program will go on forever until you hit F12"))
  95.  
  96. ; Try evaluating the above program. The test expression is t (meaning true)
  97. ; which always evaluates to t (i.e. not nil), so the while expression
  98. ; never stops. The print expression prints its argument to the LispOutput
  99. ; window, and because its in the while statement, the string gets 
  100. ; printed over and over again.
  101. ; When you hit F12, you get a dialog box which you OK, and then a stack
  102. ; dump appears in the LispOutput window. The stack dump shows what was
  103. ; happening at the time the F12 key was hit (there may be a slight
  104. ; delay between when the F12 key is hit and when the evaluation stops).
  105.  
  106. ; Now that you known how to stop an infinite loop, we can take another
  107. ; look at the while loop in our program.
  108.  
  109. (let ( (i 1) (total 0))
  110.   (while (<= i 10)
  111.     (setq total (+ total i))
  112.     (setq i (+ i 1)) )
  113.   total)
  114.  
  115. ; You can see that the test expression is (<= i 10) which will return t
  116. ; if the value of the variable i is less than or equal to 10. This 
  117. ; seems reasonable, because we want the values of the variable i to go
  118. ; from 1 to 10, and then stop.
  119.  
  120. ; The statement (setq total (+ total i)) causes the value of (+ total i)
  121. ; to become the new value of the variable total, i.e. it effectively adds
  122. ; the value of i onto the value of total.
  123. ; The statement (setq i (+ i 1)) similiarly adds 1 onto the value of i.
  124.  
  125. ; We can add some format statements to the while loop to let us follow the
  126. ; course of the expression's evaluation. (Don't worry too much how the
  127. ; formats work, just read the output to the LispOutput window.)
  128.  
  129. (let ( (i 1) (total 0))
  130.   (while (<= i 10)
  131.     (format t "Current total = ~A, current i = ~A~%" total i)
  132.     (setq total (+ total i))
  133.     (format t " New total = ~A~%" total)
  134.     (setq i (+ i 1))
  135.     (format t " New i = ~A~%" i) )
  136.   total)
  137.  
  138. ; The variable i that goes from 1 to 10 is sometimes called a counter
  139. ; variable. There exists a Lisp construct that is made especially for 
  140. ; counting called dotimes.
  141.  
  142. ; The following example prints out hello 5 times -
  143.  
  144. (dotimes (i 5)
  145.   (princ "hello ") )
  146.  
  147. ; The first argument (i 5) consists of the variable i which does the
  148. ; counting, and the expression 5 which is the number of times that the
  149. ; statements in the dotimes are to be evaluated.
  150.  
  151. ; If we evaluate the following expression, we can see that the counter
  152. ; variable actually starts at 0 and its last value is 1 less than the
  153. ; number of times the dotimes loops around.
  154.  
  155. (dotimes (i 10)
  156.   (print i) )
  157.  
  158. ; With this in mind, we can use dotimes to write a program that adds the
  159. ; numbers from 1 to 10
  160.  
  161. (let ( (total 0) )
  162.   (dotimes (i 10)
  163.     (setq total (+ total i 1)) )
  164.   total)
  165.  
  166. ; The extra 1 in (+ total i 1) makes up for the fact that i goes from 0
  167. ; to 9.
  168.  
  169. ; Numbers like 55=1+2+3+4+5+6+7+8+9+10 are sometimes called triangular
  170. ; numbers. The following program shows why -
  171.  
  172. (dotimes (i 10)
  173.   (dotimes (j (+ i 1))
  174.     (princ "#") )
  175.   (terpri) )
  176.  
  177. ; Note that the number of times the innermost dotimes goes around is
  178. ; equal to 1 + the current value of the counter for the outermost
  179. ; dotimes.
  180.  
  181. ; We can see that the 55 hashes that appear in the LispOutput window
  182. ; form a triangle.
  183.  
  184. ; We might like to write a function called triangle that given a number
  185. ; returns the sum of the natural numbers from 1 to that number.
  186.  
  187. ; For example -
  188.  
  189. (triangle 10)
  190.  
  191. ; would return the value 10.
  192. ; If you tried evaluating the above expression, you would have got an
  193. ; error, because there isn't any function called triangle.
  194.  
  195. ; But we can define one using defun -
  196.  
  197. (defun triangle (n)
  198.   (let ( (total 0) )
  199.     (dotimes (i n)
  200.       (setq total (+ total i 1)) )
  201.     total) )
  202.  
  203. ; The first argument to defun is the name of the new function. 
  204. ; The second argument is a list of names for the arguments that the
  205. ;  new function will take (for triangle there's just one argument
  206. ; which we are calling n).
  207. ; The rest is a series of expressions which will be evaluated when the
  208. ; function is used (or "called"), the last of which will give the return
  209. ; value for the function.
  210.  
  211. ; In this case the last expression is the only one, and looks very similiar
  212. ; to our program for adding the numbers from 1 to 10. The only difference
  213. ; is that we've put n where we previously had 10. When a function is called
  214. ; variables are created with the names specified for the arguments in the
  215. ; defun, whose values are the actual values of the arguments passed to the
  216. ; function. For example, evaluate the defun above, and then the following
  217. ; expression -
  218.  
  219. (triangle 10)
  220.  
  221. ; What happened was that a variable was created whose name was n and whose
  222. ; value was 10, so that when the expression
  223.  
  224. ; (let ( (total 0) )
  225. ;    (dotimes (i n)
  226. ;      (setq total (+ total i 1)) )
  227. ;    total)
  228.  
  229. was evaluated, it gave the required result.
  230.  
  231. ; Here's another program for calculating triangular numbers, with an
  232. ; example to try -
  233.  
  234. (defun triangle2 (n)
  235.   (if (= n 0)
  236.     0
  237.     (+ (triangle2 (- n 1)) n) ) )
  238.  
  239. (triangle2 10)
  240.  
  241. ; It seems a bit strange, because the body to the function contains a
  242. ; call to the function being defined.
  243.  
  244. ; What the definition says in English is -
  245.  
  246. ; (triangle 0) = 0 and for any other number
  247. ; (triangle n) = (triangle n-1) + n
  248.  
  249. ; e.g. (triangle 10) = (triangle 9) + 10.
  250.  
  251. ; The definition seems quite reasonable, and Apteryx Lisp doesn't seem
  252. ; to have any trouble evaluating it. To see how it does it, we can
  253. ; put in a few format statements - 
  254.  
  255. (defun triangle2 (n)
  256.   (format t "Starting to calculate (triangle ~A)~%" n)
  257.   (let ( (result (if (= n 0)
  258.                    0
  259.                    (+ (triangle2 (- n 1)) n) )) )
  260.     (format t " (triangle ~A) = ~A~%" n result)
  261.     result) )
  262.  
  263. (triangle2 10)
  264.  
  265. ; In order to calculate (triangle 10) it has to calculate (triangle 9)
  266. ; which requires it to calculate (triangle 8) and so on.
  267. ; We can see that we need to have at least one special case where the
  268. ; function doesn't call itself - otherwise we'd get into another
  269. ; infinite loop.
  270. ; We can also see that at the moment it's calculating (triangle 0) it's
  271. ; in the middle of calculating (triangle 1) and (triangle 2) and so on
  272. ; right up to (triangle 10). How can the variable n (and result) take on
  273. ; eleven different values at once ? The answer is that there are actually
  274. ; eleven different variables called n, one for each call (or invocation)
  275. ; of triangle2. The value of each variable n has the value passed as an
  276. ; argument to the invocation of triangle2 that created it, and each
  277. ; variable n is only referred to by the invocation that created it,
  278. ; so no confusion results between different n's.
  279.  
  280. ; This business of a function calling itself is called recursion.
  281. ; Using a looping construct like while or dotimes is called iteration.
  282. ; Recursion is less efficient than iteration if there is a straightforward
  283. ; iteration that will do the same job, but for many complex tasks 
  284. ; recursion is the simplest and most natural technique to use.
  285.  
  286. ; Note the use of "if" in the above program.
  287.  
  288. ; Here are some examples using if -
  289.  
  290. (if (< 2 3) (+ 2 2) (+ 3 3))
  291. (if (> 2 3) (+ 2 2) (+ 3 3))
  292.  
  293. ; if takes two or three arguments. The first is a test expression, which
  294. ; is evaluated. The result of this evaluation is used to decide which of
  295. ; the remaining two arguments is to be evaluated. If the test expression
  296. ; evaluates to nil (which means false) then the third expression is 
  297. ; evaluated (or if there is no third expression then the value nil is
  298. ; returned). If it evaluates to anything else (which means true), then 
  299. ; the second expression is evaluated.
  300.  
  301.  
  302. ; Here's a simple example that uses recursion. Lisp always requires
  303. ; arithmetic operators like +, *, / and - to appear before their
  304. ; arguments, because they are the names of functions, and that is where 
  305. ; function names have to be. Putting the operator first is called "prefix"
  306. ; notation.
  307.  
  308. ; But we're more used to writing expressions with these operators in 
  309. ; between their arguments. This is called infix notation. Let's write a 
  310. ; lisp function that evaluates expressions containing infix operators.
  311.  
  312. (setq infix-operators '(+ * - /))
  313.  
  314. (defun eval-infix (expr)
  315.   (eval (infix-to-prefix expr)) )
  316.  
  317. (defun infix-to-prefix (expr)
  318.   (if (and 
  319.         (listp expr)
  320.         (= (length expr) 3)
  321.         (member (second expr) infix-operators) )
  322.     (list (infix-to-prefix (second expr))
  323.       (first expr) (infix-to-prefix (third expr)))
  324.     expr) )
  325.  
  326. (infix-to-prefix '(2 + (3 * 4)))
  327.  
  328. (eval-infix '(2 + (3 * 4)))
  329.  
  330. ; (Note the use of the quote ' to prevent evaluation of the arguments
  331. ;  in the examples.)
  332.  
  333. ; The function that does all the work is infix-to-prefix.
  334. ; If its input expression is a three element list where the
  335. ; second member is a member of the list of infix operators,
  336. ; then the returned value is the list constructed by putting
  337. ; the operator first followed by the other two members of the
  338. ; input expression. The tricky thing is that these two members
  339. ; may themselves be expressions that have infix operators that
  340. ; need changing to prefix, so first we have to call the function
  341. ; infix-to-prefix on those members.
  342.  
  343. ; Any other expression is returned as is. The above function doesn't
  344. ; work properly on expressions that mix prefix and infix operators, 
  345. ; where the arguments to prefix operators need fixing.
  346.  
  347. ; An improved solution uses mapcar to apply infix-to-prefix to the
  348. ; list of arguments of a function call.
  349.  
  350. (defun infix-to-prefix (expr)
  351.   (if (consp expr)
  352.     (if (and (= (length expr) 3)
  353.           (member (second expr) infix-operators) )
  354.       (list (second expr)
  355.         (infix-to-prefix (first expr))
  356.         (infix-to-prefix (third expr)) )
  357.       (mapcar #'infix-to-prefix expr) )
  358.     expr) )
  359.  
  360. (infix-to-prefix '(triangle (1 + ((7 - 4) * (triangle 2)))))
  361.  
  362. (eval-infix '(triangle (1 + ((7 - 4) * (triangle 2)))))
  363.  
  364. ; Note the use of mapcar. mapcar takes two arguments - a function, and
  365. ; a list. The function is applied to each member of the list in turn,
  366. ; and the results are made up into a list which is then the return value
  367. ; of mapcar. Here's an example using our function triangle -
  368.  
  369. (mapcar #'triangle '(2 10 5))
  370.  
  371. ; #' is used to convert the name triangle into the function that 
  372. ; the name triangle refers to. Lisp maintains a distinction between
  373. ; names (normally called symbols) and the functions that names
  374. ; refer to.
  375.  
  376. ; We can make un-named functions using #' and lambda (having to use
  377. ; two items of notation to achieve one thing seems a bit redundant,
  378. ; and is required partly for historical reasons).
  379.  
  380. ; The syntax for lambda is similiar to that for defun, but the symbol
  381. ; lambda replaces both defun and the function name. When #' is applied
  382. ; on the front, then what is returned is the same as the function that
  383. ; would be created by the corresponding defun.
  384.  
  385. ; For example -
  386.  
  387. (defun square (x) (* x x))
  388.  
  389. (mapcar #'square '(1 2 3 4 5))
  390.  
  391. ; or using lambda to get the same effect -
  392.  
  393. (mapcar #'(lambda (x) (* x x)) '(1 2 3 4 5))
  394.  
  395. ; The word lambda is the name of a greek letter which was used to 
  396. ; represent definition of a function in the mathematical theory of
  397. ; lambda calculus.
  398.  
  399. ; We can use Lisp to study lambda calculus, but first we need to 
  400. ; learn about funcall. funcall is a function that applies a function to
  401. ; some arguments.
  402.  
  403. ; Here's an example
  404.  
  405. (funcall #'+ 3 4)
  406.  
  407. ; #'+ evaluates to the function named by +. funcall calls that function
  408. ; which the remaining arguments to funcall being the arguments to the
  409. ; function.
  410.  
  411. ; Here's the normal way of defining and using a function in Lisp -
  412.  
  413. (defun cube (x) (* x x x))
  414.  
  415. (cube 10)
  416.  
  417. ; Here's doing it by creating the actual function object and then
  418. ; assigning it as the value of a variable -
  419.  
  420. (setq cube #'(lambda (x) (* x x x)))
  421.  
  422. (funcall cube 10)
  423.  
  424. ; We can use lambda to define functions that create new functions. For
  425. ; example, here's a function that given a number creates a function that
  426. ; adds that number to its input argument
  427.  
  428. (defun adder (x)
  429.   #'(lambda (y) (+ x y)) )
  430.  
  431. (funcall (adder 3) 4)
  432.  
  433. ; The "scope" of x in the definition of adder, i.e. where it can be 
  434. ; referred to, includes the lambda expression, and the function value
  435. ; of the lambda expression is what is returned as the result of adder.
  436.  
  437. ; When (adder 3) was executed, a binding occurred between the name x and
  438. ; a variable which was created and given the value 3. This binding is
  439. ; visible from within the lambda expression. It follows then that the
  440. ; variable x created when (adder 3) was executed must remain in existence
  441. ; even after adder has finished executing, so that the invocation of 
  442. ; the result of (adder 3) with the argument 4 returns the right result.
  443.  
  444. ; Here is a function which given two functions returns the function that
  445. ; is the composition of two functions, i.e. to apply the composition of
  446. ; functions f and g to an argument x, pass x to f and pass the output of
  447. ; f to g, returning the output from g as the final result.
  448.  
  449. (defun compose (f g)
  450.   #'(lambda (x) (funcall g (funcall f x))) )
  451.  
  452. (defun plus5 (x) (+ x 5))
  453.  
  454. (defun times10 (x) (* x 10))
  455.  
  456. (setq h (compose #'times10 #'plus5))
  457.  
  458. (funcall h 3)
  459.  
  460. ; i.e (3 * 10) + 5
  461.  
  462.