Fork me on GitHub
#beginners
<
2021-03-14
>
Eric Ihli02:03:02

clojure.lang.IPersistentMap
  (assocEx
    [trie opath ovalue]
    (if (get trie opath nil)
      (throw (Exception. (format "Value for key %s already exists." opath)))
      (assoc trie opath ovalue)))
Something about those lines is causing this error:
1. Caused by java.lang.ClassCastException
   class clojure.lang.PersistentVector cannot be cast to class
   java.util.Map$Entry (clojure.lang.PersistentVector is in unnamed module of
   loader 'app'; java.util.Map$Entry is in module java.base of loader
   'bootstrap')

                  core.clj: 1567  clojure.core/key
            core_print.clj:  233  clojure.core/print-prefix-map/fn
            core_print.clj:   66  clojure.core/print-sequential
            core_print.clj:  229  clojure.core/print-prefix-map
            core_print.clj:  238  clojure.core/print-map
Any ideas? The error seems to be only related to how the custom deftype prints to REPL. The code appears to otherwise work.

hiredman02:03:22

What about that stacktrace makes you think the error is coming from that line?

hiredman03:03:41

Looks like a bogus .toString method, maybe in the call to format when building the exception, but that is not in the stacktrace

Eric Ihli03:03:28

When I comment those lines out, I don't get the error.

Eric Ihli03:03:18

Oh, I should have included the line I was evaluating to cause the error. (str (trie/->TrieAgain '() 1 {})) doesn't raise. (trie/->TrieAgain '() 1 {}) does raise.

hiredman03:03:57

it looks like you are printing a map where keys doesn't return a seq of map entries

hiredman03:03:44

ser=> (keys (reify clojure.lang.IPersistentMap (seq [_] (list [:a :b]))))
Error printing return value (ClassCastException) at clojure.lang.APersistentMap$KeySeq/first (APersistentMap.java:168).
class clojure.lang.PersistentVector cannot be cast to class java.util.Map$Entry (clojure.lang.PersistentVector is in unnamed module of loader 'app'; java.util.Map$Entry is in module java.base of loader 'bootstrap')
(user=> *e
#error {
 :cause "class clojure.lang.PersistentVector cannot be cast to class java.util.Map$Entry (clojure.lang.PersistentVector is in unnamed module of loader 'app'; java.util.Map$Entry is in module java.base of loader 'bootstrap')"
 :via
 [{:type clojure.lang.ExceptionInfo
   :message nil
   :data #:clojure.error{:phase :print-eval-result}
   :at [clojure.main$repl$read_eval_print__9112 invoke "main.clj" 442]}
  {:type java.lang.ClassCastException
   :message "class clojure.lang.PersistentVector cannot be cast to class java.util.Map$Entry (clojure.lang.PersistentVector is in unnamed module of loader 'app'; java.util.Map$Entry is in module java.base of loader 'bootstrap')"
   :at [clojure.lang.APersistentMap$KeySeq first "APersistentMap.java" 168]}]
 :trace
 [[clojure.lang.APersistentMap$KeySeq first "APersistentMap.java" 168]
  [clojure.lang.RT first "RT.java" 692]
  [clojure.core$first__5402 invokeStatic "core.clj" 55]
  [clojure.core$print_sequential invokeStatic "core_print.clj" 64]
  [clojure.core$fn__7331 invokeStatic "core_print.clj" 174]
stacktrace doesn't entirely match, but pretty close

Eric Ihli03:03:21

Ahhh. So before I implemented the IPersistentMap methods... I was just getting the default random deftype representation... , like "[email protected]". But my REPL is now trying to print something that looks like a map, because it sees it's an instance of that. Gotcha. Thanks!

hiredman03:03:37

maybe, not entirely sure

hiredman03:03:24

a tricky thing with keys is it returns a lazy seq, so exceptions may not be thrown until it is forced

hiredman03:03:46

in my example above the printing of the sequence returned by keys is forcing it and then throwing

hiredman03:03:07

(you can see the open paren dangling where it started to print the seq before it threw)

hiredman03:03:27

So my guess is something isn't right with the seq method, which is getting called when printing the result (not entirely sure what path through the printer is being triggered, that may be repl dependant)

ArtW16:03:39

Any hints on how to implement this in Clojure?

for i in range(800, 4000, 800):
    for j in range(1, 65, 16):
        print(i+j)

william16:03:08

(doseq [x (range 800 4000 800)
        y (range 1 65 16)]
  (prn (+ x y)))

william16:03:04

and lookup the difference between doseq and for

agigao18:03:07

(map + (range 800 4000 800) (range 1 65 16))

william19:03:23

that doesn't seem the same @U2HBNQQBE, @UG703UB0T's version prints the sum of all the possible combinations, yours is a zipped sum

ArtW19:03:02

Correct, I was trying to display a list of screen locations for an application I am writing in TUTOR.