This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-09-12
Channels
- # announcements (2)
- # architecture (1)
- # aws (22)
- # babashka (2)
- # beginners (39)
- # bristol-clojurians (2)
- # cider (1)
- # clj-kondo (12)
- # cljfx (75)
- # cljs-dev (16)
- # clojure (51)
- # clojure-berlin (1)
- # clojure-france (4)
- # clojure-nl (2)
- # clojure-norway (36)
- # clojurescript (5)
- # community-development (8)
- # data-science (1)
- # datomic (4)
- # emacs (4)
- # fulcro (7)
- # jobs-discuss (7)
- # juxt (1)
- # nrepl (3)
- # off-topic (38)
- # reitit (1)
- # ring (7)
- # sci (79)
- # shadow-cljs (5)
- # sql (15)
- # tools-deps (22)
- # uncomplicate (7)
- # vrac (1)
- # xtdb (18)
@djblue I think I've got IDeref working now in sci and bb (both branches are called IDeref):
user=> (defrecord Foo [x] clojure.lang.IDeref (deref [this] (prn :deref!) x))
user=> @(->Foo :x)
:deref!
:x
This warrants some refactoring/renaming but that's mainly just cleaning upThis is how I'm using it https://github.com/djblue/portal/blob/master/src/portal/runtime/client/jvm.clj#L15
What is https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/IAtom2.java#L13 used for?
@djblue I just pushed IAtom to babashka / sci (both still in the IDeref branch):
$ rlwrap lein bb
Babashka v0.2.1-SNAPSHOT REPL.
Use :repl/quit or :repl/exit to quit the REPL.
Clojure rocks, Bash reaches.
user=> (def x (reify clojure.lang.IAtom (swap [_ f] (f 1))))
#'user/x
user=> (swap! x inc)
2
I have tests for defrecord, so in theory it should work. Also implementing both interfaces should also work, but there could be bugs still
Maybe you can make a repro for me and post it in the issue: https://github.com/borkdude/sci/issues/401
So I cd into the sci directory of babashka and pulled the IDeref branch (fe4637c821fea0d5972c5b99fa6279ef79d3f1ad)
Anyway, I'm getting errors on swap as well. I'll fix it tomorrow, thanks for the repro
This works:
(defrecord Example []
clojure.lang.IDeref
(deref [this] :deref)
clojure.lang.IAtom
(reset [this new-value] :reset)
(swap [this f] :swap)
#_(swap [this f a] :swap)
#_(swap [this f a b] :swap)
#_(swap [this f a b args] :swap)
#_(compareAndSet [this oldv newv] :compare-and-set))
(prn @(->Example))
(prn (reset! (->Example) 1))
(prn (swap! (->Example) inc))
Should also work in CLJS:
cljs.user=> (sci/eval-string "(defrecord Foo [x] IDeref (-deref [this] (prn :deref!) x)) @(->Foo :x)" {:bindings {'prn prn}})
:deref!
:x
Hello, I am wondering if there is a reason why the sci's only api function is eval-string
? It seems I can do:
(defn my-eval-form [form opts]
(let [ctxt (opts/init opts)
ctxt (assoc ctxt :id (or (:id ctxt) (gensym)))]
(vars/with-bindings {vars/current-ns @vars/current-ns}
(eval-form ctxt form))))
Is that a bad idea?@jeremys that will only work for some code, e.g. not for code that contains certain aliases, unless the aliases in your form correspond to the aliases in sci
I've been thinking of exposing the sci parser as well, so you can first parse a string and then feed it to eval-form
. This is what you usually need to do in a REPL.
Random forms don't have metadata that sci needs for locations in error locations, which is another problem
note that all sci.impl namespaces are implementation details that might change, they are not a public API
If you can explain the background of your question/problem, that would maybe help improving the API
Ok thanks, the thing is I am working on a https://github.com/JeremS/textp-reader and my reader returns clojure data directly.
I'll take a look at load-string
too. I haven't looked very long at sci's code and I didn't know that metadata is used on the evald forms. Although it makes sense...
under the hood it uses this clojure parser for location metadata: https://github.com/borkdude/edamame
I use tools.reader to read the actual forms. May be I could use edamame to have the correct metadata, and feed the forms as data.
but this is why I was suggesting exposing the sci reader, since it works together with the sci ctx and will set the right aliases based on your ns form etc
so you could do:
(def ctx (sci/init opts))
(def form (sci/parse-next ctx stream))
(def result (sci/eval ctx form))
a similar thing is needed when you want to implement your own REPL based on sci: https://github.com/borkdude/babashka/blob/3a06297e5ce58f87309df86d9d5759d830b82275/src/babashka/impl/repl.clj#L46 so this needs to be exposed anyway (cc @plexus)
but if you don't use any aliases or namespaces then feeding edamame stuff in it would also work
yeah the way my reader works is in 2 phases, instaparse separates plain text from clojure text. The clojure text is then fed to tools.reader to get a form. From there I have a list of edn data that's good to be evaled in sequence. Now I'll see If I can used edamame to read he forms instead of tools reader.
I'll try different approaches later. The parser allows for stuff like
β(defn template [x]
βdiv [:class βtext{class1 class2} ]
{
Some text and crazy recursion: β(str (+ 2 x) βtext{times.})β
})β
[(defn
template
[x]
(div
{:tag :tag-args-clj,
:content
[:class (text {:tag :tag-args-txt, :content ["class1 class2"]})]}
{:tag :tag-args-txt,
:content
["\n Some text and crazy recursion: "
(str (+ 2 x) (text {:tag :tag-args-txt, :content ["times."]}))
"\n "]}))]
the diamonds I find a bit confusing, why not just parens? but I'll leave that up to you
the idea comes from https://docs.racket-lang.org/pollen/ which is derived from https://docs.racket-lang.org/pollen/. The β
char is used in pollen... Well I didn't just copy the character, it has the advantage of having no meaning in clojure proper.
The basic Idea is that you could have something like latex exept clojure would be used instead of latex...
I gotta go, if you want I let you know how my experiments go. Thank you for the help!
@jeremys I exposed a preliminary API with commit 7894773dd071e010483b220d135c1a935a679458
:
user=> (require '[sci.core :as sci] :reload-all)
nil
user=> (def ctx (sci/init {}))
#'user/ctx
user=> (def form (sci/parse-string ctx "(+ 1 2 3)"))
#'user/form
user=> form
(+ 1 2 3)
user=> (sci/eval ctx form)
6
user=> (def multiple-forms "(+ 1 2 3) (+ 4 5 6)")
#'user/multiple-forms
user=> (def reader (sci/reader multiple-forms))
#'user/reader
user=> (def next-form (sci/parse-next ctx reader))
#'user/next-form
user=> next-form
(+ 1 2 3)
user=> (sci/eval ctx next-form)
6
user=> (def next-form (sci/parse-next ctx reader))
#'user/next-form
user=> next-form
(+ 4 5 6)
user=> (sci/eval ctx next-form)
15
user=> (def next-form (sci/parse-next ctx reader))
#'user/next-form
user=> next-form
:sci.core/eof
Also made this issue: https://github.com/borkdude/sci/issues/404
@borkdude I made some quick tests with eval, it seems like I can eval the code I'd like to without changing my reader. I still have to put a coherent API together but it seems like sci will work wonders for what I have in mind. I'll report back when it's done. Thanks!
Added a nodeJS REPL test example https://github.com/borkdude/sci/blob/d0543150e1493abcb29c8c9aaf743b1622715925/test-resources/sci/examples/repl.cljs