unrepl

discussing specification of an edn-based repl and its implementations.
volrath 2017-11-22T09:25:38.000194Z

@cgrand good morning, last night I did a more generic implementation of elision expansion, and I noticed something weird for maps, that I think it's related to the into used in unrepl.print/ednize

cgrand 2017-11-22T09:25:52.000052Z

tell me

volrath 2017-11-22T09:25:56.000147Z

[14] user=> (zipmap (map char (range 97 (+ 97 11))) (range 11))
> {\a 0 \b 1 \c 2 \d 3 \e 4 \f 5 \g 6 \h 7 \i 8 \j 9 ...}
[15] user=> (zipmap (map char (range 97 (+ 97 11))) (range 11))
> { ... \a 0 \b 1 \c 2 \d 3 \e 4 \f 5 \g 6 \h 7 \i 8 \j 9}
[16] user=> (zipmap (map char (range 97 (+ 97 11))) (range 11))
> {\a 0 \b 1 \c 2 \d 3 \e 4 \f 5 \g 6 \h 7 \i 8 \j 9 ...}
[17] user=> (zipmap (map char (range 97 (+ 97 11))) (range 11))
> {\a 0 \b 1 ... \c 2 \d 3 \e 4 \f 5 \g 6 \h 7 \i 8 \j 9}
[18] user=> (zipmap (map char (range 97 (+ 97 11))) (range 11))
> {\a 0 \b 1 \c 2 \d 3 \e 4 ... \f 5 \g 6 \h 7 \i 8 \j 9}
[19] user=> (zipmap (map char (range 97 (+ 97 11))) (range 11))
> {\a 0 \b 1 \c 2 \d 3 \e 4 \f 5 \g 6 ... \h 7 \i 8 \j 9}
[20] user=> (zipmap (map char (range 97 (+ 97 11))) (range 11))
> {\a 0 \b 1 \c 2 \d 3 \e 4 \f 5 \g 6 \h 7 \i 8 \j 9 ...}

volrath 2017-11-22T09:26:02.000208Z

take a look at the ...

volrath 2017-11-22T09:26:14.000279Z

it changes positions

volrath 2017-11-22T09:26:25.000411Z

non deterministicly afaik

volrath 2017-11-22T09:26:51.000518Z

it always holds the last char though

cgrand 2017-11-22T09:28:29.000311Z

in elisp you read maps as lists or alists?

volrath 2017-11-22T09:28:54.000050Z

hah.. good point

volrath 2017-11-22T09:28:56.000051Z

nevermind

volrath 2017-11-22T09:28:59.000096Z

it can be the parser

cgrand 2017-11-22T09:29:36.000001Z

At some point I thought “it doesn’t matter” but if it makes life too hard...

volrath 2017-11-22T09:29:49.000278Z

yes it does

volrath 2017-11-22T09:30:04.000133Z

but pretty sure it's the parser, I'll take a look

volrath 2017-11-22T09:30:46.000213Z

oh no

volrath 2017-11-22T09:30:49.000509Z

it isn't

volrath 2017-11-22T09:31:07.000201Z

