On Nov 23, 2008, at 2:30 PM, Stuart Sierra wrote:
> Hmm, you mean write the REPL in Clojure? I hadn't though of that. > Intriguing idea. It would be neat if the REPL were just a function, > so you could start it from within a program using arbitrary input/ > output streams. Something to think about... I've uploaded a patch along those lines: ant-compile-main.patch, http://tinyurl.com/5azp3u based on our recent work on this. This includes Compile.java, main.clj, and modifies build.xml. I'd appreciate interested folks giving it a try and giving feedback. (I've included instructions at the end of this message if you're unfamiliar with doing that.) The patch changes clojure.jar to point to the new class "clojure.main" for its main entry point. In the patched Clojure, a new, flexible Clojure main is defined in src/clj/clojure/ main.clj . I decided not to include compile as one of the options in main.clj for now because it shares little with the other options and made the help text longer. I'd be comfortable with a "clj" script that does eval, scripting, and repl and a separate "cljc" script that does compiling (analogous to java and javac). Opinions welcome. Here are some examples of using the proposed clojure.main via "java - jar clojure.jar": Display usage info: % java -jar clojure.jar --help Usage: java -jar clojure.jar [option*] [file-arg*] [--] [arg*] options: -h, --help Print this help message and exit -e, --eval expr Evaluate an expression and print its value -r, --repl Run an interactive Read-Eval-Print Loop file Run code from from file - Run code from standard input With no options, Clojure runs a repl. The eval options may be repeated but must not appear after other options. The remaining options stop options processing and consider the rest of the command line arguments as file-args and args, separated by "--", all of which are optional. Clojure binds the list of args to *command-line-args*, loads any files named by file-args, then starts the repl or loads from the file or standard in. With no options, run a repl: % java -jar clojure.jar Clojure user=> (+ 3 4) 7 user=> Evaluate Clojure code from the command line: % java -jar clojure.jar -e 3 -e "(+ 3 4)" -e "*ns*" -e "\"this is fun \"" 3 7 #<Namespace clojure.core> this is fun Here are some Clojure source code files to illustrate the order of things: % cat init.clj (print "hi from init.clj, arguments are ") (prn *command-line-args*) % cat init2.clj (print "hi from init2.clj, arguments are ") (prn *command-line-args*) % cat script.clj (print "hi from script.clj, arguments are ") (prn *command-line-args*) Combining eval and repl, demonstrating that the repl can load files and see arguments: % java -jar clojure.jar -e "\"welcome to the repl\"" --repl init.clj -- 1 2 :a :b welcome to the repl hi from init.clj, arguments are ("1" "2" ":a" ":b") Clojure user=> *command-line-args* (1 2 :a :b) user=> Run a script from a file by just giving the filename: % java -jar clojure.jar script.clj hi from script.clj, arguments are nil Now using a filename, no files to load, and arguments: % java -jar clojure.jar script.clj -- 1 2 3 hi from script.clj, arguments are ("1" "2" "3") Now using a filename, files to load before it, and arguments % java -jar clojure.jar script.clj init.clj init2.clj -- a b c hi from init.clj, arguments are ("a" "b" "c") hi from init2.clj, arguments are ("a" "b" "c") hi from script.clj, arguments are ("a" "b" "c") Executing Clojure code piped into standard in: % echo "(prn (sort '(:a :z :m :q)))" | java -jar clojure.jar - (:a :m :q :z) The patch also includes a repl written in Clojure in src/clj/clojure/ main.clj. It supports optional keyword arguments that let you customize it quite a bit while defaulting to the familiar behavior of java version: ------------------------- clojure.main/repl ([& options]) Read-eval-print loop. Options are sequential keyword-value pairs. Available options and their defaults: - :ns, symbol naming the initial namespace for the repl default: 'user - :prompt, function of no arguments, prompts for more input default: #(printf "%s=> " (ns-name *ns*)) - :flush, function of no arguments, flushes output default: flush - :read, function of one argument, returns the next object read from the input, or its argument iff the input is exhausted default: #(read *in* false %) - :eval, funtion of one argument, returns the evaluation of its argument default: eval - :print, function of one argument, prints its argument to the output default: println - :caught, function of one argument, a throwable, called when read, eval, or print throws an exception or error default: #(.println *err* (repl-exception %)) Using the customization we can, for example, run a sub-repl with customized prompt and eval as one might like to do to produce examples for a book or explore reader macros. This version of eval returns a string that notes what it got from the reader and the result of the eval. user=> (clojure.main/repl :prompt #(print "? ") :eval #(str % " => " (eval %))) ? 14 14 => 14 ? (/ 14 3) (/ 14 3) => 14/3 ? '(1 2 3) (quote (1 2 3)) => (1 2 3) ? ^#'+ (clojure.core/meta (var +)) => {:arglists ([] [x] [x y] [x y & more]), :file "core.clj", :name +, :inline #<core$fn__2834 clojure.core [EMAIL PROTECTED]>, :line 540, :doc "Returns the sum of nums. (+) returns 0.", :inline-arities #{2}, :ns #<Namespace clojure.core>} ? nil user=> Comments and suggestions are welcome. It would be great if we could converge on something that Rich would find worthwhile to include in Clojure. --Steve Here's a quick rundown on patching Clojure to try out a patch (requires that the svn command (subversion) be available in your path) and that you copy the patch to /tmp: download a fresh clojure, patch it, and run the jar: cd /tmp svn co https://clojure.svn.sourceforge.net/svnroot/clojure/trunk clojure cd clojure patch -p0 < /tmp/ant-compile-main.patch ant java -jar clojure.jar Enjoy! --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---