Fork of https://github.com/google/lisp-koans so that I could go through them. THIS CONTAINS ANSWERS.

functions.lsp 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. ;; Copyright 2013 Google Inc.
  2. ;;
  3. ;; Licensed under the Apache License, Version 2.0 (the "License");
  4. ;; you may not use this file except in compliance with the License.
  5. ;; You may obtain a copy of the License at
  6. ;;
  7. ;; http://www.apache.org/licenses/LICENSE-2.0
  8. ;;
  9. ;; Unless required by applicable law or agreed to in writing, software
  10. ;; distributed under the License is distributed on an "AS IS" BASIS,
  11. ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. ;; See the License for the specific language governing permissions and
  13. ;; limitations under the License.
  14. ; borrows from about_methods.py
  15. (defun some-named-function (a b)
  16. (+ a b))
  17. (define-test test-call-a-function
  18. "DEFUN defines global functions"
  19. (assert-equal 18 (some-named-function 7 11)))
  20. (define-test test-shadow-a-function
  21. "Local functions are defined with FLET or LABELS. One major difference
  22. between the two is that local functions defined with LABELS may refer
  23. to themselves, whereas local functions defined with FLET may not."
  24. (assert-eq 18 (some-named-function 7 11))
  25. "flet binds a function to a name within a lexical environment"
  26. (flet ((some-named-function (a b) (* a b)))
  27. (assert-equal 77 (some-named-function 7 11)))
  28. (assert-equal 18 (some-named-function 7 11)))
  29. ; borrowed from Common Lisp The Language chapter 5.2.2
  30. (defun func-with-opt-params (&optional (a 2) (b 3) )
  31. ; each optional parameter has a form like (var default-val)
  32. (list a b))
  33. (define-test test-optional-parameters
  34. "Optional parameters are filled in with their default value."
  35. (assert-equal (func-with-opt-params :test-1 :test-2) '(:test-1 :test-2))
  36. (assert-equal (func-with-opt-params :test-1) '(:test-1 3))
  37. (assert-equal (func-with-opt-params) '(2 3)))
  38. ;; ----
  39. (defun func-with-opt-params-and-indication (&optional (a 2 a?) (b 3 b?))
  40. (list a a? b b?))
  41. (define-test test-optional-parameters-with-indication
  42. "Common Lisp optional params may bind a symbol which indicate whether the
  43. value was provided or defaulted. Each optional parameter binding has the
  44. form (var default-form supplied-p)."
  45. (assert-equal (func-with-opt-params-and-indication :test-1 :test-2) '(:test-1 t :test-2 t))
  46. (assert-equal (func-with-opt-params-and-indication :test-1) '(:test-1 t 3 nil))
  47. (assert-equal (func-with-opt-params-and-indication) '(2 nil 3 nil)))
  48. ;; ----
  49. (defun func-with-rest-params (&rest x)
  50. x)
  51. (define-test test-func-with-rest-params
  52. "With &rest, the remaining params, are handed in as a list. Remaining
  53. arguments (possibly none) are collected into a list."
  54. (assert-equal (func-with-rest-params) nil)
  55. (assert-equal (func-with-rest-params 1) '(1))
  56. (assert-equal (func-with-rest-params 1 :two 333) '(1 :two 333)))
  57. ;; ----
  58. (defun func-with-key-params (&key a b)
  59. (list a b))
  60. (define-test test-key-params ()
  61. "Key params allow the user to specify params in any order"
  62. (assert-equal (func-with-key-params) '(nil nil))
  63. (assert-equal (func-with-key-params :a 11 :b 22) '(11 22))
  64. ; it is not necessary to specify all key parameters
  65. (assert-equal (func-with-key-params :b 22) '(nil 22))
  66. ; order is not important
  67. (assert-equal (func-with-key-params :b 22 :a 0) '(0 22)))
  68. (defun func-key-params-can-have-defaults (&key (a 3 a?) (b 4 b?))
  69. (list a a? b b?))
  70. (define-test test-key-params-can-have-defaults
  71. "key parameters can have defaults also"
  72. (assert-equal (func-key-params-can-have-defaults) '(3 nil 4 nil))
  73. (assert-equal (func-key-params-can-have-defaults :a 3 :b 4) '(3 t 4 t))
  74. (assert-equal (func-key-params-can-have-defaults :a 11 :b 22) '(11 t 22 t))
  75. (assert-equal (func-key-params-can-have-defaults :b 22) '(3 nil 22 t))
  76. ; order is not important
  77. (assert-equal (func-key-params-can-have-defaults :b 22 :a 0) '(0 t 22 t)))
  78. ;; ----
  79. ;; borrowed from common lisp the language 5.2.2
  80. (defun func-with-funky-parameters (a &rest x &key b (c a))
  81. (list a b c x))
  82. (define-test test-many-kinds-params
  83. "CL provides the programmer with more than enough rope to hang himself."
  84. (assert-equal (func-with-funky-parameters 1) '(1 nil 1 nil))
  85. (assert-equal (func-with-funky-parameters 1 :b 2) '(1 2 1 (:b 2)))
  86. (assert-equal (func-with-funky-parameters 1 :b 2 :c 3) '(1 2 3 (:b 2 :c 3)))
  87. (assert-equal (func-with-funky-parameters 1 :c 3 :b 2) '(1 2 3 (:c 3 :b 2))))
  88. ;; Note that &rest parameters have to come before &key parameters.
  89. ;; This is an error: (defun f (&key a &rest x) () )
  90. ;; But this is ok: (defun f (&rest x &key a) () )
  91. (define-test test-lambdas-are-nameless-functions
  92. "A lambda form defines a function, but with no name. It is possible
  93. to execute that function immediately, or put it somewhere for later use."
  94. (assert-equal 19 ((lambda (a b) (+ a b)) 10 9))
  95. (let ((my-function))
  96. (setf my-function (lambda (a b) (* a b)))
  97. (assert-equal 99 (funcall my-function 11 9)))
  98. (let ((list-of-functions nil))
  99. (push (lambda (a b) (+ a b)) list-of-functions)
  100. (push (lambda (a b) (* a b)) list-of-functions)
  101. (push (lambda (a b) (- a b)) list-of-functions)
  102. (assert-equal 66 (funcall (second list-of-functions) 2 33))))
  103. (define-test test-lambdas-can-have-optional-params
  104. (assert-equal 19 ((lambda (a &optional (b 100)) (+ a b)) 10 9))
  105. (assert-equal 110 ((lambda (a &optional (b 100)) (+ a b)) 10)))
  106. ; returns sign x
  107. (defun sign-of (x)
  108. (if (< x 0) (return-from sign-of -1))
  109. (if (eq x 0) (return-from sign-of 0))
  110. 1)
  111. (define-test test-return-from-function-early
  112. (assert-equal (sign-of -5.5) -1)
  113. (assert-equal (sign-of 0) 0)
  114. (assert-equal (sign-of 201) 1))
  115. ;; ----
  116. ;; Lambdas create "lexical closures", meaning that the resulting function, when
  117. ;; called, will execute in an environment wherein the lexical bindings to all
  118. ;; referred to names still apply.
  119. ;; This example from "Common Lisp The Language" Ch. 7
  120. (defun adder (x)
  121. "The result of (adder n) is a nameless function with one parameter.
  122. This function will add n to its argument."
  123. (lambda (y) (+ x y)))
  124. (define-test test-lexical-closure-over-adder ()
  125. (let ((add-100 (adder 100))
  126. (add-500 (adder 500)))
  127. "add-100 and add-500 now refer to different bindings to x"
  128. (assert-equal 103 (funcall add-100 3))
  129. (assert-equal 503 (funcall add-500 3))))
  130. ;; ----
  131. ;; The closure gives the returned function access to the bindings, not just the
  132. ;; values. This means that two functions which close over the same variables
  133. ;; will always see the same values of those variables if one does a setq.
  134. (defun two-funs (x)
  135. "Returns a list of two functions.
  136. The first takes no parameters and returns x.
  137. The second takes one parameter, y, and resets x to the value of y."
  138. (list (function (lambda () x))
  139. (function (lambda (y) (setq x y)))))
  140. (define-test test-lexical-closure-interactions
  141. "An illustration of how lexical closures may interact."
  142. (let ((tangled-funs-1 (two-funs 1))
  143. (tangled-funs-2 (two-funs 2)))
  144. (assert-equal (funcall (first tangled-funs-1)) 1)
  145. (funcall (second tangled-funs-1) 0)
  146. (assert-equal (funcall (first tangled-funs-1)) 0)
  147. (assert-equal (funcall (first tangled-funs-2)) 2)
  148. (funcall (second tangled-funs-2) 100)
  149. (assert-equal (funcall (first tangled-funs-2)) 100)))
  150. (define-test test-apply-function-with-apply
  151. "APPLY calls the function parameter on a list of all the remaining
  152. parameters"
  153. (let (f1 f2 f3)
  154. (setq f1 '+)
  155. (setq f2 '-)
  156. (setq f3 'max)
  157. (assert-equal 3 (apply f1 '(1 2)))
  158. (assert-equal -1 (apply f2 '(1 2)))
  159. ; after the function name, the parameters are consed onto the front
  160. ; of the very last parameter
  161. (assert-equal 6 (apply f1 1 2 '(3)))
  162. (assert-equal 4 (apply f3 1 2 3 4 '()))))
  163. (define-test test-apply-function-with-funcall
  164. "FUNCALL calls the function parameter on a list of all the remaining
  165. parameters. Remaining params do not expect a final list."
  166. (let (f1 f2 f3)
  167. (setq f1 '+)
  168. (setq f2 '-)
  169. (setq f3 'max)
  170. (assert-equal 3 (funcall f1 1 2))
  171. (assert-equal -1 (funcall f2 1 2))
  172. (assert-equal 6 (funcall f1 1 2 3))
  173. (assert-equal 4 (funcall f3 1 2 3 4))))