clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
cfleming 2020-09-29T00:01:17.313800Z

No, itโ€™s something weirder than that:

(prn (first (errors-from (:new (second errors)))))
{:unexpected :except, :expected #{":only" ":rename" ":exclude" :eof}}
=> nil
(prn {:unexpected :except, :expected #{":only" ":rename" ":exclude" :eof}})
{:unexpected :except, :expected #{":only" ":rename" ":exclude" :eof}}
=> nil
(contains? common-errors (first (errors-from (:new (second errors)))))
=> false
(= {:unexpected :except, :expected #{":only" ":rename" ":exclude" :eof}} (first (errors-from (:new (second errors)))))
=> false

cfleming 2020-09-29T00:04:20.314600Z

Arg, one of those keywords is an AST class which prints as the actual keyword:

(->> (tree-seq #(or (sequential? %) (map? %)) identity (first (errors-from (:new (second errors)))))
       (mapv #(vector % (class %))))
=>
[[{:unexpected :except, :expected #{":only" ":rename" ":exclude" :eof}} clojure.lang.PersistentArrayMap]
 [[:unexpected :except] clojure.lang.MapEntry]
 [:unexpected clojure.lang.Keyword]
 [:except cursive.psi.impl.ClEditorKeyword]
 [[:expected #{":only" ":rename" ":exclude" :eof}] clojure.lang.MapEntry]
 [:expected clojure.lang.Keyword]
 [#{":only" ":rename" ":exclude" :eof} clojure.lang.PersistentHashSet]]

cfleming 2020-09-29T00:05:01.314900Z

That would do it ๐Ÿ™‚

cfleming 2020-09-29T00:06:33.315700Z

They donโ€™t normally do that but I defined a print-method for them for some testing a while back.

2020-09-29T00:06:33.315800Z

it was tricky printing like I thought!

cfleming 2020-09-29T00:06:42.316Z

Indeed it was!

plexus 2020-09-29T06:20:27.317800Z

Are there any tools/libraries that help moving/renaming namespaces in bulk, including references? I found clojure.tools.namespace.move but I'm wondering if anything better has come along since, since it just does a naive regex replace

codeasone 2020-09-29T13:53:11.330200Z

I heard that Cursive was great for this sort of thing. I'm not a cursive user myself, but it maybe worth taking a look at how it is handling such refactors.

Vladislav 2020-09-29T16:02:31.331300Z

use cursive for it, as mentioned above

jumar 2020-09-30T08:15:39.342400Z

Clj-refactor was able to do it too - bot sure if thatโ€™s using clojure.tools

slipset 2020-09-29T08:53:58.323400Z

A little something about protocols: My first question is: is this the correct way to type-hint the return type of a fn in a protocol?:

(defprotocol Foo
  (^String foo [this]))

;; foo should be typehinted to return a String
This seems correct to me, but I'm not familiar nor comfortable with type-hints. Second question. Given a multi-arity protocol function, is this the correct way to type-hint it?
(defprotocol Bar
  (^String bar
    [this]
    [this that]))
Follow up question (which I'm not sure is very sensical, is there a way to have a different return type on these two fns? Third or fourth question, depending, when I look at the macroexpand of the Foo protocol, there's a lot going on, but I find this bit interesting:
(gen-interface
    :name
    typehints.protocols.Foo
    :methods
    ([foo [] Object]))
So even though I've type-hinted foo to return a String, it seems like the interface method is generated with a return type of Object ?

Cameron 2020-09-29T09:23:33.323800Z

I have to go but I may write more in a bit when I'm back, hope that helps at least

slipset 2020-09-29T09:33:14.324Z

It does, thanks!

nickt 2020-09-29T12:23:34.325300Z

Hey folks, how can I use interleave such that lists of different lengths zip with nil? e.g. (partition 2 (interleave [1 2 3] [4 5])) => ((1 4) (2 5) (3 nil))

nickt 2020-09-29T12:24:17.325600Z

oops, fixed

MatthewLisp 2020-09-29T12:32:22.326600Z

Hello folks ๐Ÿ˜„ Does anyone happen to have worked with .HAR files in Clojure? is there any libraries ready to use? I haven't found any

2020-09-29T12:35:09.326800Z

I wrote my one version of interleave)

(defn exhaustive-interleave
  "Same as clojure.core/interleave but continue until any input is not empty"
  {:added "1.0"
   :static true}
  ([] ())
  ([c1] (lazy-seq c1))
  ([c1 c2]
   (lazy-seq
    (let [s1 (seq c1) s2 (seq c2)]
      (when (or s1 s2)
        (cons (first s1) (cons (first s2)
                               (exhaustive-interleave (rest s1) (rest s2))))))))
  ([c1 c2 & colls]
   (lazy-seq
    (let [ss (map seq (conj colls c2 c1))]
      (when (some identity ss)
        (concat (map first ss) (apply exhaustive-interleave (map rest ss))))))))

javahippie 2020-09-29T12:35:20.327Z

Do you mean this one? https://en.wikipedia.org/wiki/HAR_(file_format)

MatthewLisp 2020-09-29T12:35:32.327300Z

yes

MatthewLisp 2020-09-29T12:36:25.327500Z

technically it's just a JSON ๐Ÿ˜… but i wonder if there's anything beyond only parsing it as JSON

javahippie 2020-09-29T12:36:43.327700Z

When I read the spec correctly, it is json based. If thatโ€™s the case, you could process with e.g. cheshire

javahippie 2020-09-29T12:37:25.327900Z

Ah, now I get you. What things beyond parsing do you have in mind?

nickt 2020-09-29T12:40:12.328100Z

๐Ÿค˜ thanks

markmarkmark 2020-09-29T12:40:48.328300Z

here's a one-liner that does the zip: (defn zip [[a & as] [b & bs]] (lazy-seq (cons [a b] (when (some seq [as bs]) (zip as bs)))))

MatthewLisp 2020-09-29T12:45:20.328500Z

Honestly i don't know, but if anyone made anything i'd like to check it out before reinventing the wheel

MatthewLisp 2020-09-29T12:45:46.328700Z

maybe i'll find out while building my solution ๐Ÿ˜„

ghadi 2020-09-29T13:29:00.329800Z

(concat shorter-end (repeat nil)) then interleave as normal

evocatus 2020-09-29T17:43:30.332Z

Do you miss Leiningen templates when using cli-tools?

practicalli-john 2020-09-30T09:46:21.343300Z

I've been using Clojure CLI this year after about 9 years of using Leiningen and it's templates. At first I missed a few templates until I realised I could just create a deps.edn file and copy over the dependencies. I don't miss using Leiningen plugins. They were useful when I started learning, but did hide away details of how things worked. I'm now creating my own templates for Clojure CLI tools, it seems very straightforward when using clj-new template, a template to create templates.

๐Ÿ‘ 1
evocatus 2020-09-29T17:44:24.332800Z

If you do full-stack development do you make it one big project (backend+frontend) or separate them?

practicalli-john 2020-09-30T09:49:08.343600Z

Unless there is reason to create a monolithic full stack app, I will separate front from back. This encourages development of a good API around the backend and allows greater flexibility in the architecture. It's also easier to scale separate parts for their own specific needs

๐Ÿ‘ 1
evocatus 2020-09-30T22:02:33.356900Z

I get your point, thanks

alexmiller 2020-09-29T17:47:04.333200Z

you can still use leiningen templates with the cli tools with clj-new

seancorfield 2020-09-29T18:07:14.333900Z

@gr.evocatus https://github.com/seancorfield/clj-new is what Alex is referring to. See a list of CLI tools here https://github.com/clojure/tools.deps.alpha/wiki/Tools

๐Ÿ‘ 1
2020-09-29T18:58:32.334600Z

(cond-> {:foo "foo"}
        true (assoc :bar "bar")
        true (update :foo str "123")
        some-bool? (assoc :baz "baz"))
How would I go about making this a bit nicer? Specifically avoid the trues for the default operations.

ghadi 2020-09-29T18:59:35.335100Z

mix -> and cond->

ghadi 2020-09-29T18:59:52.335800Z

(-> {:foo "foo"}
    (assoc :bar "bar")
    (update :foo str "123")
    (cond-> some-bool? (assoc :baz "baz"))

2020-09-29T18:59:55.335900Z

Does that play nicely with multiple conditions? e.g:

(cond-> {:foo "foo"}
        true (assoc :bar "bar")
        true (update :foo str "123")
        some-bool? (assoc :baz "baz")
        some-other-bool? (assoc :quux "quux"))

2020-09-29T19:02:09.336200Z

I guess I'd end up with:

(-> {:foo "foo"}
    (assoc :bar "bar")
    (update :foo str "123")
    (cond-> some-bool? (assoc :baz "baz")
            some-other-bool? (assoc :quux "quux")))

2020-09-29T19:02:30.336600Z

Looks good to me! Thanks @ghadi

ghadi 2020-09-29T19:10:01.336900Z

np. @curlyfry a little of that can go a long way

mafcocinco 2020-09-29T19:21:09.337200Z

Could also do this:

(cond-> {:foo "foo123" :bar "bar"}
        some-bool? (assoc :baz "baz"))
The things that are always true can just be included in the initialization step fo the map.

mafcocinco 2020-09-29T19:22:34.337400Z

Without more context on how dynamic you need it to be, Iโ€™m not sure. But the general principle holds that anything in a static true section should be moveable into the initial map.

2020-09-29T19:49:34.337900Z

@curlyfry alternatively merge:

(merge {:foo "foo"}
       {:bar "bar"
        :foo "123"}
       (when some-bool?
         {:baz "baz"})
       (when some-other-bool?
         {:quux "quux"}))

2020-09-29T19:52:01.338800Z

Requires that you explicitly get update values, but itโ€™s extremely straightforward:

(let [{foo :foo} mah-map]
  (merge {:bar "bar"
          :foo (str foo "123")}
         (when some-bool?
           {:baz "baz"})
         (when some-other-bool?
           {:quux "quux"})))