Mercurial > abomination
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