unrepl

discussing specification of an edn-based repl and its implementations.
volrath 2017-11-28T10:40:21.000032Z

hey @cgrand, I wonder what do you think about having special print-limits settings for exceptions, particulary print-length... cider lets you set print-length and print-level for exceptions, I'm not entirely sure print-level is useful, but I can see people wanting to customize exception's print-length (I do it in my cider config)

volrath 2017-11-28T10:44:44.000098Z

also imo, string-length at 80 might be a bit short for exceptions, simple exception messages would get elided, like this one:

#unrepl/string ["java.lang.RuntimeException: Unable to resolve symbol: x in this context, compili" #unrepl/... {:get (unrepl.replG__16476/fetch :G__17055)}

pesterhazy 2017-11-28T10:45:18.000243Z

👍 on the default

pesterhazy 2017-11-28T10:45:35.000021Z

what would be a better default in your mind?

volrath 2017-11-28T10:47:34.000487Z

I think for exceptions I would go for unrestricted string-length... print-length would mostly affect the trace vector, so I think it would be cool to make it customizable

pesterhazy 2017-11-28T10:48:14.000333Z

I've seen ex-infos with ridiculous strings in it (where you pr-str your entire state)

volrath 2017-11-28T10:48:16.000351Z

in general, i think the ideal would be to have exception print-limits separated from the rest

pesterhazy 2017-11-28T10:48:42.000327Z

but maybe that's too niche

pesterhazy 2017-11-28T10:49:00.000491Z

I think I tend to agree with you that it should be unlimited for exceptions

cgrand 2017-11-28T11:01:02.000184Z

I agree with the premises: exceptions suck in unrepl

cgrand 2017-11-28T11:01:15.000154Z

but exceptions are already bad on their own

cgrand 2017-11-28T11:01:51.000003Z

Could we take a step back and consider how to make exceptions less bad

cgrand 2017-11-28T11:03:22.000086Z

I lean towards, as a first step totally reversing exceptions: * display them bottom up * display them inside out (most wrapped exception first)

cgrand 2017-11-28T11:04:00.000074Z

so that the line at the bottom is the closest to what occured and where

cgrand 2017-11-28T11:08:00.000236Z

elide wrapped-by (the reverse of the parent exception relationship), elide previous frames, print ex-info when present

volrath 2017-11-28T11:15:44.000386Z

right now, afaik, ex-info always comes from unrepl.repl/blame-ex, right? it's always something like: "Exception during foo phase"

cgrand 2017-11-28T11:17:14.000411Z

that should be removed by the client

cgrand 2017-11-28T11:17:38.000424Z

and display something only when it’s not during eval

volrath 2017-11-28T11:17:43.000253Z

i agree, I'm actually doing that

cgrand 2017-11-28T11:17:58.000391Z

Expression computed succesfully but failed to print

volrath 2017-11-28T11:18:10.000108Z

I like that

cgrand 2017-11-28T11:18:21.000297Z

Unreadable input

cgrand 2017-11-28T11:18:37.000282Z

Sad unicorn (like sad mac, for when it comes from unrepl)

volrath 2017-11-28T11:19:38.000218Z

but since the phase is already part of the message payload, couldn't we just take that ex-info out?

volrath 2017-11-28T11:20:03.000378Z

I mean, from this part:

volrath 2017-11-28T11:20:07.000459Z

:via
        [{:type clojure.lang.ExceptionInfo,
          :message "Exception during eval phase.",
          :data {:unrepl.replG__16476/ex #error {#unrepl/... nil #unrepl/... {:get (unrepl.replG__16476/fetch :G__17054)}},
                 :unrepl.replG__16476/phase :eval},
          :at [clojure.core$ex_info invokeStatic "core.clj" 4725]}
         {:type clojure.lang.Compiler$CompilerException,
          :message #unrepl/string ["java.lang.RuntimeException: Unable to resolve symbol: x in this context, compili" #unrepl/... {:get (unrepl.replG__16476/fetch :G__17055)}],
          :at [clojure.lang.Compiler analyze "Compiler.java" 6720]}
         {:type java.lang.RuntimeException,
          :message "Unable to resolve symbol: x in this context",
          :at [clojure.lang.Util runtimeException "Util.java" 221]}],

