This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-11-22
Channels
- # announcements (2)
- # babashka (64)
- # beginners (41)
- # calva (4)
- # cider (1)
- # clj-kondo (78)
- # cljdoc (31)
- # cljsrn (4)
- # clojars (2)
- # clojure (109)
- # clojure-germany (1)
- # clojure-italy (8)
- # clojure-nl (2)
- # clojure-spec (8)
- # clojure-uk (28)
- # clojurescript (61)
- # code-reviews (2)
- # cryogen (2)
- # cursive (23)
- # datomic (21)
- # duct (15)
- # fulcro (37)
- # graalvm (17)
- # graphql (3)
- # jackdaw (3)
- # joker (11)
- # lein-figwheel (4)
- # malli (42)
- # off-topic (97)
- # pathom (4)
- # pedestal (1)
- # portkey (3)
- # re-frame (7)
- # reagent (13)
- # reitit (2)
- # shadow-cljs (54)
- # spacemacs (1)
i just watched a documentary on time space and naturally i'm wondering if time travel is possible is every language mutable?
Mutability is just time travelling back to a value you already declared, and having to constantly deal with the butterfly effect
hmm... but there is a quantifiable number of butterfly effects though right, directly tied to the number of values declared ... so technically that's still vars * butterfly-paths number of immutable variables ?
hi! bashing my head against trying to read the filesize of a binary file in resources/
everything I try either explodes, or gives me the wrong value (as it's interpreting the file as an encoded stream)
but inside a jar this gives Exception in thread "main" java.lang.IllegalArgumentException: Not a file: jar:file:/full/path/to/target/uberjar/my.jar!/libspire.so
Nah, unless I'm missing something, the problem should have been that io/resource
is basically going to get the java URL
for the file, which is going to look something like jar:file:/full/path/to/target/uberjar/my.jar!/libspire.so
. io/file
is going to try to wrap this URL
with the java File
object, which I believe is expecting a legitimate path, not a path into a jar. So, it fails and gives that error. Anyone feel free to correct me on any of those details, as there's a few parts I'm hazy on myself, although that should be the jist
io/file is for files on disk and doesn't work for jar resources
slurp is for text, and doesn't work for binary input
try creating an InputStream from the resource and checking .available maybe?
user=> (.available (io/input-stream (io/resource "clojure/core.clj")))
263653
I don't have binary jar resources handy off the top of my head, but that method is binary clean
Hi, I have a question regarding ordering of keys in map.
I have a map, say my-map
in the following snippet, I wanted to understand if the order of keys and vals will be preserved in the results of (keys my-map)
and (vals my-map)
no matter how many times I call them, as long as I supply the same my-map
.
(def my-map {:name "Alice" :age 30 :place "BLR"})
(keys my-map) => (:name :age :place)
(vals my-map) => ("Alice" 30 "BLR")
Or, will the order in the results of (keys my-map)
and (vals my-map)
change because my-map
cannot guarantee its own order while calling (keys my-map)
or (vals my-map)
?
I am currently using https://github.com/clj-commons/ordered library to first make my-map
an ordered map, then apply keys
and vals
operations to ensure required ordering.the order is the same for multiple calls to an identical map, but as soon as you add or remove an element the order is not guaranteed
if you’re using ordered then the the maintains the insertion order of the elements, which may or may not be what you want
@retrogradeorbit I am curious, what happens if you try (.count (io/input-stream (io/resource "libspire.so")))
(I'm half sending this out blind since I don't have a repl and similar situation up on my end)
spire.core=> (.count (io/input-stream (io/resource "libspire.so")))
Execution error (IllegalArgumentException) at spire.core/eval8772 (form-init2733631356982990701.clj:1).
No matching field found: count for class .BufferedInputStream
spire.core=> (count (io/input-stream (io/resource "libspire.so")))
Execution error (UnsupportedOperationException) at spire.core/eval8774 (form-init2733631356982990701.clj:1).
count not supported on this type: BufferedInputStream
i looked at https://stackoverflow.com/questions/34360826/get-the-size-of-a-resource and https://stackoverflow.com/questions/9694754/clojure-how-to-get-the-path-of-a-running-jar-root-source-directory but it's nasty
i haven't tried but it seems you need to get a JarFile
, then getEntry
your resource and then you can getSize
or getCompressedSize
. i couldn't yet get past the hurdle of the JarFile
so not sure if this works at all...
alright one more thing I'm just curious to see
(with-open [in (io/input-stream (io/resource "libspire.so"))
out (.ByteArrayOutputStream.)]
(io/copy in out)
(.size out))
without copying https://clojurians.slack.com/archives/C03S1KBA2/p1574445620432500?thread_ts=1574410028.393100&cid=C03S1KBA2
Well, one reason I avoided available is
Returns an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking by the next invocation of a method for this input stream.
And specifically
Note that while some implementations of InputStream will return the total number of bytes in the stream, many will not. It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream.
I was gambling that the resource implementation of inputstream would know the full size (where other implementations are allowed not to)
I would like to find another method that finds the full size without a linear time procedure though.
off the top of my head, if that information is not cached somewhere (I say 'cached' in the abstract; stored) already, I do not think that would be possible, as at some point something is going to have to read through and basically count it for the first time. As always, though, I want to think on it to make sure I'm not missing something
the information is in the jar itself
or the filesystem if it's read off disk
so here https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#available() "many will not" here http://www.docjar.com/docs/api/java/io/FilterInputStream.html#available (the inputstream type we end up with via JarURLCOnnection$JarURLINputStream) there's no such concern - if I read correctly
It also doesn't promise to report the full size, just the amount that it promises can be read without blocking. We know that the jar file we are reading from carries this information as a precise number, but the api doesn't expose that. The safer thing is either to O(n) copy the whole thing, or to read up to N bytes at a time, in a loop, and then calculate the total amount consumed at the end(?)
ah damn, I should have thrown that out earlier ahahah I figured it would, I had this answer right after I wrote the first suggestion, and I figured the first suggestion wouldn't work as it was (as count is a member of BufferedInputStream I believe, but not a public one), but I wanted to test it on my end first as I don't like shouting out too many things blind
on my end, I have a workflow at times that allows me to be a bit lazy (I guess not just in programming) where instead of looking up something or thinking out the answer, I'll test a few answers that I know will allow me to narrow down the overall answer without having to think about it, but I feel self conscious when I use that method while helping someone because if I leave in the middle without solving the question, its going to look like I was just guessing ahahaha
is there a best practice regarding dependencies for clojure projects ? I have a cross-platform project (js, jvm). For the Js side, the jvm dependencies would make no sense therefore I marked them as :provided
, however this adds an extra burden to the end users of the jvm side which now have to add two dependencies instead of one to use the project 😕 . Any ideas/opinions on this topic ?
Split the project?
then the burden goes to me 😓. Ideally I am searching for a way to say “jvm dependencies” not for clojurescript 🙂
When depending on a deps.edn project with :local-root, is there any way to get the dependency’s test paths and test dependencies (specified via the :test alias) added to the project?
There are a variety of ideas possible for this but nothing at the moment
I'm trying to generate a Java file and import it later in the same process, but for some reason it doesn't work:
(io/resource "hgs/platform/abc/antlr/ABCMusicLexer.java")
=> #object[.URL 0x6b11a979 "file:/.../hgs/platform/abc/antlr/ABCMusicLexer.java"]
(import '(hgs.platform.abc.antlr ABCMusicLexer))
Execution error (ClassNotFoundException) at .URLClassLoader/findClass (URLClassLoader.java:471).
hgs.platform.abc.antlr.ABCMusicLexer
Is it possible at all? Am I doing something wrong?1. you can't import a java file, only a class can be imported 2. the class can only be imported if the classloader can find it (usually you want it to be loadable via a classpath entry, not always an option if the file doesn't exist at startup)
also the '
isn't needed by import (it doesn't hurt anything either, but it isn't needed)
you could look at how clojure dynamically creates new classloaders that can find the classes it creates at runtime, I'm not sure what the best practice is for what you are doing, but what clojure does clearly works
ediited the thing about classpath - if you have a known destination dir (eg. how clojure can use target/
for files on disk) you could start up with that on classpath, and put classes you make there
OK, seems to be a task that isn't worth it since it's a one-off one. If I need something like this for a more serious task, I will probably be able to use ztellman/virgil
.
oh yeah, I should have remembered virgil
It seems like there is a time between switching namespaces that symbols do not get qualified with the current ns anymore:
$ clj
Clojure 1.10.1
user=> (def x 1)
#'user/x
user=> (ns foo {:x x})
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: x in this context
foo=> (ns bar {:x user/x})
nil
the whole ns form is evaluated in the fresh ns right?
(ins)user=> (create-ns 'foo)
#object[clojure.lang.Namespace 0x54d18072 "foo"]
(ins)user=> (intern 'foo 'bar 1)
#'foo/bar
(ins)user=> (ns foo {:bar bar})
nil
(ins)foo=> (meta (the-ns 'foo))
{:bar 1}
@hiredman I tried that with *ns*
but it got me an error:
$ clj
Clojure 1.10.1
user=> (ns bar {:current-ns *ns*})
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: *ns* in this context
again, not a problem, but just observing this behaviour. when linting code it becomes kind of important to know
aah:
Clojure 1.10.1
user=> (ns bar {:current-ns clojure.core/*ns*})
nil
bar=> (meta (the-ns 'bar)
)
{:current-ns #object[clojure.lang.Namespace 0xf72203 "bar"]}
added the meta check to my paste above showing what one would expect
These kinds of details tend to be learned by experimentation and/or reading source code.
yeah, but it's not something that other Clojure implementation should adhere to if that's the way to discover it, that's my motivation to ask if this is documented
what if your linter complained if symbols in ns metadata aren't fully qualified?
seems like an acceptable ask, reduces complexity of knowing what you are reading
that seems like a good addition. right now it only complains about symbols it can't resolve, but it seems even clojure vars have to be fully qualified
Is it expected that eval
doesn't see any imports in the current namespace?
java.lang.IllegalArgumentException: Unable to resolve classname: CommonTokenStream
I did a thing with eval and had to include the namespace in the string that was being evaluated. Not sure if that's what is happening or not
No problem!
Imports effect the state of the current namespace *ns*
, which is then used to resolve classes, but while the value of *ns*
is the declared namespace during compilation, it may be, and usually is, something entirely different when your code is run
I'm trying to write a user-defined function for KSQL in Clojure. KSQL wants you to give it an uberjar with an annotated java class. I've tried this with both gen-class
and a hand-authored java file that interops to Clojure. In both cases, the uberjar gets loaded fine, and my class annotations are detected via reflection. But I get exceptions like "java.lang.ExceptionInInitializerError" and "java.lang.NoClassDefFoundError: Could not initialize class clojure.java.api.Clojure" as soon as anything to do with clojure is executed, like Clojure.var("clojure.core", "require")
Feels like I must be missing something about how the uberjar needs to be built. My uberjar seems awfully small (7MB), and unpacking it, I don't see any evidence that Clojure is included in there anywhere.
I stumbled upon this issue today that looks similar: https://github.com/boot-clj/boot/issues/665 Not sure if that helps though.
when you run lein uberjar
it creates two jars, one contains standalone
in the name by default, the other does not
a common mistake is to use the wrong jar - the one that contains only your code and not your deps is an intermediate artifact that you shouldn't try to use directly
I'm using standalone. If I don't do anything with clojure, the UDF runs fine.
OK, if you picked the right jar, and it doesn't contain clojure, I can't explain that.
what is a UDF?
User Defined Function. It's the code being executed by KSQL.
you should be able to run java -cp my-uber.jar clojure.main
and get a repl
Everything works fine in the REPL.
no, I'm not saying use a repl
I'm saying use only java plus your uberjar to start a repl
Yes, that works. It only seems to be an issue when executed from the context of KSQL.
could be KSQL does something with classloaders, that can prevent clojure from working since it also uses classloaders weirdly
That's my current guess. KSQL does some sort of classpath isolation so different UDF impls don't step on each other's deps.
we are approaching the edge of what I understand here, but this thread might help https://groups.google.com/forum/#!topic/clojure/Aa04E9aJRog
Thanks, this looks promising.
Imports effect the state of the current namespace *ns*
, which is then used to resolve classes, but while the value of *ns*
is the declared namespace during compilation, it may be, and usually is, something entirely different when your code is run
Oh, huh. Is there a a way to print *ns*
during compilation just so that I compare it with the one at runtime and educate myself a bit?
Also, is there something decent I could read about all this?
*ns*
is a dynamic var. Usage of vars is not cached - the value is looked up again each time you access them. The value of a dynamic var is controlled by the callers further up the stack.