This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-04-25
Channels
- # announcements (4)
- # babashka (3)
- # beginners (79)
- # biff (4)
- # calva (17)
- # cider (18)
- # clj-kondo (21)
- # cljdoc (45)
- # cljs-dev (14)
- # cljsrn (9)
- # clojure (90)
- # clojure-europe (86)
- # clojure-italy (3)
- # clojure-nl (3)
- # clojure-portugal (1)
- # clojure-uk (9)
- # clojurescript (20)
- # code-reviews (23)
- # conjure (14)
- # cursive (12)
- # datascript (12)
- # emacs (5)
- # events (2)
- # fulcro (13)
- # gratitude (1)
- # holy-lambda (9)
- # lambdaisland (2)
- # malli (6)
- # nbb (1)
- # nextjournal (2)
- # nrepl (30)
- # off-topic (63)
- # pathom (1)
- # portal (24)
- # reagent (5)
- # reitit (13)
- # releases (2)
- # remote-jobs (1)
- # sci (90)
- # shadow-cljs (49)
- # spacemacs (5)
- # sql (13)
- # testing (20)
- # tools-build (17)
- # xtdb (27)
I'm trying to map my namespaces to sci namespaces automatically, but I'm messing something up:
(def sci-opts {:namespaces {'user (copy-ns 'user (sci/create-ns 'user))}})
Any pointers? I'm sure I'm doing something obviously stupid.
although we could allow that in the macro to just take the second element if the argument is (quote user)
Well, I don't think there's necessarily any problem with the existing API. I think it's just that I don't have an example to reference, and I'm porting some existing code from using the self-hosted cljs to sci, so honestly things are a bit chaotic. But I'm hopefully almost there!
@borkdude So I see that sci doesn't (yet) support deftype
- what will happen if you load a namespace that directly or indirectly uses deftype
?
@pmooser That's not a problem. You just cannot (at the moment) execute deftype
from source
So I'm still on my journey of playing with copy-ns
and see if I can replace my use of self-hosted cljs. I'm noticing that with a specific namespace only, when I try to use copy-ns
, I get an error, and I was wondering if that could be caused by trying to copy a namespace containing a deftype.
So
(deftype Foo [])
(defn foo [] (->Foo))
and
(sci/eval-string "(foo)" {:namespaces {'user {'foo foo}}})
just works.@pmooser I've had some of these issues too, it usually happens when there are protocols in that namespace.
So if I can ask, how does your foo
example you pasted above work, if sci
doesn't support deftype?
you can also just use copy-var
- it's a bit more boilerplate, but should work more robustly
yes, because SCI has a reference to the foo
function, it can just call that and then the rest within that function call isn't interpreted anymore, it's compiled code, so SCI isn't involved in that
Well, in this particular case, this namespace exports relatively few things, and the useful ones are things that return deftype instances, so that sounds like maybe the only real solution is to omit the namespaces, unless I'm not understanding what is happening.
So even though it doesn't support it, it might be able to call it, but not in some kind of dynamic fashion.
Sure, ok. I apologize if my questions are a bit repetitive - I'm just trying to wrap my head around it.
I'd be interested in a repro of copy-ns + protocol behavior, so it can be fixed though
I can't reproduce it like this:
foo=> (defprotocol Foo (foo [this]))
foo=> (require '[sci.core :as sci])
nil
foo=> (sci/copy-ns foo (sci/create-ns 'foo))
{Foo #'Foo, foo #'foo}
Ah:
foo=> (deftype Dude [])
foo/Dude
foo=> (sci/copy-ns foo (sci/create-ns 'foo))
Unexpected error (NullPointerException) macroexpanding sci.core/copy-ns at (<cljs repl>:1:1).
null
I didn't have any luck with :exclude
and copy-ns yet - I tried just listing all my protocols and types but it didn't seem to work.
I'm trying to figure out how to reproduce it, since I can't just start commenting out pieces of it, since it's a vital part of my program. Ah, let me try physically copying that ns to another file, seeing if I can reproduce it there, and just start nuking parts of the file until the error goes away.
@borkdude Here is a minimal reproduction:
(ns my.ns)
(defprotocol PFoo
(do-foo [this]))
(defrecord Foo [arg]
PFoo
(do-foo [this] 100))
It doesn't like the defrecord
there and I'm not sure the protocol has anything to do with it.
ok, now works:
ClojureScript 1.10.914
cljs.user=> (ns my.ns)
(defprotocol PFoo
(do-foo [this]))
(defrecord Foo [arg]
PFoo
(do-foo [this] 100))
nil
my.ns=> my.ns=> false
my.ns=> my.ns=> my.ns/Foo
my.ns=> (require '[sci.core :as sci])
nil
my.ns=> (sci/copy-ns my.ns (sci/create-ns 'my.ns))
{PFoo #'my.ns/PFoo, do-foo #'my.ns/do-foo, ->Foo #'my.ns/->Foo, map->Foo #'my.ns/map->Foo}
Sorry, I'm having some kind of issue (not related to the new version, just related to getting it):
Cloning:
Checking out: at 03819bad08547a426c041e4031010f4ef75dfc0b
Error building classpath. Unable to compare versions for org.babashka/sci: {:mvn/version "0.3.4", :deps/manifest :mvn} and {:git/url "", :git/sha "03819bad08547a426c041e4031010f4ef75dfc0b", :deps/manifest :deps, :deps/root "/Users/pmooser/.gitlibs/libs/org.babashka/sci/03819bad08547a426c041e4031010f4ef75dfc0b"}
Do you have any advice for using this in the context of interactive development, like with shadow-cljs and hot code reloading? Is there a way to keep the existing sci environment but maybe update the namespace mappings?
@pmooser Yes:
• create a sci context with sci/init
using defonce
and store that context in a mutable ref (atom or volatile)
• evaluate using eval-string*
+ that context
• in the REPL, update mapping using sci/merge-opts
and swap! the new context into the mutable ref
So something like:
(defonce sci-ctx (atom (sci/init {...initial options ...}))
(eval-string* @sci-ctx "(+ 1 2 3)")
(swap! sci-ctx sci/merge-opts {:namespaces {'foo {'bar (fn ...)}}})
@pmooser can I ask what type of app you're working on? closed or open source? domain? just curious
I think this kind of project is important for the clojure ecosystem. Rich used to talk about clojure-in-clojure, but I think that's kind of never happening, and the self-hosted cljs is such a marginalized experience that any time something weird happens with it and shadow-cljs, immediately all fingers always point to the self-hosted cljs code.
im looking at SCI as a drop-in replacement for clojail.
in the past i used clojail to run expressions from a large collection of #clojure IRC logs in a sandbox with a java security policy in case there was anything malicious.
one thing i immediately noticed is that SCI doesn’t have a notion of timeout
when eval’ing a string. given a lot of my inputs are things like (map inc (range))
and similar expressions which will run forever, i need some way of short-circuiting if it hasn’t returned in say 10sec. is that something SCI can accommodate?
@devn That's correct, SCI does not have a timeout, you should use a host-specific wrapper for this, e.g. in a JVM use a Thread with .stop or so
related: capturing *out*
in addition to value is possible right?
for example: (time (inc 1))
’s value and output
@devn yes, sci has its own *out*
which you can bind to clojure's *out*
if you want:
(sci/binding [sci/out *out*] ....)
(sci/with-out-string ....)
clojail does seem quite a bit more permissive, but im going to give SCI a try on the input and see how it works out
time
is something we can probably just add.
it is available in babashka which uses SCI. you can copy it from there for now.
https://github.com/babashka/babashka/blob/9727cabaf3499c7129657cb91b097c92152fe144/src/babashka/impl/clojure/core.clj#L17
This also works:
user=> (sci/binding [sci/out *out*] (sci/eval-string "(time (inc 1))" {:classes {'java.lang.System System} :namespaces {'clojure.core {'time (sci/copy-var time (sci/create-ns 'clojure.core))}}}))
"Elapsed time: 0.262606 msecs"
2
i jumped in here like “ok, time to reboot this old bit-rotted project” and then got flung into “oh right, what i allow and don’t is actually half the project”
ok one more question for ya: in your example above where you bind out — i want to produce a map containing the input expr, the value of the expr, and the out value