This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-08-29
Channels
- # aleph (5)
- # announcements (2)
- # bangalore-clj (2)
- # beginners (52)
- # cider (10)
- # cljsrn (1)
- # clojure (160)
- # clojure-dev (24)
- # clojure-europe (3)
- # clojure-france (1)
- # clojure-india (1)
- # clojure-italy (3)
- # clojure-nl (6)
- # clojure-spec (13)
- # clojure-uk (51)
- # clojurescript (45)
- # code-reviews (1)
- # core-async (41)
- # cursive (41)
- # datomic (17)
- # emacs (37)
- # fulcro (42)
- # graphql (7)
- # joker (4)
- # music (1)
- # nrepl (2)
- # off-topic (21)
- # pathom (19)
- # pedestal (12)
- # re-frame (48)
- # reitit (6)
- # rewrite-clj (8)
- # shadow-cljs (41)
- # specter (6)
- # sql (21)
- # tools-deps (8)
- # vim (7)
- # xtdb (27)
Can redefine a def
, like I can a defn
function with with-redefs
?
I'm trying to write a test but I need to mock out a value
@caleb.macdonaldblack yep! https://clojuredocs.org/clojure.core/with-redefs#example-542692d6c026201cdc3270c1
@trailcapital Oh. I must have had a different error somewhere else when I tried that the first time. Thanks 🙂
I didn't see the example though. I just assumed it only worked with functions
Just bear in mind that some uses of def
'd values are "compiled in" and won't be seen if you try to redef them...
user=> (def foo 42)
#'user/foo
user=> (def bar foo)
#'user/bar
user=> (defn quux [x] (+ bar x))
#'user/quux
user=> (quux 0)
42
user=> (with-redefs [foo 13] (quux 0))
42
user=> (with-redefs [bar 13] (quux 0))
13
bar
is compiled to refer to the value that foo
has at the time -- so redefining foo
has no affect on bar
's value
Ah yeah I'm aware of that one. Had some issues in the past working with pedestal around that. I was reevaluating functions in the repl that were referenced in interceptors defined with def
and trying to figure out why it wouldn't work.
I was surprised to see that vectors don't implement ISeq. (seq? [:a :b])
is false. Can anyone shed some light for me?
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ISeq.java -- vectors don't support those operations, they need to be coerced to seqs
seqs are logical lists
seq
is the operation that yields the seq view of a collection (which often is not itself a logical list)
things that can be seq
-ed are seqable?
@seancorfield I looked at that briefly but I think i got tunnel vision on determining what can have first
called on it and figured seq?
fit that bill and vectors satisfied that. But I forgot about next and more
thanks @alexmiller. My gut still tells me that vectors are certainly logical lists. (I don't mean this argumentatively, i mean i'm trying to fix my thinking/reasoning)
But i'm reading the http://clojure.org stuff again trying to internalize this so I develop that intuition. But it sounds like seqable?
would guarantee that first
will succeed
vectors can provide a logical list view (an implementation of the seq interface)
but they do not directly implement the seq interface
seqable? guarantees that first will succeed after you call seq on it
(seq [:a :b])
-> (:a :b)
and (seq? (seq [:a :b]))
will be true (he says, without trying it in a REPL!)
you will note that first
does the seq
call for you
user=> (doc first)
-------------------------
clojure.core/first
([coll])
Returns the first item in the collection. Calls seq on its
argument. If coll is nil, returns nil.
calls seq on its argument
most of the seq-oriented functions do this
Note also
user=> (seq? #{:a :b})
false
user=> (seq? {:a 1 :b 2})
false
But both are seqable?
and when you call seq
on them, you get things that are seq?
(`ISeq`)
yeah i was looking at seq?
first. I think since lots of things call seq
for me transparently i don't often have to worry about seq/seqable and that's why when it matters i a little mushy
Does there exist a macro like if-let
or when-let
that works with destructured bindings?
I suppose I could roll my own but it doesn't seem to make sense for (if-let [[x y z] val])
to always evaluate to the true branch no matter what the val
is
both of those can use destructuring
if you want something other than what they do, then you would need to roll your own
if-let / when-let will respect depend on whether val is logically true or not
user=> (if-let [[a b c] nil] "t" "f")
"f"
user=> (if-let [[a b c] [1 2 3]] "t" "f")
"t"
somehow I always thought of it in terms of the truthiness of the left side of the bindings
it's really x in (if-let [[a b c :as x] val] ...)
(defmacro if-let*
"Like `clojure.core/if-let`, but only evaluates to `then` if all bound vars
are truthy, including destructured ones"
([bindings then]
`(if-let* ~bindings ~then nil))
([bindings then else]
(let [bindings* (destructure bindings)]
`(let* ~bindings*
(if (and ~@(->> bindings* (partition 2) (map first) (distinct)))
~then ~else)))))
(if-let* [{:keys [a b]} {:a 10}]
(+ a b) :error)
;; => :error
You might use it more often in a desktop application or database or something like that. But a lot of modern applications can be written without state.
is this thing up to date: https://clojure.github.io/tools.emitter.jvm/ ? is there some other built-in way to grab compiled bytecode?
what do you want to do with compiled bytecode? Disassemble it and print out the disassembly listing, or decompile it back to approximately equivalent Java source code? clj-java-decompiler can do either of those things: https://github.com/clojure-goes-fast/clj-java-decompiler
whats the easiest way to get expensive map-operations (that rely on external stuff like web-requests) to execute in paralell?
pmap
depends on number of cores and does not lead to optimal performance gains. Can you map over promises? E.g.,
(require '[org.httpkit.client :as http])
(defn- fetch [urls]
(let [promises (doall (map http/get urls))
responses (doall (map deref promises))]
responses))
if that's the prefferable option for asynchronous stuff, i'll look into it;D (verrry new to clojure)
i guess in your example http/get already works using promises,... are there any recommended resources on how to work with promises and such?
@andy.fingerhut i want to ship it over the network into different vm runtime as part of deployment process
only a subset of functions, ship them over to another app and patch relevant namespaces. it's still very much proof of concept thing
I'm trying to use sorted-set-by
to represent a priority queue, but ran into the case where trying to conj an element with the same "priority" results in a no-op:
(let [cmp (fn [x y] (compare (:cost x) (:cost y)))
s (sorted-set-by cmp {:cost 0 :color "red"})]
(conj s {:cost 0 :color "green"}))
;; => #{{:cost 0, :color "red"}}
is this the wrong data structure to be using? I thought of some workarounds like checking for 0 in the comparator and returning 1 instead, but that feels quite hacky
@qythium probably you're getting hit by this - https://clojuredocs.org/clojure.core/sorted-set-by#example-542692d5c026201cdc327096
hmm, hash-maps don't implement IComparable though, is it a good idea to compare their hashes as a fallback?
@qythium there is https://github.com/greglook/clj-arrangement if you want
Thanks! that looks interesting, although > maps are compared by their entries in sorted order of their keys. this seems like it would be expensive when I'm dealing with large heavily-nested maps
yeah, but it seems that you need this kind of comparator to be able to use sorted-set-by
According to the clojuredocs the comparator just needs to be consistent? My problem domain is partially ordered with relation to cost
, so essentially I just need a fast artificial way of imposing a total ordering
I am catching up late here, and someone else may have already suggested this to you, but there is a data.priority-map data structure library that may do exactly what you want: https://github.com/clojure/data.priority-map
do protocol and multimethod bring too much complication because to understand what to call, the user have to grok over all the codebase.
this is because the definition of protocol and (multi)methods can be dynamically added.
The a la carte nature is what makes them simple. It does make searching for them harder though.
why do you have to search at all?
as a consumer, you just subscribe to the abstraction
My experience is that often in codebases, the abstraction is poorly documented so the implementations are the documentation. There's also the cases where you make a breaking change to the protocol, because it's internal, and then you need to search for them then too.
in general, we have found that it is best to never have someone call directly into your protocol as an API, but to instead front it with a method that gives you a point of modification on top
so like in spec, there is a Spec protocol with methods like conform*, but users don't call that, they call conform function, which calls conform* on your behalf (and has its own custom logic to deal with stuff, like resolving spec name to spec object)
in practice, we've found this greatly improves your ability to create good abstractions that survive over time
More specifically, they are problems someone else creates for me to clean up / live with!
well, I mean "you" in the general sense (could also be "you" of 6 months ago :)
I've seen you mention this before, and beyond having additional logic in the fronting function (only call the underlying protocol on Tuesdays, or reverse the arguments) I wasn't sure of what the general case was there. The fronting function wouldn't help with understanding the abstraction though would it? What sort of things do you find it useful to do in that fronting function?
all of the above and often you'll find there is some special case or transformation that applies to all cases
anyone seen this behaviour where (seq (.getURLs (.getContextClassLoader (Thread/currentThread))))
is empty? this is when eval'ing inside nrepl/cider on a new clojure-cli based project
it's pretty annoying because it means io/resource
sees an empty classpath and so won't find any resources
i did it in our work project nrepl/cider based project and also in just clj
and both came up nil
io/resource works in clojure with cider nrepl generally. io/resource doesn't loop over each url.
Is (io/resource "clojure/core.clj")
returning nil for you?
I have :paths ["src" "test" "resources"]
in deps.edn
, and a file resources/activities/system.edn
, but (io/resource "activities/system.edn")
returns nil...
Is there any way to add add "middleware" to clojure.tools.logging
to change the format of what is logged when calling info
, warn
, debug
, etc?
Add logback dependency
project.clj:
;; Logging
[ch.qos.logback/logback-classic "1.2.3" :exclusions [org.slf4j/slf4j-api]]
[org.slf4j/slf4j-api "1.7.26"]
[org.slf4j/jul-to-slf4j "1.7.25"]
[org.slf4j/jcl-over-slf4j "1.7.25"]
[org.slf4j/log4j-over-slf4j "1.7.26"]
[org.clojure/tools.logging "0.4.1"]
And logback.xml in your resources:
<!-- Logback configuration. See -->
<!-- Scanning is currently turned on; This will impact performance! -->
<configuration scan="true" scanPeriod="10 seconds">
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
<include resource="logback-stdout-appender.xml"/>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
<!-- For loggers in the these namespaces, log at all levels. -->
<logger name="user" level="ALL" />
</configuration>
logback-stdout-appender.xml:
<!-- Console output -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoder defaults to ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} %-5level [%thread] %logger{} - %msg%n</pattern>
</encoder>
</appender>
There you can change the format.When using Transit ( https://github.com/cognitect/transit-format ), how closely does the version number need to match? I am communicating between the -clj and -cljs implementations, and the highest common release version between them is 0.8.247
The transit format itself has not changed since it was released so any implementation should be working from the same spec. That said, there might be some implementation details that are not spec-related.
So as it stands you would recommend simply using the latest version for each of them then?
As general advice, yes
But I am getting a difference in the data after translation when using both of them on that version number
Namely, keyword values of a nested map are turning into strings when sent from clojure -> clojurescript
> Watch out, logging is macro based, so you should wrap it with macros too -- @dominicm @ https://clojurians.slack.com/archives/C03S1KBA2/p1567093683142300?thread_ts=1567093003.139200&cid=C03S1KBA2 Why should one wrap macro usage (only?) in another macro? (I didn't want to hijack that thread with my n00b question.)
As a general rule, you don't need to. But you probably want some semantics of that macro. For example, info being a macro is what allows it to get the current namespace for including in the log message.
no built in, this is likely the most natural way to do it
user=> (apply hash-map (apply concat (partition 2 1 [1 2 3 4])))
{1 2, 3 4, 2 3}
Final impl + test
(let [next-in-cycle #(apply hash-map (apply concat (partition 2 1 (take (inc (count %))
(cycle %)))))
left [:N :L :S :W]
turn-left (next-in-cycle left)
turn-right (next-in-cycle (reverse left))]
(= (map (juxt turn-left turn-right) left)
[[:L :W] [:S :N] [:W :L] [:N :S]]))
Aw, you beat me to it! I was literally just about to paste that in after checking in the REPL!
sorter with @UJY23QLS1 + @UARBFQGVB
(let [next-in-cycle #(-> (inc (count %))
(take (cycle %))
(as-> x (zipmap x (rest x))))
left [:N :L :S :W]
turn-left (next-in-cycle left)
turn-right (next-in-cycle (reverse left))]
(= (map (juxt turn-left turn-right) left)
[[:L :W] [:S :N] [:W :L] [:N :S]]))
given your use case: (zipmap x (rest (cycle x)))
This can work with more than numbers
user=> ((fn [xs] (zipmap xs (rest xs))) [:a :b :c :d])
;; => {:a :b, :b :c, :c :d}
java-time related question: how do I truncate a java-time value, if I want to truncate it by any arbitrary unit?! java-time/truncate only accepts predetermined units such as 1 second, 1 nanosecond, ...
Do I have to turn the timestamp into a numerical value (unix time), do computation there and return it? or is there a simpler native way?
@veix.q5 you might want to look at clj-time to see if there’s anything in there that will do this for you
I don’t know off the top of my head. I do know that it has a lot of useful functions.
can you explain what you mean by truncate? Truncate only takes a unit as you truncate to that unit. It truncate to the month would be 2019-08, truncate to the year would be 2019. What does it mean to truncate 39 minutes?
@dpsutton well my understanding is that time itself is a sequence of delta-ts (iterate (partial + delta-t) origin) , 2019-08 is basically an imaginary representation.
when's the last 39 minute duration depends on when we all started counting 39 minute blocks of time
if you want to truncate to the day or month, we all agree on those and can easily do so. If you want to truncate to an arbitrary last duration, it depends on when the durations began.
but maybe i'm misunderstanding you as i still don't know what you would expect to result from truncating the current time by 39 minutes
day or month units and the overall human representation of time (the way they split seasons and rotations of the sun) are built into a whole, which is good for our monkey experience. what I'm saying is that with a representation that is more fine-grained, I could have both the monkey time AND the simple time.
trivially speaking, you can just round an ms ts to the nearest (* 1000 60 60 39)
, but based on what starting point?
we don't and won't have a data type that is rounded to 39 minutes
I have a timeseries that is supposed to be divided into time windows. the size of the windows is algorithmically discovered through finding an optimum solution to a model.
then you don't want a time type, you want an interval type
or you can just use eg. MS and then do the standard rounding / quotient / truncation etc. math
I could imagine a representation based on a starting / synchronization point and a period, but I know of no standard data type that works that way
we use data types like this in audio synthesis but typically it's simplified by a procedural representation where time is nearly always processed incrementally in order when these artificial periods come into play
@veix.q5 a better way to put this might be that instead of defining a piece of data representing a processing period, you define a "rate of update" and then register various things to be invoked or updated at that frequency
in some environments there can be local redefinition of the rate of update, the only radical outlier I can think of is the Chuck language where objects have arbitrary update rates (and it's nearly unusably slow last I tried it due to not sharing an update scheduler between assorted objects and instead allowing each object to have its own update timer)
this could be totally unrelated to what you are doing - surely with a rate like 39 minutes per cycle you aren't talking about DSP in a conventional sense, but there might be some shared design concerns :D
but there definitely is a ScheduledExecutor that comes with the vm, and you can give it 39 minutes as a rate of update if this procedural approach works
in most audioi synthesis DSLs it would be called the "control rate"
ScheduledExecutor and the audio stuff concern cases where Real time is at issue? right? otherwise, for Symbolic time, is it any different to a transducer that keeps a counter/memory up to "39" for example?
I don't think I understand your use case