Fork me on GitHub
#beginners
<
2019-11-28
>
Sam Ferrell01:11:18

i'm defining a new client/server protocol in which the client sends EDN to the server in the shape of ... {:kind :tx :data {:name :foo/bar :args [13 "baz" :fizz]}}

Sam Ferrell01:11:55

basically i want to "route" the request based on the :kind and :name

Sam Ferrell01:11:13

would using a multimethod seem like an obvious choice for this?

valerauko03:11:09

iirc defmulti can handle one pattern at a time so you'd have to write it separately for kind and name

solf03:11:08

defmulti takes a function in parameter, you can write (fn [x] [(:kind x) (get-in x [:data :name]) in defmulti and match it with e.g. (defmethod foo [:tx :foo/bar] ...)

💯 4
solf03:11:11

Any way of setting *warn-on-reflection* true only for our own files? I'm flooded with warnings from dependencies

valerauko04:11:56

how does it behave if you set it through leiningen's :global-vars ?

andy.fingerhut04:11:41

You can put (set! **warn-on-reflection** true) in individual source files.

solf06:11:04

Right now it's set through lein's :global-vars, I was hoping there was a way to set it on, say, all ./src files

solf06:11:03

Although when you set it on a source file, it stills applies to every other source file right? As it's a global var. So maybe setting it in the entry point of my app instead of in lein's global-vars does what I want

andy.fingerhut06:11:35

It is bound in each file, not globally, in my experience, when you use that expression in a source file.

andy.fingerhut06:11:46

If a source file does something like load-file on other source files (which is pretty uncommon from Clojure projects I have seen), then I think it propagates through to the files being loaded, but it does not propagate to other namespaces that a namespace requires, for example.

andy.fingerhut06:11:54

I mean, try it and see.

solf07:11:56

you're correct, I had tested in a repl before and it seemed to propagate, but it actually seems source-file bound

keymone13:11:00

what's the right incantation to make (s/def (f "foo") any?) work? spec complains that k must be fully qualified keyword so i'm trying to make a macro that returns essentially ::foo but no luck so far

keymone13:11:50

(let [nk (f "foo")] (s/def nk any?)) works, so /shrug

keymone13:11:20

eh... no it doesn't

keymone14:11:18

something like this works though:

(defmacro nsdef [k spec]
  `(s/def ~(keyword namespace-name (cond-> k keyword? name string? identity))
     ~spec))

keymone14:11:43

no, it still doesn't goddamit

JanisOlex13:11:23

Hi, people. I need UI component I can use in my browser which allows to edit clojure code (does some syntax highlight, bracketing, idention) and thats all In general from REPL I neeed R part... as E part will be handled by clojure on the server

Edward Hughes15:11:18

Well, the nice thing there is that functionally you're reading a string from a field and passing it to a server-side REPL. You can use the interface from this if you wanted something ready made, though implementing paren-matching/function highligting would be good for practice. https://github.com/oakes/Nightlight

JanisOlex16:11:55

But NIghtLight is full fledged IDE, I just want some sort of I dont know simple "TextArea" sort of tag or something I can drop into the page.... I doubt I can integrate whole nightlight in a simple web browser app

Edward Hughes16:11:29

<title contenteditable>Hello World</title> <style contenteditable>head, title, style {display: block;}</style>

Edward Hughes16:11:23

You'll want to set the font-family: and white-space: properties for it to monospace and pre to get the font and preserve line breaks.

Michaël Salihi08:11:20

You have Klipse https://github.com/viebel/klipse There are Clj/Cljs demo on this page : https://book.klipse.tech/

Adrian Smith16:11:38

Do we have any editors yet that can do this: https://www.youtube.com/watch?v=d8-b6QEN-rk ?

naiali16:11:11

Hi peepz, I am trying to install tailwindcss webjar, but lein deps fails with

Could not find metadata org.webjars.npm:caniuse-lite/maven-metadata.xml in local (/home/naiali/.m2/repository)
Failure to find org.webjars.npm:caniuse-lite/maven-metadata.xml in  was cached in the local repository, resolution will not be reattempted until the update interval of clojars has elapsed or updates are forced
Could not find metadata org.webjars.npm:caniuse-lite/maven-metadata.xml in local (/home/naiali/.m2/repository)
I removed .m2 and tried again, no joy 😅 complete n00b here, so I am completely stuck

delaguardo16:11:13

I don’t know tailwindcss webjars, but there is a library to work with tailwind from clojure - https://github.com/mrmcc3/tailwind-clj

naiali16:11:10

brilliant! I'll give it a try. Thank you!

naiali16:11:37

where do I start looking/fixing?

zyxmn17:11:20

is zipmap expected to keep the order of keys in the map generated to be same as the keys coll arg ?

hiredman17:11:26

The map zipmap creates is a hashmap, which are not ordered

hiredman17:11:30

In general the default for maps in clojure is unordered

zyxmn17:11:47

thanks , just noticed that it is ordered to keys arg for colls of size 8 or less , anything larger the result is unordered

yuhan17:11:53

That's an implementation detail you shouldn't rely on (array-map vs hash-map)

yuhan17:11:39

(type {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8})
;; => clojure.lang.PersistentArrayMap

(type {1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9})
;; => clojure.lang.PersistentHashMap

zyxmn17:11:54

:thumbsup:

yuhan17:11:51

Interestingly, the explicit hash-map constructor with 0 args returns the wrong type

(type (hash-map))
;; => clojure.lang.PersistentArrayMap

yuhan17:11:56

I wonder if that is a bug

zyxmn17:11:40

its not what it says on the tin , so probably it is a bug

seancorfield18:11:54

Hash maps with small numbers of elements (including zero elements) are implemented as array maps. Not a bug.

seancorfield18:11:17

user=> (type {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8})
clojure.lang.PersistentArrayMap
user=> (type {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9})
clojure.lang.PersistentHashMap
user=> 
The change is at the 8/9 element boundary @qythium /cc @zyxmndaleyjes

seancorfield18:11:52

Ah, I see you already posted that above. Anyways, not a bug -- by design.

👍 4
zyxmn18:11:21

I've added an example to zipmap just in case someone else mistakes it to be ordered like I did

seancorfield18:11:01

Yeah, it's tempting when tutorials use small hash maps and they seem to maintain order.

seancorfield18:11:16

I would avoid such things, personally, because it has the potential to be very confusing: built-in hash maps and sets being unordered, mixed with code that expects "special" hash maps and sets to be ordered. To say nothing of the issue of predictable performance on lookup/traversal...

andy.fingerhut18:11:35

I am pretty sure that at least some of the third party ordered set/map implementations have good performance guarantees.

andy.fingerhut18:11:18

As you warn about, though, all it takes is one call to some function like merge or similar, with a non-ordered map in the "wrong" position, to return an unordered map again.

yuhan18:11:59

Yep, I understand the whole implementation/interchangeability thing, but I would think the hash-map and array-map functions were supposed to explicitly return those respective types

yuhan18:11:53

from the source code:

(defn hash-map
  "keyval => key val
  Returns a new hash map with supplied mappings.  If any keys are
  equal, they are handled as if by repeated uses of assoc."
  {:added "1.0"
   :static true}
  ([] {})
  ([& keyvals]
   (. clojure.lang.PersistentHashMap (create keyvals))))

seancorfield19:11:16

Ah, I'd missed the subtlety of that... I guess now I'm more surprised that (hash-map :a 1) does not produce an array map! 🙂

yuhan18:11:42

(type (hash-map :a 1)) ;; => clojure.lang.PersistentHashMap

yuhan18:11:56

also, (self-hosted) clojurescript has the "correct" behaviour:

$ lumo
ClojureScript 1.10.520
cljs.user=> (type (hash-map))
cljs.core/PersistentHashMap

andy.fingerhut18:11:20

It does seem a bit surprising, perhaps, that hash-map can return an object of type PersistentArrayMap, but yeah, if you try writing code that treats the concrete type of map returned by a function as an implementation detail, with no ordering guarantees (unless it is one of the ordered map types that explicitly guarantee ordering), then you will be happier long term.

👍 4
gibb19:11:10

I’m pretty new to Clojure and I am wondering about declaring variables in the leiningen project.clj file. I want to implement some gRPC services and the dependencies look like this:

[io.grpc/grpc-core "1.13.1"]
   [io.grpc/grpc-netty "1.13.1"]
   [io.grpc/grpc-protobuf "1.13.1"]
   [io.grpc/grpc-stub "1.13.1"] 
Is there any way I could declare the version string there in a variable to avoid some writing?

seancorfield19:11:20

@gbson You can but it relies on a "quirk" of Leiningen and you wouldn't be able to do that if you switched to CLI/`deps.edn` at some future date.

seancorfield19:11:34

You could put (def grpc-version "1.13.1") above the defproject form in project.clj and then use ~grpc-version in the dependency vector to get the version value substituted as I recall (been a long time since I've used Leiningen!).

gibb19:11:47

Ah - should I perhaps use some other build tools now?

gibb19:11:12

I’m only building a really simple application now to move some data around, to get familiar with the language

seancorfield19:11:01

Leiningen is a "classic" and most tutorials/books still use it but more and more people are using the "official" CLI (`clj` / clojure scripts) with deps.edn.

seancorfield19:11:14

Are you on Windows or macOS/Linux?

gibb19:11:27

Develop on mac and deploy on linux

seancorfield19:11:52

'k, so you can brew install clojure to get the new CLI tools.

seancorfield19:11:10

(assuming you already have Homebrew on your Mac!)

gibb19:11:43

Ooh git dependencies!

seancorfield19:11:53

Git and local deps, yeah. Lots of nice stuff with the new tooling.

seancorfield19:11:19

Check out https://github.com/seancorfield/dot-clojure as a guide for what you can do with your ~/.clojure/deps.edn file.

gibb19:11:33

Nice - currently we provide our api stubs as git projects so it may be very easy to use them here then

gibb19:11:34

Oh clojure works with java 11 now? That’s neat

andy.fingerhut19:11:03

Clojure 1.10.x works with all JDK versions 8 and later.

andy.fingerhut19:11:46

There are a few issues with warnings/etc. that you might experience on later JDKs that do not occur with earlier JDKs, but those are mostly because of tightening security restrictions in later JDKs, less because of Clojure. e.g. as described here: https://clojure.org/guides/faq#illegal_access

andy.fingerhut19:11:05

which you can mostly ignore, and/or handle via techniques described in the answer there, if you care to.

Darrell20:11:38

Is there a simple way of generating a random boolean?

andy.fingerhut20:11:51

(= (rand-int 2) 0) should return true or false with equal probability.

andy.fingerhut20:11:23

You can use rand-int with a larger range, and whatever condition on the return value you want, if you want non-equal probabilities for true vs. false.

didibus23:11:46

@darrell I normally just do: (rand-nth [true false])

Darrell18:11:34

Thanks @U0K064KQV! Sorry for the late reply. I had to run to dinner yesterday.