On Dec 16, 5:13 pm, "Stephen C. Gilardi" <squee...@mac.com> wrote:
> The enclosed patch updates clojure.main to fix a bug and implement
> changes discussed here recently. Details below. Feedback welcome.
>
> --Steve
>
> [1] clojure.main no longer calls gen-class. Instead there is now a
> stub clojure.main class written in Java so it is always available with
> Clojure's runtime. Each of the entry points provided by class
> clojure.main ensures that namespace clojure.main is loaded (using
> "require") and then calls the corresponding fn in namepace clojure.main.
>
> class clojure.main entry points:
>
>      - main : unified entry point for clojure. Can run a repl or a
> script, calls clojure.main/main
>
>      - legacy_repl : called by the new, stubbed clojure.lang.Repl,
> calls clojure.main/legacy-repl
>
>      - legacy_script : called by the new, stubbed clojure.lang.Script,
> calls clojure.main/legacy-script
>
> Because the clojure.main class is always compiled along with the rest
> of the Clojure runtime, it can be Clojure's unified entry point
> whether or not ahead-of-time compiled Clojure code is available.
>
> The pre-unification Clojure entry points (clojure.lang.Repl,
> clojure.lang.Script) are still available and now run via fns in
> namespace clojure.main. As a result, those fns will get a good workout
> even if users don't make any changes to how they drive clojure.jar.
>
> [2] clojure.main/repl's handling of (read-line) was different than
> that of clojure.lang.Repl and not useful. This was because
> clojure.main/repl *always* reads from *in*, while clojure.lang.Repl
> created its own LineNumberingPushbackReader on System.in instead. In
> order to handle (read-line) well while still using *in* exclusively,
> clojure.main/repl needed to become aware of lines in the input stream
> rather than treating all whitespace the same. I've implemented that,
> notably without any change to LispReader.java so loading from files
> remains exactly the same.
>
> Some visible changes to the repl:
>
> - The repl now only prompts when the input stream is pointing to the
> start of a new line of input.
>
>    - Multiple expressions on a line will only yield a single prompt.
> Blank lines (or lines containing only whitespace) will be consumed and
> yield a new prompt.
>
>    user=> 1 2
>    1
>    2
>    user=>
>    user=>
>
> - (read-line) will read a fresh line if there is nothing (or only
> whitespace) left on the current input line, or the (post-whitespace)
> rest of the input line otherwise.
>
>    user=> (read-line)
>    123
>    "123"
>    user=> (read-line) 456
>    "456"
>
>    user=>
>
>    In the first example, the repl waited on the line after (read-line)
> and I typed 123. This should be the most common case an gives the same
> effect as clojure.lang.Repl used to. (Note that it doesn't have to be
> a naked call to (read-line) as shown here, (read-line) from within
> another function down the stack would behave the same way.)
>
>    In the second example, (read-line) read 456 from the rest of the
> input line and printed the string that it read. It then waited for
> input without prompting on the next (blank) line. This is unfortunate,
> but I don't see a clean way around it--it's a consequence of code
> running during "eval" (in this case the read-line) changing the input
> stream in a way the repl can't predict. (read-line) consumes the
> newline after 456 on the input line. Whatever is typed on the line
> after "456" will be evaluated and printed. Just pressing return will
> produce a prompt (as shown).
>
> - Exceptions caught by the repl now cause the rest of the input line
> to be skipped.
>
>    user=> 1 2 3 (/ 1 0) 4 5 6
>    1
>    2
>    3
>    java.lang.ArithmeticException: Divide by zero (NO_SOURCE_FILE:0)
>    user=>
>
> - Comments to end of line (;) are now supported at the repl. This can
> be convenient when using a session transcript to demonstrate something.
>
>    user=> (use 'clojure.set) ; pull in the set functions
>    nil
>    user=> 3 4 ; 5 6
>    3
>    4
>    user=>
>
> [3] clojure.lang.LineNumberingPushbackReader extends
> java.io.PushbackReader, but was not always honoring the latter's
> contract that when a character is successfully "unread", it will be
> the next character read. In the case of LNPBR's readLine, the pushed
> back character was ignored. Most of the time this had no significant
> effect, but I needed to fix it to support (read-line) from the same
> stream. These examples show the problem and the fixed behavior:
>
> WAS:
>
> user=> (with-in-str "12\n3" [(read-line) (read)])
> ["12" 3]
> user=> (with-in-str "12\n3" (.unread *in* (.read *in*)) [(read-line)
> (read)])
> ["2" 13]
> user=>
>
> IS:
>
> user=> (with-in-str "12\n3" [(read-line) (read)])
> ["12" 3]
> user=> (with-in-str "12\n3" (.unread *in* (.read *in*)) [(read-line)
> (read)])
> ["12" 3]
>
> [4] The "prompt" hook for clojure.main/repl now takes an argument: a
> keyword that indicates where on the line the input stream is pointing.
> The "only prompt on a fresh line" behavior is implemented by only
> printing the prompt when the "where" argument is :line-start. Anyone
> using the prompt hook will need to update.
>
> [5] The "-e" and "--eval" options for the command line of clojure.main
> now evaluate all the expressions present in their string argument and
> print all non-nil return values using prn.
>
> % java -cp clojure.jar clojure.main -e "(use 'clojure.set) (union
> #{:a} #{:b})"
> #{:b :a}
> %
>
> [6] Updated clojure/build.xml with these changes:
>
>    - changed the example in description to avoid "java -jar". It now
> recommends:
>      java -cp clojure.jar clojure.main
>
>    - Changed names of compile_java and compile_clojure targets to
> compile-java and compile-clojure
>
>    - Renamed "jar" target to "clojure" -- it builds clojure.jar
>
>    - Added a "clojure-slim" target that builds clojure-slim.jar. That
> jar contains compiled Java code, but no compiled Clojure code. It is
> functionally equivalent to clojure.jar, but it's much smaller--trading
> reduced size for increased startup/execution time until all the
> Clojure code a program uses is JIT compiled into memory by Clojure.
>
>    - Added a legacy "jar" target that (also) builds clojure.jar
>
>    - Added an "all" target that builds both clojure.jar and clojure-
> slim.jar
>
>    - Made "all" the default target
>
> Notes:
>
>    - In contrast to most files in Clojure,
> LineNumberingPushbackReader.java has DOS line endings. If you have
> trouble applying this patch to that file, that may be the cause. Rich,
> please consider converting LNPBR.java to use unix line endings.
>    - src/jvm/clojure/main.java is a new file produced by the patch
>

Thanks!

Wow, that's a lot of changes. I'm not sure about this one:

- Exceptions caught by the repl now cause the rest of the input line
to be skipped.

In what way is that the right thing to do?

I'm quite concerned about compatibility, especially with all the read-
line stuff. I remember some nightmares:

http://groups.google.com/group/clojure/browse_frm/thread/e818dabbd9ce7cb5/cfcc9d37934f844a
http://groups.google.com/group/clojure/browse_frm/thread/16843146286cc16c/795e028ed81905c0

Are these changes compatible with the interactions done via, say,
emacs inferior lisp mode? It's important to consider the fact that the
repl can be interacted with by programs, not just people.

Has anyone tried this patch under Windows?

There also seems to be a difference in behavior between clojure.main
and Repl regarding shutdown:

http://groups.google.com/group/clojure/msg/eea16032c5b6b591

is that difference in the patch?

I guess I'm looking for recommendations about how best to test this
short of a push-it-and-(briefly)-break-all-svn-users.

Rich

--~--~---------~--~----~------------~-------~--~----~
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 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to