Default kulla messages

Brian Goetz brian.goetz at oracle.com
Fri Jun 26 16:37:52 UTC 2015


I've gotten a few private responses on this so let me summarize them.

There's a range of opinions on whether the default behavior should lean 
towards "onboarding new users".  We've faced this decision before in 
other contexts, and our default orientation is that we should design for 
the longer-term steady-state, and avoid over-rotating towards 
highlighting what is new -- since new is a temporary state.  In other 
words, build the UX so that it serves the intended use cases, not 
necessarily the "teach people to use the REPL case."  (There are other 
means of educating new users.)

In surveying a number of REPLs, the common theme is that their output is 
terse.  In some cases, its because there's less information to display 
(some languages don't have types, so they don't display those), but even 
in the Scala case, where there's plenty of type information, the REPL UX 
is "just the facts."  I think we would need a good reason to buck this 
trend.

Some pointed out that the user can change the verbosity level.  Which is 
true -- and a great feature -- but let's admit the reality that 99% of 
users never will; they'll just type 'jshell'.  So the default UX needs 
to serve the broadest range of users.

There's several categories of output that the REPL might report.  Let's 
enumerate them.

1.  Expression results.  (If the input was an expression, we probably 
always want to print this; if its not an expression, there's nothing to 
print.)

2.  Text sent to System.{out,err}.

3.  Diagnostics either from compiling the input or from executing a REPL 
command.

4.  Runtime exceptions produced during execution.

5.  Side-effects on the REPL state (vars/methods/classes 
declared/invalidated/dropped/changed state.)

Some of these are mutually exclusive; if there's a compilation error, 
there'll be no evaluation.

Here's what I am proposing for the default scheme:

(3) is printed first -- and we stop here (unless the diagnostic is 
merely a warning)
(2) is printed as it is generated, with no decoration
If the input was an expression, (1) is printed, prefixed by something 
like "=> "
If an exception occurred, (4) is printed
(5) is printed, parenthetically.

For (5), there are sub-categories:
  a) a new temporary variable was created
  b) a new variable was created (var declaration)
  c) a new method/class was created
  d) a variable/class/method was invalidated
  e) a variable changed its value (assignment to existing var)

By default, I'm suggesting we should print something for (a) and (c), 
and maybe (b) but not for the others.

Key to this is: other schemes can change the verbosity of individual 
elements ("created $1" vs "created temporary variable $1 of type int") 
or whether elements are printed at all, but should not change the 
overall structure.

Some examples:

repl> 1 + 1
=> 2
(declared temporary variable $1 of type int)

repl> int x = 3
(declared variable x of type int)  // maybe

repl> x + 1
=> 4
(declared temporary variable $2 of type int)

repl> if (x == 3) x = 4;
// statement -- no result, no structural side-effects

repl> int m() { return 43; }
(declared method m)

repl> m()
=> 43
(declared temporary variable $3 of type int)

repl> /drop m
(dropped method m)

repl> /drop m
error: cannot drop m, does not exist

repl> $1/0
java.lang.ArithmeticException: divide by zero
... stack trace ...

repl> System.out.println("Hello World")
Hello World


Some felt that we should print type and value for every assignment. 
But, let's not forget that the user can always ask for these if they 
want, just by evaluating the variable:

repl> x = f(...)

repl> x
=> Foo[blah, blah ]

So I think we should err on the side of *not* printing values that are 
not the result of evaluating a top-level expression.




On 6/22/2015 5:40 PM, Brian Goetz wrote:
> The messages produced by JShell during the course of
> evaluation/declaration have been in a placeholder state for a while, and
> its probably time to paint the bikeshed of what the default messages
> should look like (there are multiple message schemes, which can crank up
> and down the verbosity, but the default set is the most important.)
>
> Here's what JShell prints now for an expression and a method declaration:
>
> -> 1 + 1
> |  Expression value is: 2
> |    assigned to temporary variable $1 of type int
>
> -> void foo() { }
> |  Added method foo()
>
> These are all useful bits of information:
>   - the result of the expression, if any
>   - side-effects on the REPL state
>     - temporary name and type, for expressions
>     - var/method/class name and type, for declarations
>
> However, plenty of people have commented that these messages are "kind
> of verbose".
>
> The Scala REPL output contains all this information too, but more
> compactly:
>
> scala> 1 + 1
> res1: Int = 2
>
> scala> def m() { }
> m: ()Unit
>
> The Ruby IRB output is more taciturn:
>
> irb(main):001:0> 1 + 1
> => 2
> irb(main):002:0> def m()
> irb(main):003:1>     puts "Hello"
> irb(main):004:1> end
> => nil
>
> The Perl re.pl even more so:
>
> $ 1 + 1
> 2
> $ sub m {
>  >     return 1;
>  > }
> (empty line)
>  >
>
>
> While we could gather more examples, I think there's a pattern emerging:
> expression evaluation should put the result front-and-center.
>
> Here are some possible options for the evaluation of 1+1 in jshell:
>
> --
> 2 (assigned to temporary $1)
> --
> 2 (assigned to temporary $1 : int)
> --
> $1 (int): 2
> --
> => 2
> (assigned to temporary $1 : int)
> --
> int: 2
> (assigned to temporary $1 of type int)
>
> There are obviously many more variations.
>
> I propose using, as the default level:
>
> => expression value
>
> to indicate the result of an expression, with statements producing no
> output, coupled with a convention to put all side-effect-on-REPL-state
> information in parentheses on its own line:
>
> repl> 1 + 1
> => 2
> (assigned to temporary $1 of type int)
>
> repl> void m() { }
> (defined method m())
>
> repl> /drop m
> (dropped method m())
>
> repl> int x = 3
> (declared variable x of type int)
>
> repl> x = 4
> (no output)
>
>
> I think this scheme captures the essential information without too much
> noise (users can select a higher verbosity level if they want.)
>


More information about the kulla-dev mailing list