This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-12-01
Channels
- # adventofcode (11)
- # aws (8)
- # beginners (70)
- # boot (2)
- # cider (9)
- # cljs-dev (29)
- # cljsrn (2)
- # clojure (67)
- # clojure-android (2)
- # clojure-dusseldorf (5)
- # clojure-greece (12)
- # clojure-italy (4)
- # clojure-nl (3)
- # clojure-poland (3)
- # clojure-russia (5)
- # clojure-spec (80)
- # clojure-uk (9)
- # clojurescript (73)
- # core-async (17)
- # cursive (1)
- # data-science (5)
- # datomic (29)
- # emacs (5)
- # fulcro (257)
- # graphql (2)
- # hoplon (2)
- # jobs (2)
- # klipse (3)
- # leiningen (9)
- # lumo (4)
- # nyc (1)
- # off-topic (48)
- # om (7)
- # other-languages (11)
- # pedestal (4)
- # re-frame (18)
- # remote-jobs (1)
- # rum (10)
- # shadow-cljs (5)
- # spacemacs (20)
- # sql (5)
- # test-check (44)
- # unrepl (8)
- # yada (9)
totally random, but the word "predicate"... in clojure it means something that evaluates to either true
or false
. Does this have anything to do with the english grammar "subject and predicate of a sentence" meaning of the word predicate or is it totally coincidence that these use the same word?
@derpocious > state, affirm, or assert (something) about the subject of a sentence or an argument of proposition. “a word that predicates something about its subject”
a predicate asserts something about the argument, and that assertion is either true or false
you can use the socket server with a repl listener to add one by just adding command line parameters https://clojure.org/reference/repl_and_main#_launching_a_socket_server
@vienas00
1) add [org.clojure/tools.nrepl "0.2.12"] to lein deps
2) embed repl into program
=> (use '[clojure.tools.nrepl.server :only (start-server stop-server)]) ; => nil
=> (defonce server (start-server :port 7888)) ; => #'user/server
3) $ lein repl :connect 127.0.0.1:7888 # use actual IP instead of 127.0.0.1
see https://github.com/clojure/tools.nrepl for more details
please correct me if I'm wrong (haven't tested this yet)
Hi!
Encountered this code
user=> (merge '^{:foo :bar} {:a 1 :b 2} {:b 3 :c 4})
{:a 1, :b 3, :c 4}
Please suggest what ^{}
construction means and why it's ignored by merge.
That is clojure metadata. Try calling meta
on that value.
Thank you @donaldball! It makes sense.
@ghsgd2 Yes I can see that, but how can I change a working program? and interact with it?
require namespaces, invoke functions, update stateful entities
all namespaces and vars are global and accessible
or you can redefine function definitions from the repl, affecting the running program
@vienas00 The way I work is that I start a REPL in my editor and as I write code in source files, I evaluate it into the REPL, so the program is a live, running, evolving thing all the time. So the "working program" is something I start from the REPL, via my editor, while developing.
Once I have a program in production, I can still run it with a REPL server embedded in it -- for example using the Socket Server built into Clojure itself (starting the program with appropriate JVM arguments to tell Clojure to start the Socket Server) -- and then I can connect to it via a telnet session (for the Socket Server) or a full nREPL client (for an embedded nREPL Server) and I can treat it the same way as I do during development.
@seancorfield Can you give us some examples of things you’ve done on production applications via a live REPL?
@admay one example I can give is trapping data in an exception handler, and then dumping that data to a file format I can use in a regression test via the repl
@admay Mostly we use the live REPL on production for debugging: running functions that query data, so we can see what they are actually returning in based on our (large) production database, but we have used it to patch data in the databases -- because using Clojure to transform and update data (in MySQL and/or MongoDB) is usually easier than a raw command-line tool for the specific database. In addition, we sometimes redefine a function to have some extra debug output (logging via timbre
, for example) when we're trying to track down a problem.
@seancorfield ditto on timbre, not to mention it’s easy to change log levels and blacklist / whitelist namespaces from the repl which makes seeing the right logs much easier
also it’s much easier to make a small function which queries the state of some stateful process than it is to hook that up with the right api and auth etc. etc.
In very rare situations, we have applied a live patch -- a new definition of a function -- when it's been a critical bug that we don't want to do an entire new build for. We mostly only do that on our internal-facing apps (since our member-facing apps run on a cluster of servers and connecting to and updating each instance would often be more work than just running a build!).
especially when the repl makes it easy to extract precisely the info I want out of that state
the repl is nicer than any status query api I’d have the time/energy to make haha
Agreed, yes, being able to temporarily dial up logging is very useful.
so eg. there’s a namespace that keeps track of user quotas and running tasks - often repl code dereferencing the state atom is much more effective than attempting to query the state via an api then use that data in a ui
But -- big caveat -- running code via a live REPL into your customer-facing production applications is of course fraught with danger so you need to be careful 😈
it reduces friction to increasing info and reduces the cost of providing info we very rarely need
yes, indeed - you do need to be careful
We run our regular DB migrations all via Clojure so, for us, using Clojure to run DB queries -- or DB updates -- is a pretty natural way to work.
> fraught with danger This is what I’ve always worried about. My team has a few very new Clojure developers on it and I don’t want them to feel pressured into using something they aren’t 100% comfortable with. Those a great examples of how/why to use a REPL connection with a prod environment and I’m definitely going to start looking into incorporating it in my practices. Maybe starting with a REPL connected to our QA and DEV environments first and then moving to PROD when we’ve nailed down application safety.
Thanks @seancorfield and @noisesmith!
contains?
works on associative types
vectors implement the associativity by mapping indexes to values
since it has a value at index 4, it returns true
> (contains? [1 1 1 1] 4)
false
@alexkeyes if you want to check if a vector contains a value, you can with some
and an anonymous function like (some #(= 4 %) [1 1 1 1 1])
However, this won’t return true of false, it will return true or nil. Usually that won’t be a problem, but it’s worth noting I think
for a deeper dive… http://insideclojure.org/2015/01/27/clojure-tips-contains/
note the link to Rich’s explanation at the end too
@alexmiller I know Rich isn’t a big fan of sequential lookup but is there any reason why there aren’t two functions for contains?
like contains-key?
and contains-value?
contains?
is effectively contains-key?
because contains-value?
is sequential lookup
So it’s just, “We don’t think sequential lookup is good. We don’t want to encourage it because there are better ways. Here are the better ways, use these instead.”
yes - if you need to look up a value, put it in a hashed set
or as a key in a hashed map
So rather than (some #(= 4 %) [1 1 1 1 1])
you’d suggest (contains? (set [1 1 1 1 1] 4))
I’d suggest not using [1 1 1 1 1]
the point here is to choose the right data structure that supports the operations you will need in your program
then you won’t find that you are missing an operation
most collection libraries in other languages define a set of ops and a set of colls and make everything work on everything. the problem with this approach is that it destroys your ability to reason about the performance of any particular operation as it may be fast on one collection but slow on another (in terms of O(1) vs O(log) vs O(n)).
@alexmiller Just shared that back and forth with my team, that’s a great bit of information. I very rarely see an emphasis on ‘how to choose the proper data structures’ in beginner documentation
Clojure takes a different approach in defining a small set of collection operations based on traits. Not every collection implements every trait, but when they do they are expected to follow certain performance expectations.
This allows you to reason about the expected performance of arbitrary code you see in the wild just from operations it uses.
I wrote a lot more about this in Clojure Applied btw
you might also find http://insideclojure.org/2016/03/16/collections/ and http://insideclojure.org/2015/01/02/sequences/ to be useful too
hey all, I have some code that returns a promise object, but I want to evaluate it and get the result.
if you mean synchronously getting the value out of a promise, it's not possible with native js promises, but is with promesa promises
(def url "")
(js/fetch url
(fn [data]
(println "got data "))
(fn [error]
(println "data error")))
hi, please suggest how to limit exception stacktrace length or turn off it altogether in tests i. e.
$ lein test
lein test test
lein test :only test/issue
ERROR in (issue) (AFn.java:429)
expected: (= “Foo” (app/func ""))
actual: clojure.lang.ArityException: Wrong number of args (1) passed to: app/func
at clojure.lang.AFn.throwArity (AFn.java:429)
clojure.lang.AFn.invoke (AFn.java:32)
app$fn__260.invokeStatic (app.clj:40)
app/fn (app_test.clj:39)
Also clojure.test ignores test cases declaration order and runs them in random order.
in general, unit tests should not be written in a way that order matters
possibly pipe it to grep
that's true but it's convenient for me to see results in the same order
lein test | grep Failed