<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Curmudgeoclast</title>
	<atom:link href="http://techblog.daveastels.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://techblog.daveastels.com</link>
	<description>This sucks, wouldn&#039;t it be cool if...?</description>
	<lastBuildDate>Thu, 26 Apr 2012 19:42:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Environment headers</title>
		<link>http://techblog.daveastels.com/2012/04/26/environment-headers/</link>
		<comments>http://techblog.daveastels.com/2012/04/26/environment-headers/#comments</comments>
		<pubDate>Thu, 26 Apr 2012 19:42:28 +0000</pubDate>
		<dc:creator>dastels</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[clojure]]></category>

		<guid isPermaLink="false">http://techblog.daveastels.com/?p=547</guid>
		<description><![CDATA[I&#8217;m working on a web app in Clojure and finding or (re)inventing various useful bits of code, which I&#8217;ll be posting here. To start, here a few bits of code to create a banner identifying the environment you&#8217;re looking at. First, read in the environment from a property file and create ways to query it. [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working on a web app in Clojure and finding or (re)inventing various useful bits of code, which I&#8217;ll be posting here.</p>
<p>To start, here a few bits of code to create a banner identifying the environment you&#8217;re looking at.</p>
<p>First, read in the environment from a property file and create ways to query it.</p>
<blockquote><p><code>
<pre>
(def env-props (read-properties "env.properties"))
(def environment (.getProperty env-props "env"))
(def development? (= "development" environment))
(def staging?     (= "staging" environment))
(def production?  (= "production" environment))
</pre>
<p></code></p></blockquote>
<p>I decided to put the banner up when logged in as admin, so that I&#8217;m keenly aware of where I am when I have that level of control. I also wanted the banner displayed everywhere other than production regardless of the user. <em>(The <strong>grid-12</strong>, <strong>alpha</strong>, and <strong>omega</strong> classes are part of the 960-system css framework I&#8217;m using.)</em></p>
<blockquote><p><code>
<pre>
(unless (and (not (any-role-granted? :admin))
             production?)
  [:div#environment-banner.grid-12
    [:div {:class (str "grid-12 alpha omega " environment)}
      (str "============>>> " environment " <<<============")]])
</pre>
<p></code></p></blockquote>
<p>Finally, some css to make it standout. I went with a traffic light color scheme.</p>
<blockquote><p><code>
<pre>
div#environment-banner div {
    text-align: center;
    text-transform: uppercase;
    font-weight: bolder;
    padding-top: 10px;
    padding-bottom: 10px;
}

div#environment-banner div.development {
    background: green;
    color: white;
}

div#environment-banner div.staging {
    background: orange;
    color: black;
}

