Fork me on GitHub
#beginners
<
2019-01-03
>
zoltan.jose07:01:31

Hello, all! I have a couple of queries that I have been pondering on for a while: * Is there an idiomatic way to design error handling for a project? Say, specifically, for a web project? Currently, I am using failjure, and while it is nice for small snippets, I find that I am now tied to using it everywhere, and readability is also taking a hit due to the main logic being hidden within the failjure code itself. What cleaner ways are there to approach error-handling in general in Clojure? * What would be some nice open source projects to read to get a good sense of best practices in Clojure (libraries, backend code, etc). * Any good (and updated) resources on learning ClojureScript? I have the book from Packtpub, and it seems promising enough, but the very first chapter jumps into using a bunch of different (and wildly varying) ways of just setting up a ClojureScript project. That appears to be kind of overwhelming. Also, figwheel seems to have a newer avatar (figwheel-main), but most people still seem to be using the old figwheel. Use figwheel or go with figwheel main?

jstaab17:01:48

My two cents here @, as far as error handling goes, is that monads aren't usually considered idiomatic in clojure. My recommendation, if you're writing a web service would be to validate incoming data (using spec or schema) and handle external errors (using exceptions) at the edges of your system. This would push both out of your business logic, and give you more confidence that the meat of your code is just on the happy path. If errors are more a part of your domain, I'd go with a monadic approach. For learning clojurescript, http://clojurescriptmadeeasy.com is probably the best blog on clojurescript in particular, though it's a bit sparse. Learning cljs is a weird process, since you need to know javascript, including idiosyncrasies of your host (node/browser), as well as clojure. For actually using clojurescript, I've settled on shadow-cljs, which has some rough edges, but is pretty full-featured and is a bit less magical than lein-cljsbuild for example.

jstaab17:01:04

Also http://cljs.github.io is a good cljs reference.

zoltan.jose08:01:06

@jstaab Thank you so much for your response. It is very helpful indeed! 🙂

zoltan.jose08:01:26

Also, for ClojureScript, yes, I agree - finding resources that are cohesive seems to be rather difficult! I will check out the resource that you mention. Cheers, and thank you for your help again.

peterhull9009:01:33

Is there a straightforward way to get a lazy sequence of lines from a sequence of filenames? I tried line-seq inside with-open but didn't work because I needed to realize the line sequence before with-open closed the reader. I want to do processing on a set of files as if they were all catted together in one big file.

rahul08032710:01:11

@ Are you doing the processing outside the with-open block?

peterhull9010:01:47

Yes. With one file it's easy to do it inside; with multiple files I ideally want to get a line sequence without having to store all the lines/intermediates

rahul08032710:01:43

problem is the with-open will close it before anything happens. you need to keep all those files open simultaneously if youre using line-seq. how big are your files? i'd suggest reading them all into memory if small enough

peterhull9010:01:14

In practice they are not too big, so assembling them in memory works. I was just wondering if there was a neater solution to the problem. (usually there is with clojure!) Thanks for your help.

rahul08032711:01:51

@ Something ugly i hacked together, does the stuff lazily but isnt that clean. might help:

