Fork me on GitHub
#beginners
<
2021-04-29
>
sova-soars-the-sora00:04:44

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

sova-soars-the-sora00:04:14

I am thinking map-indexed or maybe reduce-kv ... any insight would be appreciated

hiredman00:04:10

Don't use a vector of vectors

hiredman00:04:57

Use two maps, one from pairs of indices to strings, another from strings to pairs of indices

seancorfield00:04:36

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).

seancorfield00:04:47

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]

walterl00:04:20

For interest sake, what do you find monstrous about that?

seancorfield01:04:58

It’s repetitive and that, together with the nesting, suggests “you’re doing it wrong”.

walterl01:04:10

Interesting. I clearly need to develop that sense [further]. Thanks for the explanation.

seancorfield01:04:50

(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)

seancorfield01:04:34

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.

seancorfield00:04:51

It would also matter whether the same string can appear in multiple locations — and what search-it-real-good should return in such cases?

sova-soars-the-sora16:04:24

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. @U0NCTKEV8 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.

Franco Gasperino03:04:00

What is the preferred method of shuttling edn content over http, specifically for data exchange between clojure and clojurescript? Transit or similar?

Alex Miller (Clojure team)04:04:56

transit was designed primarily for that purpose

Aron06:04:42

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?

phronmophobic06:04:49

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)))))

phronmophobic07:04:03

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)))))

Aron07:04:07

sorry, I know not the most relevant part : )

phronmophobic07:04:40

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

Aron07:04:59

yeah, it made sense, i like it

phronmophobic07:04:03

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

Aron07:04:05

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

phronmophobic08:04:32

: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

phronmophobic08:04:21

eg

(go
  (let [x1 (async/pipe c1
                       (chan 1 (filter pred1)))
        x2 (async/pipe c2
                       (chan 1 (filter pred2)))]
    (<! x1)
    (<! x2)
    (>! c3 42))

Aron08:04:52

I am inside a subscription, I think that solves this too?

Aron06:04:57

so it's like promise.all without the rejection

Noah Bogart13:04:25

is it possible to run a clj -X my-ns/hello style command from another directory than the src directory?

Alex Miller (Clojure team)13:04:12

it has to be on the classpath

Alex Miller (Clojure team)13:04:21

so yes (if the other dir is on the classpath)

Noah Bogart13:04:18

i want to use python to run a -main function in a single clojure file with a single dep

Noah Bogart13:04:17

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

Noah Bogart13:04:48

-M /path/to/file -m the.ns?

Alex Miller (Clojure team)14:04:14

if you're loading it as a main class, it must be on the classpath, so there is file path involved

Alex Miller (Clojure team)14:04:43

if you need to add to the cp, you can add :paths ["whatever"] to the -Sdeps above

Alex Miller (Clojure team)14:04:29

/usr/local/bin/clojure -Sdeps '{:paths ["path"] :deps {org.clojure/data.json {:mvn/version "2.2.2"}}}' -M -m main-ns

Alex Miller (Clojure team)14:04:55

I'm guessing as you have not described the file structure, but if you did then I could be more specific

Alex Miller (Clojure team)14:04:11

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

Noah Bogart14:04:51

oh that's an interesting idea, i'll try that

Noah Bogart14:04:06

is it possible to pass in args in that case?

Noah Bogart14:04:40

ah yes, *command-line-args*

Noah Bogart14:04:51

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

Noah Bogart14:04:33

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

Alex Miller (Clojure team)14:04:36

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?

Noah Bogart14:04:08

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

Noah Bogart14:04:26

thanks for the help

Ho0man15:04:34

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)

ghadi15:04:49

please provide an example of the signature you're trying to call

borkdude15:04:59

@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.

borkdude15:04:36

(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)

Eric Ihli22:04:42

(-> [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?

hiredman22:04:45

you have to zip/up and then zip/down again

hiredman22:04:59

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

👍 4