This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-04-20
Channels
- # aws (1)
- # beginners (14)
- # boot (30)
- # cider (6)
- # clara (9)
- # cljsjs (3)
- # cljsrn (22)
- # clojure (247)
- # clojure-dusseldorf (75)
- # clojure-france (38)
- # clojure-italy (6)
- # clojure-japan (8)
- # clojure-nl (3)
- # clojure-russia (16)
- # clojure-serbia (4)
- # clojure-spec (1)
- # clojure-uk (53)
- # clojurescript (168)
- # consulting (3)
- # copenhagen-clojurians (1)
- # core-async (7)
- # css (1)
- # datascript (3)
- # datomic (8)
- # dirac (22)
- # events (1)
- # hoplon (2)
- # jobs (1)
- # jobs-discuss (2)
- # leiningen (4)
- # lumo (138)
- # mount (13)
- # nyc (1)
- # off-topic (24)
- # om (34)
- # onyx (15)
- # pedestal (30)
- # re-frame (9)
- # reagent (23)
- # ring (1)
- # ring-swagger (24)
- # rum (6)
- # spacemacs (6)
- # specter (51)
- # uncomplicate (14)
- # unrepl (1)
- # untangled (17)
- # yada (12)
Quick question
If I require a namespace in one file, and change one of the vars in that namespace, will that var be changed or have its default value when I require the same namespace in another file?
(Maybe should have posted this in #beginners)
@tech_hutch no it won't change, you have to re-evaluate the var you changed
or re-load the file (via an editor or a call to load-file
I don't understand
well, what do you mean by 'change one of the vars in that namespace'?
how are you changing it?
So, if I require namespace b
from namespace a
, change b/thing
to "second value", then require b
in namepace c
, what will b/thing
be?
how are you changing it?
Uh, set!
, I suppose. I hadn't really thought about it yet.
there is only one version of a var with a given name, so foo/bar will be the same in every namespace that requires it.
So changing it in one file will change it for another? (I can guarantee that c
will run later than a
.)
is there a one liner for doing gunzip in clojure, without sending it to the shell to call gunzip? i.e. using pure java libraries
@qqq java.util.zip.GZIPInputStream should be an option if nothing else
+user=> (slurp "h.gz")
"�\b(�X�H���� 0:6"
+user=> (require '[ :as io])
nil
+user=> (-> "h.gz" (io/input-stream) (java.util.zip.GZIPInputStream.) (slurp))
"hello\n"
that's a decent one liner I think
@noisesmith : thanks!
@qqq if it helps, I just googled "gzip java" looked at the first page with a blog post with some code, squinted my eyes and looked for a class name with "GZIP" in the name and ignored everything else, then proceeded to try a few things in the repl
(of course this assumes a bunch of past experience using interop and java io stuff, but hopefully the process is encouraging)
my next step would have been to look at the javadoc, but my first guess (that something with InputStream in the name needs another InputStream as its constructor arg) worked out
@tech_hutch you're kindof confusing editing files with set!. Editing files does nothing unless you load them or run them in a repl.
I'm not talking about editing files
How would I modify a var from a namespace I'm requiring? def
?
every namespace sees the same values of vars, including any mutations
@tech_hutch don't - there's things that actually are designed for programmatic mutating, only change defs as a part of a dev workflow
if someone else needs to change it it should hold an atom, ref, or agent that gets dereffed on usage
I may not be using the right terminology
In namespace b, let's say I have (def *thing* "text")
. I want to be able to set this from another file. What's the best way to go about this?
don't
that's not what vars are for
if you need to mutate a value in namespace b, define it as a proper mutable type (def thing (atom "text"))
then you can just do eg. (reset! b/thing "other text")
but even better is to avoid needing to mutate top level values, but that's a whole other conversation
Hm, okay
https://github.com/bbatsov/clojure-style-guide/blob/master/README.md#earmuffs-for-dynamic-vars What does it mean here by rebinding, then?
tech_hutch:
(def ^:dynamic *my-dynamic-var*)
(binding [*my-dynamic-var* 10]
*my-dynamic-var*)
it's talking about dynamic vars, thread local bindings
Is there anything like danielz/system but for mount? I guess just a set of ready made defstates?
in java.nio.ByteBuffer , how do I set the value of "arrayOffset" or the "posiiton" field ?
@didibus Would you use it as a dependency or as a copy-paste repository of examples?
yonatanel: I was thinking dependency, but a repository of examples would be a good start
if you want to be able to take multiple times, and always get the same value, (go val)
won't work
since cheshire already uses transients, was thinking that it would be neat to do transform while accumulating the transient
transients? Where do I go to learn more about this @U06QSF3BK ? I'm currently getting burned by trying to convert dashed clojure keywords into underscored keys in the json response from a web api. It's too slow the way I'm doing it, but if I can't figure out how to do it performantly, we'll be forced to use underscore keys in our clojure code :c
parse-object
and parse-array
use transient within cheshire: https://github.com/dakrone/cheshire/blob/master/src/cheshire/parse.clj#L19
was hoping to have place where to convert values too, within the loop that modifies the transient
key-fn
is applied within the loop that modifies the transient that accumulates a json object, so this would probably work for you
yeah, that's the level I set the transformation at -- :key-fn #(-> % (str/replace #"-" "_") keyword)
.. given what you've told me, perhaps my bottleneck is elsewhere
@didibus danielsz/system has an experimental branch where mount is used instead of component.
I'm writing a selenium application, and would like to be able to pause the application from the console
what is the best approach to listen to input from user on console and in parallel running the selenium tests?
@pyr I think I would use to-chan for this with a vector of one element
why does clojure's let default to SEQUENTIAL bind instead of PARALLEL bind? one advantage of parallel bind is that when readin the code, it says: we don't guaratnee the order or execution -- so when I'm reading line 3 of the let, I don't ahve to wonder "did lines 1 & 2 do anything"
parallel bind with a let doesn't make a whole lot of sense
@tbaldridge : ha! I was hoping you would answer 🙂
@qqq yeah, that's kindof what I was talking about the other day. Compare Prolog to Clojure and you can see the difference. Prolog doesn't have a defined order (most of the time), but you pay a bit in performance for that freedom.
@tbaldridge : ah, I thought it was due to backtracking / search -- what does it have to do with order ?
Well if you don't have a backtracking execution engine, then most likely you have an imperative execution engine. In the case of an imperative execution engine (like the JVM) then a sequential let makes the most sense.
What is true in the case of the JVM that is false in the case of Emacs, or did Emacs get it wrong?
Really I think it's this: sequential maps very cleanly to both imperative execution engines and stack machines. The JVM is both of those.
@qqq I'm not sure about the implementation benefits, but I very often rely on the sequential nature of it. I tend to use a let instead of the threading macros most of the time because they are easier to read since they embed a name for each step and you can insert prints and logs and other cross-cutting concerns in-between the steps.
um...you don't need that, just reuse the same name
(let [a 4 a (inc a) a)
why would it be bad?
it's usage of lexical scope, it might be bad in languages that don't have proper scoping, but with let in clojure it works quite well.
(let [names (get-names client :from x)
_ (println names)
sorted-names (sort names)
normalized-sorted-names (map normalize sorted-names)
_ (log "Names fetched and normalized to " normalized-sorted-names)
normalized-sorted-names)
Hum, ya, I guess it's just a preference of style. I work with a big team, so I find the naming helps others read my code, but I might try out the as-> a little more, see if I like it
well you're in a bit of a minority there. Using lets and shadowing is the most common style I've seen.
I find the as->
macro hard to follow. Everytime I’ve used it and have to go back to reading what I wrote a couple weeks later, I can barely understand it.
(maybe because as-> didn't exist until about 2-3 years ago)
Some other langauge (forgot which) had a linter, which flageed many things, of which one was shadowing.
even in clojure shadowing of vars via locals is often a bad sign and can lead to bugs -- but shadowing of locals with other locals is very common
the other thing I like about (as-> ... $) over let is that: (1) with (as-> .... $), I know that "the flow is linear" (2) with let, the expr can be any directed acyclic graph
that is a warning that exists but it's a different thing than what we're talking about
@qqq You mean like with let it's unclear it will just return the value of the last binding? But as-> makes that clear?
no, as in if you draw the dependency of the exprs, with as->, it's a line and with let, it can be any directed acyclic graph
Cause I hate it when I'm threading and I realize oh crap, for this steps I actually need the value of 3 previous steps. With let I can do that no problem
@bronsa: I'm not saying "kill let", I'm saying "if it's linear, I prefer to use as-> instead of let"
not many will agree with you that not naming intermediate values is better than naming them
then I shove this object through the pipeline/functions, calling it "$" all the way through
@qqq to be fair, as-> feels a bit more functional and let a little more imperative, so good on you. But personally, the threading tend to confuse me. I even normally just nest s-expressions manually, I find even that to be clearer.
my fav is when you use name in rubby and then change your mind and then it secretly becomes the name of the class
fun fact: as-> just compiles down to a bunch of nested lets that each shadow the one above it 😛
(as-> 1 a (+ a 4) (dec a)) is (let [a 1] (let [a (+ a 4)] (dec a)))
so, im writing a custom :store function for ring wrap-multipart-params. are there any good examples of this out there (or any handy premades)?
@tbaldridge You have advocated against with-redefs
here in the past. You asked if there was some source recommending it's use for testing. Here is one such source http://blog.josephwilk.net/clojure/isolating-external-dependencies-in-clojure.html (albeit offering it as an alternative among others). It has come up once again in our dev team and even relatively experienced engineers are happy to recommend it's use (e.g. "it's ok in unit tests")
I get the impression you wouldn't agree even with that. Would you mind rattling off a few of the pitfalls you've seen?
I'll try to follow up with a doc and see if I can get it into http://clojure-doc.org/ or something.
@cddr, mostly around multiple threads. The problem is it's really hard to define when the scope of with-redefs terminates. The start of this blog post shows an example, then explains why this happens: http://blog.cognitect.com/blog/2016/9/15/works-on-my-machine-understanding-var-bindings-and-roots
Aside from the problem the blog post shows, it also makes it really hard to run multiple tests in parallel, as you can now have one test that changes global data for other tests.
Yes, I mention that Its important to note that with-redefs are visible in all threads and it does not play well with concurrency
.
Its a while since I wrote that post and its very, very rare I reach for with-redefs. Tends to be a design smell that its required. Its really an edge case tool @cddr
Yeah, and I can't think of a better way to say "doesn't play well with concurrency"...except it really doesn't play well. Like putting your kid in a cage with a lion, doesn't play well.
Even stuff like lazy seqs don't work: (with-redefs [foo 4] (map (fn [x] (+ foo x)) (range 10000)))
One of the problems with "doesn't play well with concurrency" though is that sometimes people don't realize where the concurrency is in their programs.
If one of the libraries we use handles all the difficult bits, it can be possible to "get shit done" without even worrying about concurrency
I mean. I'm convinced. I just need to figure out how best to convince those on my team that remain seduced by the thing that seems easy until it isn't.
The other thing that might help, is you can explain that with-redefs mutates global state. Which goes against most of Clojure's designs. At least with binding
the changes are local to the current thread.
My general approach to convience people its a bad idea, is to explore
how the code can be redesigned/reshaped to not need it. Then reflect on this code, is it easier to test, is it better designed. It usually is. And hence reaching for the with-redefs gets answered with, well lets first check this is not just bad design. It might be sometimes, though not all.
I think the history of testing has us reaching for tools to fix hard to test code that really reflects our bad design.
@roberto functional programing
Seriously that's it, pass these things in as parameters. If you need to mock something use Component/Integrant, etc. Or test the inputs to your side-effecting functions instead of the functions themselves
So for example if you need to test that you're sending a HTTP request correctly, don't stub out http-send, that's a IO function in the middle of your code, refactor to move http-send to the edges of your code, then write a "prepare-http-request" function and test the output of that.
hmmm, yeah, but I find conflicting recommendations. For example, if I am building a web scraper with selenium, and I want to write some unit tests, I normally use redefs
to mock interactions.
Now if I follow the advice to use component
or create protocols
, I will only have one implementation (and a test implementation), but recently in the component channel the recommended advice by the creator of component was to not use protocols unless you have more than one implementation (and test/mock implementations don’t count).
yeah, I get that type of unit testing, but at some point I want to test the interactions too
I don't know that I agree that "test/mock implementations don't count". Got a link to that recommendation?
but yeah, I find myself creating protocols when I’m in a bind trying to write a unit test. Especially if I want to figure out how high level abstractions will interact.
I agree that not everything needs to be a component, or have its own protocol, but anything you need to mock needs to be a component. That's pretty core to how component works.
So there might be a misunderstanding there.
A quick google couldn't find it, but someone who saw how it was worded could find it
Hey, folks! I'm still new to Clojure and wondered about the rational behind some functions returning lazy lists.
Not sure if clj sort
takes advantage, but it only has to perform at most O(n) work to return the first element. So by leveraging laziness, you can in theory get better performance on the sort. Again, not sure if clj actually does this for this case.
@g3ntleman it's an easy extension of cons-cells in lisps. Assuming a cons cell is [head tail] and you can do [1 [2 [3 nil]]]. What if you could do [1 f] where f is a function, which when called returns the rest of the list?
@g3ntleman bingo....lazy seqs
@danburton Yes, that's what I'm doing.
If you are looking for down-to-the-metal absolute speed, then clj may not be for you. But you're dealing with a O(n) vector worth of memory anyways. O(n) cons cells aren't going to increase the memory big-oh footprint.
Other way to ask this question: Are there ways to sort a vector without constructing O(n) list cells?
Is there a particular application domain where you are concerned about this difference?
So any idea, why it's handy that sort does not return the same collection type back that was put in?
Most clj sequence operations return a lazy seq. This allows you to chain multiple transformations, and it only needs to pass over the sequence once.
"If coll is a Java array, it will be modified. To avoid this, sort a copy of the array"
Probably because Java has a really fast sort algorithm that takes arrays as inputs. So the fastest approach is to convert to an array, sort, then call seq
on the array which is O(1)
You'd have to pay O(n) at the end if you wanted the same type out @g3ntleman
@csm yes: https://github.com/clojure/clojure/blob/clojure-1.9.0-alpha14/src/clj/clojure/core.clj#L3086-L3090
should i be wary of resolving vars at runtime, say in an endpoint that sees some traffic. like is there a reflection cost?
Example code? How are you resolving them?
that’s eliminating the compiler’s ability to prevent some easy to find mistakes
and also breaks some helpful tooling
but AFAIK it is the same runtime expense as just using the var the normal way
right. it smelled like a cowboy approach. I’m naming a var of a datalog ruleset from the client, but I can with a tiny bit more code just pass a keyword over instead of a symbol, and use that to lookup the var
if you need a data structure to do lookups on, namespaces are silly for that
use a proper hash map
To be exact, @uwo, it's about the cost of two hashmap lookups and then a normal deref
so not slow but yeah, I wouldn't do it a lot
@roberto @tbaldridge I said "Don't create protocols with only one implementation." If you have a test/stub/mock version and a "real" version, that's two implementations, which is fine.