volrath 2017-11-28T11:20:44.000122Z

(this is not what I was asking at the beginning of this, but I'm also curious)

volrath 2017-11-28T11:21:51.000248Z

what I'm doing right now is just ommiting the first element in that vector, since I'm using the :phase to insert a exception title

cgrand 2017-11-28T11:25:39.000187Z

@volrath: thanks, I forgot an x...

volrath 2017-11-28T11:26:11.000078Z

perfect 🙂

volrath 2017-11-28T11:27:01.000342Z

so ok, let me get back to what you were saying before and ask you some (probably noob) questions

volrath 2017-11-28T11:28:22.000434Z

when you're saying "display the exceptions bottom up", are you talking client-wise or protocol-wise?

cgrand 2017-11-28T11:29:18.000426Z

client-wise it’s going to be roundtrip-painful (unless you get the whole exception at once)

volrath 2017-11-28T11:29:32.000401Z

right

cgrand 2017-11-28T11:30:24.000096Z

well bottom-up client side is ok, inside-out not

volrath 2017-11-28T11:33:22.000085Z

can you explain the difference? not sure if I follow... right now I don't know how to get the wrapping information from the exception message payload. Not sure if it's because that information is not there or because I am missing something

cgrand 2017-11-28T11:34:27.000438Z

ok I just realized that’s already what Throwable->map does

cgrand 2017-11-28T11:35:06.000333Z

wrapping information is the :via vector

volrath 2017-11-28T11:36:02.000444Z

cool

volrath 2017-11-28T11:42:36.000069Z

But Throwable->map doesn't return the wrapping inside out, does it?

volrath 2017-11-28T11:43:06.000052Z

what I'm doing right now is reverse that vector

pesterhazy 2017-11-28T12:01:14.000244Z

Btw I've seen that exceptions get returned in different shapes on clojure 1.8 vs 1.9

volrath 2017-11-28T12:06:24.000184Z

I guess as long as Throwable->map returns the same in both, we're good

pesterhazy 2017-11-28T12:07:33.000314Z

couldn't figure this out while running on CI: https://clojurians.slack.com/archives/C03S1KBA2/p1511870643000121

dominicm 2017-11-28T12:12:19.000400Z

@pesterhazy I think ./clj is the official answer to this

pesterhazy 2017-11-28T12:13:19.000255Z

@dominicm is that bundled with clojure?

pesterhazy 2017-11-28T12:13:51.000117Z

official instructions for doing things manually would be appreciated

cgrand 2017-11-28T12:19:03.000246Z

0.1.143 for spec.alpha

cgrand 2017-11-28T12:19:21.000027Z

core.specs.alpha 0.1.24

cgrand 2017-11-28T12:19:47.000140Z

is there any effort to port tools deps to CLJS?

dominicm 2017-11-28T12:24:51.000393Z

@cgrand none that I know of

pesterhazy 2017-11-28T14:06:16.000076Z

@cgrand, oh the spec dep is right there on the mvn site 🤦

cgrand 2017-11-28T14:06:39.000300Z

yeah but mvn central was down for me

cgrand 2017-11-28T17:38:14.000757Z

v0.2.0 of packed printer with a cleaner implementation and works in CLJS too

cgrand 2017-11-28T18:32:56.000126Z

I pushed to npm too

volrath 2017-11-28T20:45:39.000248Z

@cgrand notice after resolving the first elision there are a couple of misalignments? I'm trying to pad the file name and lineno using the max length of what i can see in the :trace vector, but since it is elided, I cannot render it well

volrath 2017-11-28T20:46:07.000477Z

but anyway, I think it's good enough for now

ghadi 2017-11-28T20:54:59.000213Z

@volrath nice. since 1.8/direct linking every stack frame is doubled because of invoke+invokeStatic, would be cool to elide adjacent frames

ghadi 2017-11-28T20:55:22.000273Z

this is really really cool.

cgrand 2017-11-28T20:57:05.000052Z

Nice, an intersting problem is how to deal with misalignment

volrath 2017-11-28T20:58:09.000556Z

cool, thanks for the input! tbh I don't know much about this, could you point me to some info?

volrath 2017-11-28T20:58:37.000065Z

rerendering is a pain in the ass...

volrath 2017-11-28T20:59:14.000355Z

@cgrand you never got to tell me your thoughts on managing print limits for exceptions separately

cgrand 2017-11-28T21:07:29.000126Z

@volrath wider strings, yes

volrath 2017-11-28T21:09:19.000399Z

higher/customizable *print-length*? that's the one I think could help the most

cgrand 2017-11-28T21:09:42.000178Z

why? for the alignment?

volrath 2017-11-28T21:09:52.000344Z

and for the elisions..

volrath 2017-11-28T21:10:16.000461Z

clicking the buttons when getting an exception can get old really fast

volrath 2017-11-28T21:10:46.000009Z

in the end, I think we should let the user decide what's best for their workflow

cgrand 2017-11-28T21:12:21.000262Z

one setting for everything does not work

ghadi 2017-11-28T21:12:24.000277Z

basically pre-clojure 1.8 functions got compiled into a java class that implemented a single method invoke()

ghadi 2017-11-28T21:13:10.000222Z

Now with this direct-linking mode (which improves performance) the invoke() which is an instance method, calls down to an invokeStatic() which is a static class method. This results in longer stack frames

ghadi 2017-11-28T21:13:43.000255Z

if you see a foo.invoke() that immediately calls foo.invokeStatic() in a stack trace, one of them should disappear

volrath 2017-11-28T21:15:39.000693Z

even though I do believe that customization is the key of happiness, that's not my point... stacktraces are consumed by people in different ways

volrath 2017-11-28T21:16:13.000089Z

I'm not saying a different print-limits management for every data type or anything like that

volrath 2017-11-28T21:18:25.000532Z

but I feel this is something people should be able to customize. as we know, exceptions/stacktraces are not the best thing in clojure, and unless we find the holygrail on how to deal with them (doubt it), i think we should give people the ability to customize

volrath 2017-11-28T21:19:19.000463Z

got it, I'll look into it, thanks!

cgrand 2017-11-28T21:21:34.000261Z

one set of settings repl wide won’t cut

cgrand 2017-11-28T21:22:06.000571Z

one set of settings per print context (eval, ex, log etc.) is awkward

volrath 2017-11-28T21:28:03.000114Z

I'll update the issue I created for settings with this and with the other problem we discussed the other day, about being able to edit settings from aux that also affect user (so that we don't have to ever use unrepl/do in user)

