1 / 17

Scoping

Scoping. “It is necessary for him who lays out a state and arranges laws for it to presuppose that all men are evil and that they are always going to act according to the wickedness of their spirits whenever they have free scope.” -Niccolo Machiavelli. State is a Necessary Evil.

bmortensen
Download Presentation

Scoping

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Scoping “It is necessary for him who lays out a state and arranges laws for it to presuppose that all men are evil and that they are always going to act according to the wickedness of their spirits whenever they have free scope.” -Niccolo Machiavelli

  2. State is a Necessary Evil • Without state, you can’t have File IO, user input, long term memory, etc. • Scope helps control state by restricting the visibility of variable/function names • A binding environment is a mapping between names and functions/variables • Can be nested

  3. Global Scope • defun, defvar and defconstant create globally accessible entities • defun makes defining functions easier • defconstant saves repetition, and makes your code more readable • defvar introduces mutable state, and should be avoided except when combined with LISP’s more imperative data structures (much later…)

  4. Local Scope for Variables • let, let* and defun create local environments for variables • We usually don’t change variable values inside of these environments, but you can:

  5. Local Scope for Functions • Function names can also be defined locally using flet and labels • Instead of writing helper functions with defun, you can put them in the main function body • Benefits of information hiding, similar to private methods in object oriented languages

  6. Labels • Syntax: (labels ((fn args body)*) body) • Example: (defun sum (xs) (labels ((sum-help (xs acc) (if (consp xs) (sum-help (cdr xs) (+ (car xs) acc)) acc))) (sum-help xs 0)))

  7. Flet • flet is to let, what labels is to let* • In other words, flet can’t define functions in terms of functions within the same flet • The means flet cannot define recursive functions, so it is not as useful as labels

  8. Closures • Allow you to maintain global state without the use of global variables • A marriage of local variables and functions • Combine the safety of local reference with the universal access of global reference • Preferred over global variables

  9. (let ((n 0)) (defun next-n () (setf n (1+ n))) (defun set-n (val) (setf n val)) ) >(next-n) 1 >(next-n) 2 >(setf n 100) 100 >(next-n) 3 >(set-n 100) 100 >(next-n) 101 Closure Example

  10. Blocks • Allow for procedural programming • Primary use is to make side-effects occur, so it is possible to write many programs without ever needing a block • This is one of those ways to cheat that should be avoided if possible

  11. Progn • Expressions in a progn block are evaluated in order and the return value of the last expression is returned >(progn (setf x 5) (setf y 3) (+ x y)) 8 >x 5 >y 3

  12. Block • block is similar to progn, but with an “escape hatch” >(block escape (setf x 3) (setf x (* x 3)) (return-from escape x)) 9 >(block nil (setf x 4) (setf x (+ x 20)) (return x)) 24

  13. Simple Error Checking • Another situation where you may need to return to a point in the center of your code is for error checking • For simple error checking, this is unnecessary: (defun sum (x acc) (if (consp x) (if (numberp (car x)) (sum (cdr x) (+ (car x) acc)) "Error: sum expects a list of numbers as input") acc))

  14. Error Handling • More complex error handling, where execution must continue despite errors, can be done with the catch and throw functions • throw takes a tag and a return value • catch takes a tag and zero or more S-expressions • Tags are compared using eq

  15. Throw-Catch Example >(defun positive-only (arg) (cond ((< arg 0) (throw 'negative arg)) (t (setf value arg)))) POSITIVE-ONLY >(catch 'negative (positive-only 55) (positive-only -5) (positive-only 99)) -5 >value 55  Only the first call to positive-only worked

  16. Unwind-Protect • Allows evaluation of certain expressions despite a throw • First argument may not terminate successfully • Second (or more) expressions are evaluated regardless of whether an error was signaled with throw • Similar to the finally keyword in Java

  17. Unwind-Protect Example >(defun positive-only (arg) (cond ((< arg 0) (throw 'negative arg)) (t (setf value arg)))) POSITIVE-ONLY >(unwind-protect (catch 'negative (positive-only -2)) (positive-only 99)) -2  Result of the throw is the return value >value 99  Second expression of unwind-protect evaluated

More Related