Mercurial > abomination
view 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 |
line wrap: on
line source
1 #+title: Calling it quits without parentheses2 #+author: Robert McIntyre & Dylan Holmes3 #+EMAIL: rlm@mit.edu4 #+SETUPFILE: ../../aurellem/org/setup.org5 #+INCLUDE: ../../aurellem/org/level-0.org8 [TABLE-OF-CONTENTS]10 # * Calling it quits without parentheses11 Is it possible to make a =quit= command for Clojure such that simply12 typing the word =quit= at an REPL exits the REPL? An intuitive =quit=13 command would be especially useful for people new to Lisp syntax or14 the REPL; the challenge is to make a genuine Clojure command that15 executes without being called with parentheses. We found three16 solutions.18 #+srcname: header19 #+begin_src clojure :results silent20 (ns abomination.no-parens21 (:use clojure.contrib.def))22 #+end_src24 * By modifying =toString=25 #+srcname: toString26 #+begin_src clojure27 (in-ns 'abomination.no-parens)28 (gen-class :name abomination.no-parens.Quit29 :prefix quit-)31 (defn quit-toString32 [this]33 (System/exit 0))36 (defvar quit (abomination.no-parens.Quit.)37 "a sneaky way to support a `quit` command")38 #+end_src40 When you type any variable at the REPL, the REPL attempts to print it41 as a nicely-formatted string by calling its =toString= method. Our42 trick is to define a class with a =toString= method that exits the43 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 same47 line, we use =:prefix= to establish the convention that any function48 named =quit-[something]= will be adopted as the =[something]= method49 for the newly-defined Quit class. We use this convention to write our50 own =toString= method for Quit.52 Next, we define a suitable =toString= method for the Quit class so53 that attempting to print an instance of the Quit class has the effect54 of 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 the61 REPL instead of returning a string.63 #+begin_src clojure :exports both64 (binding [*compile-path* "/home/r/proj/abomination/classes"]65 (compile 'abomination.no-parens))67 #+end_src69 #+results:70 : abomination.no-parens72 * By wrapping the command in a lazy sequence73 #+srcname: lazy-seq74 #+begin_src clojure :results silent75 (in-ns 'abomination.no-parens)76 (defvar quit* (lazy-seq :the-great-bringer-of-death! (System/exit 0))77 "the first time it's evaulated it will kill the JVM")78 #+end_src80 * By =delay=-ing the command81 #+srcname: delay82 #+begin_src clojure :results silent83 (in-ns 'abomination.no-parens)84 (defvar quit** (delay (System/exit 0))85 "when this is evaulated at the REPL, it will exit the JVM.")86 #+end_src88 The same thing, accomplished in a much more elegant and clojureish89 way.91 # STUD CRUFT PIZZA93 #+begin_quote94 And death i think is no parenthesis95 \mdash{}E. E. Cummings96 #+end_quote99 * COMMENT code generation100 #+begin_src clojure :tangle ../src/abomination/no_parens.clj :results silent :exports none :noweb yes101 <<header>>102 <<toString>>103 <<lazy-seq>>104 <<delay>>105 #+end_src