unrepl

discussing specification of an edn-based repl and its implementations.
plexus 2017-06-07T10:31:11.229562Z

> I understand the concern but after some earlier iterations I came to the conclusion that the input stream must be left untouched. @cgrand could you say a bit more about why you came to this conclusion?

cgrand 2017-06-07T10:35:39.285789Z

I considered two approaches: full framing (eg {:id id :code "code"} and interspersed “metadata” (adding stuff between forms).

cgrand 2017-06-07T10:38:08.317022Z

interspersed metadata require the client to perfectly parse user input which is a strong requirement (and makes it brittle towards language change).

cgrand 2017-06-07T10:46:08.415214Z

framing makes further upgrades difficult (transitioning from framed to streamed and (potentially) framed again) especially when some further input is already buffered. furthermore framing encourages to multiplex usages of a single connection, which adds complexity to the server. Plus in no time you are reinventing nrepl-sans-bencode 🙂

dominicm 2017-06-07T10:59:57.585601Z

I've made that comment. EDN over socket as a new transport for nrepl could bring some of the benefits on unrepl.

dominicm 2017-06-07T11:00:19.591095Z

But nrepl is fairly tied to bencode, and everything is tied to the limitations of the 4 data types that are there.

plexus 2017-06-07T11:18:39.812931Z

thanks @cgrand, that makes sense

cgrand 2017-06-07T11:28:41.931596Z

really?

plexus 2017-06-07T11:51:02.201357Z

yeah, I think those are reasonable arguments.

dominicm 2017-06-07T12:10:51.465994Z

the problem still exists somewhat from what I can tell though, right?

dominicm 2017-06-07T12:11:16.471757Z

as a curious idea, could unrepl provide a form that you can put code into? & that would essentially be (unrepl/with-id)?

dominicm 2017-06-07T12:11:30.474876Z

e.g. (unrepl/with-id 1 (+ 1 1))

pesterhazy 2017-06-07T12:12:46.492393Z

well

pesterhazy 2017-06-07T12:13:08.497228Z

In unravel I just send [my-eval-id (form-to-eval)]

pesterhazy 2017-06-07T12:13:31.502823Z

low-tech solution to track replies

cgrand 2017-06-07T12:14:02.509781Z

*1? exceptions etc?

cgrand 2017-06-07T12:14:41.518938Z

Is offset management that hard? (is my proposed solution too cumbersome?)

pesterhazy 2017-06-07T12:15:13.526477Z

I feel I'm missing the context

cgrand 2017-06-07T12:15:43.533797Z

@pesterhazy it may be something you have missed

cgrand 2017-06-07T12:16:15.541409Z

now unrepl sends :echo messages right after read but before eval

cgrand 2017-06-07T12:16:55.550954Z

these messages contains the offset (from the start of the unrepl session) and length of the form being evaluated

pesterhazy 2017-06-07T12:17:16.555630Z

offset being the number of evals executed so far?

cgrand 2017-06-07T12:17:27.558226Z

number of input characters

pesterhazy 2017-06-07T12:17:28.558371Z

ah no chars

cgrand 2017-06-07T12:17:55.564554Z

UTF-16 code units with normalized newlines to be precise 🙂

cgrand 2017-06-07T12:18:07.567532Z

(aka don’t send CRLF)

pesterhazy 2017-06-07T12:18:30.573081Z

that's for when I send (+ 1 2) (+ 3 4), that is, I'll get multiple :echos?

pesterhazy 2017-06-07T12:19:09.582230Z

I think that's a useful feature

cgrand 2017-06-07T12:20:30.601651Z

> (+ 1 2)(map inc (range 5))(str "hello" " " "world")
< [:echo {:from [1 1], :to [1 8], :offset 0, :len 7} 1]
< [:started-eval {:actions {:interrupt (unrepl.repl/interrupt! :session335 1), :background (unrepl.repl/background! :session335 1)}} 1]
< [:eval 3 1]
< [:echo {:from [1 8], :to [1 27], :offset 7, :len 19} 2]
< [:started-eval {:actions {:interrupt (unrepl.repl/interrupt! :session335 2), :background (unrepl.repl/background! :session335 2)}} 2]
< [:eval (1 2 3 4 5) 2]
< [:echo {:from [1 27], :to [2 1], :offset 26, :len 26} 3]
< [:started-eval {:actions {:interrupt (unrepl.repl/interrupt! :session335 3), :background (unrepl.repl/background! :session335 3)}} 3]
< [:eval "hello world" 3]
[:prompt {:file "unrepl-session", :line 2, clojure.core/*warn-on-reflection* false, clojure.core/*ns* <#C4C63FWP5|unrepl>/ns user}]

pesterhazy 2017-06-07T12:21:00.609095Z

seems great for showing exactly where an error is

pesterhazy 2017-06-07T12:21:15.612614Z

in the terminal I could show a little arrow e.g.

pesterhazy 2017-06-07T12:21:55.622856Z

My problem was a different one. I was to correlate doc replies, i.e. I want to send something like (send-to-tooling-cx '(doc clojure.core/filter) {:callback show-result})

pesterhazy 2017-06-07T12:22:29.631604Z

for that, I need to keep track of evaluations, But using a simple vector with an eval-id works well

pesterhazy 2017-06-07T12:22:46.636108Z

Am I right in assuming that :echo wouldn't help for this case?

cgrand 2017-06-07T12:23:05.640679Z

I think you are wrong in this case

pesterhazy 2017-06-07T12:23:22.644853Z

I mean I get an echo number back

pesterhazy 2017-06-07T12:23:36.648236Z

but then I would still have to correlate the echo response with what I sent

pesterhazy 2017-06-07T12:23:57.653460Z

and in pathological cases, I might get an echo late, or not at all

cgrand 2017-06-07T12:24:26.660448Z

when you send (doc cojure.core/filter) you know the offset in your outgoing tooling stream, so when you get the echo you can obtain the eval id

pesterhazy 2017-06-07T12:25:27.675131Z

how do I know the offset? I just count how man bytes I've sent so far?

cgrand 2017-06-07T12:25:27.675376Z

:echo occurs after read and before eval

cgrand 2017-06-07T12:25:45.679756Z

couting chars would be better but yes

dominicm 2017-06-07T12:26:17.687362Z

Oh, didn't realise echo gave back id. I thought it had, I was confused this came up again. Yeah, only "issue" is multiplexing.

dominicm 2017-06-07T12:26:27.689637Z

which is a non-feature

cgrand 2017-06-07T12:27:05.698717Z

so there’s no pathological case I think (I’d rather be proven wrong now than in 6 months)

pesterhazy 2017-06-07T12:27:13.700589Z

hm I still prefer my simple-minded solution - it only requires me to keep track of one correlation, not two

pesterhazy 2017-06-07T12:27:37.706755Z

anyway there's no downsides to allowing both approaches, right?

cgrand 2017-06-07T12:28:19.717303Z

I’m not going to prevent you from evaluating what you want

pesterhazy 2017-06-07T12:29:07.728679Z

I appreciate it 🙂

pesterhazy 2017-06-07T12:36:20.837717Z

🙂

cgrand 2017-06-07T12:49:15.041453Z

send-to-tooling-cx is local only or not yet written?

pesterhazy 2017-06-07T12:51:49.083163Z

it was pseudo-code. The actual function is called call-remote: https://github.com/pesterhazy/unravel/blob/master/src/unravel/loop.cljs#L155 @cgrand

cgrand 2017-06-07T13:01:16.250312Z

Thanks

cgrand 2017-06-07T13:40:23.039553Z

@pesterhazy did you consider processing messages in a slightly different way? Currently you dispatch on connection+tag first. I would dispatch on the group-id first.

pesterhazy 2017-06-07T13:42:36.088111Z

sorry, I don't follow. What would the group-id be?

cgrand 2017-06-07T13:42:57.095751Z

the third component of a message (the eval id if you wish)

pesterhazy 2017-06-07T13:43:16.102730Z

ah

pesterhazy 2017-06-07T13:43:38.110626Z

what would I do with the group-id?

cgrand 2017-06-07T13:46:01.165030Z

I’m thinking about the tooling connection

pesterhazy 2017-06-07T13:46:03.165853Z

I mean that would be part of using :echo I guess - keeping associations of group-ids and callbacks

pesterhazy 2017-06-07T13:46:25.173636Z

and outbound messages and group-ids

cgrand 2017-06-07T13:49:43.249234Z

Hmm trying to sort out my ideas...

cgrand 2017-06-07T13:50:12.260534Z

Let forget the dispatch order for now.

cgrand 2017-06-07T13:52:34.315151Z

But about :echo: make send! takes a callback, the callback is called when :echo is received, and it sets the real callback in your callbacks atom.

cgrand 2017-06-07T13:54:44.365932Z

my concern about dispatch order is that this “real” callback may be stateful (or have an explicit passed (reduce-style) state) and used to process all the messages (`:eval`, :outetc.) for one form

pesterhazy 2017-06-07T14:03:36.577050Z

right that'll work

pesterhazy 2017-06-07T14:04:33.600161Z

haven't run into issues with stateful callbacks yet

pesterhazy 2017-06-07T14:05:09.614175Z

my plan was to worry about that when I start seeing related issues

pesterhazy 2017-06-07T14:07:27.668785Z

do you have a concrete example of such an issue?

cgrand 2017-06-07T14:40:28.480414Z

It's not much of an issue it's just that I think that it could be useful to process related messages together in stateful functions.

cgrand 2017-06-07T20:15:46.149152Z

Given how :echo evolved I'm tempted to rename it :read

dominicm 2017-06-07T20:24:12.318467Z

When evaluating, is it possible to mark the position in a file that it is? (This might be a general clojure question)

cgrand 2017-06-07T20:33:30.510625Z

I'm not sure I understand. Do you mean saying "eval this form which was read at line 42 of foo.clj"?

cgrand 2017-06-07T20:37:53.598953Z

You have to set a couple of dynvars for the file name. Line numbers are metadata to most read forms – but you can't explicitly set them in the source because reading overwrites them.

dominicm 2017-06-07T21:41:09.771978Z

You understand correctly what I'm asking.

dominicm 2017-06-07T21:41:36.779504Z

I don't fully understand what you mean about metadata. But I think it's important that they can be set.

dominicm 2017-06-07T21:45:04.832977Z

So, as a client to unrepl, should I set the line no & column?

cgrand 2017-06-07T23:48:33.281269Z

See :set-source