Sunday, June 3, 2012

Land of Lisp Chp2 Summary

Alright. I'm late. Story of my life. Moving right along.
Chapter 1 covered fluffery like history, why learn Lisp, and getting an interpreter set up.
Chapter 2 covered some programming basics.

  • Setting up variables 
    • Global with defparameter, which is probably intended to 'define' the operating 'parameters' of the code set. Whether this should actually be used to store operating variables I'm uncertain, certainly globals are probably better avoided at any rate.
    • Static global with defvar, though I'm sure I'm misunderstanding this one, it was only glossed over.
    • In a local context with let. A more traditional variable. An interesting point is that let literally defines the scope of the variables using the () syntax. In a and b only exist within the {code body} of the outer set of brackets.
setf was glossed over but can, apparently, be used to assign a value to a global defined with defparameter though presumably not defvar, though this isn't explicitly stated (in fact, calling defvar a static may be incorrect, all that is stated explicitly is that it cannot be redefined to a different value using another defvar call whereas defparameter can be).


Then the simple arithmetic shift function which binary shifts {value} by {int}. Binary math is one of the basics I need to work on. Defining ash is simple, grokking it takes some effort.

Finally we have function definitions.

Creates a global (I think?) function. This is the 2nd chapter, things like scope and the subtleties of variable definition aren't being explicitly stated. Anyway. {name} is, clearly, the name you'd use to call this function later. {parameter names} is simply a list of variable names for the function's parameters. {function list} is the code that will be executed. So.

Anytime you call sna it will add foo and bar, the result of which will be implicitly returned to the calling context (either the function call it was used within or to output if it was called directly from the REPL. Which reminds me, the REPL is the basic interface to the Lisp interpreter. It stands for Read Eval Print Loop. It does precisely what it says.


Moving along, there's local function definitions with flet. The syntax is slightly different.

Once again, there's a {name}, {parameter names}, and {function code} however they're enclosed in double ()s. No idea why, yet. That took me a second. The addition of ellipsis indicates that you can define multiple functions for the {code body} in the same way as let. Finally there's the {code body} which contains the code where {name} is in scope.


And the last function definition method covered was labels. labels, apparently, is a window into recursion. It allows functions to be called within other functions defined in the same labels form. I think the book actually has a typo in its example here. First because it won't pass the interpreter and second because the listed example doesn't make sense for Lisp. And the parentheses don't match. Oh, and the proposed output doesn't even make sense.
The book:

That doesn't interpret. It blows chunks because the function 'b' isn't defined. Which makes sense visually. Here's my rewriting which passes the interpreter test:

I laid it out slightly differently too, makes it easier for me to read. To be honest I don't care if it breaks convention (I don't even know what they are yet), I'm not used to reading all those parentheses and I'm not writing code for the perusal of others so I'm going to write it however makes it easiest to read. Moving right along. Here's the generic syntax, assuming I'm right and the book is not:

Condensed like that it's hard to read, but again it's very much the same syntax as flet it just allows each {name} in the function list to reference any other functions in the list. 


Here's an interesting point. LisP is short for List Processor. As the name implies everything in LisP is a list. (I'm pulling this from an aborted attempt to plow through another book on ANSI Common Lisp from a few years ago) Even the functions. The basic syntax is always

where keyword is a builtin command or defined function name, and list is the parameters for the keyword to operate on. Using that nomenclature you can rewrite all of the above. I'm going to make some guesses down here about the underpinnings of the language. I'll probably be wrong, but hey. Grokking it piece by piece.

let takes as parameters a list of tuples for variables and an arbitrary list of additional commands to be parsed. The action that the keyword let performs is basically to replace the occurrences of the keyword with the value each time it sees one of its tuples in the command list.

defun takes a keyword , a list of keywords, and an arbitrary list of commands. The first keyword is taken for a label, or name, or reference, or something. I'm not sure how it's handled or what it's called in the guts of the interpreter. Then you have, basically, which looks a lot like let, doesn't it? I presume the interpreter does something like applying let to each item in {list of keywords} on each function call and then parsing the {list} in that context. flet and labelscan be similarly rewritten by assuming flet to apply defun to each item in {list of functions} which then would apply let to each {list of keywords} within the defuns etc etc ad nauseum. That's why we let the interpreter do it. But in the end it always ends up in a flat list which it processes based on the interpreter's builtins and passes the results back up the stack all the way to, eventually, the REPL. I'm not quite sure how labels works to implement recursion, I assume there's different kinds of internal names? Anyway, that will come later.





I've decided that I can't be bothered to manually do a linked list out of these. Just hit the land of lisp tag and be done with it.

Edit: I went through and crammed all the code bits into gists. It isn't perfect and may not be the best solution, but it'll do.

No comments: