beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
zhuxun2 2020-09-14T00:52:24.166300Z

Is there a way to compile my project into a executable jar without lein? I do have a deps.edn and one of my namespaces has a -main function.

dpsutton 2020-09-14T01:06:23.166600Z

Check out depstar

๐Ÿ‘ 1
seancorfield 2020-09-14T01:07:05.167300Z

@zhuxun2 There's a #depstar channel if you get stuck or have follow-on questions about it.

๐Ÿ‘ 1
Risetto 2020-09-14T14:35:58.170700Z

Can I destruct one of my arguments, while let doing it for another one? The first argument is a string, and the second one a map which I would like to destruct

Risetto 2020-09-14T14:38:31.170900Z

Using :keys maybe?

cgrand 2020-09-14T14:43:19.173600Z

@olle142 something like that?

(let [{x :my-string {:keys [a b] #_any-kind-of-destructuring-can-go-here} :my-submap} {:my-string "s" :my-submap {:a 12 :b 34}}]
   [x a b])
=> ["s" 12 34]

Risetto 2020-09-15T09:20:56.226900Z

Yes that is exactly it, thank you very much @cgrand

Matthew Pettis 2020-09-14T15:34:13.175300Z

Is there the concept of NA or NaN in clojure? That is, is there a NA value such that (+ 1 NA) would yield NA? nil doesn't work, as (+ 1 nil) gives me a null pointer exception...

alexmiller 2020-09-14T15:34:45.175500Z

##NaN

๐Ÿ‘ 2
alexmiller 2020-09-14T15:35:37.176700Z

which is really just java.lang.Double/NaN

Matthew Pettis 2020-09-14T15:36:28.177800Z

Thanks. I haven't tried yet, but I'm guessing that nil works with nicely with missing string arguments. I'm trying some limited incanter type operations, and I'd like the missing construct.

2020-09-14T15:36:31.178Z

Beware that (= ##NaN ##NaN) returns false for reasons from the IEEE standard for floating point values, and thus ##NaN used as a set element or a map key will not be able to be looked up successfully, and any collections you might want to call = on will return false if either or both of them contain ##NaN values.

๐Ÿ‘ 1
2020-09-14T15:37:47.178400Z

Some examples and discussion here: https://clojure.org/guides/equality#_floating_point_not_a_number

Matthew Pettis 2020-09-14T15:38:02.178600Z

This seems consistent with many constructs, like NULL in SQL... is there a function that returns true for ##NaN? like a isNaN function?

2020-09-14T15:39:01.178800Z

Yes there is a Java method:

user=> (Double/isNaN ##NaN)
true

Matthew Pettis 2020-09-14T15:39:06.179Z

I see from your link maybe I can make (.equals ##NaN ##NaN) work...

Matthew Pettis 2020-09-14T15:39:25.179200Z

OK, that helps, thanks.

2020-09-14T15:40:14.179400Z

You cannot override the definition of Clojure's =, or the way it looks up elements in sets or as map keys, without hacking on Clojure's Java implementation.

Matthew Pettis 2020-09-14T15:43:36.179600Z

Got it. I was thinking that if Double/isNaN didn't exist, I could implement something like (defn isNan [x] (.equals ##NaN x))

Matthew Pettis 2020-09-14T15:44:19.179800Z

... I am much removed from the skill to rewrite internals ๐Ÿ™‚ ...

2020-09-14T15:45:42.180Z

I would not recommend it ๐Ÿ™‚. I was merely answering the possible followup question of whether one could change how those language features work in Clojure.

๐Ÿ‘ 1
Matthew Pettis 2020-09-14T16:15:42.181600Z

I'll bring this back to top level... Is this the idiomatic way to parse a list of strings, some of which will parse, and some of which will fail to parse?

Matthew Pettis 2020-09-14T16:15:46.181800Z

(map #(try (Integer. %) (catch Exception e ##NaN)) ["1" "" nil])

Pablo 2020-09-14T16:21:23.182Z

Hello everyone, I have a doubt about dependencies in CLJ(S). I have a project where, among other things, I use re-frame@0.10.8 and reagent@0.8.1. I want to upgrade re-frame to 1.1.1, but in the changelong said that re-frame upgrades reagent to 0.10.0 on its version 0.12.0. Should I also upgrade reagent version in my project, or do the libraries compile and use the versions they need from their own dependencies?

dpsutton 2020-09-14T16:24:01.182100Z

sure. although I would probably not keep the nans. not sure what your usecase is but i would probably do (keep #(try (Long/parseLong %) (catch Exception _ nil)) collection)

Matthew Pettis 2020-09-14T16:28:25.182300Z

Thanks. My use case is reading in a CSV, which has a column that should be measurements, but some are missing. Let's say I have two such columns, and I want to average them. If one of the columns has a missing value, I want the corresponding row output to have a missing value. Dropping values means columns won't line up, and keeping nil values makes arithmetic throw exceptions. So I want to make an output for each row, and if there are missing values, the computation should be missing. I'm coming from R and python-pandas, where I am operating on tabular-shaped dataframes. I have some small subset of those operations I want/need to do in Clojure to be able to leverage other tools in Clojure. Thanks for the help.

Matthew Pettis 2020-09-14T16:38:09.182500Z

I'll add, for posterity, and anyone who stumbles on this: This has a lot of great information as well: https://stackoverflow.com/questions/2640169/whats-the-easiest-way-to-parse-numbers-in-clojure

phronmophobic 2020-09-14T16:57:03.183Z

unless there's a specific reason to stay at 0.8.1, then I would upgrade

donyorm 2020-09-14T18:13:42.184400Z

Hey I'm working on a web server using ring and jetty, and getting a bunch of 500 errors, with almost no information anyone know how to get more details/a stack trace from that setup?

ryan echternacht 2020-09-14T18:43:55.185200Z

I'm looking to write some coercion code that expects a string or nil, coerces nil to "" and otherwise returns the string

ryan echternacht 2020-09-14T18:44:40.186100Z

in other languages, I might write (or s "") . is that idiomatic? is there something more idiomatic?

dpsutton 2020-09-14T18:45:03.186500Z

I canโ€™t think of anything wrong with it

donyorm 2020-09-14T18:45:05.186600Z

I believe this is considered idiomatic

valtteri 2020-09-14T18:45:24.187100Z

Looks good to me as well.

ryan echternacht 2020-09-14T18:46:00.188Z

cool, thanks

dpritchett 2020-09-14T18:48:31.189500Z

๐Ÿ‘‹

valtteri 2020-09-14T18:48:56.189900Z

Another option is to call str on the argument. If itโ€™s nil itโ€™ll coerce it to "" . Note that str also coerces all different types of values.

ryan echternacht 2020-09-14T18:53:27.190900Z

oh, I didn't realize str coerced nil to "". Thanks. It's for some url handling stuff, so everything is a string or nil anyway

Malik Kennedy 2020-09-14T20:40:49.193Z

Having some issues around using sorted-set-by, I'm trying to order a set of strings by their length but it demolishes the entire list to only (I think) one string per length? I want all the lists and for the set-y-ness's to apply to the string not the length, just want to be sorted by length. Please assist.

(def domains
  (into (sorted-set) 
    (map clojure.string/lower-case
      (drop-while #(< (count %) 4)
        (sort-by count
          (re-seq #"(?m)^.*$" (slurp "domains.txt")))))))
(count domains)
;; => 52664
(defn count-comparator [a b]
  (compare (count a) (count b)))
(def domains
  ;; right here vvvvvvvvvvvv
  (into (sorted-set-by count-comparator) 
    (map clojure.string/lower-case
      (drop-while #(< (count %) 4)
        (sort-by count
          (re-seq #"(?m)^.*$" (slurp "domains.txt")))))))
(count domains)
;; => 19
;; should be higher, whats wrong with my comparator? (I assume?)

Franklin 2020-09-14T20:41:12.193400Z

I'm having trouble upgrading the dependencies for this project

Franklin 2020-09-14T20:41:16.193700Z

(defn js-dir
      "Prefix with full JavaScript directory."
      [path]
      (str "resources/public/js/compiled/" path))

(defproject onaio/chimera "0.0.13"
  :description "Collection of useful Clojure(Script) functions."
  :dependencies [[clj-time "0.15.2"]
                 [com.cognitect/transit-cljs "0.8.264"]
                 [com.taoensso/tempura "1.2.1"]
                 ;; For CSV->XLSForm
                 [clojure-csv/clojure-csv "2.0.2"]
                 [dk.ative/docjure "1.11.0"]
                 [onelog "0.5.0"]
                 [org.clojure/clojure "1.8.0"]
                 [org.clojure/clojurescript "1.10.773"
                  :exclusions [org.clojure/clojure]]
                 [org.clojure/core.async "1.3.610"]
                 [org.omcljs/om "0.9.0"]
                 [slingshot "0.12.2"]
                 ;; JS
                 [cljsjs/moment "2.24.0-0"]]
  :license "Apache 2"
  :url "<https://github.com/onaio/chimera>"
  :profiles {:dev {:dependencies [[midje "1.8.3"]]}}
  :plugins [[jonase/eastwood "0.2.1"]
            [lein-bikeshed-ona "0.2.1"]
            [lein-cljfmt "0.3.0"]
            [lein-cljsbuild "1.1.2"]
            [lein-environ "1.0.1"]
            [lein-kibit "0.1.2"]
            [lein-midje "3.1.3"]]
  :cljfmt {:file-pattern #"[^\.#]*\.clj[s]?$"}
  :eastwood {:exclude-linters [:constant-test]
             :add-linters [:unused-fn-args
                           :unused-locals
                           :unused-namespaces
                           :unused-private-vars]
             :namespaces [:source-paths]
             :exclude-namespaces [chimera.async]}
  :test-paths ["test"]
  :cljsbuild {
              :builds {:dev
                       {:compiler {:output-to ~(js-dir "chimera.js")
                                   :output-dir ~(js-dir "out")
                                   :optimizations :whitespace
                                   :pretty-print true
                                   :source-map ~(js-dir "chimera.js.map")}}
                       :test
                       {:source-paths ["src" "test"]
                        :notify-command ["phantomjs"
                                         "phantom/unit-test.js"
                                         "phantom/unit-test.html"
                                         "target/main-test.js"]
                        :compiler {:output-to "target/main-test.js"
                                   :optimizations :whitespace
                                   :pretty-print true}}
                       :prod
                       {:source-paths ["src"]
                        :compiler {:output-to ~(js-dir "chimera.js")
                                   :output-dir ~(js-dir "out-prod")
                                   :optimizations :advanced
                                   :pretty-print false}
                        :jar true}}
              :test-commands {"unit-test"
                              ["phantomjs"
                               "phantom/unit-test.js"
                               "phantom/unit-test.html"
                               "target/main-test.js"]}}
  :global-vars {*warn-on-reflection* true})

Franklin 2020-09-14T20:41:46.194500Z

I keep getting this error

seancorfield 2020-09-14T20:41:47.194600Z

Let me create a local lein project and see what happens with that project.clj...

๐Ÿ‘ 1
Franklin 2020-09-14T20:41:50.194900Z

Syntax error compiling var at (midje/util/exceptions.clj:75:3).
Unable to resolve var: aviso.exception/*traditional* in this context

Franklin 2020-09-14T20:43:02.195700Z

Thank you very much @seancorfield

ghadi 2020-09-14T20:43:03.195900Z

if you have a long block of text, use a snippet CMD-Shift-Enter (on Mac, probably control on Windows). It will even do clojure syntax highlighting

Franklin 2020-09-14T20:43:35.196200Z

Thanks... good to know

seancorfield 2020-09-14T20:44:25.196400Z

@franklineapiyo How do you run lein ancient in interactive mode?

seancorfield 2020-09-14T20:45:00.196600Z

The report from lein ancient only identifies these three deps as being outdated -- is this what you get too?

[dk.ative/docjure "1.14.0"] is available but we use "1.11.0"
[org.clojure/clojure "1.10.1"] is available but we use "1.8.0" (use :check-clojure to upgrade)
[midje "1.9.9"] is available but we use "1.8.3"

Franklin 2020-09-14T20:45:22.196800Z

yes... I have updated all the other's just now

jsn 2020-09-14T20:45:23.197Z

Have you read this: https://clojuredocs.org/clojure.core/sorted-set-by ?

โค๏ธ 1
Franklin 2020-09-14T20:45:32.197200Z

lein ancient :interactive

jsn 2020-09-14T20:46:03.197400Z

The 2nd example seems to be specifically about your problem

seancorfield 2020-09-14T20:47:27.197600Z

That gives me this warning

(warn)  option ':interactive' is not applicable for this task.

Franklin 2020-09-14T20:48:27.197800Z

sorry.. that's not the correct command

Franklin 2020-09-14T20:48:44.198Z

lein ancient upgrade :interactive

Malik Kennedy 2020-09-14T20:49:24.198200Z

Oops, youre right thanks!

seancorfield 2020-09-14T20:52:00.198500Z

Okay, the conflict is coming from onelog "0.5.0" which is bringing in an older version of Aviso:

Retrieving io/aviso/pretty/0.1.12/pretty-0.1.12.pom from clojars

seancorfield 2020-09-14T20:52:25.198700Z

I did lein deps :tree and looked through to see what was using aviso pretty.

seancorfield 2020-09-14T20:53:00.198900Z

That is earlier than the change to pretty which introduced the *traditional* var (0.1.15).

seancorfield 2020-09-14T20:54:55.199100Z

And the problem shows up when lein ancient tries to run your tests after the updates I think...?

Franklin 2020-09-14T20:55:41.199300Z

yes

seancorfield 2020-09-14T20:56:33.199500Z

Possible solutions: add :exclusions to the onelog dependency to exclude io.aviso/pretty; or add a top-level dependency directly on io.aviso/pretty "0.1.37"

Franklin 2020-09-14T20:57:20.199700Z

alright... thanks will try that.... I didn't think of using lein deps :tree... that's one new thing I just learned

seancorfield 2020-09-14T20:57:20.199900Z

That still may not work, because onelog may depend on something in the older version of Aviso Pretty but it's worth a try.

๐Ÿ‘ 1
seancorfield 2020-09-14T20:58:27.200200Z

I would definitely recommend not using interactive tools that "help" by modifying your project configuration -- do it manually instead.

Franklin 2020-09-14T20:59:09.200400Z

Thanks you very much... It's pretty late over here... so I'm going to sleep on in though... it's pretty late on this side of the planet... ๐Ÿ˜„

seancorfield 2020-09-14T20:59:40.200600Z

I personally would also recommend not using Midje. It's considered non-idiomatic and drags in a lot of transitive dependencies that can be problematic.

Franklin 2020-09-14T21:00:06.200800Z

what do you think is the better substitute for midje?

seancorfield 2020-09-14T21:00:16.201Z

Just use plain old clojure.test

Franklin 2020-09-14T21:00:25.201200Z

aaah... alright

seancorfield 2020-09-14T21:00:37.201400Z

Midje isn't compatible with any standard test runners or test tooling.

seancorfield 2020-09-14T21:01:56.201600Z

It's why I created expectations.clojure.test so there's a fully clojure.test-compatible version of Expectations. It provides the expressiveness of classic Expectations but still lets you use all the standard clojure.test tooling built into all the editors and (standard) test runners.

mkurtak 2020-09-14T21:19:42.205400Z

Hi Iโ€™m having a trouble with implementing priority queue with sorted-set-by. I am not able to figure out how to implement โ€œdequeโ€ operation. first function correctly returns element with lowest priority, but i am not able to get sorted set without the first element using supplied comparator.

(sorted? (rest (sorted-set my-compare [3 1 2 4])))
returns false Could anybody help?

dpsutton 2020-09-14T21:26:05.206500Z

if you're using clojure.core/sorted-set it takes the elements of the set, not a comparator and a collection as you are using it. what is returned from (sorted-set my-compare [3 1 2 4])?

dpsutton 2020-09-14T21:29:56.206900Z

did you mean to use sorted-set-by ?

dpsutton 2020-09-14T21:33:13.208300Z

but just kinda doing dimensional analysis on it, the sorting of the set has a custom sorter whereas the call to sorted? does not use this custom sorter. So most likely they will not agree. EDIT: just read how sorted? works and this doesn't seem true to me now. the sorted-set will implement clojure.lang.Sorted. but the seq returned from rest won't

jsn 2020-09-14T21:36:03.208600Z

but rest returns a seq, not a set

jsn 2020-09-14T21:38:53.209200Z

@michal.kurtak try using disj perhaps?

mkurtak 2020-09-14T21:47:27.210700Z

sorry iโ€™ve used sorted-set-by of course. the thing is, iโ€™ve expected that rest function returns same collection type but without the first elemenet

jsn 2020-09-14T21:50:25.211800Z

I wonder if sorted-set is a good fit for priority queues; it's gonna drop items if the comparator sees them as equal

mkurtak 2020-09-14T21:51:23.212700Z

yes, i understand your point. i have unique values so i thought it is good enough. The disj trick worked. Thank you

mkurtak 2020-09-14T21:52:33.213300Z

This is the code without comparator (but the same works with comparator)

(let [s (sorted-set 3 2 1 4)]
    (sorted? (disj s
                   (first s))))

mkurtak 2020-09-14T21:55:45.214300Z

BTW, what will you suggest for priority queue? sorted-map?

jsn 2020-09-14T21:57:04.215700Z

no idea. my first take would still probably be sorted-set-by, but with some kind of tie-breaker (or, as in your case, a guarantee that there are no duplicates)

jsn 2020-09-14T22:00:12.216600Z

or a sorted-map with sets / vectors for values, depending on what the specific task needs

seancorfield 2020-09-14T22:46:13.217800Z

@michal.kurtak Have you looked at clojure.data.priority-map? https://github.com/clojure/data.priority-map (I am not the author or maintainer, despite having made the most recent commit)

mkurtak 2020-09-15T14:19:38.233300Z

Hi, thank you for your tip. I think this what i โ€™ve been looking for the case with non-unique values (for unique values sorted-set is sufficient). Iโ€™ve also managed to use sorted-map with little trick from https://clojuredocs.org/clojure.core/sorted-map-by (you have to wrap sorted-map-by to data that holds both sorted and unsorted map and lookup for value in unsorted map in comparator), but clojure.data.priority-map is better because all standart colletion functions (first, rest, count, containsโ€ฆ) work out of box without wrappers

2020-09-14T22:56:17.218Z

You could have the sort key be not only the length, but a vector of [length string-value]. That will sort first by the length, and only use the string-value as a tie-breaker for same-length strings.

2020-09-14T22:59:02.218200Z

Note that if your input strings have duplicates of the same identical string, then sorted-set-by will only include one of those in the resulting sorted-set.

2020-09-14T23:00:23.218400Z

If you want to retain duplicates, then it sounds more like what you would want is to sort a sequence, i.e. list, vector, array, etc., and give back a sequence with the same number of items, including any duplicate strings in the input. That cannot be done with a sorted-set unless you somehow make each equal string into different values, e.g. by making it a vector with a unique id for each string or something like that.

2020-09-14T23:01:14.218600Z

It can be done with a vector or array, and you can use sort or sort-by with appropriate comparator functions.