Fork me on GitHub

hi guys I believe I found a potential bug with

user=> (def ACTIVE true)
(def ACTIVE true)
user=> (match [nil] [ACTIVE] 1)
(match [nil] [ACTIVE] 1)
or perhaps i may be doing something wrong.. any clues? whereas the same thing, if I use true directly works as expected
user=> (match [nil] [true] 1)
(match [nil] [true] 1)

IllegalArgumentException No matching clause:   user/eval6529 (form-init8320221599224080614.clj:1)


@ragsboss : I am NOT a developer of core.match. However, (1) I can replicate the problem you have reported and (2) I agree with you in that I'm not expecting it to match.


qqq: @qqq thank you for your input on this. I realized what I was doing wrong. The way I’m using it ACTIVE inside the match will bind to the matched value instead of what we naturally expect.. this is explained in scope and Symbols.. I found this unintuitive but not sure how to report it as I see no way to contact the authors of this package..


@ragsboss : oh, so the point is "ACTIVE" is a global, NOT a local, thus it binds ACTIVE instead of looks up the vaule of ACTIVE ?

Oliver George12:05:00

I suspect the clojure JIRA server has a place for core.match but I can't see a solution to avoid the surprise short of improved documentation.

Oliver George02:05:15

I think the confusion is "matching literal" vs "binding"


I’ve a map like:

{k1 v1
 k2 v2}
where k1 and k2 are strings and the (nonzero) values of v1 and v2 should sum to 0. Given such a map, I’d like to destructure it and bind the k for positive v to a var (call it to) and k for negative v to another var (call it from). However, either v1 or v2 could be the pos/neg value. Is there a way to do this without an if? core.{logic, unify} maybe (though that seems a bit heavy-handed)?


(let [[[k1 v1] [k2 v2]] (sort-by val m)] ...)


noisesmith: An elegant solution--thanks!


or with the other names (let [[[from v1] [to v2]] (sort-by val m)] ...)


+user=> (let [[[from v1] [to v2]] (sort-by val {:a 2 :b -2})] [from to])
[:b :a]


