Mercurial > abomination
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1c7ace5054ac |
---|---|
1 #+title: Calling it quits without parentheses | |
2 #+author: Robert McIntyre & Dylan Holmes | |
3 #+EMAIL: rlm@mit.edu | |
4 #+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 <:t | |
7 #+SETUPFILE: ../templates/level-0.org | |
8 #+INCLUDE: ../templates/level-0.org | |
9 | |
10 [TABLE-OF-CONTENTS] | |
11 | |
12 # * Calling it quits without parentheses | |
13 Is it possible to make a =quit= command for Clojure such that simply | |
14 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 or | |
16 the REPL; the challenge is to make a genuine Clojure command that | |
17 executes without being called with parentheses. We found three | |
18 solutions. | |
19 | |
20 #+srcname: header | |
21 #+begin_src clojure :results silent | |
22 (ns abomination.no-parens | |
23 (:use clojure.contrib.def)) | |
24 #+end_src | |
25 | |
26 * By modifying =toString= | |
27 #+srcname: toString | |
28 #+begin_src clojure | |
29 (in-ns 'abomination.no-parens) | |
30 (gen-class :name abomination.no-parens.Quit | |
31 :prefix quit-) | |
32 | |
33 (defn quit-toString | |
34 [this] | |
35 (System/exit 0)) | |
36 | |
37 (defvar quit (abomination.no-parens.Quit.) | |
38 "a sneaky way to support a `quit` command") | |
39 #+end_src | |
40 | |
41 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= method | |
43 that exits the REPL; this trick ensures that any variable of that class will close | |
44 the REPL when the REPL attempts to print it. | |
45 | |
46 First, we use =gen-class= to make a new class named Quit; in that same line, we use | |
47 =:prefix= to establish the convention that any function named | |
48 =quit-[something]= will be adopted as the =[something]= method for the | |
49 newly-defined Quit class. We use this convention to write our own | |
50 =toString= method for Quit. | |
51 | |
52 Next, we define a suitable =toString= method for the Quit class so that | |
53 attempting to print an instance of the Quit class has the effect of | |
54 closing the REPL. We do this by defining a function =quit-toString= | |
55 which closes the REPL; by the convention established above, the Quit | |
56 class automatically adopts =quit-toString= as its =toString= method. | |
57 | |
58 Finally, we use =defvar= to create an instance of the Quit class; we | |
59 name this instance =quit=. Now when you type =quit= into the REPL, the | |
60 REPL executes the =toString= method of the Quit class, exiting the REPL instead of returning a | |
61 string. | |
62 | |
63 #+begin_src clojure :exports both | |
64 (binding [*compile-path* "/home/r/aurellem/classes"] | |
65 (compile 'abomination.no-parens)) | |
66 #+end_src | |
67 | |
68 #+results: | |
69 : abomination.no-parens | |
70 | |
71 * By wrapping the command in a lazy sequence | |
72 #+srcname: lazy-seq | |
73 #+begin_src clojure :results silent | |
74 (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_src | |
78 | |
79 * By =delay=-ing the command | |
80 #+srcname: delay | |
81 #+begin_src clojure :results silent | |
82 (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_src | |
86 | |
87 The same thing, accomplished in a much more elegant and clojureish | |
88 way. | |
89 | |
90 #+begin_src clojure :tangle no_parens.clj :results silent :exports none :noweb yes | |
91 <<header>> | |
92 <<toString>> | |
93 <<lazy-seq>> | |
94 <<delay>> | |
95 #+end_src | |
96 | |
97 # STUD CRUFT PIZZA | |
98 | |
99 #+begin_quote | |
100 And death i think is no parenthesis | |
101 \mdash{}E. E. Cummings | |
102 #+end_quote |