Fork me on GitHub
#beginners
<
2020-03-18
>
jumpnbrownweasel00:03:44

@streetmapp I got the impression that you're wanting to create a static web app and only refresh pages occasionally, is that right? If so, people may be able to recommend Clojure server-side template libraries. Or did you want to create a single-page dynamic app? In that case @noisesmith is asking which ClojureScript framework you're using.

coldbrewedbrew00:03:58

@mark540 i'm really starting from nothing. It seemed like a simple project to get started with. I just have the fact I'll have data most likely generated in json form and want to have it end up represented in a table. I guess my end state would be to ultimately have things dynamic. But don't have much details outside of that just yet

jumpnbrownweasel00:03:30

If you're just learning I recommend starting with server-side HTML generation since there is much less to learn to get started. I have not been doing that in Clojure but others will have recommendations. I know that @seancorfield has recommended Selmer in the past.

seancorfield00:03:13

It might even be worth considering a command line process to read the JSON and generate HTML which you could run periodically (I'd probably still use Selmer for that) so you wouldn't even need a "web app" -- just somewhere to put your generated HTML and serve it.

v00:03:41

Hello, has anyone played with crux and rocksdb?

seancorfield01:03:20

Nope but there's a #crux channel full of folks who have. No idea about rocksdb.

clayton01:03:51

I have a question about fully qualified keywords, and when they might be used. I understand that ::keyword translates into something like :my-namespace/keyword, but I'm confused why that's useful. I've found a blog post (https://kotka.de/blog/2010/05/Did_you_know_III.html) that explains it a bit more, but the example use case it gives sounds very uncommon. From the blog post:

We all know and love :keywords. They are a often used as keys in maps and their ability to be called like a function on maps makes for some very concise code. However what happens if two libraries modify the same map? On the same key? Then we are in trouble, because one overwrites the other. To remedy this issue, Clojure provides (similar to Symbols) namespace-qualified keywords. Simply add a double-colon in front and the keyword will be qualified with the current namespace.
Does anyone know of a more common use case for fully qualified keywords? I'm new to clojure so maybe this use case is more common than it seems, but I wasn't very satisfied with this use case. Any help is appreciated 🙂

seancorfield01:03:19

That's a very old blog post. Things have changed a lot around qualified keywords, with the introduction of clojure.spec (which uses them heavily).

clayton02:03:46

thanks! will take a look at clojure.spec

andy.fingerhut02:03:42

You can of course avoid using ::keyword syntax, instead using :full.qualifer.typed.out/my-kw , or :namespace-alias/my-kw after doing a (:require [some.full.namespace.name :as namespace-alias]

👍 1
andy.fingerhut02:03:54

Those are just different syntax for the same resulting qualified keyword, but do not themselves demonstrate why you would want to use them.

Eddie02:03:54

Spec is definitely the dominate use case, and I think the use case mentioned in the blog post is still important, even if it is rare. If it does happen, it isn't the easiest thing to debug. I get particularly paranoid on the rare occasion that important information gets put into an object's metadata . Think of all generic attribute names that one might want to put into metadata (`:version`, :timestamp, etc). If you use qualified keywords, you won't get mixed up with the metadata from libraries (or maybe, if you application is large, your other code).

t-hanks 1
seancorfield02:03:50

Another use case I like to mention @clayton.marshall12 (sorry for the delay, I was eating dinner): in a database, id often exists in multiple tables as a primary key but its meaning is determined by the combination of the table and the PK. It's natural in Clojure to use qualified names for hash maps that represent rows from database tables, so you might have :product/id, :product/name, and :invoice/id, :person/id, :person/name and so on.

seancorfield02:03:12

That's why next.jdbc defaults to qualified keys for columns, using the table name as the qualifier -- and that works with joins as well.

thanks3 2
Gulli18:03:02

What is a good way to manage enviroment variables in a project (something similar to application.conf in Spring for instance)?

thom18:03:44

Aero is nice (although slightly opinionated about environment variables)

chrisulloa18:03:34

I would use stuart sierra component to load up environment variables @glfinn83

Gulli12:03:53

Hey @christian.gonzalez, could you share some code on how you do this? I've found tutorials on using mount and cprop

chrisulloa17:03:26

Hey there, this is the library I mentioned https://github.com/stuartsierra/component I would consider creating a config map that retrieves all the environment variables for your system (there can be different configs per environment, like dev, staging, prd) then passing it to your system

(defn example-system [config-options]
  (let [{:keys [host port]} config-options]
    (-> (component/system-map
          :config-options config-options // env vars passed to components here
          :db (new-database host port)
          :sched (new-scheduler)
          :app (example-component config-options))
        (component/system-using
          {:app {:database  :db
                 :scheduler :sched}}))))

chrisulloa17:03:48

It’s a bit of a learning curve compared to mount/cprop, but I think it’s actually worth it

mbarillier18:03:55

this is likely in 4clojure or a koan or something, but: what's the idiomatic way to transform two vectors into a map? e.g. (fn [:a :b :c] ["foo" "bar" "baz"]) => {:a "foo" :b "bar" :c "baz"}?

chrisulloa18:03:19

a component that defines the app config, then the start lifecycle loads up the env vars, but there are a few other tools for that if anyone else has ideas

Isaac Ballone20:03:07

I have a js file that exports only a single function, and I want to add it to my cljs project. So I made a folder externs/myfunc.js. Then I went into my project.clj to add :externs ["externs/myfunc.js"] under my compiler section of cljsbuild. So in theory Google Closure won't overwrite my function name when doing its magic. I'm using Intellij + Cursive and my IDE can see js/MyFunc is added to the namespace, but when I restart my code, it can't find it. So I guess my question is: am I supposed to include the js file in my HTML file, or is the cljs compiler supposed to pull in my externs file automagically?

noisesmith20:03:30

I haven't used cljs in a while but I thought the externs file should just include declarations and the actual code should be elsewhere

Isaac Ballone20:03:32

You know now that you mention that, I think I remember seeing some examples only having empty variables

noisesmith20:03:55

right, that's how externs files work, you need to put the js file elsewhere so it ends up in your app

Isaac Ballone20:03:55

I'm going to try including it in my HTML and call it good

noisesmith20:03:51

yeah, it should be sourced in the html and then the externs file makes sure references to those functions don't get rewritten when the cljs is optimized

Isaac Ballone20:03:15

Alright, so https://lispcast.com/clojurescript-externs/ showed an alternative solution so you can be lazy and use a library as an externs 🙂. Then you just put it :externs ["resources/public/js/yourfunc.js"] and disable any warnings with :closure-warnings {:externs-validation :off} . Now I can just include it in the header

noisesmith20:03:07

the link I posted above shows how to auto-generate externs, and also how to write them

noisesmith20:03:27

I'd think auto-generation is better than suppressing a warning if it works

Timur Latypoff21:03:02

What is the correct type hint for destructured map argument?

(defn type-hinted-fn [^MyRecord {:keys [a b c] :as ^MyRecord r}]
  r)
Is the first placement of ^MyRecord correct or the second one, or both are equivalent?

alexmiller21:03:04

latter I would think

alexmiller21:03:12

seems like that works

user=> (map meta (destructure '[{:keys [a b c] :as ^MyRecord r} x]))
(nil nil nil nil {:tag MyRecord} nil nil nil nil nil nil nil)

alexmiller21:03:07

it's really the local binding symbols that carry the meta

alexmiller21:03:49

I guess maybe a better question would be, why do you need to type hint the record?

alexmiller21:03:32

you don't see stuff like this very often as there are not many cases that could benefit from it

Timur Latypoff07:03:47

I am making a very high-volume real-time financial data service, and from profiling I think I am seeing assoc performance increase if I sprinkle type hints in a couple of critical places. I am not 100% sure how record field access is optimized, but I like to imagine that with type hints the compiler chooses a more "static" field access path. I might be imagining things though — will continue profiling today.

alexmiller12:03:12

I think you’re imagining things in this case