(zipmap (map char (range 97 (+ 97 11))) (range 11))
[:read {:from [1 1], :to [2 1], :offset 0, :len 52} 1]
[:started-eval {:actions {:interrupt (unrepl.replG__24139/interrupt! :session24584 1), :background (unrepl.replG__24139/background! :session24584 1)}} 1]
[:eval {\a 0, #unrepl/... {:get (unrepl.replG__24139/fetch :G__24587)} #unrepl/... nil, \b 1, \c 2, \d 3, \e 4, \f 5, \g 6, \h 7, \i 8, \j 9} 1]
[:prompt {:file "unrepl-session", :line 2, :column 1, :offset 52, clojure.core/*warn-on-reflection* false, clojure.core/*ns* #unrepl/ns user}]

volrath 2017-11-22T09:31:19.000152Z

there the elision is 2nd

cgrand 2017-11-22T09:31:45.000323Z

yeah I know — I wasn’t blaming your parser, just trying to figure out things.

volrath 2017-11-22T09:32:41.000211Z

haha no worries, me too.

cgrand 2017-11-22T09:33:21.000057Z

so my position was “it doesn’t matter — let revisit when clients authors show up with pitchforks”

cgrand 2017-11-22T09:33:26.000368Z

do you have a fork?

volrath 2017-11-22T09:34:00.000076Z

no

cgrand 2017-11-22T09:34:04.000315Z

phew

volrath 2017-11-22T09:34:09.000133Z

haha

volrath 2017-11-22T09:34:41.000417Z

I can fix it on my side though, I can just make sure to print the ... at the end

volrath 2017-11-22T09:34:47.000560Z

at least for now

cgrand 2017-11-22T09:34:52.000302Z

yeah but...

cgrand 2017-11-22T09:37:06.000123Z

the current solution is bad for all: • those who read maps as maps can’t lookup for elision because the key is random • those who read maps as list can’t rely on it being at the end. So in both cases you have to do a linear scan (yeah I know reading a map is linear anyway) instead of a get or looking at the last value

volrath 2017-11-22T09:38:22.000116Z

so you're thinking on changing the structure for ednizedkvs? kind of like with ednized strings

cgrand 2017-11-22T09:39:44.000328Z

not going that far but requiring the server to print the elisions last AND to reverse padding and actual elision, so that the key would always be #unrepl/... nil

volrath 2017-11-22T09:41:14.000536Z

ok

volrath 2017-11-22T09:41:34.000207Z

sounds good

baptiste-from-paris 2017-11-22T13:02:49.000230Z

it’s really a genuine question but why do you need this-as if you don’t use it ?

baptiste-from-paris 2017-11-22T13:02:50.000386Z

e.G

baptiste-from-paris 2017-11-22T13:02:58.000186Z

(defn make-pr-str-stream
  []
  (let [transform (fn [v enc cb]
                    (this-as this
                      (cb nil (prn-str v))))]
    (Transform. #js {:writableObjectMode true
                     :transform transform})))

cgrand 2017-11-22T13:34:30.000170Z

dead code left after refactoring?

cgrand 2017-11-22T13:50:42.000525Z

@baptiste-from-paris check it out ^^

baptiste-from-paris 2017-11-22T13:57:09.000460Z

done

cgrand 2017-11-22T14:21:24.000675Z

I dusted off a text layout algorithm that I adapted to data, here is the result https://gist.github.com/cgrand/fd67ff7459b1a446a14a533095261c14

cgrand 2017-11-22T14:21:46.000506Z

So it’s an experiment in compact pretty printing

cgrand 2017-11-22T14:25:33.000544Z

Do you like the produced layouts?

volrath 2017-11-22T14:33:11.000198Z

what would be the context? where/how do you see this coming into play?

cgrand 2017-11-22T14:38:20.000018Z

I could see it used by unravel to format values.

volrath 2017-11-22T14:42:30.000070Z

cool... I don't know the details of the implementation but I guess it should take care special care of pair of values (kvs, tagged literals)

volrath 2017-11-22T14:42:53.000524Z

would love to see it inside unravel 🙂

cgrand 2017-11-22T15:00:07.000922Z

Good point about pairs. The algorithm lays out unbreakable spans (and spans have an indent value). A first naive approach would be to merge the last span of the key and the first one of the value and add an extra indent for the value.

cgrand 2017-11-22T15:34:13.000555Z

Actually I think there’s a better way

volrath 2017-11-22T15:56:22.000398Z

I think I found a bug with blob customization (trying it right now)

volrath 2017-11-22T15:56:34.000208Z

one second

volrath 2017-11-22T15:57:18.000612Z

so, the unrepl_make_blob task reads the session action map with {:default tagged-literal}

volrath 2017-11-22T15:57:32.000797Z

the thing is that this outputs the actual tagged literal into the blob

volrath 2017-11-22T15:58:08.000622Z

it puts something like :my.own/action (some.ns/fun #unrepl/param :bar)

volrath 2017-11-22T15:59:10.000482Z

whereas what's seem to be need is something like :my.own/action (some.ns ~(tagged-literal 'unrepl/param :bar))

volrath 2017-11-22T16:00:08.000097Z

I tried to fix it but couldn't to be hones I couldn't get it to work and i think it might be an easy fix, so I rather ask

volrath 2017-11-22T16:00:48.000837Z

the easiest way to reproduce the problem is by simply generating a new custom blob and try to upgrade to unrepl with it

volrath 2017-11-22T16:01:12.000063Z

it will raise a read error because the #unrepl/param is not recognized

cgrand 2017-11-22T16:01:45.000777Z

AFK could you show me the relevant portion of the generated blob?

volrath 2017-11-22T16:02:25.000364Z

sure, one moment

volrath 2017-11-22T16:03:47.000418Z

:actions (into
                                                                {:exit `(exit! ~session-id)
                                                                 :start-aux `(start-aux ~session-id)
                                                                 :log-eval
                                                                 `(some-> ~session-id session :log-eval)
                                                                 :log-all
                                                                 `(some-> ~session-id session :log-all)
                                                                 :print-limits
                                                                 `(let [bak# {:unrepl.print/string-length p/*string-length*
                                                                              :unrepl.print/coll-length *print-length*
                                                                              :unrepl.print/nesting-depth *print-level*}]
                                                                    (some->> ~(tagged-literal 'unrepl/param :unrepl.print/string-length) (set! p/*string-length*))
                                                                    (some->> ~(tagged-literal 'unrepl/param :unrepl.print/coll-length) (set! *print-length*))
                                                                    (some->> ~(tagged-literal 'unrepl/param :unrepl.print/nesting-depth) (set! *print-level*))
                                                                    bak#)
                                                                 :set-source
                                                                 `(unrepl/do
                                                                    (set-file-line-col ~session-id
                                                                      ~(tagged-literal 'unrepl/param :unrepl/sourcename)
                                                                      ~(tagged-literal 'unrepl/param :unrepl/line)
                                                                      ~(tagged-literal 'unrepl/param :unrepl/column)))
                                                                 :unrepl.jvm/start-side-loader
                                                                 `(attach-sideloader! ~session-id)}
                                                                {:my.own/action (unrepl.repl/ensure-ns (foo/bar #unrepl/param :baz))})

volrath 2017-11-22T16:05:01.000036Z

there, now i'ts better

volrath 2017-11-22T16:06:18.000149Z

every other action's params are ~(tagged-literal 'unrepl/param :some/name), and the generated by the customization is #unrepl/param :some/name

volrath 2017-11-22T16:07:59.000321Z

if I try to upgrade with that blob, I get

$> cat test-blob.clj - | nc localhost 5555
user=> [:unrepl.upgrade/failed]
RuntimeException No reader function for tag unrepl/param  clojure.lang.LispReader$CtorReader.readTagged (LispReader.java:1245)

volrath 2017-11-22T16:08:55.000058Z

by now I'm just using ~(tagged-literal 'unrepl/param :my/param) to generate a custom blob, but maybe this is an easy fix

cgrand 2017-11-22T16:09:01.000001Z

You are right

cgrand 2017-11-22T16:10:57.000300Z

It’s a rather easy fix: need a reader and a record for unrepl/param

volrath 2017-11-22T16:14:19.000572Z

yeah the record for the unrepl/param was the one I didn't figure out, I had problems with the ~, I forgot about unquote

volrath 2017-11-22T16:15:16.000830Z

I'll submit a PR later tonight, I'm heading out.. thanks for the help!

cgrand 2017-11-22T16:56:25.000054Z

@volrath there’s a way simpler fix: pass a default tag reader to read in gen-blob.

baptiste-from-paris 2017-11-22T17:45:11.000335Z

what blob.clj is used for ?

volrath 2017-11-22T17:45:28.000037Z

@cgrand Now I'm afk, but i'm under the impression that's a clojure.core/read, not a clojure.edn/read, is it possible to add readers to that function? If so, that would definitely be better.

baptiste-from-paris 2017-11-22T17:46:51.000393Z

humm lein unrepl-make-blob strange ^^

baptiste-from-paris 2017-11-22T17:47:47.000053Z

ohhhhh https://github.com/Unrepl/unrepl/blob/master/UPGRADE.md

volrath 2017-11-22T17:51:39.000654Z

Just to be sure, are you talking about this read? https://github.com/Unrepl/unrepl/blob/master/tasks/leiningen/unrepl_make_blob.clj#L15

baptiste-from-paris 2017-11-22T17:52:33.000473Z

so that’s what transfors classical nREPL message in unrepl ones

cgrand 2017-11-22T19:14:25.000276Z

There’s no nREPL involved!

cgrand 2017-11-22T19:17:00.000142Z

Hey I’ve got a new one: unREPL the underground REPL

baptiste-from-paris 2017-11-22T20:08:01.000590Z

so you telling me that I understood all wrong ^^

baptiste-from-paris 2017-11-22T20:08:09.000056Z

#embarrassed

cgrand 2017-11-22T20:11:07.000031Z

when we say “repl” it’s a plain repl (generally socket one so clojure 1.8) as provided by clojure

baptiste-from-paris 2017-11-22T20:11:21.000008Z

oh

baptiste-from-paris 2017-11-22T20:11:23.000082Z

ok ok

cgrand 2017-11-22T20:13:32.000414Z

However as a proof of concept we have the nREPL-bridge project which recreates a plain repl on top of nREPL. Then you can upgrade it to unrepl.

baptiste-from-paris 2017-11-22T20:31:33.000027Z

okay but blob.clj is transforming REPL message to unrepl protocol right ?

baptiste-from-paris 2017-11-22T20:31:40.000056Z

or I am completly lost

volrath 2017-11-22T20:42:11.000071Z

@cgrand I'm back, I don't see how I can pass a default tag reader to clojure.core/read, not sure if I'm missing out on something... I tried to go with the other approach, having a tag reader for #unrepl/param but I'm a bit blocked. Best I can get is

{:readers {'unrepl/param (fn [param-kw]
                                        '(unquote (tagged-literal 'unrepl/param param-kw)))}
              :default tagged-literal}
But then the parent form (list 'unrepl.repl/ensure-ns v) would have to be syntax-quoted..

cgrand 2017-11-22T22:23:57.000320Z

*default-data-reader-fn* but I’m blocked too by a subtle error related to pr-dup

cgrand 2017-11-22T22:32:44.000052Z

Not so subtle, it’s just too late.