Fork me on GitHub
#beginners
<
2023-11-12
>
Haider03:11:36

hi everyone, i have a question about the effects of conj in the context of constructing a 2D vector from Java arrays. Specifically, I wrote a function that iterates over an image stack and then grabs a reference to a Java array at each step—representing pixel values for the ith image slice—and appends it to a vector.

(defn get-pixels-arrays [imgStack]
  (loop [i 1 v []]
    (if (<= i number-of-slices)
      (recur (inc i) (conj v (-> imgStack
                                 (.getProcessor i)
                                 (.getPixels)
                                 )))
      v)))

;; calling the function on an image stack of size 32
(def inputImageArray (get-pixels-arrays inputImageStack))

;; returns 32
(count inputImageArray)
But after creating the vector, I cannot grab individual elements of the nested array and get a value of 1 from count when I apply it to any one of the nested arrays.
(count (take 1 inputImageArray)) ;; returns 1 instead of 262144
(take 5 (take 1 inputImageArray)) ;; returns the entire array instead of the first 5 elements.
This behaviour seems to be an artefact of using conj because when I use take and count directly on the array, they work fine:
(def test-array (-> inputImageStack
              (.getProcessor 1)
              (.getPixels)))

(count test-array) ;; returns 262144
(take 5 test-array) ;; returns first 5 elements
Could someone help me understand what is going on? Thank you

hiredman03:11:04

I would double check the return value of .getPixels

hiredman03:11:36

Sounds like it might return an array of arrays of numbers, not an array of numbers

hiredman03:11:01

The docs seem to show it as an array of numbers

hiredman03:11:49

So maybe double check that the code you think is running is actually what is running (restart your repl, verify your code loads without errors, etc)

Haider03:11:34

running (type test-array) returns [F

hiredman03:11:50

Where is number-of-slices defined?

hiredman03:11:12

I guess what I am getting at is there is no way it is an artefact of conj

Haider03:11:21

it is present in my code. i have checked the value, it is 32.

(def number-of-slices (.getSize inputImageStack)) 

Haider03:11:27

hmmm, okay

hiredman03:11:38

So something else is going on

hiredman03:11:19

How sure are you that the function you are calling is the function source you are looking st

hiredman03:11:57

Did you edit the definition and eval the new version afterwards, etc

Haider03:11:46

i am using calva on VS code and i re-evaluate the function every time i make a change.

hiredman03:11:50

If you put (println "hello world") at the top of the function does it print when you call the function

Haider03:11:04

i will try that now

Haider03:11:33

yes, it does

hiredman03:11:30

I would change the else branch in the loop from v to (do (println i) v)

hiredman03:11:42

And see what value is printed for i

hiredman03:11:25

I guess that is just going to be the same as the count

hiredman03:11:11

Maybe print the count of each array before conj it

hiredman03:11:47

And then you can see if it is the same as the count when you pull it out of the vector

hiredman03:11:17

You want first not take 1

hiredman03:11:42

Take 1 returns a seq of length 1

hiredman03:11:19

Take is: give me a seq of the first n items

hiredman03:11:27

You may want to look at nth since you have a vector

Haider03:11:17

oh, that makes sense!

Haider03:11:45

getting the correct number for count now

Haider03:11:58

thank you so much

Haider03:11:33

i didn’t look at the docs for take closely enough

anovick04:11:07

In Python there's a built-in function help available in the REPL that when provided a function, it opens up documentation of that thing, like a man page. Is there something similar to that in Clojure?

anovick04:11:54

things I'm interested to see in the documentation: • the docstring (if available, of course) • usage examples (the ones on ClojureDocs are really useful)

seancorfield06:11:22

Which editor are you using? I think both Emacs (with CIDER) and VS Code (with Calva) will show you docstrings, clojuredocs examples, and individual argument names etc, while you are typing or via a hot key.

1
daveliepmann11:11:45

Docstring, arglists, and jump-to-definition should be supplied by the IDE (as well described in the https://lambdaisland.com/blog/29-12-2017-the-bare-minimum-clojure-mayonnaise). For usage examples I have a Firefox search term set up so "clj juxt" goes to https://clojuredocs.org/search?q=juxt though I'm trying to switch to cider-clojuredocs.

Dave17:11:46

Tupelo library says it has an unwrap function in the documentation: https://cljdoc.org/d/tupelo/tupelo/23.05.31/doc/readme#_combining_scalars_and_vectors However I can't seem the find the function anywhere in the code: https://github.com/search?q=repo%3Acloojure%2Ftupelo+unwrap&type=code I am also getting errors with the latest version not recognizing this function.

Syntax error compiling at (src/dave/notebooks/evdev.clj:6:49).
Unable to resolve symbol: unwrap in this context.
Anyone know what might be going on here?

tomd17:11:46

This is where git's "pickaxe" can come in handy. A quick search makes me think it was renamed to <> https://cljdoc.org/d/tupelo/tupelo/23.05.31/api/tupelo.core#%3C%3E

👍 1
tomd17:11:48

The fact that nearly every commit in that repo is titled "misc" doesn't speak particularly well for it imo, and no doubt makes this sort of search harder

Dave18:11:57

Hmm, after playing around with it, I think they split the functionality between <> and the only. I thought Tupelo was a pretty popular library. I kinda felt left out not using it.

daveliepmann18:11:11

> I thought Tupelo was a pretty popular library. For what it's worth, I've heard of it but no team I've worked with has used it

2
phill22:11:01

Tupelo's author was prolific on StackOverflow and answered many, many questions correctly and helpfully and with a plug for Tupelo. This may have bolstered an impression of Tupelo's wide popularity.

today-i-learned 2
1
marc18:11:51

Hi there! I have two lists, be it localmails and remotemails . Make both be {:email value :attribute attr :attribute2 attr ...}. I need to split localmails in three lists: New, Updated, Deleted by comparing with remotemails , that is: see what entries are not in the remote list, which have different attributes, which are on remoteemails but not in localmails. Could someone point me in the right direction? Like the names of the functions I wan't to learn about 🙂 thx

1
Bob B18:11:43

this could likely be accomplished with something like a reduce that does a comparison and adds to an output map, or potentially with the clojure.set namespace, if those lists can be transformed into sets (relations) and joined to produce one output set

Bob B18:11:01

alternatively, it's likely possible to use something like clojure.data/diff to do an initial separation (eliminate the equal ones), and then pare down to just the emails and diff them

marc22:11:07

Nice, diff looks exactly right. That would give me the three lists, then I'll just have to see the Updated list for changes. Thanks for the tip!

marc12:11:46

For anyone looking, what I have done is: 1. Use set/join to get a single list of all items (I join via :email). There are no duplicate keys on either map which is ok. 2. filter to exclude the ones which the remote ID is nil -- aka: New items, CREATED 3. filter to exclude the ones which the local ID is nil -- aka: Gone items 4. use (difference ...) with the three sets above to get the "maybe updated" which I then pass through another function to compare fields and return a map of updates to do thx @U013JFLRFS8 for the pointers!

marc17:11:22

Following up on the above, note that set/join does something akin to a LEFT JOIN in SQL, meaning that elements not found in the first collection are dropped. !