Mercurial > abomination
view 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 source
1 #+title: Calling it quits without parentheses2 #+author: Robert McIntyre & Dylan Holmes3 #+EMAIL: rlm@mit.edu4 #+MATHJAX: align:"left" mathml:t path:"../MathJax/MathJax.js"5 #+STYLE: <link rel="stylesheet" type="text/css" href="../css/aurellem.css" />6 #+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t7 #+SETUPFILE: ../templates/level-0.org8 #+INCLUDE: ../templates/level-0.org10 [TABLE-OF-CONTENTS]12 # * Calling it quits without parentheses13 Is it possible to make a =quit= command for Clojure such that simply14 typing the word =quit= at an REPL exits the REPL? An intuitive =quit=15 command would be especially useful for people new to Lisp syntax or16 the REPL; the challenge is to make a genuine Clojure command that17 executes without being called with parentheses. We found three18 solutions.20 #+srcname: header21 #+begin_src clojure :results silent22 (ns abomination.no-parens23 (:use clojure.contrib.def))24 #+end_src26 * By modifying =toString=27 #+srcname: toString28 #+begin_src clojure29 (in-ns 'abomination.no-parens)30 (gen-class :name abomination.no-parens.Quit31 :prefix quit-)33 (defn quit-toString34 [this]35 (System/exit 0))37 (defvar quit (abomination.no-parens.Quit.)38 "a sneaky way to support a `quit` command")39 #+end_src41 When you type any variable at the REPL, the REPL attempts to print it as a nicely-formatted string by calling its =toString=42 method. Our trick is to define a class with a =toString= method43 that exits the REPL; this trick ensures that any variable of that class will close44 the REPL when the REPL attempts to print it.46 First, we use =gen-class= to make a new class named Quit; in that same line, we use47 =:prefix= to establish the convention that any function named48 =quit-[something]= will be adopted as the =[something]= method for the49 newly-defined Quit class. We use this convention to write our own50 =toString= method for Quit.52 Next, we define a suitable =toString= method for the Quit class so that53 attempting to print an instance of the Quit class has the effect of54 closing the REPL. We do this by defining a function =quit-toString=55 which closes the REPL; by the convention established above, the Quit56 class automatically adopts =quit-toString= as its =toString= method.58 Finally, we use =defvar= to create an instance of the Quit class; we59 name this instance =quit=. Now when you type =quit= into the REPL, the60 REPL executes the =toString= method of the Quit class, exiting the REPL instead of returning a61 string.63 #+begin_src clojure :exports both64 (binding [*compile-path* "/home/r/aurellem/classes"]65 (compile 'abomination.no-parens))66 #+end_src68 #+results:69 : abomination.no-parens71 * By wrapping the command in a lazy sequence72 #+srcname: lazy-seq73 #+begin_src clojure :results silent74 (in-ns 'abomination.no-parens)75 (defvar quit* (lazy-seq :the-great-bringer-of-death! (System/exit 0))76 "the first time it's evaulated it will kill the JVM")77 #+end_src79 * By =delay=-ing the command80 #+srcname: delay81 #+begin_src clojure :results silent82 (in-ns 'abomination.no-parens)83 (defvar quit** (delay (System/exit 0))84 "when this is evaulated at the REPL, it will exit the JVM.")85 #+end_src87 The same thing, accomplished in a much more elegant and clojureish88 way.90 #+begin_src clojure :tangle no_parens.clj :results silent :exports none :noweb yes91 <<header>>92 <<toString>>93 <<lazy-seq>>94 <<delay>>95 #+end_src97 # STUD CRUFT PIZZA99 #+begin_quote100 And death i think is no parenthesis101 \mdash{}E. E. Cummings102 #+end_quote