changeset 0:1c7ace5054ac

initial commit
author Robert McIntyre <rlm@mit.edu>
date Sun, 16 Oct 2011 07:32:21 -0700
parents
children a4cb0b71fc78
files .hgignore org/no_parens.org readme.txt
diffstat 3 files changed, 107 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Sun Oct 16 07:32:21 2011 -0700
     1.3 @@ -0,0 +1,3 @@
     1.4 +syntax: glob
     1.5 +src*
     1.6 +html*
     1.7 \ No newline at end of file
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/org/no_parens.org	Sun Oct 16 07:32:21 2011 -0700
     2.3 @@ -0,0 +1,102 @@
     2.4 +#+title: Calling it quits without parentheses
     2.5 +#+author: Robert McIntyre & Dylan Holmes
     2.6 +#+EMAIL:     rlm@mit.edu
     2.7 +#+MATHJAX: align:"left" mathml:t path:"../MathJax/MathJax.js"
     2.8 +#+STYLE: <link rel="stylesheet" type="text/css" href="../css/aurellem.css" />
     2.9 +#+OPTIONS:   H:3 num:t toc:t \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t
    2.10 +#+SETUPFILE: ../templates/level-0.org
    2.11 +#+INCLUDE: ../templates/level-0.org
    2.12 +
    2.13 +[TABLE-OF-CONTENTS]
    2.14 +
    2.15 +# * Calling it quits without parentheses
    2.16 +Is it possible to make a =quit= command for Clojure such that simply
    2.17 +typing the word =quit= at an REPL exits the REPL?  An intuitive =quit=
    2.18 +command would be especially useful for people new to Lisp syntax or
    2.19 +the REPL; the challenge is to make a genuine Clojure command that
    2.20 +executes without being called with parentheses. We found three
    2.21 +solutions.
    2.22 +
    2.23 +#+srcname: header
    2.24 +#+begin_src clojure :results silent
    2.25 +(ns abomination.no-parens
    2.26 +  (:use clojure.contrib.def))
    2.27 +#+end_src
    2.28 +
    2.29 +* By modifying =toString=
    2.30 +#+srcname: toString
    2.31 +#+begin_src clojure
    2.32 +(in-ns 'abomination.no-parens)
    2.33 +(gen-class :name abomination.no-parens.Quit
    2.34 +	   :prefix quit-)
    2.35 +
    2.36 +(defn quit-toString
    2.37 +  [this]
    2.38 +  (System/exit 0))
    2.39 +
    2.40 +(defvar quit (abomination.no-parens.Quit.)
    2.41 +  "a sneaky way to support a `quit` command")
    2.42 +#+end_src
    2.43 +
    2.44 +When you type any variable at the REPL, the REPL attempts to print it as a nicely-formatted string by calling its =toString=
    2.45 +method. Our trick is to define a class with a =toString= method
    2.46 +that exits the REPL; this trick ensures that any variable of that class will close
    2.47 +the REPL when the REPL attempts to print it.
    2.48 +
    2.49 +First, we use =gen-class= to make a new class named Quit; in that same line, we use
    2.50 +=:prefix= to establish the convention that any function named
    2.51 +=quit-[something]= will be adopted as the =[something]= method for the
    2.52 +newly-defined Quit class. We use this convention to write our own
    2.53 +=toString= method for Quit.
    2.54 +
    2.55 +Next, we define a suitable =toString= method for the Quit class so that
    2.56 +attempting to print an instance of the Quit class has the effect of
    2.57 +closing the REPL. We do this by defining a function =quit-toString=
    2.58 +which closes the REPL; by the convention established above, the Quit
    2.59 +class automatically adopts  =quit-toString= as its =toString= method.
    2.60 +
    2.61 +Finally, we use =defvar= to create an instance of the Quit class; we
    2.62 +name this instance =quit=. Now when you type =quit= into the REPL, the
    2.63 +REPL executes the =toString= method of the Quit class, exiting the REPL instead of returning a
    2.64 +string.
    2.65 +
    2.66 +#+begin_src clojure :exports both
    2.67 +(binding [*compile-path* "/home/r/aurellem/classes"]
    2.68 +  (compile 'abomination.no-parens))
    2.69 +#+end_src
    2.70 +
    2.71 +#+results:
    2.72 +: abomination.no-parens
    2.73 +
    2.74 +* By wrapping the command in a lazy sequence
    2.75 +#+srcname: lazy-seq
    2.76 +#+begin_src clojure :results silent
    2.77 +(in-ns 'abomination.no-parens)
    2.78 +(defvar quit* (lazy-seq :the-great-bringer-of-death! (System/exit 0))
    2.79 +  "the first time it's evaulated it will kill the JVM")
    2.80 +#+end_src
    2.81 +  
    2.82 +* By =delay=-ing the command 
    2.83 +#+srcname: delay
    2.84 +#+begin_src clojure :results silent
    2.85 +(in-ns 'abomination.no-parens)
    2.86 +(defvar quit** (delay (System/exit 0))
    2.87 +  "when this is evaulated at the REPL, it will exit the JVM.")
    2.88 +#+end_src
    2.89 +
    2.90 +The same thing, accomplished in a much more elegant and clojureish
    2.91 +way.
    2.92 +
    2.93 +#+begin_src clojure :tangle no_parens.clj :results silent :exports none :noweb yes
    2.94 +<<header>>
    2.95 +<<toString>>
    2.96 +<<lazy-seq>>
    2.97 +<<delay>>
    2.98 +#+end_src
    2.99 +
   2.100 +# STUD CRUFT PIZZA
   2.101 +
   2.102 +#+begin_quote
   2.103 +And death i think is no parenthesis
   2.104 +\mdash{}E. E. Cummings
   2.105 +#+end_quote
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/readme.txt	Sun Oct 16 07:32:21 2011 -0700
     3.3 @@ -0,0 +1,2 @@
     3.4 +Here, Dylan and I use some neat tricks to give a "quit" command to
     3.5 +clojure which can be called with no parens.