Fork me on GitHub
#beginners
<
2019-12-07
>
Space-Otter00:12:01

Hey guys, I am new to Clojure and I really like it! I hope this is the right place to ask this. My knowledge about Java is pretty small so maybe you can help me out. I can’t catch following exception:

(ns exam-archiver.core
  (:require [clojure.data.xml :as xml])
  (:gen-class)) 

(defn my-func [s]
   (try
      (xml/parse (<http://java.io|java.io>.StringReader. s))
      (catch javax.xml.stream.XMLStreamException e false)))

(my-func "<ab>")
;; Error printing return value (XMLStreamException) at <http://com.sun.org|com.sun.org>.apache.xerces.internal.impl.XMLStreamReaderImpl/next
;; (XMLStreamReaderImpl.java:604).
;; ParseError at [row,col]:[1,7]
;; Message: The element type "ab" must be terminated by the matching end-tag "</ab>".

bfabry00:12:02

it's throwing a clojure ExceptionInfo, not a XmlStreamException

bfabry00:12:05

the ExceptionInfo is wrapping the original stream exception to provide more information. so you need to catch it

bfabry00:12:10

user=> *e
#error {
 :cause "ParseError at [row,col]:[1,5]\nMessage: XML document structures must start and end within the same entity."
 :via
 [{:type clojure.lang.ExceptionInfo
   :message nil
   :data #:clojure.error{:phase :print-eval-result}
   :at [clojure.main$repl$read_eval_print__9086 invoke "main.clj" 442]}
  {:type javax.xml.stream.XMLStreamException
   :message "ParseError at [row,col]:[1,5]\nMessage: XML document structures must start and end within the same entity."
   :at [.apache.xerces.internal.impl.XMLStreamReaderImpl next "XMLStreamReaderImpl.java" 652]}]
 :trace

hiredman00:12:21

the other reason you are unable to catch it like that is parse returns a lazy datastructure, so the computation doesn't happen until the datastructure is realized, which doesn't happen until the repl tries to print it

👍 1
Space-Otter00:12:26

Uh.. I see. Thank you a lot!

Space-Otter00:12:37

So I can’t use xml/parse to check for well formed xml files?

bfabry00:12:58

you can, you just need to make sure you realise the lazy sequence

hiredman00:12:13

it isn't a lazy seq, it is a tree where the collection of branches are lazy seqs, which is tricky to realize, the easiest thing might be a combination of dorun and tree-seq

Space-Otter00:12:40

I am realizing that I must dig deeper into it 😄

Space-Otter00:12:28

But thanks for the quick response!

ScArcher03:12:14

Quick question, I have this in a (cond and it's throwing a ClassCastException any idea why

(>= index (count data)) false
If I replace the (count data) with a hard coded number it works.

dpsutton03:12:02

Can you paste the full code?

ScArcher03:12:10

(defn doit [data]
(loop [index 0 stack [] count 0]
(cond
(>= index (count data)) false
:else
true)))

ScArcher03:12:20

I'm passing in [1 2 3 4 5 6]

ScArcher03:12:14

I missed a paren there, but just added it.

tws03:12:51

You’re overloading count.

seancorfield03:12:42

Shadowing (just to be pedantic).

👍 2
tws04:12:17

details matter

ScArcher03:12:02

Thank you!!!!

tws03:12:03

It’s trying to call a function you’ve set to zero.

ScArcher03:12:05

i am idiot 🙂

tws03:12:07

We all are.

seancorfield03:12:56

Overloading means something else.

seancorfield03:12:42

Linters like Eastwood (and probably clj-kondo) would help you here by flagging such things I think.

ScArcher04:12:04

I'm using Calva with clj-kondo and it's been awesome, but it didn't catch this one.

seancorfield04:12:23

Really? Oooh, complain to @borkdude! 🙂

borkdude08:12:25

There is an open issue for shadowing, so it will be there eventually

clj-kondo 3
somethingpretentious11:12:52

Hello, I'm currently trying to do the https://adventofcode.com/2019/day/2#part2 challenge in clojure and I'm running into an error. I'm trying to get the nth value from a vector but it's saying they key must be an integer (I think it may currently be a long) but it's worked previously doing the exact same thing... full code is here and the error is thrown on line 43 https://github.com/michael1241/adventofcode/blob/master/day2.clj

somethingpretentious11:12:13

Any advice would be appreciated, thanks! Edit: Never mind, fixed it 🙂

hrvladev18:12:33

Is there a way this code:

user=>
(let [[first rest last] [1 2 3 4 5]]
  (prn first)
  (prn rest)
  (prn last))
1
2
3
nil
to bind using destructuring: - first to 1 - rest to (2 3 4) - last to 5 ?

raf22:12:57

maybe a function

(defn f [xs] ([(first xs) (butlast xs) (last xs)]))
(let [a b c (f[1 2 3])])
(typed via phone and I didnt handle edge cases, but you get the idea)

baflo20:12:52

Maybe sth like

(let [[first rest last] ((juxt first #(rest (butlast %)) last) [1 2 3 4 5]])
  ...)

hiredman19:12:18

No

👍 1
😞 1
ScArcher21:12:49

Does (read-line) interact strangely with the REPL?

ScArcher21:12:10

I wrote a function that calls (read-line) but for some reason the function keeps getting called twice.

ScArcher21:12:29

Even when I call (read-line) it's calling it twice.

dpsutton21:12:16

What is your environment?

seancorfield21:12:57

@scott.archer How are you running your REPL? (read-line) works well in a plain REPL started from the command-line but may well not work properly in a REPL you've started inside an editor/IDE...

ScArcher22:12:38

I think it’s a Calva issue. I asked in that channel and filed an issue on github. It worked fine in the command line REPL.

ScArcher22:12:57

It’s funny I was completely confused. It was causing very strange behavior in my program, but it was nice to break it down and I finally saw it was related to (read-line). I replaced the call with the value I was entering and worked around it for now.

Danny23:12:43

I seem to have sinned and am using core.async to try to solve AOC Day 7, and I've been stuck for well over 14 hours. Is there anyone familiar enough with async to help? If I take some function

(defn penguin [...]
  ;; and launch 5 go blocks
  (go ...)
  (go ...)
  (go ...)
  (go ...)
  (go ...)
  
  ;; and then loop over final outputs receieved on another channel
  ;; (each go block above will send to this channel once)
  (loop [n 0]
    (if (= 4 n) 
        (<!! final-output-chan)
        (do 
          (<!! final-output-chan)
          (recur (inc n))))))

;; then run a single one, it WORKS
(penguin ...)

;; but dare to run multiple
(dosync (penguin ...) (penguin ...) )
;; OR
(map penguin ...)

;; And the entire thing hangs, breaks, or all of the above.
What I want to happen is have each iteration of (penguin ...) sit and wait for the last answer EVERY TIME and simply just run them with map over different inputs. Where's my logic going wrong? Am I wishing for a pie in the sky?

enforser23:12:46

How are you putting things on the channel inside of penguin?

Danny23:12:07

each of those (go ...) blocks lanches a separate function that does blocking io. Those functions take channels, take and put on them, then finally add their answers to the "final-output-chan" I.e.

(defn penguin [...]
 (let [giraffe-chan (chan (sliding-buffer 1))
       final-output-chan (chan (sliding-buffer 5))]

  ... ;; other go blocks
  (go (>! giraffe-chan "friend" 
    (giraffe giraffe-chan final-output-chan)

  ... ;; the waiting loop)

(defn giraffe [mychan final-output-chan]
  ...
  (<!! mychan) ;; "friend"
  ...
  (>!! final-output-chan "secret-code"))
I'm not sure this answer's your question.

enforser23:12:35

I’m guessing that if you’re using blocking IO that is what is causing the program to hang - because the 8 threads allocated to async are likely all blocking. Could try to change all of the blocking calls into non-blocking temporarily - or just throw print statements around and see if they stop printing after 7-8 blocking calls are executed.

enforser23:12:55

It could be the <!! in giraffe calls that are adding up - and blocking if they haven’t received the value yet. If 8 of those block at once, then async will lock up. (Disclaimer: It’s been a while since I’ve used async, so I might be off here)

Danny23:12:52

😮 Wait that might be it! There's essentially 6 chans per penguin and 4-5 of them at a time hold/block while waiting for intput. And then the loop blocks while waiting for all 5 (go ...) to finish. I guess the question is, how do I organize the code to allow all threads to be "released" and non-blocking before starting the next penguin

enforser23:12:33

Well, I think the loop is fine to have blocking since it will take up a maximum of 1 thread. Everywhere else should be in a go block, and use >! and !<

Danny00:12:28

I'm going around seeing what I can turn in to non blocking. I believe the puts don't have to be blocking, but the inputs might need to be. (more detail) I have to run multiple penguins. A, B, C, D, E. They pass messages between themselves in a circle. A -> B -> C -> D -> E -> (back to) A I think the outputs could be instant, but inputs I believe should wait or block?? Each penguin waits for input, but can send out as soon as it gets it. (i.e. A needs to wait for B to produce output, C to produce output, D to produce output, and finally E to produce output before resuming)

enforser00:12:52

can all of A, B, C, D, and E run in parallel at some point or they just passing one value around?

Danny00:12:09

Now that you mention it, Only 1 of A, B, C, D, and E are ever running at one point in time.

Danny00:12:23

With that in mind, it appears that async might not be a solution to go with here. I simply need a way to resume as they get input and save their place as they push output. Ahhhh but it was so cool to see them work like this!