This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-05-11
Channels
- # beginners (132)
- # boot (2)
- # cider (17)
- # cljs-dev (6)
- # cljsrn (24)
- # clojure (134)
- # clojure-austin (2)
- # clojure-dusseldorf (11)
- # clojure-france (1)
- # clojure-greece (27)
- # clojure-italy (17)
- # clojure-madison (1)
- # clojure-russia (31)
- # clojure-serbia (1)
- # clojure-sg (2)
- # clojure-spec (30)
- # clojure-uk (66)
- # clojurescript (73)
- # core-async (2)
- # cursive (8)
- # data-science (2)
- # datomic (23)
- # dirac (8)
- # emacs (18)
- # gsoc (1)
- # hoplon (36)
- # immutant (26)
- # leiningen (6)
- # off-topic (21)
- # om (19)
- # onyx (6)
- # other-languages (1)
- # pedestal (3)
- # proton (2)
- # random (1)
- # re-frame (1)
- # reagent (2)
- # remote-jobs (2)
- # ring-swagger (8)
- # rum (21)
- # slack-help (1)
- # spacemacs (4)
- # specter (16)
- # untangled (6)
any of clojure's iteration constructs will coerce the string to a sequence
eg. (map int "this is a string") => (116 104 105 115 32 105 115 32 97 32 115 116 114 105 110 103)
and (map (memfn charCodeAt) "this is a string") => (116 104 105 115 32 105 115 32 97 32 115 116 114 105 110 103)
How to use async function like this: https://gist.github.com/scttnlsn/9744501?
I need some fn to be debounced, but I have no idea even how to apply this stuff. I’ve imported all the dependencies from core.async
, but the usage of the debounce
fn from the gist is not that straightforward like _.debounce
from lodash
for instance.
Here’s the listing:
(defn debounce [in ms]
(let [out (chan)]
(go-loop [last-val nil]
(let [val (if (nil? last-val) (<! in) last-val)
timer (timeout ms)
[new-val ch] (alts! [in timer])]
(condp = ch
timer (do (>! out val) (recur nil))
in (if new-val (recur new-val)))))
out))
@crvst this seems to be using it for debouncing function calls instead of chans: https://gist.github.com/owenrh/8baeb98c5081ea648381
for writing docstrings in clojure do we use normal comments ;
or should I use a different notation?
vitruvia: https://github.com/bbatsov/clojure-style-guide
have a look at that page and search for docstring
. Lots of useful info in general
@U0DPX8ZQB what about the docstrings in these regex expressions? https://gist.github.com/clojens/7932406
I’m giving a talk on Clojure today at my company. One topic i wanted to touch on was encapsulation. I was hoping to get some quick feedback on how to present the idea. 🙂 Its often argued that in OO classes “encapsulate”. I assumed the benfiet was to create more flexible programs by hiding low level details of some functionality (not data). This way those details could change without effecting callers. In clojure you can achieve a similar effect with cough closures. Is that all you would feel needs to be said on the subject? Or is there another way to think about it?
this comes up on the mailing list quite a bit @drewverlee . Might want to search for a @tbaldridge rant
I don't remember too many epic rants on the subject...but I do have opinions 🙂
Alex (from the twitter) seems to be suggesting because objects have a more tighter coupling to each other. Their more resilient to change. I think he is conflating data and functions together. I dont see why you would have more clojure functions acting on a given dataset in either language.
@drewverlee first thing that has to be done though is to define OOP. I go into it a bit here: https://www.youtube.com/watch?v=6tFSrnK7vmw
But the problem is this: you can make a mostly immutable OOP system (complete with inheritence).
You can make OOP systems without encapsulation, for example Python doesn't encapsulate except by convention.
And if people want abstract interfaces, there's things like protocols that allow for abstractions but without the drawbacks of traditional OOP systems.
oh man,
(defn -setup-tables
"Makes sure all the database tables exist, does not perform updates though"
[tables]
(doseq [k (keys tables)
:for [entry (get tables k)
tn (:real-name entry)
tcfg (:cfg entry)]]
(far/ensure-table
far-opts
tn
(:pk tcfg)
(:opts tcfg))))
I'm constantly getting a NPE on that
from the doseq line
is there anything obviously wrong here? I am not a huge user of doseq/for
this is what tables are
(def -tables
(into {}
(map (fn [tbl]
{tbl {:real-name (-prefix tbl)
:cfg (get -configs-proto tbl)}})
(keys -configs-proto))))
And they do indeed exist:
{:Eateries {:real-name testing-Eateries, :cfg {:pk [:id :s], :opts {:throughput {:read 2, :write 2}, :block? true}}}, :Users {:real-name testing-Users, :cfg {:pk [:id :s], :opts {:throughput {:read 2, :write 2}, :block? true}}}, :SeatingQueues {:real-name testing-SeatingQueues, :cfg {:pk [:eatery-id :s], :opts {:range-keydef [:user-id :s], :throughput {:read 2, :write 2}, :block? true}}}, :SeatingPools {:real-name testing-SeatingPools, :cfg {:pk [:eatery-id :s], :opts {:range-keydef [:user-id :s], :throughput {:read 2, :write 2}, :block? true}}}, :SeatingHistory {:real-name testing-SeatingHistory, :cfg {:pk [:history-id :s], :opts {:range-keydef [:user-id :s], :throughput {:read 2, :write 2}, :block? true}}}, :CreditTransactions {:real-name testing-CreditTransactions, :cfg {:pk [:transaction-id :s], :opts {:range-keydef [:eatery-id :s :user-id :s], :throughput {:read 2, :write 2}, :block? true}}}, :HoldsTransactions {:real-name testing-HoldsTransactions, :cfg {:pk [:user-id :n], :opts {:range-keydef [:eatery-id :s], :throughput {:read 2, :write 2}, :block? true}}}}
Is doseq "collecting" up the NPEs as it's a macro or something like that? so I'm just looking on the wrong line for the NPE?
Aaaaad, I found it...thank you for 🦆 ing today, :for was supposed to be :let
I do find the NPE from a weird use of a macro frustrating. If there is any sort of OSS ticket like this I could apply myself towards to better clojure error messages on this front, I'd be game.
If I want to include a branch of a library instead of the master into my project how would I go about that?
grounded_sage: one way is to checkout the branch, build the jar and install it locally (with a different project version) and then just reference that in your project
Cheers. I had a feeling this would be the way to do it. Was hoping to see if there was other ways.
how do people structure clojure applications which have to make 1000s of blocking io calls per second? utilize a variable thread pool? use continuation passing style? some other concurrency model? newish to the jvm so my understanding of concurrency constructs might not be great
why do the io calls need to block?
well, maybe they don’t. to be precise, I’d like to make 1000s of db calls via jdbc per sec. I don’t know if there’s a non blocking jdbc model
once you are talking about that kind of input, it’s much more useful to talk about the specific db
yes, that’s true
there’s an async psql driver iirc
anyway, I think a reasonable model if you want to maximize throughput is to have a connection pool, and a worker pool, and a queue that gets jobs plus (callbacks or channels or promises or whatever) to deliver the data to when fetched
c3p0 is a connection pool for jdbc that’s easy to use from clojure
oh, and the queue I mention above could easily be a channel (that’s just an implementation detail)
can anyone tell me why the regex "[^A-z\s0-9]"
doesn't filter out the ^
symbol? for example if I use it on "test^"
I want to get "test"
but I just get the same string
@vitruvia [^x] negates the matching of x
if you want to match x and ^, you need [x^]
I think he's trying to filter out characters that don't match.
including ^
then you want [^^x] I think
=> (re-seq #"[^^x]+" "fooxbar^baz")
("foo" "bar" "baz")
right, and if you also want to exclude the symbol itself, you need to provide it twice, once to negate, another time to specify itself
but I'm not trying to exclude the symbols inside []
, I'm trying to exclude anything that is not
in [^A-z\s0-9]
the ^ means “match the opposite of everytihng inside this []”
it is a meta-character in that context, a syntax of regex
it doesn’t stand for itself
then you need it to be matched for the negation to work, and currently it is not matched
also I find the double-negation odd, you can remove the negation from the character class and remove the = nil step and get the same logical result
I think (str/lower-case (apply str (re-seq #"[A-z\s0-9]+" %)))
should get the same result, much more efficiently
change A-z to A-Za-z
^ is inbetween Z and a
peregrine.circle=> (str/lower-case (apply str (re-seq #"[A-z\s0-9]+" "hello, ^world")))
"hello ^world"
peregrine.circle=> (str/lower-case (apply str (re-seq #"[A-Za-z\s0-9]+" "hello, ^world")))
"hello world"
=> (char (inc (int \Z)))
\[
by the way @noisesmith do you think this is a good course? http://mooc.fi/courses/2014/clojure/ I hear good things about their java courses but I don't know if this one is good too
I don’t know that course at all, sorry - I can recommend http://purelyfunctional.tv though
I think they have some free videos still, and the guy who makes them really knows the material well
https://purelyfunctional.tv/free-content/ - yeah, some of the videos are free
Are there any good resources for knowing what syntax-quote actually is doing? I thought it was the same as a normal quote (except it allows unquote), but when I do (backtick + single quote):
`'(~a 2 3) ;=> (quote (1 2 3))
...I get a different result than (backtick + backtick):
``(~a 2 3) ;=>
;; (clojure.core/seq
;; (clojure.core/concat
;; (clojure.core/list user/a)
;; (clojure.core/list 2)
;; (clojure.core/list 3)))
@rgdelato ` breaks down and reconstructs your form, not only does it allow unquote and unquote splicing, it also namespace qualifies any symbols not bound locally
the result of the concat will look like (user/a 2 3) and hopefully a is 1 and you get your expected result
of course this wouldn’t be correct coming from a macro, as it emits code that tries to call a as a function (and you report that a is a number)
@rgdelato regarding your actual question, I think this is the best explanation of syntax-quote https://clojure.org/reference/reader#syntax-quote
note in particular this paragraph
For Lists/Vectors/Sets/Maps, syntax-quote establishes a template of the corresponding data structure. Within the template, unqualified forms behave as if recursively syntax-quoted, but forms can be exempted from such recursive quoting by qualifying them with unquote or unquote-splicing, in which case they will be treated as expressions and be replaced in the template by their value, or sequence of values, respectively.
the whole seq / concat / list transformation nest is part of the templating
okay, I'm kind of understanding it. it'll certainly take some time to sink in, but this is a good starting point. thank you for the explanation 😄
Is there a built-in function like
(defn get-at [coll id-key id key]
(-> #(= (id-key %) id)
(filter coll)
first
key))
e.g., (get-at [{:id 1 :label "one"} {:id 2 :label "two"} {:id 3 :label "three"}] :id 2 :label)
==> "two"
I find myself using this pattern a lot recently.sounds like something spectre would do https://github.com/nathanmarz/specter
Hmm, thanks. I read the specter readme a while back and filed it away as something to look at later.
@deg you might want to upvote https://dev.clojure.org/jira/browse/CLJ-2056
actually, not reading closely enough - I guess you’re one step beyond that
It's the heavy heavy monster sound!
@alexmiller Yup, not the same, but quite useful. Upvoted.
I just gave a short clojure talk to my coampny, I guess every lisp talk needs a 10 minutes discussion about if parens are readable.
it’s not that lisp/clojure have more parens. it’s that they have less of everything else.
@alexmiller I’m sure its an argument your tired of hearing. In the conversation i earnestly asked them what measure they used for readability. I think most were just uncomfterable with the idea that in 5 minutes they knew the entire language syntax. The best attempt i have seen to address readability was at my first StrangLoop: https://www.youtube.com/watch?v=uEFrE6cgVNY
Someone also said it was harder because “we talk in statements so our PL should have them” to which i had no rebuttal because i was having trouble understanding it.
@ghadi that does not seem accurate :)
bar codes seem pretty fundamental to breaking music into rhythmic units
like the parens in lisp
ghadi: "In Clojure, parens are optimized for parafoveal vision, so it's scientifically easier to read." That should shut 'em up for a while.
@ghadi Most people i meet are using language because someone else told them to. So one way is to just be in charge :man_in_business_suit_levitating:
a lisp has the same parens you’d see with function calls most other places, they are just moved one full word to the left f() -> (f)
I guess we could just not care if people said "eww, gross!" except when people say "eww, gross!" it means learning is turned off
“we talk in statements so our PL should have them” except, they aren't really english statements, are they? So you have to learn an entirely new language. So why make it more complex than it needs to be?
And when you do, you just end up wrestling with the syntax in order to produce your desired AST. So why not just program the AST directly?
ghadi: "In Clojure, parens are optimized for parafoveal vision, so it's scientifically easier to read." That should shut 'em up for a while.