annotate org/no_parens.org @ 3:06131b93e54f

changes from dylan?
author Robert McIntyre <rlm@mit.edu>
date Mon, 02 Mar 2015 15:35:00 -0500
parents a4cb0b71fc78
children be0be0a90ba4
rev   line source
rlm@0 1 #+title: Calling it quits without parentheses
rlm@0 2 #+author: Robert McIntyre & Dylan Holmes
rlm@0 3 #+EMAIL: rlm@mit.edu
rlm@3 4 #+SETUPFILE: ../../aurellem/org/setup.org
rlm@3 5 #+INCLUDE: ../../aurellem/org/level-0.org
rlm@3 6
rlm@0 7
rlm@0 8 [TABLE-OF-CONTENTS]
rlm@0 9
rlm@0 10 # * Calling it quits without parentheses
rlm@0 11 Is it possible to make a =quit= command for Clojure such that simply
rlm@0 12 typing the word =quit= at an REPL exits the REPL? An intuitive =quit=
rlm@0 13 command would be especially useful for people new to Lisp syntax or
rlm@0 14 the REPL; the challenge is to make a genuine Clojure command that
rlm@0 15 executes without being called with parentheses. We found three
rlm@0 16 solutions.
rlm@0 17
rlm@0 18 #+srcname: header
rlm@0 19 #+begin_src clojure :results silent
rlm@0 20 (ns abomination.no-parens
rlm@0 21 (:use clojure.contrib.def))
rlm@0 22 #+end_src
rlm@0 23
rlm@0 24 * By modifying =toString=
rlm@0 25 #+srcname: toString
rlm@0 26 #+begin_src clojure
rlm@0 27 (in-ns 'abomination.no-parens)
rlm@0 28 (gen-class :name abomination.no-parens.Quit
rlm@0 29 :prefix quit-)
rlm@0 30
rlm@0 31 (defn quit-toString
rlm@0 32 [this]
rlm@0 33 (System/exit 0))
rlm@0 34
rlm@1 35
rlm@0 36 (defvar quit (abomination.no-parens.Quit.)
rlm@0 37 "a sneaky way to support a `quit` command")
rlm@0 38 #+end_src
rlm@0 39
rlm@1 40 When you type any variable at the REPL, the REPL attempts to print it
rlm@1 41 as a nicely-formatted string by calling its =toString= method. Our
rlm@1 42 trick is to define a class with a =toString= method that exits the
rlm@1 43 REPL; this trick ensures that any variable of that class will close
rlm@0 44 the REPL when the REPL attempts to print it.
rlm@0 45
rlm@1 46 First, we use =gen-class= to make a new class named Quit; in that same
rlm@1 47 line, we use =:prefix= to establish the convention that any function
rlm@1 48 named =quit-[something]= will be adopted as the =[something]= method
rlm@1 49 for the newly-defined Quit class. We use this convention to write our
rlm@1 50 own =toString= method for Quit.
rlm@0 51
rlm@1 52 Next, we define a suitable =toString= method for the Quit class so
rlm@1 53 that attempting to print an instance of the Quit class has the effect
rlm@1 54 of closing the REPL. We do this by defining a function =quit-toString=
rlm@0 55 which closes the REPL; by the convention established above, the Quit
rlm@1 56 class automatically adopts =quit-toString= as its =toString= method.
rlm@0 57
rlm@0 58 Finally, we use =defvar= to create an instance of the Quit class; we
rlm@0 59 name this instance =quit=. Now when you type =quit= into the REPL, the
rlm@1 60 REPL executes the =toString= method of the Quit class, exiting the
rlm@1 61 REPL instead of returning a string.
rlm@0 62
rlm@0 63 #+begin_src clojure :exports both
rlm@1 64 (binding [*compile-path* "/home/r/proj/abomination/classes"]
rlm@0 65 (compile 'abomination.no-parens))
rlm@1 66
rlm@0 67 #+end_src
rlm@0 68
rlm@0 69 #+results:
rlm@0 70 : abomination.no-parens
rlm@0 71
rlm@0 72 * By wrapping the command in a lazy sequence
rlm@0 73 #+srcname: lazy-seq
rlm@0 74 #+begin_src clojure :results silent
rlm@0 75 (in-ns 'abomination.no-parens)
rlm@0 76 (defvar quit* (lazy-seq :the-great-bringer-of-death! (System/exit 0))
rlm@0 77 "the first time it's evaulated it will kill the JVM")
rlm@0 78 #+end_src
rlm@0 79
rlm@0 80 * By =delay=-ing the command
rlm@0 81 #+srcname: delay
rlm@0 82 #+begin_src clojure :results silent
rlm@0 83 (in-ns 'abomination.no-parens)
rlm@0 84 (defvar quit** (delay (System/exit 0))
rlm@0 85 "when this is evaulated at the REPL, it will exit the JVM.")
rlm@0 86 #+end_src
rlm@0 87
rlm@0 88 The same thing, accomplished in a much more elegant and clojureish
rlm@0 89 way.
rlm@0 90
rlm@0 91 # STUD CRUFT PIZZA
rlm@0 92
rlm@0 93 #+begin_quote
rlm@0 94 And death i think is no parenthesis
rlm@0 95 \mdash{}E. E. Cummings
rlm@0 96 #+end_quote
rlm@1 97
rlm@1 98
rlm@1 99 * COMMENT code generation
rlm@1 100 #+begin_src clojure :tangle ../src/abomination/no_parens.clj :results silent :exports none :noweb yes
rlm@1 101 <<header>>
rlm@1 102 <<toString>>
rlm@1 103 <<lazy-seq>>
rlm@1 104 <<delay>>
rlm@1 105 #+end_src