(defn foo [^:bar x]
  ... is there anything I can do here
  ... which will get me the value :bar


(defn foo [^:bar x] (prn x)) (defn get-hint [the-fn] (map meta (first (:arglists (meta the-fn))))) (get-hint #'foo) ({:bar true}) you can outside but maybe it is very unlikely whilst the var is being defined


i.e (defn foo [^:bar x] (let [qqq (get-hint #'foo)] (prn qqq))) won't work


@gmercer : in summary: outside; possible inuside :not obvious how to do the (:arglists (meta the-fn)) 'trick' is realy cool


I never thought of that; thanks!


@qqq see last statement of (source defn) for clues


however, is there a book of common 'clojure patterns' ?


I often feel when coding that I have working, but ugly code; whereas there should be some idiom that solves the problem cleanly


@qqq until such a book is written, I think you can ask for per-case suggestions here once in a while. maybe there are books about "functional programming" or "lisp" patterns not necessarily clojure ones, the number of clojure practitioners might be too small to yield books.


Joy Of Clojure? "Thinking the Clojure way" seem's to be the premise you're looking for @qqq


read this book several years ago, I am not sure it is the best functional patterns dictionary out there. more of a high-level tour for the simple idioms. I might be wrong of course.


in clojure, in jargon and otherwise, what are the differences between a form and an expression?


@qqq possibly a bit way out .. The Little Schemer - actually do the exercises in Dr. Racket, Practical Common Lisp - again Dr. Racket is your friend, How To Design Programs (Scheme) MIT Press ... these recommendations are relevant if you are referring to breaking your imperative programming habits - also watching MIT 6.001 Structure and Interpretation;list=PLE18841CABEA24090


If you were writing an user facing API for some software that you've written, and you wanted to add a verbose option, what would be the most elegant way to achieve this? My knee jerk reaction would be to litter my code with (if verbose print.... Etc but this seems messy and inelegant to me. Is there some other magic I could work with macros for instance to create verbose versions of my functions?


doesn't this map directly to log levels?


with the right log formatter it could work


@noisesmith this looks very relevant, I haven't used or seen this before, thanks for the suggestion I'll check it out :)


hey everyone, I am new to clojure and STM and have a question, a ref's value is protected accross threads? that is if I have threads 1 and 2 and both execute a transaction in which they alter the same ref, one of those transactions will fail because a write was done before and retry? or is it only in a single thread? thanks a lot for your help


you can't possibly have two transactions at once in one thread


the point of STM is to protect data across threads


that's great! thanks a lot!


also, in real code, we rarely need refs/transactions, usually our updates to shared state are rare enough that using an atom and the swap! function suffices


that was my next question, I have a very specific case in which I'm not sure if a ref is best option. Can I DM you and explain it?


sure, but you can also discuss it here


I wish to create a course registration system that can be accessed by multiple students at the same time. So I have multiple schools which have multiple courses each. Each course has a number of available spots. Given that all the students should be able to register for courses at the same time (no matter the school), I thought that using a ref for each course should be the best option in order to avoid "overbooking of the courses" and also not blocking every course during a transaction.


for something like a course, wouldn't you want the data to persist if the server restarted?


this sounds more like a db thing


this is a personal project


I wish to do everything in memory


and mostly learn how to deal with parallelism and concurrency


OK - the easier way to do this is to have an atom with a hash-map with keys for each course


you can also use refs of course, but usually we don't turn to those until the contention on the atom is hurting performance


will try with an atom and see performance


then I'll try with a ref


thanks for your help


there's very little to this, but I find it useful so I figured I'd share: it's a lein project with no code, only a few dependencies, designed to create an uberjar for running a stand alone clojure with a few favorite deps


you probably would want a different list of static deps, but since it's a one file repo that's a pretty simple thing to fix up


Can anyone offer any advice on why attempting to open a website using up to date Selenide using

(import [com.codeborne.selenide Selenide])
(Selenide/open "")
opens the website using Firefox, but after around a minute closes WebDriver down with
May 06, 2017 7:27:55 PM com.codeborne.selenide.impl.WebDriverThreadLocalContainer closeUnusedWebdrivers
INFO: Thread 20 is dead. Let's close webdriver FirefoxDriver: firefox on ANY (da9dc339-3f7f-bb4f-aeec-953fefd1bf52)
May 06, 2017 7:27:55 PM com.codeborne.selenide.impl.WebDriverThreadLocalContainer closeWebDriver
INFO: Close webdriver: 20 -> FirefoxDriver: firefox on ANY (da9dc339-3f7f-bb4f-aeec-953fefd1bf52)
May 06, 2017 7:27:55 PM com.codeborne.selenide.impl.WebDriverThreadLocalContainer closeWebDriver
INFO: Close proxy server: 20 -> null
May 06, 2017 7:27:55 PM com.codeborne.selenide.impl.WebDriverThreadLocalContainer$CloseBrowser run
INFO: Trying to close the browser FirefoxDriver ...
1494095275784	Marionette	INFO	New connections will no longer be accepted
[Child 5121] ###!!! ABORT: Aborting on channel error.: file /builds/slave/m-rel-m64-00000000000000000000/build/src/ipc/glue/MessageChannel.cpp, line 2143
[Child 5121] ###!!! ABORT: Aborting on channel error.: file /builds/slave/m-rel-m64-00000000000000000000/build/src/ipc/glue/MessageChannel.cpp, line 2143
May 06, 2017 7:27:56 PM com.codeborne.selenide.impl.WebDriverThreadLocalContainer closeWebDriver
INFO: Closed webdriver in 264 ms
It appears to be something about the Repl. Native Java invoking the same api works fine.


how are you starting clojure?


my hunch is that clojure itself is unlikely to break the tool, but something in nrepl, REPLy, or leingengen, or boot etc. is more likely to be the culprit


lein repl or creating a repl using Cursive.


right, and cursive is using lein


lein new repl
and adding
[com.codeborne/selenide "4.4.3"]


I'd try lein trampoline repl which elminates the nrepl factor


and you can also try making an uberjar and running it with java -cp target/foo-standalone.jar -m clojure.main which also eliminates leinengen from the picture


@noisesmith trampoline hasn’t resolved it. Will try and uberjar. Cheers!


just fixed that uberjar invocation, and if the problem continues, I'd be interested to see what gdb says the program was doing around where that error happens...


@noisesmith just running using ..

(ns selenium-exploration.core
  (:import (com.codeborne.selenide Selenide))

(defn -main
  [& args]
  (Selenide/open "")
  (Thread/sleep 100000))


actually, that was a

lein run
than ran for 100 seconds fine.


Died invoking (-main) in the repl.



lein repl
(defn -main
  [& args]
  (Selenide/open "")
  (Thread/sleep (* 3 60 1000)))
loads the browser, which sits around for 4 minutes (3 minutes during Thread.sleep) and then a minute after. It always appears to last a minute after being in scope….




anything which used clojure's agent pools needs to call that to exit promptly


Not following. You suggest I call this? How would shutting anything down help to keep something (the web driver or associated thread) alive? I’m new to (shutdown-agents)


Unless you’re basically advising a change to keep it ‘in scope’. I’m just trying to assign the driver to an atom.


oh - sorry - I mean not calling (shutdown-agents) is what makes it last another minute after that


okay, that makes a bit more sense. Thank you 🙂


maybe you just need for -main not to exit? if that's the case you can just do @(promise) - guaranteed not to exit


Trying that, the atom attempt failed.


That seems to be working.


for something more sophisticated, if you have other stuff running too, you can have the main block on a promise, and then deliver to the promise when you are OK with it exiting


my assumption is that Selenide is somewhere starting a thread that's set as a daemon, so that if all the non-daemon threads exit it does too


So would a repl start a new thread for each command possibly?


no, not at all


so clearly something different is going wrong in the repl...


Selenide specifically isn’t a requirement for me, Selenium that it wraps is, so I’ll try with that. Maybe Selenide adds a more complex threading model.


Thanks for the help, I’ll keep digging for a while and try selenium direct.


Is there a Ring to Netty adapter that's more up-to-date than ? I'm having to do some ... unsavory things