diff org/no_parens.org @ 0:1c7ace5054ac

initial commit
author Robert McIntyre <rlm@mit.edu>
date Sun, 16 Oct 2011 07:32:21 -0700
parents
children a4cb0b71fc78
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/org/no_parens.org	Sun Oct 16 07:32:21 2011 -0700
     1.3 @@ -0,0 +1,102 @@
     1.4 +#+title: Calling it quits without parentheses
     1.5 +#+author: Robert McIntyre & Dylan Holmes
     1.6 +#+EMAIL:     rlm@mit.edu
     1.7 +#+MATHJAX: align:"left" mathml:t path:"../MathJax/MathJax.js"
     1.8 +#+STYLE: <link rel="stylesheet" type="text/css" href="../css/aurellem.css" />
     1.9 +#+OPTIONS:   H:3 num:t toc:t \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t
    1.10 +#+SETUPFILE: ../templates/level-0.org
    1.11 +#+INCLUDE: ../templates/level-0.org
    1.12 +
    1.13 +[TABLE-OF-CONTENTS]
    1.14 +
    1.15 +# * Calling it quits without parentheses
    1.16 +Is it possible to make a =quit= command for Clojure such that simply
    1.17 +typing the word =quit= at an REPL exits the REPL?  An intuitive =quit=
    1.18 +command would be especially useful for people new to Lisp syntax or
    1.19 +the REPL; the challenge is to make a genuine Clojure command that
    1.20 +executes without being called with parentheses. We found three
    1.21 +solutions.
    1.22 +
    1.23 +#+srcname: header
    1.24 +#+begin_src clojure :results silent
    1.25 +(ns abomination.no-parens
    1.26 +  (:use clojure.contrib.def))
    1.27 +#+end_src
    1.28 +
    1.29 +* By modifying =toString=
    1.30 +#+srcname: toString
    1.31 +#+begin_src clojure
    1.32 +(in-ns 'abomination.no-parens)
    1.33 +(gen-class :name abomination.no-parens.Quit
    1.34 +	   :prefix quit-)
    1.35 +
    1.36 +(defn quit-toString
    1.37 +  [this]
    1.38 +  (System/exit 0))
    1.39 +
    1.40 +(defvar quit (abomination.no-parens.Quit.)
    1.41 +  "a sneaky way to support a `quit` command")
    1.42 +#+end_src
    1.43 +
    1.44 +When you type any variable at the REPL, the REPL attempts to print it as a nicely-formatted string by calling its =toString=
    1.45 +method. Our trick is to define a class with a =toString= method
    1.46 +that exits the REPL; this trick ensures that any variable of that class will close
    1.47 +the REPL when the REPL attempts to print it.
    1.48 +
    1.49 +First, we use =gen-class= to make a new class named Quit; in that same line, we use
    1.50 +=:prefix= to establish the convention that any function named
    1.51 +=quit-[something]= will be adopted as the =[something]= method for the
    1.52 +newly-defined Quit class. We use this convention to write our own
    1.53 +=toString= method for Quit.
    1.54 +
    1.55 +Next, we define a suitable =toString= method for the Quit class so that
    1.56 +attempting to print an instance of the Quit class has the effect of
    1.57 +closing the REPL. We do this by defining a function =quit-toString=
    1.58 +which closes the REPL; by the convention established above, the Quit
    1.59 +class automatically adopts  =quit-toString= as its =toString= method.
    1.60 +
    1.61 +Finally, we use =defvar= to create an instance of the Quit class; we
    1.62 +name this instance =quit=. Now when you type =quit= into the REPL, the
    1.63 +REPL executes the =toString= method of the Quit class, exiting the REPL instead of returning a
    1.64 +string.
    1.65 +
    1.66 +#+begin_src clojure :exports both
    1.67 +(binding [*compile-path* "/home/r/aurellem/classes"]
    1.68 +  (compile 'abomination.no-parens))
    1.69 +#+end_src
    1.70 +
    1.71 +#+results:
    1.72 +: abomination.no-parens
    1.73 +
    1.74 +* By wrapping the command in a lazy sequence
    1.75 +#+srcname: lazy-seq
    1.76 +#+begin_src clojure :results silent
    1.77 +(in-ns 'abomination.no-parens)
    1.78 +(defvar quit* (lazy-seq :the-great-bringer-of-death! (System/exit 0))
    1.79 +  "the first time it's evaulated it will kill the JVM")
    1.80 +#+end_src
    1.81 +  
    1.82 +* By =delay=-ing the command 
    1.83 +#+srcname: delay
    1.84 +#+begin_src clojure :results silent
    1.85 +(in-ns 'abomination.no-parens)
    1.86 +(defvar quit** (delay (System/exit 0))
    1.87 +  "when this is evaulated at the REPL, it will exit the JVM.")
    1.88 +#+end_src
    1.89 +
    1.90 +The same thing, accomplished in a much more elegant and clojureish
    1.91 +way.
    1.92 +
    1.93 +#+begin_src clojure :tangle no_parens.clj :results silent :exports none :noweb yes
    1.94 +<<header>>
    1.95 +<<toString>>
    1.96 +<<lazy-seq>>
    1.97 +<<delay>>
    1.98 +#+end_src
    1.99 +
   1.100 +# STUD CRUFT PIZZA
   1.101 +
   1.102 +#+begin_quote
   1.103 +And death i think is no parenthesis
   1.104 +\mdash{}E. E. Cummings
   1.105 +#+end_quote