120 likes | 273 Views
Miscellaneous Topics. Packages Provide separable name spaces for functions, constants, macros We can encapsulate code in packages like classes in Java but the main intention is to provide a name space You do not import entire packages, unlike Java Package operations:
E N D
Miscellaneous Topics • Packages • Provide separable name spaces for functions, constants, macros • We can encapsulate code in packages like classes in Java but the main intention is to provide a name space • You do not import entire packages, unlike Java • Package operations: • in-package – switch to the named package • (in-package ’my-stuff) • make-package – creates a new package in which any new definitions will be placed • list-all-packages – lists all packages defined in the current run-time environment • intern – returns a matching symbol for the given string – the intention is to find the symbol in the package, (intern string &optional package) • find-symbol – same as intern except that it does not create a new symbol if the given symbol is not found (intern creates and returns the new symbol) • unintern – removes the symbol from the package • export – allows symbols to be referenced in other packages • import – allows symbols from other packages to be referenced in the current package • (export symbols &optional package) (import symbols &optional package)
More on Packages • There are a number of built-in packages • lisp (core lisp) • user (the default package in the listener, all of your functions, constants and variables are placed here unless you switch packages) • others include: keyword, system, clos, lispworks, sql, win32, common-lisp, compiler, and several others, most loaded by default • To reference items in other packages, use : and :: • package:item – look in the named package for the given item for a reference to item • package::item – same except that it interns item in the current package as well as allowing the reference • :item – interns the item in the keyword package • Packages are of great value in large-scale systems but should be avoided otherwise because name conflicts should be avoidable with a little care
Example (require ’calculus) ;; require means to load this package (use-package ’calculus) ;; get easy access to exported symbols (require ’newtonian-mechanics) ;; same for this package (use-package ’newtonian-mechanics) (require ’relativity) ;; for relativity, we import specific functions (import ’(relativity:speed-of-light relativity:ignore-small-errors)) ;; rather than use the ;; entire package (require ’phlogiston) (provide ’phlogiston) ;; this is the name of the package (in-package ’phlogiston) ;; move into the package (export ’(heat-flow cold-flow mix-fluids separate-fluids ;; we will export these burn make-fire-bottle)) ;; functions to other packages (require ’alchemy) ;; another package, we want easy access (use-package ’alchemy) ;; to the items in this package (defun heat-flow (amount x y) ;; (when feeling-weak) (quaff (elixir-of-life))) ;; quaff is defined in alchemy, so we don’t need (push-heat amount x y)) ;; a qualifer here since we are using the whole package
Compiling • Since Lisp is interpreted, there is no need to compile code • Compiling code does have three possible advantages: • It will (or may) make it execute faster • It will catch certain errors and warnings that the interpreter may not • Once compiled, you can run disassemble and examine the assembly code (if you have any reason for doing this) • To compile a function do (compile ’function-name) • To compile a file do (compile-file “filename”) • You can also compile files from the menus in the Lisp environment • Another selection is compile and load, which first compiles then file then loads the compiled version rather than the source version • Compiling a file creates a .fsl file • we usually pronounce this as a fassle file, fsl = fast load • There is a macro called eval-when, this is like eval, but it allows you to provide a time when the evaluation should take place • compile – evaluate at compile time • load – evaluate at load time • eval – evaluate at interpretation time (meaning now)
Example of a Disassemble 20692082: 0: 3B25BC150020 cmp esp, [200015BC] ; T 6: 761B jbe L1 8: 80FD01 cmpb ch, 1 11: 7516 jne L1 13: 55 push ebp 14: 89E5 move ebp, esp 16: 3C00 cmpb al, 0 18: 7514 jne L2 20: 89C7 move edi, eax 22: 81C700010000 add edi, 100 28: 700A jo L2 30: FD std 31: 89F8 move eax, edi 33: C9 leave 34: C3 ret L1: 35: E8D8679BFF call 20048882 ; #<function 20048882> L2: 40: FF7500 push [ebp] 43: 83ED04 sub ebp, 4 46: 8B7508 move esi, [ebp+8] 49: 897504 move [ebp+4], esi 52: 894508 move [ebp+8], eax 55: B800010000 move eax, 100 60: C9 leave 61: E9E6303300 jmp 209C51AA ; #<function 209C51AA> CL-USER 10 > (defun bar (x) (+ x 1)) BAR CL-USER 11 > (compile 'bar) BAR NIL NIL CL-USER 12 > (disassemble 'bar)
The Declare Compiler Directive • We’ve already used declare to declare special (global) variables, we can also declare for a number of other things, all of which are done by the compiler • Declaring a specific type for a variable • (declare (type float x)) • Declaring code to be inline or notinline • this means whether the function call is replaced by the function’s code in order to make for more efficient execution • by using notinline, you can replace built-in CL code for your own • (declare (inline myfunction) (noinline length)) • Using proclaim to make a given declare statement globally rather than in the current scope • Using optimize for compiler-specific optimizations to control such factors as execution speed, safety, space utilization, and debugging help • note that speed is inversely proportional to safety and debugging • (declare optimize (speed 5) (safety 2)) • Note: declare may only appear in certain forms (defmacro, defun, do, dolist, dotimes, flet, labels, let, prog, and a few others)
Garbage Collection • All variables (pointers) are collected together into a group of root pointers • that is, the root pointers point to groups of variables that point to the used memory • The garbage collector is invoked by the OS when heap memory is running low • It follows the root pointers to each pointer and then onto the allocated memory • as any memory item is reached, it is marked as being used • there is a loop detection mechanism in order to prevent the garbage collector from being stuck in a cycle of pointers • When done, the OS is able to use any heap item that is unmarked • the greater the number of unmarked items, the slower your garbage collector will run and therefore, your program will slow down more and more as you discontinue using items
Defadvice • A function that allows you to alter how an already defined function will work by providing before, around and after components • Consider the previous example, bar, which merely adds 1 to a number • Lets use defadvice to change bar’s behavior so that it only adds 1 to the absolute value of the parameter • (defadvice (bar ensure-positive :around) (x) (if (< x 0) (setf x (* x -1))) (call-next-advice x)) • note: call-next-advice invokes the original bar (otherwise bar would be skipped entirely), call-next-advice is only used in :around statements • In addition, lets ensure that x is a number: • (defadvice (bar ensure-positive :around) (x) (if (not (numberp x)) (format t "~A is not a number, cannot continue with this function" x) (progn (if (< x 0) (setf x (* x -1))) (call-next-advice x))))
Another Example • I want to modify reverse in two ways • I want to know the number of items to be reversed • I want to ensure that the parameter to reverse is a sequence to avoid any error • This will use both a :before and an :around • (defadvice (reverse print-length :before) (x) (print (length x))) • (defadvice (reverse check-sequence :around) (x) (if (not (sequencep x)) (warn "~a is not a sequence" x) (call-next-advice x))) • You can use :before and :around or :around and :after, but not a :before and :after or multiple :before/:after/:around statements • Only the most recently defined :before, :after, and :around will be recognized • Here, we use defadvice to ensure that the thing being reversed is limited in size (in this case, to no more than 10 items) • (defadvice (reverse shorten-length :around) (x) (if (> (length x) 10) (setf x (subseq x 0 10))) (call-next-advice x))
Calling Foreign Functions • You can call upon external routines from inside Common Lisp • call-system is a function for calling external programs • you can use this call OS routines • although this is more useful in unix/linux where each routine is individually named, probably not useful at all in Windows • or you can call compiled programs such as a C program that has been compiled • form: (call-system string) where string is a string that is the function name and params • note that any I/O may appear in the foreign language’s interface • for instance, when running a C program, scanf or printf will most likely open a console window, rather than having the I/O appear in the Lisp window
And More! • There are a lot of features we haven’t examined • Building a user interface (including GUI) • Not available in the personnel version of LispWorks • Creating sockets for network communication • In the comm package • Multiprocessing • In the mp package • Accessing SQL servers • Not available in the personnel version of LispWorks • Using the profiler tool • This allows you to see how your code executes in terms of making it more efficient • Dynamic Data Exchange • Allows you to exchange data between running processes in the Windows environment via a client-server relationship