div#environment-banner div.production {
    background: red;
    color: white;
}
</pre>
<p></code></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://techblog.daveastels.com/2012/04/26/environment-headers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Embeddable Lisp for iOS apps</title>
		<link>http://techblog.daveastels.com/2010/11/14/embeddable-lisp-for-ios-apps/</link>
		<comments>http://techblog.daveastels.com/2010/11/14/embeddable-lisp-for-ios-apps/#comments</comments>
		<pubDate>Mon, 15 Nov 2010 01:49:29 +0000</pubDate>
		<dc:creator>dastels</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[lisp]]></category>

		<guid isPermaLink="false">http://techblog.daveastels.com/?p=496</guid>
		<description><![CDATA[Overview This is a preliminary description of this language/system. The doc.html file in the repo will always be the most up to date. You can get the code to play with at github.com/dastels/DSL. DSL is a simple, interpreted, scheme inspired lisp inplementation in ObjectiveC for embedded scripting in iOS apps, although it is equally applicable [...]]]></description>
			<content:encoded><![CDATA[<h2>Overview</h2>
<p>This is a preliminary description of this language/system.  The doc.html file in the repo will always be the most up to date.</p>
<p>You can get the code to play with at <a href="http://github.com/dastels/DSL" target="_blank"><code>github.com/dastels/DSL</code></a>.</p>
<p>DSL is a simple, interpreted, scheme inspired lisp inplementation<br />
in ObjectiveC for embedded scripting in iOS apps, although it is<br />
  equally applicable in OSX apps. There is no reliance on Cocoa or<br />
  CocoaTouch, just <code>foundation</code>.</p>
<p>The primary motivation was the need to implement rules in a card<br />
game at a significantly high level of abstraction in a way that<br />
wouldn&#8217;t require recompiling (i.e. could be stored in the<br />
database). </p>
<h2>Syntax</h2>
<p>The syntax is a simple version of scheme with lexical scoping and a<br />
  minimal set of builtin special forms.  One notable omission is macro<br />
  support. Macros may be supported at some later date, if and when<br />
  they&#8217;re required.</p>
<h2>Data Types</h2>
<p>DSL has support for a basic set of data types.</p>
<h3>Integer</h3>
<p>DSL supports unsigned integers, in decimal notation.  Size<br />
  refelects the underlying ObjC <code>int</code> type.</p>
<h3>String</h3>
<p>Strings in DSL use double quotes, and consist of a sequence of<br />
characters other than double quotes.</p>
<h3>Boolean</h3>
<p>While boolean values are used regularly, literals are less common.<br />
  The most common use is probably in the default clause in<br />
  a <code>cond</code> form.  When used, <code>#t</code> indicates true<br />
  and <code>#f</code> indicates false.</p>
<h3>Cons Cell</h3>
<p>As in most, if not all Lisps, the core data type is the cons cell.<br />
  It is simply a pair of values, traditionally known<br />
  as <code>car</code> and <code>cdr</code>, or more recently head and<br />
  tail.  DSL uses the <code>car</code> and <code>cdr</code><br />
  notation.</p>
<p>A literal cons cell is made using two values in parentheses,<br />
  separated by a period.  Otherwise known as a dotted pair:</p>
<pre>
  (1 . 2)
</pre>
<p>The constant <code>nil</code> represents an empty, aka NULL cons<br />
  cell. <code>nil</code> is always equal to <code>nil</code> as well<br />
  as empty lists.  The head and tail of <code>nil</code> are<br />
  also <code>nil</code>.</p>
<h3>List</h3>
<p>A list is sequence of cons cells, linked through tails, with the<br />
  final tail being nil.  The standard notation is used, a sequence of<br />
  values separated by whitespace and enclosed in parentheses: </p>
<pre>(1  2 3)</pre>
<p>Internally, the list <code>(1 2 3)</code> is equivalent to:</p>
<pre>(1 . (2 . (3 . nil)))</pre>
<h3>Symbol</h3>
<p>Symbol is another main building block, the other being list. A<br />
  symbol is essentially an interned string.  Notationally, they are a<br />
  series of characters, without enveloping double quotes.  Allowable<br />
  characters are letters, digits, :, -, ?, and !. By convention, colon<br />
  is used in ObjC selectors, dash is<br />
  used as a word seperator to enhance readability, a trailing<br />
  questionmark indicats a predicate, while a trailing exclaimation<br />
  mark indicates womething with a side effect. Symbols must start with<br />
  a letter, and are case sensitive.</p>
<h3>Association List</h3>
<p>DSL supports association lists, which are much like dictionaries.  They are implimented as a list of dotted pairs, e.g. </p>
<pre>((name . "Dave") (language . "Lisp"))</pre>
<p>Use of association lists are covered later in the section on builtins.</p>
<h2>Runtime</h2>
<p>Your interface to DSL is though strings containing source<br />
code. These string get parsed into sexpressions which are then evaluated.</p>
<p>Symbols are stored in a symbol table.  Symbol tables are managed in<br />
  a stack.  Local scopes are created by pushing a new stmbol table<br />
  onto the stack.  New bindings are placed in the top table in this<br />
  stack.  When the value of a symbol is looked up, the search starts<br />
  with the top table and if it is not found there, the stack is<br />
  traversed back to the global symbol table.  If no value is found by<br />
  then, the symbol is unbound.  A new local scope is created upon the<br />
  entry to functions and lets, and destroyed on the respective exit.</p>
<p>Unlike some modern lisps, in DSL symbols have a single binding (as<br />
opposed to separate value, function, etc. bindings).</p>
<h2>Integration</h2>
<p>ObjectiveC objects can be wrapped and their properties can be read<br />
  and writted (depending on the property definition).  The functions<br />
  for doing that are described below.</p>
<p>In ObjC, you wrap an object simply using the DslObject class:</p>
<pre>
+ (DslObject*) withObject:(id)anObject;
</pre>
<p>For example:</p>
<pre>
[DslObject withObject:user]
</pre>
<p>You can then use the functions described later to use this object<br />
  from your lisp code.</p>
<h2>Extension</h2>
<p>You can add your own function to DSL in order to integrate DSL into<br />
your app.</p>
<p>To add your own builtin functions/forms you instantiate a<br />
DslBuiltinFunction to point to your object/method.  You then must<br />
  bind it to a name.  For example:</p>
<blockquote>
<pre>
[DSL bindName:@"car"
     toTarget:self
     andSelector:@selector(car:)]];
</pre>
</blockquote>
<p>When a builtin is evaluated, it&#8217;s arguments are not automatically<br />
  evaluated first.  If they should be, the builtin has to do it itself:</p>
<blockquote><pre>
- (DslBoolean*) logicalNot:(DslCons*)args
{
  return [DslBoolean booleanWith:![<b>[args.head eval]</b> booleanValue]];
}
</pre>
</blockquote>
<p>-initialization hooks &#8230; still need to figure this out</p>
<p>The class <code>Dsl</code> provides many functions that you will<br />
need when writing your own builtins.</p>
<h3><code>- (DslExpression*) parse:(NSString*)codeString</code></h3>
<p>This takes the lisp code in <code>codeString</code>, which is assumed<br />
to contain a single sexpression, and parses it. The resulting<br />
sexpression is returned.</p>
<blockquote><pre>
DslExpression *sexpr = [DSL parse:code];
if (sexpr) {
  [DSL eval:sexpr];
}
</pre>
</blockquote>
<h3><code>- (DslExpression*) eval:(DslExpression*)sexp</code></h3>
<p>This function evaluates the provided sexpression and returns the result. You can see an<br />
example in the previous section.</p>
<h3><code>- (DslSymbol*) internalIntern:(NSString *)name</code></h3>
<p>This is how you can convert an <code>NSString*</code> into a symbol.<br />
The main use for this is to set up bindings using the next function.</p>
<h3><code>- (DslExpression*) bind:(DslSymbol*)symbol to:(DslExpression*)value</code></h3>
<p>Bind a value to a symbol in the most local scope.  You can use this<br />
(in conjunction with <code>internalIntern</code><br />
and <code>DslObject</code>) to make objects from your system available<br />
in lisp. </p>
<h3><code>- (DslExpression*) valueOf:(DslSymbol*)symbol</code></h3>
<p>Look up the value of a symbol, starting in the most local scope and<br />
  proceeding back to the global scope until a binding for the symbol<br />
  is found, or the options are exhausted.</p>
<p>You can use this and the previous functions in a fashion similar to:</p>
<blockquote><pre>
DslSymbol *gameName = [<b>[DSL internalIntern:@"game"]</b> retain];
DslObject *gameObject = [<b>[DslObject withObject:game]</b> retain];
if (<b>[DSL valueOf:gameName]</b> == nil) {
  <b>[DSL bind:gameName to:gameObject]</b>;
}
</pre>
</blockquote>
<h3><code>- (DslCons*) makeList:(DslExpression*)firstObject, ...</code></h3>
<p>Creates a list containing the arguments.  Note that the arguments<br />
  need to be terminated by nil.</p>
