Fork me on GitHub
#beginners
<
2024-02-23
>
Jim Newton13:02:26

There's something that has always bothered me about a very common clojure error message:

Execution error (IllegalArgumentException) at homework.determinant/determinant$det (form-init487256975355084077.clj:31).
Don't know how to create ISeq from: java.lang.Long
why can't it tell me what the object is which I'm trying to treat as a sequence?

Jim Newton13:02:36

wouldn't that be useful? somewhere I guess i'm iterating across a number accidentally.

ghadi13:02:05

It’s 42

😂 1
José Javier Blanco Rivero13:02:47

That is what is saying. ISeq is a java interface which all sequences or sequentiable collections implement.

ghadi13:02:39

Suggestion: dump the top few frames in the stack trace and it should pinpoint where the mistreatment is occurring

ghadi13:02:16

However, the number may be flowing from elsewhere

Jim Newton13:02:21

I had the arguments reversed to reduce . I always think the inital value is the 3rd argument, but in clojure it is the 2nd argument.

Noah Bogart15:02:41

After doing a small amount of research about a related issue last year, I believe it comes down to two things: 1) only lists are given location metadata, so an issue in a (reduce (fn ...) coll init-val) call surfaces as an issue in the reduce call, not pointed at the specific item (the long). and 2) because of the way clojure is compiled into java bytecode, the errors come directly from the java layer, and the originating clojure forms have been discarded. There's no "source-map" like in javascript when bundling, so there's no way except line and column numbers to point to the original code (which as mentioned in (1) are only tracked on lists).

👍 1
Jim Newton13:02:08

how many pending calls to future should become problematic? I have a function which is creating lots and I sometimes (not not always) get an error like this

Jim Newton13:02:45

Isn't future managing a thread pool? or does this depend on the java version? my java version is pretty old.

Jim Newton14:02:24

Here is an example which uses pmap rather than future directly. https://gist.github.com/jimka2001/febe2a877a0a070cb4208b7795660238

Jim Newton14:02:12

i'm pretty sure the code is correct because if I change pmap to map it seems to work.

seancorfield18:02:55

future runs on the soloExecutor which is a CachedThreadPool which is essentially unbounded. Well, bounded by the number of threads the system will let it create 🙂

seancorfield18:02:53

pmap is pretty much never the right answer -- it's a bit of a sledgehammer. If you want control over concurrency, you should use interop and Java executors... that's the idiomatic answer.

seancorfield18:02:25

You can use set-agent-send-off-executor! to change the soloExecutor from the default (which is used by both send-off and future) but that's a tradeoff that may affect library code etc -- hence the recommendation to use an explicit executor in your own code.

Jim Newton07:02:59

think the issue in my code is probably not the number of threads, but the fact that each thread needs a lot of memory.

Kishor Pandey15:02:26

I defined my protocol as below , If I want to add method4 only to Irecord1 , How can I d it ?

(defprotocol  Iprotocol
  (method1 [a b])
  (method2 [a b])
  (method3 [a b])
 )

(defrecord Irecord1 [fields]
 Iprotocol
  (method1 [a b]
    ...)
  (method2 [a b]
    ...)
  (method3 [a b]
    ...)
 )


(defrecord Irecord2 [fields]
  Iprotocol
  (method1 [a b]
    ...)
  (method2 [a b]
    ...)
  (method3 [a b]
    ...))

Kishor Pandey15:02:02

Or use it for both and not implementing it in Irecord2

delaguardo15:02:02

add method4 as a part of another protocol and implement them both for record Irecord1 and only one for Irecord2

delaguardo15:02:01

(defprotocol  Iprotocol
  (method1 [a b])
  (method2 [a b])
  (method3 [a b])
 )

(defprotocol IprotocolExt
  (method4 [a b]))

(defrecord Irecord1 [fields]
  Iprotocol
  (method1 [a b]
    ...)
  (method2 [a b]
    ...)
  (method3 [a b]
    ...)
  IprotocolExt
  (method4 [a b]
    ...))


(defrecord Irecord2 [fields]
  Iprotocol
  (method1 [a b]
    ...)
  (method2 [a b]
    ...)
  (method3 [a b]
    ...))

Kishor Pandey16:02:20

when to use extend-protocol ?

delaguardo16:02:06

Most likely when you don't control the type/class definition (for example it is coming from the library)

delaguardo16:02:24

but I can't say for sure, I never use it

Kishor Pandey16:02:21

oh!.. Thank you.. that helped

jpmonettas18:02:51

extend-protocol is also useful when you want to group together implementations by protocol instead, like :

(extend-protocol clojure.core.protocols/Datafiable

  java.lang.Object
  (datafy [o] ...)
  
  java.lang.String
  (datafy [s] ...)
  
  java.util.ArrayList
  (datafy [al] ...))

🙌 2