Mercurial > abomination
view org/no_parens.org @ 1:a4cb0b71fc78
got this working again
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sun, 16 Oct 2011 07:52:40 -0700 |
parents | 1c7ace5054ac |
children | 06131b93e54f |
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: ../../aurellem/org/level-0.org8 #+INCLUDE: ../../aurellem/org/level-0.org9 #+BABEL: :mkdirp yes11 [TABLE-OF-CONTENTS]13 # * Calling it quits without parentheses14 Is it possible to make a =quit= command for Clojure such that simply15 typing the word =quit= at an REPL exits the REPL? An intuitive =quit=16 command would be especially useful for people new to Lisp syntax or17 the REPL; the challenge is to make a genuine Clojure command that18 executes without being called with parentheses. We found three19 solutions.21 #+srcname: header22 #+begin_src clojure :results silent23 (ns abomination.no-parens24 (:use clojure.contrib.def))25 #+end_src27 * By modifying =toString=28 #+srcname: toString29 #+begin_src clojure30 (in-ns 'abomination.no-parens)31 (gen-class :name abomination.no-parens.Quit32 :prefix quit-)34 (defn quit-toString35 [this]36 (System/exit 0))39 (defvar quit (abomination.no-parens.Quit.)40 "a sneaky way to support a `quit` command")41 #+end_src43 When you type any variable at the REPL, the REPL attempts to print it44 as a nicely-formatted string by calling its =toString= method. Our45 trick is to define a class with a =toString= method that exits the46 REPL; this trick ensures that any variable of that class will close47 the REPL when the REPL attempts to print it.49 First, we use =gen-class= to make a new class named Quit; in that same50 line, we use =:prefix= to establish the convention that any function51 named =quit-[something]= will be adopted as the =[something]= method52 for the newly-defined Quit class. We use this convention to write our53 own =toString= method for Quit.55 Next, we define a suitable =toString= method for the Quit class so56 that attempting to print an instance of the Quit class has the effect57 of closing the REPL. We do this by defining a function =quit-toString=58 which closes the REPL; by the convention established above, the Quit59 class automatically adopts =quit-toString= as its =toString= method.61 Finally, we use =defvar= to create an instance of the Quit class; we62 name this instance =quit=. Now when you type =quit= into the REPL, the63 REPL executes the =toString= method of the Quit class, exiting the64 REPL instead of returning a string.66 #+begin_src clojure :exports both67 (binding [*compile-path* "/home/r/proj/abomination/classes"]68 (compile 'abomination.no-parens))70 #+end_src72 #+results:73 : abomination.no-parens75 * By wrapping the command in a lazy sequence76 #+srcname: lazy-seq77 #+begin_src clojure :results silent78 (in-ns 'abomination.no-parens)79 (defvar quit* (lazy-seq :the-great-bringer-of-death! (System/exit 0))80 "the first time it's evaulated it will kill the JVM")81 #+end_src83 * By =delay=-ing the command84 #+srcname: delay85 #+begin_src clojure :results silent86 (in-ns 'abomination.no-parens)87 (defvar quit** (delay (System/exit 0))88 "when this is evaulated at the REPL, it will exit the JVM.")89 #+end_src91 The same thing, accomplished in a much more elegant and clojureish92 way.94 # STUD CRUFT PIZZA96 #+begin_quote97 And death i think is no parenthesis98 \mdash{}E. E. Cummings99 #+end_quote102 * COMMENT code generation103 #+begin_src clojure :tangle ../src/abomination/no_parens.clj :results silent :exports none :noweb yes104 <<header>>105 <<toString>>106 <<lazy-seq>>107 <<delay>>108 #+end_src