<p>Consider this snippet from the definition<br />
  of <code>reduce</code>:</p>
<blockquote><pre>
while ([data notNil]) {
  result = [self apply:function to:<b>[self makeList:result, data.head, nil]</b>];
  data = (DslCons*)data.tail;
}
</pre>
</blockquote>
<h3><code>- (DslExpression*) apply:(DslFunction*)func to:(DslCons*)args</code></h3>
<p>Very simply, invoke the given function, passing it the provided<br />
  list as it&#8217;s arguments. This can be seen in the example for <code>makelist:</code>.</p>
<h3><code>- (DslExpression*) getNth:(int)n from:(DslCons*)list</code></h3>
<p>Retrieve the nth item in a list.</p>
<h3><code>- (int) internalLength:(DslCons*)list</code></h3>
<p>Get the length if a list, returned as an <code>int</code> rather<br />
  than as a lisp integer object.</p>
<h3><code>- (DslExpression*) loadFile:(NSString*)filebasename</code></h3>
<p>Load a file of lisp code.  This is an ObjectiveC access point to<br />
  the <code>load</code> function described below.</p>
<h2>testing</h2>
<p>The test framework reads files containing comments, expressions and the<br />
expect result of evaling them, separated by blank lines. Each such<br />
triplet is separated by a line containing 4 hyphens.  For example:</p>
<blockquote>
<pre>
Applying Single Argument Lambda

(apply (lambda (x) (+ x 2)) 40)

42
----
Applying Multiple Argument Lambda

(apply (lambda (x y) (+ x y)) 40 2)

42
----
Simple Defun

(do
  (defun foo ()
         42)
  (foo))

42
----
Complex defun

(do
  (defun plusone (x)
         (+ x 1))
  (list (plusone 0) (plusone 1) (plusone 2)))

'(1 2 3)
----
More Complex defun

