This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-07-30
Channels
- # announcements (6)
- # bangalore-clj (1)
- # beginners (169)
- # boot (8)
- # calva (20)
- # cider (32)
- # clj-kondo (78)
- # cljdoc (42)
- # cljs-dev (4)
- # clojure (126)
- # clojure-china (35)
- # clojure-dev (5)
- # clojure-europe (3)
- # clojure-italy (40)
- # clojure-nl (15)
- # clojure-portugal (1)
- # clojure-spec (4)
- # clojure-uk (67)
- # clojurescript (89)
- # community-development (2)
- # core-async (34)
- # cursive (46)
- # datomic (14)
- # dirac (1)
- # duct (8)
- # emacs (11)
- # events (5)
- # fulcro (21)
- # jackdaw (14)
- # jobs-discuss (6)
- # off-topic (37)
- # pedestal (24)
- # perun (1)
- # quil (3)
- # reagent (27)
- # reitit (1)
- # remote-jobs (1)
- # shadow-cljs (47)
- # sql (1)
- # vim (9)
- # yada (1)
@iagwanderson You cannot remove any of the base keys from a record. Why do you want to do this?
After all, (some-key record)
is going to be nil
if some-key
is not present or if some-key
refers to a nil
value.
I modeled a xlsx ROW to be a record because I have several operations that depend on the type and I wanted to clean the row at some point
@iagwanderson Does the "type" depend on one field of the CSV? Maybe you want multimethods and a tagged hash map instead?
Hi there. I follow the book Web Development with Clojure 2nd Edition. But run into several problems. If I run lein migratus create guestbook
like the book describes I get: https://paste.opensuse.org/view/raw/31a637a5
This looks as a problem with newer jdk versions and obsolete flatland/ordered dependency -> you should update the dependency
By updating you mean not using `{:user {:plugins [[luminus/lein-template "2.9.10.74"]]}} in the profile? But then it seems that migratus is not available as a subcommand
The 3rd ed. is in beta: https://pragprog.com/book/dswdcloj3/web-development-with-clojure-third-edition
Note the version used and add an explicit dependency in the project.clj to the latest version: https://clojars.org/org.flatland/ordered
So you can use lein deps :plugin-tree
too (https://cljdoc.org/d/leiningen/leiningen/2.9.1/api/leiningen.deps)
This in particular is, I think, the issue you hit: https://github.com/clj-commons/ordered/issues/45
Interesting. It seems on http://learning.oreilly.com I can't see those beta books.
This is when I have {:user {:plugins [[luminus/lein-template "2.9.10.74"]]}}
in the lein profiles file. Without that migratus
doesnt even seem to be a task
Is there a distinction in naming conventions between transformation functions that may fail (and return nil) and transforms that throws on failure (I want to use the former with the keep
collection function and the latter with map
)? In F# for instance the former would likely be called try<whatever>
like tryParseInt
and return an Option.
Hi, I'm running into some problems trying out re-frame subscriptions. the commented line above works perfectly, but if I use the subscription version it doesn't work for some reason
only thing I could think of is maybe it has something to do with lazy eval? but I'm actually asking it to realize, so I'm quite lost
@shin can you post the definition of your :locales
subscription
@danieleneal sure, here you go
Everything looks fine - although you can generally only dereference subscriptions within a render function, which may be where you’re going wrong
that line (def lcl (re-frame/subscribe [:locales])
is not intended usage
would be more like
(defn some-component []
(let [locales @(re-frame/subscribe [:locales])]
... do something with locales)))
hmm, I'm using tempura (https://github.com/ptaoussanis/tempura) to play around with using different languages. you give it a list of locales and it will try to use them in the given order. I'm trying to subscribe to that, so I can change the order and thus language used or would you recommend any other way of doing that?
Hmm, various ways. The thing is once you have a subscription you can’t really go back to the land of normal function calls anymore. Dereferences are tracked and cause re-rerenders, and are cached, and when unmounted the cache is disposed, so there’s a fair amount of machinery involved.
This is why the partial
is not working
One option would be to call tr
with the locales each time you use it, seeing as you want the locales to be editable
(def tr (partial tp/tr {:dict my-dict}))
(defn some-component []
(let [locales @(re-frame/subscribe [:locales])]
text (tr locales [:text])]
... do something with text)))
There’s definitely other ways of arranging it though
I'll try it out at home, thanks very much! But is the way to do this I thought about sane or is there a better way to do things like that?
We have put all stuff regarding tr
into app-db and use subscriptions, something like this:
(def default-tconfig {:default-locale :en
:dict {:en {:missing "*** Missing localization! ***"
:message {:hello "Hi"}}
:fr {:message {:hello "Bonjour"}}
:fi {:message {:hello "Moro"}}}})
;; -- Subscriptions -----------------------------------------------------------
(rf/reg-sub
:language
(fn [db _]
(:language db)))
(rf/reg-sub
:tconfig
(fn [db _]
(-> db :tconfig)))
(defn tr-query [tconfig lang]
(partial tempura/tr tconfig [lang]))
;; Returns new translations fn 'tr' after :language or :tconfig changed in app-db.
(rf/reg-sub
:tr
:<- [:tconfig]
:<- [:language]
(fn [[tconfig lang] _]
(tr-query tconfig lang)))
and then we have event that fetches translations from backend and sets that dictionary into :tconfig
in app-db.
Then in view you can just @(rf/subscribe [:tr])
and you get function with correct language and dictionary. And if the language would be changed in the app-db, then all subscriptions get updated with new tr
function.With re-frame, once you have subscriptions, you can build on them with more subscriptions, but you can’t pass a subscription to a normal functions in the place of a value. You can run a normal function on the de-referenced value of a subscription, because you now have an actual value - like (tr opts @locales @text)
the thing to remember is that subscriptions are objects whose dereferences are tracked so that components that dereference them re-render when the value changes
what is a quick and simple way of testing if my function actually returns a lazy seq, instead of killing a restarting the repl each time it starts evaluating an infinite seq?
You could do something like this:
(defn lazy-seq? [coll]
(= (class coll) clojure.lang.LazySeq))
=> #'user/lazy-seq?
(lazy-seq? (for [x (range 10)] x))
=> true
@sakalli Also if you wanna peek into the infinite seq, try https://github.com/borkdude/finitize
@sakalli Another useful trick is to (set! *print-length* 100)
in the REPL. This will prevent lockup if an infinite sequence is printed.
Where is the proper place to put a doc string within defmulti
and defmethod
after the name of the defmulti, and defmethod shouldn't require its own
if you have (defmulti foo "get a foo from the arg" ...)
(defmethod foo :bar ...)
how would you even ask for the method's doc other than getting the one for the multi?
a defmulti creates a var, those carry docstrings, a defmethod alters the multi, it doesn't have its own var to put doc on, or ask doc from
hi all! mega beginner here, i'm doing this (https://practicalli.github.io/clojure-webapps) practicalli tutorial, and when I try to run the repl with lein repl I get this error, couldn't find any usefull info online
Caused by: java.lang.NoClassDefFoundError: IllegalName: todo_list.core/_dev_main.proxy$java.lang.Object$SignalHandler$d8c00ec7
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:654)
at java.lang.ClassLoader.defineClass(ClassLoader.java:761)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
is there a file src/todo_list/core.clj
which contains something like (def -dev-main (proxy ....))
the project runs, but not the repl
(defn -dev-main
"A very simple web server using Ring & Jetty that reloads code changes via the development profile of Leiningen"
[port-number]
(jetty/run-jetty (wrap-reload #'app)
{:port (Integer. port-number)}))
hmm - I'd try running lein clean
then starting the repl again
when I use (require) in the repl, is the :all implied (Compared to doing (ns myns (:require randomlib :refer :all))?
no options are implied
:refer :all should only rarely be used (there's an annoying thing where all the lib README files seem to show it in their examples...)
no luck, I'm on WSL btw, could this have anything to do?
it really could - if you are confident enough you could convert the project to not use the ring plugin, that's a likely source of hard to debug magic
cool! i'll try that
also be sure your leiningen and clojure versions are the newest stable versions, and you might try downgrading your jvm if it's a fresh one
(there's various stuff that goes weird with newer java versions and older clojure stuff, using a newer lein and clojure helps)
hmm, these are my version, I think on the clear for that
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.6.0
OpenJDK 64-Bit Server VM 1.8.0_212-8u212-b03-0ubuntu1.18.04.1-b03
yeah, that clojure is ancient
let me try taht
k, so late reply, but updating packages and switching to osx did the trick, it seems like wsl is not quite there yet, thx for your help!!
you can always call all the functions, the normal way to do this is via :as
OK - use :refer :all if it's appropriate, just know it's not considered normal
the normal thing is (require '[clojure.set :as set])
then you can use (set/union ...)
(set/intersection ...)
etc.
well, :all isn't actually an option for (require) (unlike :require as part of a (ns) call).
it is
require as used alone is exactly the same function that ns calls
and has the same options (once you sort out the quoting differences outside a macro)
(ins)user=> (require '[clojure.set :refer :all])
nil
(cmd)user=> (union #{:a} #{:a :b :c})
#{:c :b :a}
it's the same as in the ns form in that respect
What does the ' do here? The code I'm working with doesn't have that in the (ns) declaration.
that's what I meant by has the same options (once you sort out the quoting differences outside a macro)
' means "don't evaluate this form"
so symbols are used as is and are not resolved, and function calls are just lists
it prevents an error clojure.set
isn't bound
it's the symbolic name of something you want to load
you'd get a syntax error if you used it unquoted
the ns form is a macro, and it doesn't try to evaluate the symbols you put in the require form
macros can decide when something is evaluated or not
when you call a function (eg. require
) the args are evaluated first, then passed to the functio
so ns, being a macro doesn't actually itself evaluate anything anyway, unlike (require) which is a function and will evaluate immediately.
when you call a macro (eg. ns
) the args are passed as a list of symbols and input literals and the macro decides what to do with them
right
I mean a macro usually does evaluate things (clojure macros can use the entire clojure language as needed), but they usually just turn one list (form) into another then return it to be compiled
What benefits do we have using ClojureScript for server side instead of Clojure?
some people are trying to do something that is easier to do in a js vm rather than jvm
Looking to generate some documentation for some website back and front end stuff. I'd like to be able to autogenerate or with some massaging generating dependency/flow diagrams. I know codox
is common for pulling docs together, but I didn't see any dependency graph makers. This is what I'm thinking. Any recommendations?
Should one prefer tagging fns ^:private
to using defn-
? (question spurred by https://groups.google.com/forum/#!msg/clojure/zaWlDbOhKCM/sD_iOM_k9WcJ)
that's fair i guess. personally i think a project is easier to understand if you're clear about what's used only within a namespace
a google search yields a split internet, use w/e makes your team happy I'd say (my personal opinion would be explicitly using ^:private since a good IDE will provide auto-completion and this is more consistent with def not having a matching def-)
Hello everyone. I have a doubt regarding Clojure and i couldn’t find a clear answer. Assume i have a bank account with the balance of $100.00 I then receive 2000 request to withdraw these $100.00, usually on a Java code, you would need to lock the resource as soon as the first request arrives, so that only the first one can be made and all the others shall fail. I saw examples using the actor model were you can use a single actor to represent one account, and so the 2000 requests would be made by the account actor, leading to the expected result Does Clojure have any way on helping with this? I saw about the agents but i couldn’t find any information that i could digest on this.
@pedrommrabello agents are a straightforward way to do something much like an actor, the important difference being that an actor is a method that you send data to, and an agent is data you send a function to
but you can set a validator, so that the action won't succeed if it leaves a balance below 0 for example
you can also do this with atoms, which are much more intuitive to use
Wouldn't this be an excellent case of storing the value in an atom? Hmm, I suppose that doesn't work for multiple processes?
with multiple processes you need inter-process communication which clojure doesn't offer out of the box (unless you meant threads, and threads are why we need things like agents, atoms)
right, in that case nothing in clojure really helps - you'd want some IPC strategy, clojure doesn't really cover it
inter-process-communication
@pedrommrabello any reason this isn't handled by a database with ACID semantics?
No, just an example of how it can be dealt, not something happening in a real world scenario
right, it's also IPC if you ever reboot your VM (two processes, at different times, working on the same data world)
you can use refs to coordinate multiple stateful changes https://clojure.org/reference/refs
Hey guys, I can't figure out what I'm doing wrong here:
(deftest funcmocktest
(testing "mock a func"
(with-redefs-fn {#'clojuretesting.secondnamespace/myfunc (fn [] (print "This is a mock."))}
(is (= nil (clojuretesting.core/mysecondfuncwrapper))))))
I can't really tell what this should be doing that it wouldn't do
what do you expect here? what happens instead?
Not an exception. I'm trying to replace the myfunc so that tests of myfuncwrapper can be done without a dependency on myfunc
what exception?
`ERROR in (funcmocktest) (core.clj:7216) Uncaught exception, not in assertion. expected: nil actual: java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.IFn`
that means that somewhere either true
or false
is being called as if it were a function
it is clearly unrelated to what you show in your example, but you might recognize it in your actual code - usually ... cannot be cast to clojure.lang.IFn
is as simple as an extra set of parens somewhere
So, I trimmed down what I've got and it looks like the problem is something to do with how I'm using (with-redefs-fn). (myfunc) was still called and executed instead of the mock function.
(ns clojuretesting.core
(:gen-class)
(:require [clojuretesting.secondnamespace :refer :all]))
(defn myfuncwrapper
[]
(myfunc))
(defn -main
[]
(myfuncwrapper))
...
(ns clojuretesting.secondnamespace)
(defn myfunc
[]
(print "myfunc was called"))
...
(ns clojuretesting.core-test
(:require [clojure.test :refer :all]
[clojuretesting.core]))
(deftest funcmocktest
(testing "mock a func"
(with-redefs-fn {#'clojuretesting.secondnamespace/myfunc (fn [] (print "This is a mock."))}
(is (= nil (clojuretesting.core/myfuncwrapper))))))
the second arg to with-redefs-fn needs to be a function
so I was wrong, I forgot how with-redefs-fn works, the is returns a boolean, and it's trying to call the boolean
you need #(is ....)
(function of no arguments to call with those bindings)
or you can use with-redefs
which accepts a normal body instead of a function
Yes, now my result is the expected printing of "This is a mock". Obviously not a good test, but worked for a quick test of how to use with-redefs-fn
So, with-redefs would be what I would normally want to use though? it just takes a &args that would be commands to run while the funcs in the map are replaced?
right - it's one of the macros that takes a & body
which means any number of things to call inside the context it creates
fn, let, defn, do, all have & body
as well
and deftest of course
(with-redefs {'clojuretesting.secondnamespace/myfunc mockfunc}
(is (= nil (clojuretesting.core/myfuncwrapper))))
with-redefs accepts a vector - like let
(cmd)user=> (require 'clojure.set)
nil
(cmd)user=> (with-redefs-fn {#'clojure.set/union (constantly 42)} #(clojure.set/union #{:a :b} #{:b :c}))
42
(ins)user=> (with-redefs [clojure.set/union (constantly :OK)] (clojure.set/union 'whatever))
:OK
and using {} instead of []
it's a function rather than a macro, so it accepts a mapping for new values, and a function to run in the remapped context
you can combine functions more easily than macros, so it's often useful to provide a feature as a function (for extension / programmatic usage) and as a macro (for syntax / readable code)
So besides the API there's no tangible difference between the two. They are equally capable then?
perhaps this answers your question
(ins)user=> (source with-redefs)
(defmacro with-redefs
"binding => var-symbol temp-value-expr
Temporarily redefines Vars while executing the body. The
temp-value-exprs will be evaluated and each resulting value will
replace in parallel the root value of its Var. After the body is
executed, the root values of all the Vars will be set back to their
old values. These temporary changes will be visible in all threads.
Useful for mocking out functions during testing."
{:added "1.3"}
[bindings & body]
`(with-redefs-fn ~(zipmap (map #(list `var %) (take-nth 2 bindings))
(take-nth 2 (next bindings)))
(fn [] ~@body)))
with-redefs literally turns its body into a valid call to with-redefs-fn