123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- Some simple context-aware operations
- Description:
- As in any language, lisp interpreters allow to
- store information in "variables".
- A variable is an identifier, which is associated to a lisp
- expression using the operator "define".
- To update the value associated with a variable,
- a specific "set!" operator must be used.
- The scope of those variables is by default global, i.e.
- they can be accessed in any lisp expression after being
- defined.
- A specific case is the one of function (lambda expression) parameters.
- Those variables are not defined explicitly.
- Their scope is limited to the body of the lambda expression.
- Narrative:
- In order to reuse information,
- as a casual lisp user
- I want to associate expressions to identifiers using the keyword define.
- Scenario: simple definitions
- Given a lisp interpreter
- When the expression entered is (define a 5)
- Then the result should be 5
- When the expression entered is (define b 10)
- Then the result should be 10
- When the expression entered is <expression>
- Then the result should be <result>
- Examples:
- |expression |result|
- |(+ a b) | 15 |
- |(- a b) | -5 |
- |(* a b) | 50 |
- |(* 1 a 2 b) | 100 |
- |(/ b a) | 2 |
- |(max a b) | 10 |
- |(min a b) | 5 |
- |(cons a (cons b ()))| (5 10) |
- Scenario: overriding definitions
- Given a lisp interpreter
- When the expression entered is (define a 5)
- Then the result should be 5
- When the expression entered is (define b 10)
- Then the result should be 10
- When the expression entered is (+ a b)
- Then the result should be 15
- When the expression entered is (define b 30)
- Then the result should be 30
- When the expression entered is (+ a b)
- Then the result should be 35
- When the expression entered is (define a 20)
- Then the result should be 20
- When the expression entered is (+ a b)
- Then the result should be 50
- Scenario: some students are picky about testing
- Given a lisp interpreter
- When the expression entered is <expression>
- Then the result should display the error message <result>
- Examples:
- |expression|result|
- |(define 12 20)|12 is not a valid identifier|
- |(define + 20)|+ is not a valid identifier|
- |(define - 20)|- is not a valid identifier|
- |(define * 20)|* is not a valid identifier|
- |(define / 20)|/ is not a valid identifier|
- |(define or 20)|or is not a valid identifier|
- |(define not 20)|not is not a valid identifier|
- |(define and 20)|and is not a valid identifier|
- |(define lambda 20)|lambda is not a valid identifier|
- |(define define 20)|define is not a valid identifier|
- |(define set! 20)|set! is not a valid identifier|
- |(define cons 20)|cons is not a valid identifier|
- Scenario: modifying the value of an identifier using set!
- Given a lisp interpreter
- When the expression entered is (define a 50)
- Then the result should be 50
- When the expression entered is (set! a 30)
- Then the result should be 30
- When the expression entered is (set! b 20)
- Then the result should display the error message b is undefined
- Scenario: defining a function (a lambda expression) with one parameter
- Given a lisp interpreter
- When the expression entered is (define surprise (lambda (x) (* x x)))
- Then the result should be lambda (x) (* x x)
- When the expression entered is (surprise 10)
- Then the result should be 100
- Scenario: defining a function (a lambda expression) with two parameters
- Given a lisp interpreter
- When the expression entered is (define surprise (lambda (x y) (* x y)))
- Then the result should be lambda (x y) (* x y)
- When the expression entered is (surprise 10 20)
- Then the result should be 200
- Scenario: a function has its own context
- Given a lisp interpreter
- When the expression entered is (define x 10)
- Then the result should be 10
- When the expression entered is x
- Then the result should be 10
- When the expression entered is (define surprise (lambda (x) (* x x)))
- Then the result should be lambda (x) (* x x)
- When the expression entered is (surprise 15)
- Then the result should be 225
- When the expression entered is x
- Then the result should be 10
- Scenario: identifier is not defined
- Given a lisp interpreter
- When the expression entered is x
- Then the result should display the error message x is undefined
- When the expression entered is (surprise 15)
- Then the result should display the error message surprise is undefined
- Scenario: first group inspiration
- Given a lisp interpreter
- When the expression entered is (define n 10)
- Then the result should be 10
- When the expression entered is (define f (lambda (x) (* n x)))
- Then the result should be lambda (x) (* n x)
- When the expression entered is (f 4)
- Then the result should be 40
- When the expression entered is (set! n 100)
- Then the result should be 100
- When the expression entered is (f 4)
- Then the result should be 400
|