(defn lazy-cat'
  [colls]
  (lazy-seq
    (if (seq colls)
      (concat (first colls) (lazy-cat' (next colls))))))

(let [readers (->> ["file1"
                    "file2"]
                   (map ))
      lines   (->> readers
                   (map line-seq)
                   (lazy-cat'))]
  (do-your-stuff-here lines)
  (run! #(.close %) readers))

rahul08032711:01:35

as you can see the closing has to be done manually 😕

peterhull9011:01:57

:+1: Thanks! Makes sense (I think, will have to look at it a bit longer)

olekss.janis10:01:50

hey, I can't figure out easy way how to clean up all my namespaces. After some refactoring, I can't run tests, coz some functions which where moved to different namespaces are now colliding with where they where, so I would like to have "clean sheet" after refactoring, so unload and reload all the namespaces

carr0t10:01:34

Is this running test on the command line, or in a repl, or...?

carr0t10:01:24

My solution to a large scale refactor like that would generally be to kill/restart the test runner or exit/restart the repl

carr0t10:01:57

It's just not worth the time to try and get everything cleaned up properly vs the time it takes to exit/restart

olekss.janis10:01:24

yes looks like restart repl is the way I go

olekss.janis10:01:58

another question I feel I am missing some idiomatic approach I see pattern emerging in my code... I have top level functions called by REST layer, which all take in two ids, find the objects by those ids and call some function This "some function" is the only distinctive specifics, but getting ids, and translating them from ids to objects (maps) is common for all those kind of function... how to abstract or shorten it coz all of my functions have the same shape (same args, which are transformed)

fabrao10:01:25

Hello all, how do I convert this new double[][] { { 30 }, { 20 }, { 50 } } to clojure?

lennart.buit11:01:57

Do you mean like this: [[30] [20] [50]]

delaguardo11:01:26

[[30.] [20.] [50.]] to keep desired double type

fabrao11:01:31

I´m getting this error clojure.lang.PersistentVector cannot be cast to [[D

delaguardo11:01:55

could you show the line that throws this error?

fabrao11:01:13

(let [dataset (DefaultXYZDataset.)]
    (.addSeries dataset "USA" [[30.] [20.] [50.]])
    (.addSeries dataset "CHINA" [[30.] [20.] [50.]]))

fabrao11:01:35

it´s expecting 2d double array

saikyun11:01:56

ah, you probably have to use make-array then

saikyun11:01:19

I'm guessing (make-array (make-array 30.) ...)

lennart.buit11:01:38

(to-array-2d [[30.] [20.] [50.]])

saikyun11:01:31

ah cool @lennart.buit

saikyun11:01:34

good to know

lennart.buit11:01:46

yeah, I am checking whether it actually works tho :’)

lennart.buit11:01:07

because it appears to be an array of Objects, whereas we want an array of primitives

fabrao11:01:20

to-array-2d is not working too [[Ljava.lang.Object; cannot be cast to [[D

lennart.buit11:01:58

yeah, this is an array of boxed values, whereas you want an array of primitives

saikyun11:01:34

I found this on google :v (into-array (map double-array data))

fabrao11:01:00

it seems that (into-array (map double-array [[30.] [30.] [30.]])) worked

konradt9515:01:02

Is (shutdown-agents) the only way for a clojure app to exit when using futures? Or is there some way to shutdown futures individually?

alexmiller16:01:48

shutdown-agents is the best way. there is future-cancel but that won’t necessarily do anything useful (depends what the future task is)

alexmiller16:01:14

future-cancel is my favorite Clojure docstring btw: “Cancels the future, if possible.”

alexmiller16:01:01

apocalyptic …. or, not?

konradt9516:01:16

My futures don't need to be canceled. They reach the ready state as expected. Was just wondering if there was a non-global way to clean up the future in a way that would allow the main thread to exit. Thanks for the confirmation.

dpsutton16:01:38

would rich accept a ticket to add an ominous elipsis to that doc string?

wmichaelshirk21:01:24

Like others, I’m about to try clojurescript again for the new year; intimidated by the infrastructure advances since I last tried and since my books-on-hand were written. I’ve got a [card] game I’ve written in JS with Vue.js. I’m feeling like shadow-cljs + reagent is considered a good way to go?

jstaab21:01:34

That's pretty much where I've landed for my various projects. Definitely still some rough edges with shadow, but it's got all the features I care about, including npm integration and lots of build targets.

wmichaelshirk22:01:41

nice. If I get it cloned (it currently is one page, in browser, no server) - I might try to add some firebase integration.

wmichaelshirk22:01:47

Looks like those should be possible.

wmichaelshirk22:01:15

Do I need figwheel too? Or is that just a lein thing?

jstaab23:01:45

I believe figwheel is leiningen-focused

jstaab23:01:58

As far as I know, figwheel is browser oriented, and may be more solid than shadow-cljs, but I needed to compile the same code to node, which I don't think figwheel does.

mfikes23:01:45

Figwheel can work with node, and it can also work outside of Lein (there is figwheel-main)

jstaab00:01:09

@ how does it compare with shadow-cljs? I never really got started with figwheel except for a small browser app a few years ago because of the above assumptions.

mfikes00:01:41

I know shadow-cljs has a hot-reloading mechanism, but I've never used it, so I can't compare

jstaab00:01:40

It's pretty good, if a little buggy on the skinny branches (for example, when running tests using a custom main function it loses track of which tests exist). Does figwheel handle stuff like production builds, dependencies, bundle optimization, and integration with npm? Or is it still just the hot-reloading part?

shaken23:01:19

I am trying to understand the connections between namespaces and file names and directory structure. (Any good articles on the topic would be appreciated.) I’ve been looking at examples in the clojure namespaces and have a question about one in particular. The namespace clojure.spec.alpha is contained in the directory/file path “spec.alpha/src/main/clojure/clojure/spec/alpha.clj” and there is also “spec/gen/alpha.clj” and “spec/test/alpha.clj”. My question is what will this structure look like when alpha (or alpha2) is done and the namespace becomes just “clojure.spec”?

hiredman23:01:35

it is complicated because what matters to the clojure runtime is classpath roots

hiredman23:01:56

and which paths become classpath roots is up to whatever tooling is building your classpath

hiredman23:01:42

https://github.com/clojure/spec.alpha/blob/master/pom.xml#L101 is setting up the classpath root for building spec.alpha

hiredman23:01:49

(a classpath root)

hiredman23:01:11

so src/main/clojure/ becomes a classpath root

hiredman23:01:57

and when the clojure goes to load the namespace clojure.spec.alpha it looks for clojure/spec/alpha.clj relative to the classpath roots