(do
  (defun fib (x)
         (cond ((= x 0) 1)
               ((= x 1) 1)
               (#t (+ (fib (- x 1)) (fib (- x 2))))))
  (list (fib 0) (fib 1) (fib 2) (fib 3) (fib 4) (fib 5) (fib 6)))

'(1 1 2 3 5 8 13)
</pre>
</blockquote>
<p>As tests run, the name of each file as well as the status of each<br />
indivisual test is logged to the console, like so:</p>
<blockquote><pre>
2010-10-31 16:39:05.632 Repl[79801:207] Running: logic-functions
2010-10-31 16:39:05.634 Repl[79801:207] FAIL: Or with no args
2010-10-31 16:39:05.634 Repl[79801:207] PASS: Or with one args
</pre>
</blockquote>
<p>For failures, more detail is logged at the end of the test run:</p>
<blockquote><pre>
2010-10-31 16:39:05.658 Repl[79801:207] Failures
2010-10-31 16:39:05.658 Repl[79801:207] ----
2010-10-31 16:39:05.658 Repl[79801:207] FAIL: Or with no args
2010-10-31 16:39:05.659 Repl[79801:207] (or)
2010-10-31 16:39:05.659 Repl[79801:207] Expected true but got false
</pre>
</blockquote>
<p>Finally, a summary is logged:</p>
<blockquote><pre>
2010-10-31 16:39:05.660 Repl[79801:207] Time: 0.093374 sec, 187 Tests, 186 Passes, 1 Failures
</pre>
</blockquote>
<h2>Builtins</h2>
<h3><code>intern</code></h3>
<p><code>(intern <em>STRING</em>)</code> => <code><em>SYMBOL</em></code></p>
<p>This makes a symbol from a string in the most local symbol table.</p>
<h3><code>quote</code></h3>
<p>Avoid evaluating the argument.</p>
<p><code>(quote <em>SEXPR</em>)</code> or as a shorthand <code>'<em>SEXPR</em></code></p>
<p>For example, <code>(+ 1 2)</code> => <code><em>3</em></code>, but<br />
  <code>'(+ 1 2)</code> => <code><em>(+ 1 2)</em></code>.</p>
<h3><code>lambda</code></h3>
<p><code>(lambda (<em>PARAMS</em>) <em>BODY</em>)</code> => <code><em>FUNCTION</em></code></p>
<pre>
(lambda (x) (+ 1 x))
</pre>
<p>Create an anonymous function. This is specifically useful for<br />
  providing functions to iterator or application functions.  Mostly<br />
  useful for short functions.</p>
<p>
<code>(map (lambda (x) (+ x x)) '(1 2 3))</code> => <code><em>(2 4 6)</em></code>
</p>
<h3><code>defun</code></h3>
<p><code>(defun <em>SYMBOL</em> (<em>PARAMS</em>) <em>BODY</em>)</code></p>
<pre>
(defun double (x)
       (+ x x))
</pre>
<p><code>(map double '(1 2 3))</code> => <code><em>(2 4 6)</em></code></p>
<p>Create a named function.</p>
<h3><code>apply</code></h3>
<pre>
(apply <em>FUNCTION</em> <em>ARGUMENTS</em>)
</pre>
<p><code>(apply (lambda (x) (+ 1 x)) 2)</code> => <code><em>3</em></code></p>
<p>
<pre>(defun add1 (x) (+ 1 x))</pre>
</p>
<p><code>(apply add1 2)</code> => <em>3</em></p>
<p>
This applies a function to set of arguments.  This functionallity is<br />
core to the system, and is used internally a lot.  None the less, it<br />
is sometimes useful explicitly.
</p>
<h3><code>do</code></h3>
<p><code>(do <em>BODY</em>)</code></p>
<p><code>(do (+ 1 1) (* 1 1))</code> => <code><em>1</em></code></p>
<p>Evaluate a sequence of expressions, in order, returning the result of the final one.</p>
<p>This is used implicitly in several places: function bodies, let<br />
  bodies, and cond clause bodies.  It&#8217;s also sometimes useful to use<br />
  it explicitly.</p>
<h3><code>let</code></h3>
<p><code>(let ((<em>NAME</em> <em>VALUE</em>)...) <em>BODY</em>)</code></p>
<p>
<pre>
(let ((x 5)
      (y 2))
     (+ x y))
</pre>
<p>=> <em>7</em></p>
<p><code>let</code> creates a local scope in which to place the<br />
  bindings and evaluate <em>BODY</em> (which is an<br />
  implicit <code>do</code>)</p>
<p>Each <em>VALUE</em> is evaluated and the result bound to the<br />
corresponding <em>NAME</em> in sequence (not in parallel as in some<br />
dialects). This means you can have things like:</p>
<pre>
(let ((a 2)
      (b (+ a 1))
     b)
</pre>
<p> => <em>3</em></p>
<h3><code>cons</code></h3>
<p><code>(cons 'a 'b)</code> => <code><em>(a.b)</em></code></p>
<p><code>(cons 'a '(a b))</code> => <code><em>(a b c)</em></code></p>
<p>This creates a cons cell with the arguments as it&#8217;s car and cdr.</p>
<h3><code>list</code></h3>
<p><code>(list <em>ITEMS</em>)</code> => <code>(<em>ITEMS</em>)</code></p>
<p><code>(list 1 2 3)</code> => <code><em>(1 2 3)</em></code></p>
<p>Create a list from the arguments.</p>
<h3><code>car/cdr<br/><br />
caar/cadr/cdar/cddr<br/><br />
caaar/caadr/cadar/caddr/cdaar/cdadr/cddar/cddr</code></h3>
<p><code>(car '(a b c))</code> => <code><em>a</em></code></p>
<p><code>(cdr '(a b c))</code> => <code><em>(b c)</em></code></p>
<p>This is the tradion family of list access functions. <car><br />
    and <cdr> are the core functions:</p>
<ul>
<li><code>car</code> returns the head of the cons cell argument</li>
<li><code>cdr</code> returns it&#8217;s tail</li>
</ul>
<p>The longer forms combine <code>car</code> and <code>cdr</code>, for<br />
  example: <code>(caddr a)</code> is the same as <code>(car (cdr (cdr<br />
  a)))</code> and so on.</p>
<h3><code>length</code></h3>
<p><code>(length <em>LIST</em>)</code> => <code><em>INTEGER</em></code></p>
<p><code>(length '(a b c d))</code> => <code><em>4</em></code></p>
<p>Returns the length of <em>LIST</em>.  This is the linear sequence<br />
  of cons cells through the tail of each.</p>
<h3><code>map</code> aka <code>collect</code></h3>
<p><code>(map <em>FUNCTION</em> <em>LIST</em>)</code> => <code><em>LIST</em></code></p>
<p><pre>
(map (lambda (* 2 x))
     '(1 2 3))
</pre>
<p> => <code><em>(2 4 6)</em></code>
</p>
<p>
Applies <em>FUNCTION</em> to each element of the list, in order,<br />
returning in a list of the results of each<br />
application. The <em>FUNCTION</em> can be the name of a<br />
defined/builtin function of a lambda.</p>
<h3><code>filter</code> aka <code>select</code></h3>
<p><code>(filter <em>PREDICATE</em> <em>LIST</em>)</code> => <code><em>LIST</em></code></p>
<p><code>(filter odd? '(1 2 3))</code> => <code><em>(1 3)</em></code></p>
<p>Select all items from <em>LIST</em> that satisfy the predicate<br />
  function (returns a boolean). <em>PREDICATE</em> is applied, to each<br />
  element of the list, in order, resulting in a list of the original<br />
  items for which the function returns true.</p>
<h3> <code>reduce</code> aka <code>inject</code></h3>
<p><code>(reduce <em>FUNCTION</em> <em>SEED</em> <em>LIST</em>)</code> => <code <em>VALUE</em></code></p>
<p><code>(reduce <em>FUNCTION</em> <em>LIST</em>)</code> => <code <em>VALUE</em></code></p>
<p><code>(reduce + 0 '(1 2 3 4))</code> => <code><em>10</em></code><br/><br />
<code>(reduce + '(1 2 3 4))</code> => <code><em>10</em></code><br/><br />
<code>(reduce (lambda (a b) (if (< a b) a b)) '(7 2 8 4 2 9))</code> => <code><em>2</em></code></p>
<p>The second form uses the first element of the list as it's seed value.  I.e. it is equivalent to:</p>
<p><code>(reduce <em>FUNCTION</em> (car <em>LIST</em>) (cdr <em>LIST</em>))</code> => <code <em>VALUE</em></code></p>
<h3><code>any?</code> aka <code>detect</code></h3>
<p><code>(any? <em>PREDICATE</em> <em>LIST</em>)</code> => <code><em>BOOLEAN</em></code></p>
<p><code>(any? odd? '(1 2 3))</code> => <code><em>#t</em></code><br/><br />
<code>(any? odd? '(0 2 4))</code> => <code><em>#f</em></code></p>
<p>Check if any items in the list satisfy the predicate function, by<br />
  appling the function to each element of the list, in order, until<br />
  one returns true or all items have been<br />
  considered. If <em>PREDICATE</em> returns <code>#t</code> for an<br />
  item then <code>any?</code> returns <code>#t</code>, otherwise it returns<br />
  <code>#f</code>.</p>
<h3><code>all?</code></h3>
<p><code>(all? <em>PREDICATE</em> <em>LIST</em>)</code> => <code><em>BOOLEAN</em></code></p>
<p><code>(all? odd? '(1 3 5))</code> => <code><em>#t</em></code><br/><br />
<code>(all? odd? '(1 2 3))</code> => <code><em>#f</em></code></p>
<p>Check if all items in the list satisfy the predicate function, by<br />
  appling the function to each element of the list, in order, until<br />
  one returns false or all items have been<br />
  considered. If <em>PREDICATE</em> returns <code>#f</code> for an<br />
  item then <code>all?</code> returns <code>#f</code>, otherwise it returns<br />
  <code>#t</code>.</p>
<h3><code>if</code></h3>
<p><code>(if <em>BOOLEAN</em> <em>TRUE-SEXPR</em>)</code><br/><br />
<code>(if <em>BOOLEAN</em> <em>TRUE-SEXPR</em> <em>FALSE-SEXPR</em>)</code></p>
<p><code>(if (= x 5) (do-something))</code><br/><br />
<code>(if (= x 5) 'a 'b)</code></p>
<p>If <em>BOOLEAN</em> evaluates to true, the <em>TRUE-SEXPR</em> is<br />
  evaluated. If <em>BOOLEAN</em> evaluates to <em>FALSE</em>,<br />
  the <em>ELSE-SEXPR</em> is, if one is supplied (if there isn't one,<br />
  then nothign is done).</p>
<h3><code>cond</code></h3>
<p><code>(cond (<em>BOOLEAN</em> <em>BODY</em>)...)</code></p>
<pre>
(cond ((< x 3) 'small)
      ((< x 7) 'medium)
      ((< x 10) 'large)
      (#t 'unknown))
</pre>
<p>This is the traditional multi branch lisp conditional. The<br />
  arguments to <code>cond</code> are two element lists consisting of<br />
  something that evaluates to a boolean and an arbitrary<br />
  sequence of sexpresions (the <em>BODY</em>. The boolean expression of each pair, in order, is<br />
  evaluated until one results in <code>true</code> or all have been<br />
  evaluated.  If one evaluates to <code>true</code>, the corresponding<br />
  sexpression is evaluated in an implicit <code>do</code> and the<br />
  result becomes the result of the <code>cond</code> expression.</p>
<h3><code>or, and, not</code></h3>
<p>logical functions </p>
<p><code>(and x y ...)</code><br/><br />
<code>(or x y ...)</code><br/><br />
<code>(not x)</code></p>
<p><code>not</code> takes a single<br />
argument and results in it's logical negation.</p>
<p><code>or</code>/<code>and</code> take any number of args. <and><br />
  evaluates to <code>true</code> only if all arguments evaluate<br />
  to <code>true</code>. With no arguments it results<br />
  to <code>true</code>. <code>or</code> results in <code>true</code><br />
  if any of it's arguments evaluate to <code>true</code>.  With no<br />
  arguments it results in <code>false</code>.</p>
<p>Both <code>and</code> and <code>or</code> evaluate their arguments<br />
  only until the result is known.  I.e. <code>and</code> will stop<br />
  evaluating it's arguments as soon as one evaluates<br />
  to <code>false</code>, and <code>or</code> will stop as soon as an<br />
  argument evaluates to <code>true</code>.</p>
<h3><code>+, -, *, /, %</code></h3>
<p>These are the standard arithmetic operators (<code>%</code> is modulus)</p>
<p>Other than <code>%</code>, these take any number of arguments. For<br />
  example, <code>(- 10 3 2)</code> is the same as <code>(- (- 10 3)<br />
  2)</code>, or infix: <code>(10 - 3) - 2</code>.</p>
<h3><code>&lt;, =, &gt;</code></h3>
<p>The standard relational operators, e.g. <code>(< a 5)</code>.  They<br />
all evaluate to boolean value.</p>
<h3><code>get-string, get-integer, get-boolean</code></h3>
<p><code>(get-<em>TYPE</em> <em>OBJECT</em> <em>PROPERTY</em>)</code></p>
<p><code>(get-string user 'name)</code></p>
<p>Access properties from wrapped ObjectC objects.</p>
<h3><code>set-string, set-integer, set-boolean</code></h3>
<p><code>(set-<em>TYPE</em> <em>OBJECT</em> <em>PROPERTY</em> <em>VALUE</em>)</code></p>
<p><code>(set-string user 'name "Dave")</code></p>
<p>Set properties in wrapped ObjectC objects.</p>
<p><b>Note</b> that none of the functions that create association lists<br />
  gaurentee any order on the dotted pairs in the result.</p>
<h3><code>acons</code></h3>
<p><code>(acons <em>KEY</em> <em>VALUE</em> <em>A-LIST</em>)</code></p>
<p><code>(acons x y '((a . 1) (b . 2)))</code><br />
  => <code>((x . y) (a . 1) (b . 2))</code></p>
<p>Prepend a dotted pair (<em>KEY</em> . <em>DATA</em>) to <em>A-LIST</em>.</p>
<h3><code>pairlis</code> aka <code>zip</code></h3>
<p><code>(pairlis <em>KEYS</em> <em>DATA</em>)</code><br/><br />
<code>(pairlis <em>KEYS</em> <em>DATA</em> <em>A-LIST</em>)</code></p>
<p><code>(pairlis '(one two) '(1 2))</code> => <code>((one . 1) (two . 2))</code><br/><br />
<code>(pairlis '(one two) '(1 2) '((three . 3) (four . 4)))</code>  => <code>((one . 1)<br />
          (two . 2) (three . 3) (four . 4)))</code></p>
<p>Make dotted pairs from items in the two argument lists, matched<br />
  pairwise.</p>
<h3><code>assoc</code></h3>
<p><code>(assoc <em>KEY</em> <em>A-LIST</em>)</code><br />
  => <code>(<em>KEY</em> . <em>DATA</em>)</code></p>
<p><code>(assoc 'r '((a . b) (c . d) (r . x) (s . y) (r . z)))</code><br />
  => <code>(r . x)</code></p>
<p>Search <em>A-LIST</em> for the first pair whose <code>car</code><br />
  is <em>KEY</em>.</p>
<h3><code>rassoc</code></h3>
<p><code>(rassoc <em>DATA</em> <em>A-LIST</em>)</code><br />
  => <code>(<em>KEY</em> . <em>DATA</em>)</code></p>
<p><code>(rassoc 'a '((a . b) (b . c) (c . a) (z . a)))</code> => <code>(c . a)</code></p>
<p>Search <em>A-LIST</em> for the first pair whose <code>cdr</code><br />
  is <em>DATA</em>.</p>
<h3><code>load</code></h3>
<p><code>(load <em>FILE-BASENAME</em>)</code></p>
<p><code>(load "game-ai")</code></p>
<p><code>(load 'game-ai)</code></p>
<p>Loads a file of sexpressions into memory, then evaluates then in<br />
  the binding context of where <code>load</code> was called.  Returns<br />
  a list of the results of this evaluation.  The file will generally<br />
  contain defintions and the evaluation will load them into the symbol<br />
  table.  Occasionally you may have use for the evaluated results. The<br />
  symbol table in which any binding occurs is the symbol table that<br />
  was local when <code>load</code> was called.</p>
<p>The file must have the extension of <code>lsp</code> and be a<br />
  project resource. It is located using:</p>
<blockquote><pre>
[[NSBundle mainBundle]
    pathForResource:filebasename
    ofType:@"lsp"
    inDirectory:nil]
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://techblog.daveastels.com/2010/11/14/embeddable-lisp-for-ios-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone version of Rules app</title>
		<link>http://techblog.daveastels.com/2010/10/25/iphone-version-of-rules-app/</link>
		<comments>http://techblog.daveastels.com/2010/10/25/iphone-version-of-rules-app/#comments</comments>
		<pubDate>Tue, 26 Oct 2010 05:29:45 +0000</pubDate>
		<dc:creator>dastels</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://techblog.daveastels.com/?p=500</guid>
		<description><![CDATA[I have an iPhone Comprehensive Magic: the Gathering rules app ready for testing. See a video clip of it by clicking the image below. If you want to help beta test it, contact me.]]></description>
			<content:encoded><![CDATA[<p>I have an iPhone Comprehensive Magic: the Gathering rules app ready for testing.  See a video clip of it by clicking the image below. If you want to help beta test it, contact me.</p>
<p><center><a href="http://techblog.daveastels.com/wp-content/uploads/2010/10/iPhone_Rules_App.mov" target="_blank"><br />
<img src="http://techblog.daveastels.com/wp-content/uploads/2010/10/iPhone_Rules_App.png" alt="" title="iPhone_Rules_App" width="336" height="640" class="aligncenter size-full wp-image-506" /><br />
</a></center></p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.daveastels.com/2010/10/25/iphone-version-of-rules-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://techblog.daveastels.com/wp-content/uploads/2010/10/iPhone_Rules_App.mov" length="13499892" type="video/quicktime" />
		</item>
		<item>
		<title>Latest project: MTG rules iPad app</title>
		<link>http://techblog.daveastels.com/2010/10/15/latest-project-mtg-rules-ipad-app/</link>
		<comments>http://techblog.daveastels.com/2010/10/15/latest-project-mtg-rules-ipad-app/#comments</comments>
		<pubDate>Sat, 16 Oct 2010 06:41:09 +0000</pubDate>
		<dc:creator>dastels</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://techblog.daveastels.com/?p=465</guid>
		<description><![CDATA[Here&#8217;s a peek at an app I&#8217;m currently working on. The comprehensive rules for Magic: the Gathering. I think all that&#8217;s left is search, icon, and splash screen. Will Wizards of the Coast let me put it on the App Store? Who knows. Click the image above to play the video]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a peek at an app I&#8217;m currently working on. The comprehensive rules for <a href="http://www.wizards.com/Magic/Multiverse/" target="_blank">Magic: the Gathering</a>.  I think all that&#8217;s left is search, icon, and splash screen. Will Wizards of the Coast let me put it on the App Store?  Who knows.</p>
<p><center><br />
<a href="http://techblog.daveastels.com/wp-content/uploads/2010/10/RuleBook-3.mov" target="_blank"><br />
	<img src="http://techblog.daveastels.com/wp-content/uploads/2010/10/RuleBook.png" width="368" height="496"/><br />
</a></p>
<p>Click the image above to play the video</p>
<p></center></p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.daveastels.com/2010/10/15/latest-project-mtg-rules-ipad-app/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="http://techblog.daveastels.com/wp-content/uploads/2010/10/RuleBook-3.mov" length="7034054" type="video/quicktime" />
		</item>
		<item>
		<title>Initial comparison of iPhone 3GS &amp; 4 cameras</title>
		<link>http://techblog.daveastels.com/2010/08/10/initial-comparison-of-iphone-3gs-4-cameras/</link>
		<comments>http://techblog.daveastels.com/2010/08/10/initial-comparison-of-iphone-3gs-4-cameras/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 06:15:05 +0000</pubDate>
		<dc:creator>dastels</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://techblog.daveastels.com/?p=415</guid>
		<description><![CDATA[As some of you know, I maintain a food blog in which I try to have a lot of food porn &#8230; um &#8230; photos. Mix that with restaurant reviews/reports. The upshot is that I take the pics at restaurants with my iPhone. My iPhone 3GS. You know &#8230; the one with the (now) sucky [...]]]></description>
			<content:encoded><![CDATA[<p>As some of you know, I maintain a <a href="http://cafesnobisme.com" target="_blank">food blog</a> in which I try to have a lot of food porn &#8230; um &#8230; photos.  Mix that with restaurant reviews/reports.   The upshot is that I take the pics at restaurants with my iPhone.  My iPhone 3GS.  You know &#8230; the one with the (now) sucky camera.  It sucks in low light conditions, producing grainy pics.  It doesn&#8217;t have a flash. So dinners tend not to be too photogenic.</p>
<p>Enter the iPhone 4 with it&#8217;s low light sensor and flash (not to mention a 5MP sensor compared to the 3GS&#8217; 3MP).  I put off buying an iPhone4 for a long time (in Apple-years).  I finally decided to go for it, in the name of journalistic integrity.  And a desire to simply take more pictures.  Sure, I have a better camera (5MB, glass optics, optical zoom, flash, etc) but it doesn&#8217;t fit in my pocket, not to mention it being unable to play Plants vs. Zombies.</p>
<p>So tonight before dinner, I stopped at the nearby (oh so deviously nearby) Apple Store and (with impressive efficiency from the staff) got an iPhone4.  Since I a) wanted it for taking pictures, specifically in low lighting restaurants, and b) I had my iPhone 3GS in my pocket &#8230; I did a small exercise.  At dinner (Cumin in Wicker Park &#8230; to be appear on <a href="http://cafesnobisme.com" target="_blank">CafeSnobisme</a>) I took pictures of our dishes as I am wont to, with each phone.  Here, side by side are the results.  These are raw from the phones, uncropped and untweaked in anyway other than sizing.</p>
<p><img src="http://techblog.daveastels.com/wp-content/uploads/2010/08/3gs-appitizer.jpg" alt="3gs appitizer" title="3gs appitizer" width="320" height="427" class="aligncenter size-full wp-image-416" /><img src="http://techblog.daveastels.com/wp-content/uploads/2010/08/4-appitizer.jpg" alt="4 appitizer" title="4 appitizer" width="320" height="428" class="aligncenter size-full wp-image-422" /></p>
<p><img src="http://techblog.daveastels.com/wp-content/uploads/2010/08/3gs-sambar.jpg" alt="3gs sambar" title="3gs sambar" width="320" height="240" class="aligncenter size-full wp-image-421" /><img src="http://techblog.daveastels.com/wp-content/uploads/2010/08/4-sambar.jpg" alt="4 sambar" title="4 sambar" width="320" height="240" class="aligncenter size-full wp-image-426" /></p>
<p><img src="http://techblog.daveastels.com/wp-content/uploads/2010/08/3gs-bread.jpg" alt="3gs bread" title="3gs bread" width="320" height="427" class="aligncenter size-full wp-image-417" /><img src="http://techblog.daveastels.com/wp-content/uploads/2010/08/4-bread.jpg" alt="4 bread" title="4 bread" width="320" height="428" class="aligncenter size-full wp-image-423" /></p>
<p><img src="http://techblog.daveastels.com/wp-content/uploads/2010/08/3gs-rice.jpg" alt="3gs rice" title="3gs rice" width="320" height="427" class="aligncenter size-full wp-image-420" /><img src="http://techblog.daveastels.com/wp-content/uploads/2010/08/4-rice.jpg" alt="4 rice" title="4 rice" width="320" height="428" class="aligncenter size-full wp-image-425" /></p>
<p><img src="http://techblog.daveastels.com/wp-content/uploads/2010/08/3gs-malai-kofta.jpg" alt="3gs malai kofta" title="3gs malai kofta" width="320" height="427" class="aligncenter size-full wp-image-419" /><img src="http://techblog.daveastels.com/wp-content/uploads/2010/08/4-malai-kofta.jpg" alt="4 malai kofta" title="4 malai kofta" width="320" height="428" class="aligncenter size-full wp-image-424" /></p>
<p><img src="http://techblog.daveastels.com/wp-content/uploads/2010/08/3gs-fish-vindaloo.jpg" alt="3gs fish vindaloo" title="3gs fish vindaloo" width="320" height="427" class="aligncenter size-full wp-image-418" /><img src="http://techblog.daveastels.com/wp-content/uploads/2010/08/4-vindaloo.jpg" alt="4 vindaloo" title="4 vindaloo" width="320" height="428" class="aligncenter size-full wp-image-427" /></p>
<p>All I can say is &#8220;Holy shit &#8230; that&#8217;s pretty good!&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.daveastels.com/2010/08/10/initial-comparison-of-iphone-3gs-4-cameras/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Time flies when your life is being reinvented</title>
		<link>http://techblog.daveastels.com/2010/08/10/time-flies-when-your-life-is-being-reinvented/</link>
		<comments>http://techblog.daveastels.com/2010/08/10/time-flies-when-your-life-is-being-reinvented/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 05:38:01 +0000</pubDate>
		<dc:creator>dastels</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://techblog.daveastels.com/?p=412</guid>
		<description><![CDATA[Last post was Jan 18! I&#8217;m ashamed of myself. Then again my life totally changed (for the better) on Jan 19 and I&#8217;ve been busy catching up. I might write about that sometime .. but not now, and not here. Update. I&#8217;m no longer with Engine Yard. I&#8217;m in the process of moving to Chicago [...]]]></description>
			<content:encoded><![CDATA[<p>Last post was Jan 18! I&#8217;m ashamed of myself.  Then again my life totally changed (for the better) on Jan 19 and I&#8217;ve been busy catching up.  I might write about that sometime .. but not now, and not here.</p>
<p>Update.  I&#8217;m no longer with Engine Yard.  I&#8217;m in the process of moving to Chicago and pursuing several opportunities there, and consulting at Groupon (with my good friends at Obtiva) in the interim. </p>
<p>And hopefully, I&#8217;ll be writing more here again.  I have lots of ideas in the queue.</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.daveastels.com/2010/08/10/time-flies-when-your-life-is-being-reinvented/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Go Behave!</title>
		<link>http://techblog.daveastels.com/2010/01/18/go-behave/</link>
		<comments>http://techblog.daveastels.com/2010/01/18/go-behave/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 22:30:05 +0000</pubDate>
		<dc:creator>dastels</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://techblog.daveastels.com/?p=405</guid>
		<description><![CDATA[For my Google peeps. My buddy @stesla is giving a Google tech talk tomorrow at 11:30 in Paramiribo (techtalk 42) on BDD in Go including an introduction to the BDD framework her wrote: gospecify . We&#8217;ll be there for lunch afterward as well.]]></description>
			<content:encoded><![CDATA[<p>For my Google peeps. My buddy @stesla is giving a Google tech talk tomorrow at 11:30 in Paramiribo (techtalk 42) on BDD in Go including an introduction to the BDD framework her wrote: gospecify . We&#8217;ll be there for lunch afterward as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.daveastels.com/2010/01/18/go-behave/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rumble off to a rocky start</title>
		<link>http://techblog.daveastels.com/2009/08/22/rumble-off-to-a-rocky-start/</link>
		<comments>http://techblog.daveastels.com/2009/08/22/rumble-off-to-a-rocky-start/#comments</comments>
		<pubDate>Sun, 23 Aug 2009 02:56:06 +0000</pubDate>
		<dc:creator>dastels</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://techblog.daveastels.com/?p=371</guid>
		<description><![CDATA[Nancy hit the ground running, whereas I ground to a halt. Ruby worked fine. Rails worked fine. Mysql worked fine. Rails wouldn&#8217;t talk to Mysql, though. After much head scratching, cursing, and frantic searching for liquor&#8230; I hit upon the crux of the problem. While I was installing the mysql gem&#8230; it wasn&#8217;t getting used. [...]]]></description>
			<content:encoded><![CDATA[<p>Nancy hit the ground running, whereas I ground to a halt.  Ruby worked fine. Rails worked fine. Mysql worked fine. Rails wouldn&#8217;t talk to Mysql, though.  After much head scratching, cursing, and frantic searching for liquor&#8230; I hit upon the crux of the problem.  While I <strong>was</strong> installing the mysql gem&#8230; it wasn&#8217;t getting used.  /usr/local/lib/ruby/1.8/mysql.rb was!  To quote @thebloggess &#8220;The Fuck, Victor?!&#8221;</p>
<p>So a quick
<pre>sudo mv /usr/local/lib/ruby/1.8/mysql.rb /usr/local/lib/ruby/1.8/fucking-bogus-mysql.rb</pre>
<p> later (with the mysql gem installed) I was up &#038; running. A bunch of Ruby, Erb, CSS, and Javascript later and it&#8217;s looking pretty good.</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.daveastels.com/2009/08/22/rumble-off-to-a-rocky-start/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rumblin&#8217;</title>
		<link>http://techblog.daveastels.com/2009/08/22/rumblin/</link>
		<comments>http://techblog.daveastels.com/2009/08/22/rumblin/#comments</comments>
		<pubDate>Sun, 23 Aug 2009 02:44:10 +0000</pubDate>
		<dc:creator>dastels</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://techblog.daveastels.com/?p=369</guid>
		<description><![CDATA[All my blogging energies have gone into the EngineYard blog for the last while. This is a just a note to say that Nancy &#038; I are once again taking part in the rails rumble. This time focussing on getting shit done. Pure &#038; simple. No detailed design or up front thinking.. just a general [...]]]></description>
			<content:encoded><![CDATA[<p>All my blogging energies have gone into the EngineYard blog for the last while.  </p>
<p>This is a just a note to say that Nancy &#038; I are once again taking part in the rails rumble.  This time focussing on getting shit done.  Pure &#038; simple. No detailed design or up front thinking.. just a general idea. No testing, think it up &#038; code it up.  And now we&#8217;re past the half way point and things are taking shape nicely.</p>
<p>We&#8217;re having fun and it&#8217;s something that might be fun to hack at afterward.</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.daveastels.com/2009/08/22/rumblin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WWDC 2009</title>
		<link>http://techblog.daveastels.com/2009/06/13/wwdc-2009/</link>
		<comments>http://techblog.daveastels.com/2009/06/13/wwdc-2009/#comments</comments>
		<pubDate>Sun, 14 Jun 2009 00:19:57 +0000</pubDate>
		<dc:creator>dastels</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://techblog.daveastels.com/?p=366</guid>
		<description><![CDATA[Well, WWDC is over. I made it this year&#8230; and glad of it. What a week (well, 4 days for me)! Lost of new toys &#038; tech. Lots of cool ideas for my after hours fiddling. iPhone 3Gs, iPhone OS 3.0, Snow Leopard, new Mac Book Pros. It&#8217;s a good time to be a cocoahead. [...]]]></description>
			<content:encoded><![CDATA[<p>Well, WWDC is over.  I made it this year&#8230; and glad of it.  What a week (well, 4 days for me)!</p>
<p>Lost of new toys &#038; tech.  Lots of cool ideas for my after hours fiddling.</p>
<p>iPhone 3Gs, iPhone OS 3.0, Snow Leopard, new Mac Book Pros.  It&#8217;s a good time to be a cocoahead.  Go watch the <a href="http://events.apple.com.edgesuite.net/0906paowdnv/event/index.html?internal=ijalrmacu">keynote</a> if you haven&#8217;t.</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.daveastels.com/2009/06/13/wwdc-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

