https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java#L1388-L1412
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java#L1233-L1259
Hi. I have a vector of vectors of strings ... ^.^
(def vovos [ ["super" "snax" "zero"] ["blastin" "bumpin" "barging in"] ["two" "tamales" "tortillas"]])
And I want to search the [[s+][s+][s+]]
for a specific term and return the vector-index.
For exampla, desired resultsa:
(search-it-real-good vovos "snax")
> 0, 1
(search-it-real-good vovos "tamales")
> 2, 1
I am thinking map-indexed
or maybe reduce-kv
... any insight would be appreciated
Don't use a vector of vectors
Use two maps, one from pairs of indices to strings, another from strings to pairs of indices
Yup, that would likely be a much better representation, depending on what else you’re doing with this data (how you add/remove values, for example).
Otherwise you need something like this monstrosity:
dev=> (defn search-it-real-good [vs q]
#_=> (some (fn [[i x]]
#_=> (some (fn [[j y]] (when (= y q) [i j]))
#_=> (map-indexed vector x)))
#_=> (map-indexed vector vs)))
#'dev/search-it-real-good
dev=> (search-it-real-good vovos "snax")
[0 1]
dev=> (search-it-real-good vovos "tamales")
[2 1]
thanks everyone
It would also matter whether the same string can appear in multiple locations — and what search-it-real-good
should return in such cases?
thanks a lot! uh, in this case they are very long sentences i'm matching against and ought only occur once. if they occur twice, the first occurrence is the desired result -- which is coincidentally how your code already works ^.^ so yeah. @hiredman mentioned to do it differently with reverse-index and primary index, which is the right answer for almost every use case like this, but the sequence of strings as vectors is important to preserve and this operation only needs to be called once in a while to memoize a location so i think it's fine. however, in the future, i'm wondering how to represent, say, chapters of a book split on page (of variable length) that would make sense for doing such searching, and especially when the contents of the pages and their sequence is mutable/ up in the air.
but how? A sentinel value at the head of the vector to say if it’s ‘actually’ a vector? That still seems a bit janky, to me
For interest sake, what do you find monstrous about that?
{:data-type :list :contents []}
that plus some multi-methods that dispatch on :data-type
should get you pretty far
alternatively, you can use metadata, but I tend to prefer keeping things explicit and visible
yeah, fair, I already have my tokenizer like that
It’s repetitive and that, together with the nesting, suggests “you’re doing it wrong”.
Interesting. I clearly need to develop that sense [further]. Thanks for the explanation.
(def vovo-map (into {} (mapcat (fn [i v] (map (fn [j x] [x [i j]]) (range) v)) (range) vovos)))
that produces a hash map from strings to index pairs that would turn search-it-real-good
into just (get vovo-map s)
If you have a common access pattern, it’s often better to optimize for it in terms of the data structure you use in the first place.
What is the preferred method of shuttling edn content over http, specifically for data exchange between clojure and clojurescript? Transit or similar?
transit was designed primarily for that purpose
what is a way to take a specific message from a channel, another specific message from another channel, and when both arrived (in any order) send a message to a third channel?
actually, I think a layer of nesting can be removed like so:
(go
(let [x1 (async/pipe c1
(chan 1 (filter pred1)))
x2 (async/pipe c2
(chan 1 (filter pred2)))]
(>! c3 (+ (<! x1)
(<! x2)))))
+?
sorry, I know not the most relevant part : )
you didn't specify what message to send to the third channel, so I just combined them with the shortest operator that came to mind
yeah, it made sense, i like it
it's still a little underspecified with respect to how channels should be closed and whether or not c1
or c2
might have other consumers, but it's hopefully a good start
interesting because it's obvious, but (and I am guessing on my own subconscious here) because in one case i have nothing to combine just the fact that the event happened at all (no content beyond that), I didn't realize it's this straightforward to wait on two channels at once
:thumbsup: , the only thing to watch out for is to pipe
both channels before reading from either channel to make sure messages are being consumed until the expected message shows up
eg
(go
(let [x1 (async/pipe c1
(chan 1 (filter pred1)))
x2 (async/pipe c2
(chan 1 (filter pred2)))]
(<! x1)
(<! x2)
(>! c3 42))
I am inside a subscription, I think that solves this too?
so it's like promise.all without the rejection
I haven't tested it, but I think something like this should work:
(go
(let [x1 (go (<! (async/pipe c1
(chan 1 (filter pred1)))))
x2 (go (<! (async/pipe c2
(chan 1 (filter pred2)))))]
(>! c3 (+ (<! x1)
(<! x2)))))
is it possible to run a clj -X my-ns/hello
style command from another directory than the src directory?
it has to be on the classpath
so yes (if the other dir is on the classpath)
i want to use python to run a -main
function in a single clojure file with a single dep
i have /usr/local/bin/clojure -Sdeps {:deps {org.clojure/data.json {:mvn/version "2.2.2"}}}
but I'm unsure what to write after to call the -main
of my target clojure file
-M -m the.ns
-M /path/to/file -m the.ns
?
if you're loading it as a main class, it must be on the classpath, so there is file path involved
if you need to add to the cp, you can add :paths ["whatever"]
to the -Sdeps above
/usr/local/bin/clojure -Sdeps '{:paths ["path"] :deps {org.clojure/data.json {:mvn/version "2.2.2"}}}' -M -m main-ns
I'm guessing as you have not described the file structure, but if you did then I could be more specific
if the file is a script (no -main, no ns, just run top-level functions to be run), then you could skip adding it to the classpath or using -m:
/usr/local/bin/clojure -Sdeps '{:deps {org.clojure/data.json {:mvn/version "2.2.2"}}}' -M path/to/file.clj
oh that's an interesting idea, i'll try that
is it possible to pass in args in that case?
ah yes, *command-line-args*
if i run my command myself, it works: /usr/local/bin/clojure -Sdeps '{:deps {org.clojure/data.json {:mvn/version "2.2.2"}}}' -M /Users/noah/Personal/JSONTestSuite/parsers/test_clojure/src/test_json.clj /Users/noah/Personal/JSONTestSuite/test_parsing/y_array_empty-string.json
if i use the python script (which prints that out before using subprocess
to run it), i get an Error building classpath. Don't know how to create ISeq from: clojure.lang.Symbol
error
(this is the python script: https://github.com/nst/JSONTestSuite/blob/master/run_tests.py)
given that the command runs by itself, I'm going to guess it's in how you're calling it from python. I would be most suspicious of the escaping/quoting/spaces in the -Sdeps. Is there more to that error or an error file?
sadly, no. after doing a bit of digging in how python does this stuff, it seems i can't/shouldn't quote the {:deps }
map. removing the single quotes solves it, which is surprising to me
thanks for the help
Hi everyone,
I have a question regarding java interop : how can I type hint java method calls with variable length arguments ?
(using ^"ClassName[]"
did not seem to work)
The method's signature : handleEventsWith(EventHandler<? super T>... handlers)
please provide an example of the signature you're trying to call
@ho0man you can get this type by doing (type (into-array ClassName []))
,e.g:
user=> (type (into-array java.nio.file.Path []))
[Ljava.nio.file.Path;
And then you can use "[Ljava.nio.file.Path;"
as the type hint.(btw, if this question arises from the usage of java.nio.file interop, take a look at babashka.fs which solves most of this using a clojure API)
Thanks a lot @borkdude
(-> [1]
zip/vector-zip
zip/down
(zip/replace [2])
zip/path)
;; => [[1]]
I was expecting that path to be [[2]]
. Once I replace a node, how do I get zip/path to reflect the new path? I see I could use https://clojuredocs.org/clojure.zip/root, but how would I get back down to where I was in the zipper after using root?you have to zip/up and then zip/down again
the path records the tree you walk through to get where you are, and even though you replaced a node, when you walked down to it it was the previous value