Fork me on GitHub

does anyone have an example of using etaoin? I've tried lein new app etaoinexample and then adding the dependency.

:dependencies [[org.clojure/clojure "1.10.1"]
                 [etaoin "0.4.1"]]
but I get this error:
Unable to resolve symbol: firefox in this context
where I try to call this in core.clj: (def driver (firefox))


In the instructions that contain that expression, several lines above is this one: (use 'etaoin.api). Did you perhaps skip that?


It might be preferable to create a namespace where you write your code, e.g. (ns my.project.namespace (:require [etaoin.api :as api])) and then you can use api/firefox instead of just firefox


this helps me, thanks. It's one of the hardest parts of clojure to me: trying to figure out the ceremony of :require I'm not sure where I'm missing the explanation in the docs


I appreciate your help.

Aviv Kotek10:11:40

with lein, there is :dev and :test profiles, it's not to use :test profile, should the :dev profile be used for test purposes? i.e include test-lib dep, etc? then "lein with-profiles dev test"? I find it more intuitive just to run "lein test"(which merges :test profile if declared), what are the differences between :dev and :test profiles? which should I pick?


lein test should already merge in the dev profile IIRC, and with-profile foo is almost always an error (it replaces the profile for the task), you usually want with-profile +foo (it merges new data to the profile for the task)

🙏 1

Each profile should be dedicated to some task, and you might want a supplimental profile to enable integration as opposed to just unit tests for example. You shouldn't need to manipulate profiles for normal tasks.

Aviv Kotek08:11:23

there is one disadvantage of "test" not able to run in REPL (running tests), so in conclusion- it's common to use the :test profile for tests?


the :test profile is always used for the :test task, if you want to run tests in your repl, you might want to add with-profile +test to your repl startup


What are my options when using NPM packages with Figwheel? I don’t have shadow-cljs as an option anymore, and figwheel’s NPM guide constantly leads to compilation errors for me.


I only need to use a single NPM package, is there a manual / hacky workaround with externs and the Closure Compiler?


The package is react-spring, I can’t find it on CLJSJS.


@seancorfield i look forward to your REPL presentation next month


Thanks @st3fan -- if there's anything specific you'd like to see/hear about, LMK via DM and I'll see whether I can incorporate it. I want it to be an interactive talk/demo so folks can get as much out of it as possible!

👍 4

Just show us the magic 🙂

👍 3

Hi! I’m not sure if this is an appropriate question for the channel, but was wondering if y’all had advice on “code smells”, or moving toward more idiomatic clojure. I have a couple functions that map a map of a map, and the repetition is making me feel like i’m doing something incorrect…but am not quite sure how to best phrase the incorrectness beyond “doesn’t feel clojurey”.


For example, a fn “text->env-map” which takes text like CLOJURE=cool\nREPL=awesome\n and converts it to ({"CLOJURE" "cool"}{"REPL" "awesome"})


I have it written, and working, as so:

(defn text->env-map
  (map #(conj {} %)
        (map #(clojure.string/split % #"=")
             (clojure.string/split-lines text))))

Lennart Buit21:11:47

You can use a transducer here, or threading


for all f,g (map f (map g x)) can be replaced with (map (comp f g) x)


But i am still pretty new to clojure, and am not sure if i’m taking too blunt of an approach.


it’s just feeling increasingly unreadable.


so in your case (comp #(conj {} %) #(string/split % #"=")) or just #(conj {} (string/split % #"="))


Ah! I had not used comp before, that’s really nice!


Check out the threading macros for making deeply nested chains of calls like that more readable, too:


(->> x (map f) (map g)) is worse than comp IMHO


(though I see it more often)


Good point. I’ve used threading macros, but maps trip me up because of the order of the variable being put in.


(e.g. i have a set of functions where (-> ) works great, as the second position is perfect, but then i want to pass that to a map, and it now needs to be the last position)


Agree in this specific case, comp is a better way to go


I still prefer the threaded version. for me, it's easier to read and extend


Thank you!


There is also ->> to put the thread in the last position


and some-> to short circuit in case a nil happens

👍 1

I like comp more for named functions: (comp foo bar) reads nice and clean. With literal functions, I may go with -> and multiple maps for readability. Puts each unit of work on different lines.


I suppose you can do that with comp, too


or just do that inside the function literal


yeah, or that


#(-&gt; % (string/split #"=") (-&gt;&gt; (conj {})))


OK never mind - the nesting works but it's dumb

😄 1

comp plus named functions seems to perhaps lend itself more nicely to spec and testing too? Or at least it’s encouraging a number of small, easy to reason about functions.


It really depends on what exactly you’re doing.. judgement call which is better in a particular case


Over-testing is as bad as under-testing IMO


The natural question is then what’s the right balance? Well.. hard to answer in a general way.


Adding ever more tests is diminishing returns, after some point. Each unit of resources to add a new test prevents fewer bugs. Bugs are, by definition, problems nobody thought of. Problems for which there was no test case. There are plenty of code bases with a million micro-unit tests for every (+ 2 2) level function, which still have large bugs anyway. It depends a lot on how much damage happens if there’s a failure. If you are launching a Space Shuttle or doing life-critical code like building a pacemaker, you should probably go overboard on testing every possible code path. Most commercial software has much less harsh failure modes, though.


hahaha, yah my scenario is a bit less mission critical.