123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- ;; Copyright 2013 Google Inc.
- ;;
- ;; Licensed under the Apache License, Version 2.0 (the "License");
- ;; you may not use this file except in compliance with the License.
- ;; You may obtain a copy of the License at
- ;;
- ;; http://www.apache.org/licenses/LICENSE-2.0
- ;;
- ;; Unless required by applicable law or agreed to in writing, software
- ;; distributed under the License is distributed on an "AS IS" BASIS,
- ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ;; See the License for the specific language governing permissions and
- ;; limitations under the License.
- ; borrows from about_methods.py
- (defun some-named-function (a b)
- (+ a b))
- (define-test test-call-a-function
- "DEFUN defines global functions"
- (assert-equal ___ (some-named-function 7 11)))
- (define-test test-shadow-a-function
- "Local functions are defined with FLET or LABELS. One major difference
- between the two is that local functions defined with LABELS may refer
- to themselves, whereas local functions defined with FLET may not."
- (assert-eq 18 (some-named-function 7 11))
- "flet binds a function to a name within a lexical environment"
- (flet ((some-named-function (a b) (* a b)))
- (assert-equal ___ (some-named-function 7 11)))
- (assert-equal ___ (some-named-function 7 11)))
- ; borrowed from Common Lisp The Language chapter 5.2.2
- (defun func-with-opt-params (&optional (a 2) (b 3) )
- ; each optional parameter has a form like (var default-val)
- (list a b))
- (define-test test-optional-parameters
- "Optional parameters are filled in with their default value."
- (assert-equal (func-with-opt-params :test-1 :test-2) ___)
- (assert-equal (func-with-opt-params :test-1) ___)
- (assert-equal (func-with-opt-params) ___))
- ;; ----
- (defun func-with-opt-params-and-indication (&optional (a 2 a?) (b 3 b?))
- (list a a? b b?))
- (define-test test-optional-parameters-with-indication
- "Common Lisp optional params may bind a symbol which indicate whether the
- value was provided or defaulted. Each optional parameter binding has the
- form (var default-form supplied-p)."
- (assert-equal (func-with-opt-params-and-indication :test-1 :test-2) ___)
- (assert-equal (func-with-opt-params-and-indication :test-1) ___)
- (assert-equal (func-with-opt-params-and-indication) ___))
- ;; ----
- (defun func-with-rest-params (&rest x)
- x)
- (define-test test-func-with-rest-params
- "With &rest, the remaining params, are handed in as a list. Remaining
- arguments (possibly none) are collected into a list."
- (assert-equal (func-with-rest-params) ___)
- (assert-equal (func-with-rest-params 1) ___)
- (assert-equal (func-with-rest-params 1 :two 333) ___))
- ;; ----
- (defun func-with-key-params (&key a b)
- (list a b))
- (defun test-key-params ()
- "Key params allow the user to specify params in any order"
- (assert-equal (func-with-key-params) ___)
- (assert-equal (func-with-key-params :a 11 :b 22) ___)
- ; it is not necessary to specify all key parameters
- (assert-equal (func-with-key-params :b 22) ___)
- ; order is not important
- (assert-equal (func-with-key-params :b 22 :a 0) ___))
- (defun func-key-params-can-have-defaults (&key (a 3 a?) (b 4 b?))
- (list a a? b b?))
- (define-test test-key-params-can-have-defaults
- "key parameters can have defaults also"
- (assert-equal (func-key-params-can-have-defaults) ____)
- (assert-equal (func-key-params-can-have-defaults :a 3 :b 4) ___)
- (assert-equal (func-key-params-can-have-defaults :a 11 :b 22) ___)
- (assert-equal (func-key-params-can-have-defaults :b 22) ___)
- ; order is not important
- (assert-equal (func-key-params-can-have-defaults :b 22 :a 0) ___))
- ;; ----
- ;; borrowed from common listp the language 5.2.2
- (defun func-with-funky-parameters (a &rest x &key b (c a))
- (list a b c x))
- (define-test test-many-kinds-params
- "CL provides the programmer with more than enough rope to hang himself."
- (assert-equal (func-with-funky-parameters 1) ___)
- (assert-equal (func-with-funky-parameters 1 :b 2) ___)
- (assert-equal (func-with-funky-parameters 1 :b 2 :c 3) ___)
- (assert-equal (func-with-funky-parameters 1 :c 3 :b 2) ___))
- ;; Note that &rest parameters have to come before &key parameters.
- ;; This is an error: (defun f (&key a &rest x) () )
- ;; But this is ok: (defun f (&rest x &key a) () )
- (define-test test-lambdas-are-nameless-functions
- "A lambda form defines a function, but with no name. It is possible
- to execute that function immediately, or put it somewhere for later use."
- (assert-equal 19 ((lambda (a b) (+ a b)) 10 9))
- (let ((my-function))
- (setf my-function (lambda (a b) (* a b)))
- (assert-equal ___ (funcall my-function 11 9)))
- (let ((list-of-functions nil))
- (push (lambda (a b) (+ a b)) list-of-functions)
- (push (lambda (a b) (* a b)) list-of-functions)
- (push (lambda (a b) (- a b)) list-of-functions)
- (assert-equal ___ (funcall (second list-of-functions) 2 33))))
- (define-test test-lambdas-can-have-optional-params
- (assert-equal ___ ((lambda (a &optional (b 100)) (+ a b)) 10 9))
- (assert-equal ___ ((lambda (a &optional (b 100)) (+ a b)) 10)))
- ; returns sign x
- (defun sign-of (x)
- (if (< x 0) (return-from where-to-return -1))
- (if (eq x 0) (return-from where-to-return 0))
- 1)
- (define-test test-return-from-function-early
- (assert-equal (sign-of -5.5) ___)
- (assert-equal (sign-of 0) ___)
- (assert-equal (sign-of ___) 1))
- ;; ----
- ;; Lambdas create "lexical closures", meaning that the resulting function, when
- ;; called, will execute in an environment wherein the lexical bindings to all
- ;; referred to names still apply.
- ;; This example from "Common Lisp The Language" Ch. 7
- (defun adder (x)
- "The result of (adder n) is a nameless function with one parameter.
- This function will add n to its argument."
- (lambda (y) (+ x y)))
- (defun test-lexical-closure-over-adder ()
- (let ((add-100 (adder 100))
- (add-500 (adder 500)))
- "add-100 and add-500 now refer to different bindings to x"
- (assert-equal ___ (funcall add-100 3))
- (assert-equal ___ (funcall add-500 3))))
- ;; ----
- ;; The closure gives the returned function access to the bindings, not just the
- ;; values. This means that two functions which close over the same variables
- ;; will always see the same values of those variables if one does a setq.
- (defun two-funs (x)
- "Returns a list of two functions.
- The first takes no parameters and returns x.
- The second takes one parameter, y, and resets x to the value of y."
- (list (function (lambda () x))
- (function (lambda (y) (setq x y)))))
- (define-test test-lexical-closure-interactions
- "An illustration of how lexical closures may interact."
- (let ((tangled-funs-1 (two-funs 1))
- (tangled-funs-2 (two-funs 2)))
- (assert-equal (funcall (first tangled-funs-1)) ___)
- (funcall (second tangled-funs-1) 0)
- (assert-equal (funcall (first tangled-funs-1)) ___)
- (assert-equal (funcall (first tangled-funs-2)) ___)
- (funcall (second tangled-funs-2) 100)
- (assert-equal (funcall (first tangled-funs-2)) ___)))
- (define-test test-apply-function-with-apply
- "APPLY calls the function parameter on a list of all the remaining
- parameters"
- (let (f1 f2 f3)
- (setq f1 '+)
- (setq f2 '-)
- (setq f3 'max)
- (assert-equal ___ (apply f1 '(1 2)))
- (assert-equal ___ (apply f2 '(1 2)))
- ; after the function name, the parameters are consed onto the front
- ; of the very last parameter
- (assert-equal ___ (apply f1 1 2 '(3)))
- (assert-equal ___ (apply f3 1 2 3 4 '()))))
- (define-test test-apply-function-with-funcall
- "FUNCALL calls the function parameter on a list of all the remaining
- parameters. Remaining params do not expect a final list."
- (let (f1 f2 f3)
- (setq f1 '+)
- (setq f2 '-)
- (setq f3 'max)
- (assert-equal ___ (funcall f1 1 2))
- (assert-equal ___ (funcall f2 1 2))
- (assert-equal ___ (funcall f1 1 2 3))
- (assert-equal ___ (funcall f3 1 2 3 4))))
|