beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Eric Ihli 2020-11-19T01:21:51.463900Z

I'm looking for a resource that can help me learn how to parse arbitrary binary data. Given a description along the lines of "Offset 0000, 32 bit integer, magic number. Offset 0004, 32 bit integer, number of rows. etc...", It would be a huge help to see an example of a simple program that parses a custom binary data structure and... kind of like http://www.gigamonkeys.com/book/practical-parsing-binary-files.html but in Clojure. Actually, I think I might just go with that and try translating it to Clojure.

2020-11-19T18:48:17.498700Z

you could also check out gloss, which is meant for this sort of thing https://github.com/ztellman/gloss

st3fan 2020-11-19T01:32:47.464Z

They are definitely implementation details, but i still want to test them independently of the public api.

st3fan 2020-11-19T01:37:30.464900Z

Is there a nice way to do the following? I feel there is too much repetition going on …

(defn should-add-label [settings issue]
  (and
   (check-issue-status settings issue)
   (check-issue-assignee settings issue)
   (check-issue-milestone settings issue)
   (check-issue-labels settings issue)))

st3fan 2020-11-19T01:39:39.466100Z

(every? #(% settings issue) [#'check-status #'check-assignee #'check-milestone])

seancorfield 2020-11-19T01:40:02.466300Z

Another possibility then is to use with-test to provide tests with the defn of the private function itself. http://clojure.github.io/clojure/clojure.test-api.html#clojure.test/with-test That way the tests "stay private" too, in a way, since they are right there with the "implementation detail".

st3fan 2020-11-19T01:41:37.466600Z

interesting

st3fan 2020-11-19T01:41:50.466800Z

there is so much in the core 😕

st3fan 2020-11-19T01:43:38.467100Z

Sometimes it helps to think out loud

2020-11-19T01:58:34.467900Z

There may be an every-fn or every-pred already in core

st3fan 2020-11-19T02:05:07.468400Z

ah yes but the predicates take only one argument

2020-11-19T02:10:53.469800Z

Oh, wait it takes multiple args, but as ands to the predicate weird

2020-11-19T02:11:51.471Z

Nope, confusing myself with all the anonymous functions, the returned predicates takes multiple args as expected

st3fan 2020-11-19T02:13:15.471300Z

Ok I need to re-read that

2020-11-19T02:59:05.471500Z

Me too

0xclj 2020-11-19T04:05:59.472Z

I have POST /parse-reply {body :body} (compojure-api) The content of (str(slurp body)) is along the lines of:

"--xYzZY
Content-Disposition: form-data; name=\"attachments\"


--xYzZY
Content-Disposition: form-data; name=\"dkim\"

{<http://x-com.y.gappssmtp.com|x-com.y.gappssmtp.com> : pass}
--xYzZY
Content-Disposition: form-data; name=\"subject\"

Re: TEST RESPONSE
--xYzZY
Content-Disposition: form-data; name=\"to\"

<mailto:x@y.com|x@y.com>
--xYzZY
Content-Disposition: form-data; name=\"spam_score\"

0.011
"
^ A multipart-form with boundary --xYzZY Is there a way I can convert it into JSON or if I have to parse the string to get the values by name like "spam_score" or "to" email address, how should I go about it? I’m thinking of splitting the string with --xYzZY and follow the parse-split cycle further until I get the value (yet to verify if the fields are always returned in the same position for the parse-split cycle to work).

Ben Sless 2020-11-19T08:40:08.484300Z

An aside: I recommend against using slurp in production unless the endpoint sees very little traffic. Json libraries like Cheshire and jsonista can parse byte arrays directly

👍 1
0xclj 2020-11-19T11:03:25.486500Z

Thanks!

👍 1
2020-11-19T04:56:53.473Z

There is a ring middleware to decode form data

0xclj 2020-11-19T06:30:31.473100Z

Yeah. Referring the last comment response of: https://stackoverflow.com/questions/33824124/multipart-params-are-not-extracted-by-ring-middleware#comment56033214_33829549 Went through: <https://github.com/ring-clojure/ring-defaults> but not sure how to get it working. Especially the handler:

(require '[ring.middleware.defaults :refer :all])

(def site
  (wrap-defaults handler site-defaults))
The service I’m working on, has no handler defined.

theSherwood 2020-11-19T06:56:52.476600Z

Hi. I’m trying to create a clojurescript library that makes use of some javascript files. I”m using leiningen and :foreign-libs under :cljsbuild in order to bundle the js into the library. However, that doesn’t seem to make the js code available to the application code consuming the library. Could anyone point out to me the proper way to incorporate javascript files into clojurescript libraries?

pinealan 2020-11-19T08:05:04.478100Z

Is there someway in clojurescript to define constant values during compile-time, like the https://webpack.js.org/plugins/environment-plugin/ plugin?

2020-11-19T08:35:48.484100Z

Euh... What does that plugin do?

2020-11-19T08:43:19.484500Z

You can define constants with ^:const which will inline the value if its EDN

2020-11-19T08:44:06.484700Z

Otherwise, you can use macros to perform whatever compile time things you want

pinealan 2020-11-19T08:51:00.485Z

I was trying to do it with macro just now but the compiler wasn’t happy about it

# .clj
(ns my.core)
(defmacro getenv [key]
  (System/getenv key))

# .cljs
(ns my.core 
  [:require-marcors my.core])

(def ENV (getenv))
(defn hi [] env)
This causes cljs compiler to warn me
WARNING: Can't take value of macro my.core/getenv at line 4
WARNING: Can't take value of macro my.core/getenv at line 5
I know it’s a very hacky way of using macro as a function, but I’m not sure how else to pass the JVM environment during compilation into runtime

2020-11-19T09:58:19.485500Z

I wouldn't say the use of a macro for this is hacky. Like if you want this functionality, macros are a great way to get it. Much better than the JS pre-processing that webpack plugin must have to do. Now, that error normally means you are passing a macro to something that expects a function. I assume that's not the real code.you try, cause you have typos and all in it. Macros in ClojureScript can be a bit tricky to setup right, and then I'd just double check you don't have a dumb mistake, like missing a parens or forgetting to pass an arg, etc.

2020-11-19T10:03:13.485800Z

Also seems you might be hitting this bug: https://github.com/bhauman/figwheel-main/issues/165

2020-11-19T10:03:35.486100Z

So it could be a false positive warning. Apparently is fixed in a newer version of figwheel

pinealan 2020-11-19T12:16:48.486800Z

thanks for the link, I wasn’t using figwheel, but I’ll double check the macro usage

NoahTheDuke 2020-11-19T14:08:15.487300Z

is there a way to load into a default namespace with deps.edn?

NoahTheDuke 2020-11-19T14:09:32.488500Z

in lein's project.clj, I can say :repl-options {:init-ns default.core} and when the repl starts, it loads the file and enters the namespace so I don't have to do anything extra

NoahTheDuke 2020-11-19T14:14:08.490200Z

in my project's root directory, when i enter clj, it loads into the repl with my dependencies in the classpath, but it doesn't load the current project's files, and I have to call (load "default/core") to load them before I can call (in-ns 'default.core)

alexmiller 2020-11-19T14:19:09.490900Z

you can use the -e features of clojure.main to evaluate expressions before you start the repl:

% clj -M -e "(require 'clojure.set)(in-ns 'clojure.set)" -r
#object[clojure.lang.Namespace 0x5bf22f18 "clojure.set"]
clojure.set=&gt;

alexmiller 2020-11-19T14:21:43.493100Z

that can be bundled into an alias in deps.edn as well (requires a , instead of spaces to avoid some word splitting through the shell):

{:aliases
 {:repl {:main-opts ["-e" "(require,'clojure.set)(in-ns,'clojure.set)" "-r"]}}}
and then clj -M:repl

NoahTheDuke 2020-11-19T14:22:16.493400Z

cool, thank you. i don't see -e noted anywhere in https://clojure.org/guides/deps_and_cli or https://clojure.org/reference/deps_and_cli. oh, it's in https://clojure.org/reference/repl_and_main okay

NoahTheDuke 2020-11-19T14:22:29.493600Z

didn't look at that page

alexmiller 2020-11-19T14:23:59.494200Z

yeah, -i can be useful to load a .clj file containing whatever in advance too

dpsutton 2020-11-19T14:58:14.495100Z

There’s a typo in your require macros expression. Is that present in the source or just in slack?

theSherwood 2020-11-19T16:26:55.495800Z

Any feedback on using javascript files in cljs library code? https://clojurians.slack.com/archives/C053AK3F9/p1605769012476600

st3fan 2020-11-19T16:47:31.496800Z

What is the idiomatic Clojure equivalent of Python's if "foo" in ("foo", "bar", "baz"): ?

dpsutton 2020-11-19T16:49:28.497600Z

(or (contains? {"foo" "bar"} "foo") ({"foo" "bar"} "foo")) you can use the function contains? or use the fact that sets are callable themselves

dpsutton 2020-11-19T16:50:14.498200Z

eval both of those expressions at the repl to see the different values they return

st3fan 2020-11-19T16:50:19.498400Z

oh sets are callable 🙂

Chris Emerson 2020-11-19T19:04:20.000600Z

Beware of contains? because it trips most new people up at some point. It's behaviour is sometimes different to what you expect!

Chris Emerson 2020-11-19T19:04:41.001100Z

contains? checks for the presence of a key, for sets it does what you would expect, since keys=values, and for vectors it checks whether the index is present (contains? #{:a :b} :a)            ;;=> true (contains? #{:a :b} :c)            ;;=> false (contains? {:a :b} :a)             ;;=> true (contains? {:a :b} :b)             ;;=> false (contains? [1 2] 1)              ;;=> true (contains? [1 2] 2)              ;;=> false

st3fan 2020-11-19T19:06:45.001600Z

Right so you need a # in your example @dpsutton 🙂

Chris Emerson 2020-11-19T19:07:45.002Z

yep! (contains? {"foo" "bar"} "foo") => true (contains? {"foo" "bar"} "bar") => false

Chris Emerson 2020-11-19T19:08:22.002300Z

but if you used a set instead of a map:

(contains? #{"foo" "bar"} "bar")
=&gt; true

dpsutton 2020-11-19T19:13:34.005400Z

oh right. my bad 🙂

Daniel Stephens 2020-11-19T19:14:34.006200Z

(some #{:some :things :to :check :are :contained} [:some :vec :of :things]) I quite like this pattern, uses the fact that sets can be called and lets you check for more than one thing (if needed) existing in the coll, no idea on the performance but it's never been my bottleneck

Chris Emerson 2020-11-19T19:15:15.006600Z

that's a great tip

☺️ 1
st3fan 2020-11-19T19:15:21.006800Z

Yeah that is nice - because right now I do (some #(contains? (set labels) (:name %)) (:labels issue))

st3fan 2020-11-19T19:16:08.007600Z

Oh I can't directly translate that but i can shorten it with that trick

st3fan 2020-11-19T19:17:04.008400Z

(some (set ignored-labels) (map :name (:labels issue)))

👍 1
2020-11-19T19:27:49.009600Z

I'd usually just define ignored-labels as a set

2020-11-19T19:28:40.010400Z

also consider: (some (comp (set ignored-labels) :name) (:labels issue)) - some already traverses, you don't need to map too

st3fan 2020-11-19T19:29:13.010800Z

st3fan 2020-11-19T19:29:38.011300Z

That is really cool

2020-11-19T19:30:01.011800Z

you can even do something like (def ignored-issue (comp (set ignored-labels) :name)) then do (some ignored-issue (:labels issue))

2020-11-19T19:30:24.012100Z

or maybe "ignored-label" is a better name there

2020-11-19T19:31:15.013100Z

I find a tendency to reduce line / definition count as if that were meaningful simplicity, where giving the right things the right names is the clearest approach

st3fan 2020-11-19T19:31:56.013600Z

"more smaller functions" ?

dpsutton 2020-11-19T19:32:18.014400Z

Also there are caveats if the set can contain false or nil when invoking the set

2020-11-19T19:32:32.014700Z

not just that - because the one liner has the same number of functions - the question is what is exposed as a name

st3fan 2020-11-19T19:32:50.015100Z

right

mathpunk 2020-11-19T19:46:49.018300Z

I have some data with timestamps like "2020-11-19T17:32:32.277Z" and I think it would be a little nicer to transform that to our time zone, and/or "time ago" format. Near as I can tell the move is to use java.time directly, instead of the various wrappers I can find (which seem to be for Java 8 ). There are a rather overwhelming number of classes and I cannot figure out which one, if any, has a constructor that will take a string like I've got. Any tips?

Daniel Stephens 2020-11-19T19:47:39.018500Z

ZonedDateTime/parse

🎉 1
Daniel Stephens 2020-11-19T19:48:25.019200Z

Instant/parse would also work, but if you are messing with timezones the first thing you'd probably do from there is convert to a ZonedDateTime

2020-11-19T19:49:18.020400Z

there's multiple classes usable, but they each have parse methods

2020-11-19T19:49:19.020500Z

you may also be seeing the instant tagged literal in a print out

mathpunk 2020-11-19T19:54:11.021Z

I don't think so, hiredman, the data I've got is not coming from a Clojure program

mathpunk 2020-11-19T19:55:34.021700Z

thanks folks! i thought I'd be using a constructor (Like. so) instead of a method

seancorfield 2020-11-19T19:57:26.022700Z

@mathpunk If you would prefer a wrapper, the clj-time README links to several (as part of trying to stop people using clj-time these days!).

2020-11-19T20:00:35.022800Z

the difference is that the parse methods make you specify the format you are parsing, where a constructor wouldn't (not that it couldn't, that would just be weird...)

sova-soars-the-sora 2020-11-19T20:06:44.024100Z

Hi, html5 audio element needs my server to send "Accept-Ranges" "bytes" and while the default ring file-response sends "Content-Length" $len the audio element still says Live Broadcast as opposed to showing the seek bar as needed

sova-soars-the-sora 2020-11-19T20:08:18.024400Z

I guess the header is supposed to read "Content-Range" ? hrm

sova-soars-the-sora 2020-11-19T20:15:47.025Z

Apparently it needs 3 headers set:

Accept-Ranges:bytes
Content-Length:7437847
Content-Range:bytes 0-7437846/7437847
but it doesn't look like Content-Range is by default in ring/file-response...

2020-11-19T20:16:11.025100Z

this might be relevant - each response still uses Content-Lenth, which just describes that payload not the resource https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/206

sova-soars-the-sora 2020-11-19T20:20:12.026200Z

So basically it looks like I gotta add the "Content-Range" header... but i'm not sure how to get the byte length of a file

sova-soars-the-sora 2020-11-19T20:27:45.026600Z

oh. looks like (.length ) does the trick with http://java.io

Daniel Stephens 2020-11-19T20:28:16.026700Z

(defn format-when [zdt-str]
  (let [zdt (ZonedDateTime/parse zdt-str)
        dur (Duration/between zdt (ZonedDateTime/now))
        secs (.getSeconds dur)]
    (if (&lt; secs (* 5 60 60))
      (let [[v a b] (-&gt;&gt;
                      [[(quot secs (* 60 60 24)) "day" "days"]
                       [(quot (rem secs (* 60 60 24)) (* 60 60)) "hour" "hours"]
                       [(quot (rem secs (* 60 60)) 60) "minute" "minutes"]
                       [(rem secs 60) "second" "seconds"]]
                      (filter (comp (complement zero?) first))
                      first)]
        (if v (format "%s %s ago" v (if (= 1 v) a b))
              "now"))
      (str (.toLocalDateTime (.withZoneSameInstant zdt (ZoneId/systemDefault)))))))
=&gt; #'user/format-when
(format-when "2020-11-18T17:32:32.277Z[Australia/Sydney]")
=&gt; "2020-11-18T06:32:32.277"
(format-when "2020-11-19T17:32:32.277Z")
=&gt; "2 hours ago"
(format-when (str (Instant/now)))
=&gt; "now"
this is some very rough code I dug out, did something similar to this when I was starting out with clojure, probably helpful for the interop more than the clojure!

sova-soars-the-sora 2020-11-19T20:47:45.027300Z

opened a new issue @ ring ^_^

st3fan 2020-11-19T20:58:54.028200Z

Maybe I am overthinking this, but what is preferred in Clojure land? pr / pr-number or pull-request / pull-request-number ?

st3fan 2020-11-19T20:59:11.028700Z

"pr" is a pretty common term in github speak of course

st3fan 2020-11-19T21:00:10.029300Z

Oh hm their API calls it pull_number actually .. interesting

2020-11-19T21:01:26.030100Z

as far as I know "pull request" is a github UI concept, it's been adopted elsewhere but isn't part of git itself

2020-11-19T21:01:38.030300Z

I think this is off topic though

2020-11-19T21:02:38.031Z

@st3fan for example the clojure.core project uses github as a mirror, but it's not how contributions are accepted, you'd use JIRA instead

st3fan 2020-11-19T21:03:21.031400Z

Sorry my question is about naming not about contributing to Clojure 🙂

2020-11-19T21:04:11.032Z

right, OK - regarding naming, pull-request is the name of a github UI feature

st3fan 2020-11-19T21:05:04.032600Z

i'm working on a github client - so that is ok, i don't have to hide that detail

2020-11-19T21:08:13.036Z

https://lore.kernel.org/git/1113577744.27227.53.camel@hades.cambridge.redhat.com/ the first instance of "pull request" on the git mailing list predates github by 3 years

Joe 2020-11-19T21:08:56.036600Z

I'm writing a small application which models populations changing over time - a sort of zero player game, similar to game of life. I want to draw the output of the steps on a canvas (a grid with squares on it that fill and empty) with the output being redrawn with each step. Is there a go-to Clojure library for this? I was thinking of quil, but only because it's the only one I've heard of. Are there alternatives I should be thinking about?

2020-11-19T21:10:03.037Z

have you seen rich's ants simulation?

Joe 2020-11-19T21:10:29.037500Z

I've heard about it in the context of core.async, i didn't realize it had a drawing component

2020-11-19T21:10:49.037900Z

it predates core.async by a lot

Joe 2020-11-19T21:11:18.038600Z

Oh, not async, state management

2020-11-19T21:11:36.038900Z

I am not sure if the original is around any more https://gist.github.com/michiakig/1093917 is maybe a copy, it renders using java's built in 2d canvas stuff

Joe 2020-11-19T21:13:25.039700Z

That looks good enough to do what I want, thanks!

sova-soars-the-sora 2020-11-19T21:14:23.040200Z

Neato

sova-soars-the-sora 2020-11-19T21:16:23.042500Z

There's an awesome story in Surely You're Joking Mr. Feynman about how Richard Feynman had a line of ants in his apartment and bathroom. Rather than try and get rid of them, he started experimenting. For example, he put some sugar on a table and then used a coaster to "elevate/teleport" ants to the table. Sure enough, ants were able to figure out there was an elevator and they would start waiting on the coaster to get a ride. But they couldn't really figure out that the elevator went 2 ways. Very interesting. Also he used chalk to draw a line for each ant's path to the sugar in his bathroom. It was like a newton's linear approximation. First it was curvy and clunky, and over time each ant successively did a straighter-and-straighter line towards the sugar.

Joe 2020-11-19T21:17:07.042700Z

Love that book!

🐜 1
alexmiller 2020-11-19T21:32:38.042800Z

it's not a mirror

alexmiller 2020-11-19T21:32:50.043Z

the github repo is the repo

alexmiller 2020-11-19T21:34:30.043200Z

this seems to be a pervasive thing people believe but I'm not really sure why as it has always been this way (since moving to git)

st3fan 2020-11-19T21:51:10.044400Z

I'm a really happy camper right now. I rewrote the backend for http://devbots.xyz in Clojure (from Go) and it is really nice compact code and ... 10x less LoC 7000 vs 700

👍 3
😲 2
1
5
mathpunk 2020-11-19T22:03:44.045700Z

ooh, i did work out how to use ZoneId/systemDefault but i didn't know about Duration/between, thank you

st3fan 2020-11-19T22:23:09.047800Z

Is it possible to programatically "load" a namespace? for example my bots nicely organized in their own namespace and right now I have code like this:

(def apps [needs-triage/bot needs-review/bot lock-issue/bot lock-pull-request/bot])
(def apps-by-id (into {} (map #(vector (:id %) %) apps)))
But it would be nice if I can just discover all devbots.bots.* namespaces at runtime ...

st3fan 2020-11-19T22:24:12.048300Z

They do contain multimethods, so I think I need to fully "load" them before the multimethod dispatch works.

st3fan 2020-11-19T22:24:20.048600Z

(not sure what the right terminology is)

alexmiller 2020-11-19T22:31:45.049Z

load is the right word

alexmiller 2020-11-19T22:32:36.050Z

you can load dynamically via require (or load, but that's considered lower level), but discovery is not generally a thing you can ask a jvm to do

alexmiller 2020-11-19T22:33:29.050900Z

you can inspect parts of your classpath as files/jar paths to "discover" things like that (and there are java libs that have support for that kind of thing)

alexmiller 2020-11-19T22:36:36.052700Z

probably best way to handle is with some kind of runtime config that lists the ns'es to load

st3fan 2020-11-19T22:38:20.053800Z

these namespaces are embedded in my app, so i can also require them in core and then iterate over available namespaces and filter on devbots.bots. - maybe that is a simple start