ghadi 2017-11-28T21:35:17.000226Z

you need contextual display... but you probably need the same data in the different contexts

ghadi 2017-11-28T21:35:24.000305Z

*underlying data

ghadi 2017-11-28T21:38:04.000134Z

I have been too lazy to implement this for a while, but translating "Well-Known Signatures" in stacktraces to user-friendly displays. For example, an exception while realizing a lazy seq always contains LazySeq.sval() and LazySeq.seq() adjacently.

ghadi 2017-11-28T21:38:52.000146Z

It couple be potentially nice to translate that into something like "Lazy Sequence"

ghadi 2017-11-28T21:39:02.000353Z

or "Lazy Sequence Realization"

ghadi 2017-11-28T21:39:29.000416Z

There are a lot of landmark function calls in clojure.lang.RT and clojure.lang.* that we could rewrite

cgrand 2017-11-28T22:39:19.000304Z

@ghadi I’ve also been thinking about using frequencies of stack frames to drive elision.

cgrand 2017-11-28T22:41:04.000213Z

@volrath I’m wondering if setting print limits each time on aux.

volrath 2017-11-29T08:50:25.000295Z

@cgrand what do you mean?

cgrand 2017-11-28T23:09:36.000320Z

Sounds a little like “what about ditching the function row in favor of a touch bar?”