This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-06-08
Channels
- # announcements (7)
- # babashka (44)
- # beginners (162)
- # cider (22)
- # clara (11)
- # clj-kondo (14)
- # cljsrn (8)
- # clojure (91)
- # clojure-dev (24)
- # clojure-europe (6)
- # clojure-france (4)
- # clojure-italy (11)
- # clojure-nl (4)
- # clojure-spec (11)
- # clojure-uk (14)
- # clojurescript (92)
- # community-development (1)
- # core-logic (1)
- # cryogen (1)
- # cursive (6)
- # data-science (3)
- # datahike (3)
- # datomic (32)
- # degree9 (3)
- # dirac (3)
- # emacs (9)
- # eql (1)
- # events (1)
- # find-my-lib (1)
- # fulcro (67)
- # graphql (13)
- # helix (9)
- # jobs (1)
- # jobs-discuss (92)
- # leiningen (31)
- # malli (8)
- # meander (3)
- # news-and-articles (1)
- # off-topic (46)
- # pathom (2)
- # practicalli (1)
- # re-frame (52)
- # reitit (12)
- # shadow-cljs (40)
- # spacemacs (10)
- # sql (4)
- # xtdb (8)
Which one is more idiomatic: (. System (getProperties))
or (. System getProperties)
? I know they're equivalent and I find the latter more readable. Any opinions? Thank you.
not that you need more options, but for static methods, I use (System/getProperties)
I'm aware of this third alternative, but I'm actually thinking in broader scenarios like when using with the ..
or doto
macros.
I don’t think I’ve ever used the .
or ..
syntax. if it’s a static call, I use the above. here’s an example of calling a non static method:
(.getBytes ^String line "utf-8")
https://clojure.org/reference/java_interop gives a number of examples
here’s an example with doto
:
(doto (new java.util.HashMap)
(.put "a" 1)
(.put "b" 2))
Regarding your original question, no preference
Thank you, all!
Hi. I'm trying to use a React component that takes a generator function as a parameter. Can I use lazy-sec for it? The component is written in typescript, I use reagent.
Well, I've made a try. Got TypeError: gen.next is not a function.
Are there any possibilities?
Found a way, using GeneratorFunction constructor, but I'll keep it as a last resort.
How can I become proficient in mocking/stubbing in Clojure? Any deep dive course/book that covers it? From what I see there is no lack of great manuals/courses on core.test or test.check/generative testing but not much info on mocking. I’m trying to understand why is that. Perhaps it is not as helpful/important as in other languages? Or is it as simple as just learning how to use with-redefs/with-redefs-fn?
have you seen this lib: https://github.com/alexanderjamesking/spy? docs are pretty good IMO
In my experience, Java devs use mocking to unit test some business logic that calls a stateful resource like a database, often because their code is a big, dependency-injected object graph. Clojure nudges you towards putting your business logic into pure functions that can easily be unit tested without mocking things.
Haven't seen it before. I saw mockery, clj-fakes + simple with-redefs.. It's kind of confusing where to start and what to use for a beginner. Anyway, thanks! I'll check out alexanderjamesking/spy
Places in my code where I do access external resources tend to be small functions that delegate the heavy lifting to pure functions. I test these with integration tests.
Personally, I’ve not seen the need for mocking much in my clojure code, as things like databases convert data into clojure data structures as a first step. Everything further in the system just manipulates / works with those, so your mock is just a normal clojure datastructure, perhaps with some particular shape. Actions like sending emails etc are a simple function of datastructure to effect which a function at the edge consumes to do the task, so anything generating those effects you just need to test the produced structure is correct. Eric’s book Grokking Simplicity covers some of this type of thinking really well I think =)…
Is there a shortcut for getting a value from a string indexed map? ("key" m) doesn't work like keyword indexed map. Is it only (get m "key")
?
They're both super-useful. For instance, it's very handy to be able to pass a keyword to a higher-order function like map.
lol just trying to figure out which one to use when I have string keys in the same function... perhaps I should aim for consistency in my case
note that if your map is nil (nil :key)
will throw, if your key is nil (k m)
will throw. But in both cases (get m k)
will do just fine
its simply what should happen if a keyword is in the first position (:foo ...)
It could either throw an error as not a function, or it look up
I'm trying to write a (defrecord ...)
, can someone tell me where the docstrings to? I don't see it in the https://clojuredocs.org/clojure.core/defrecord. I suspect I can include a dostring for the defrecord
itself and also one docstring per field ?
I don't have a complete list handy, but not all constructs in Clojure enable providing doc strings.
i believe this is one of those. emit-defrecord
doesn't mention anything about docstrings
You can alter the metadata on one or both of the record constructor functions that defrecord creates, modifying its doc string.
@U0CMVHBL2. sorry I didn't understand your comment.
Demonstration of my meaning in a REPL session:
user=> (defrecord MyRec1 [a b])
user.MyRec1
user=> (->MyRec1 1 2)
#user.MyRec1{:a 1, :b 2}
user=> (doc ->MyRec1)
-------------------------
user/->MyRec1
([a b])
Positional factory function for class user.MyRec1.
nil
user=> (alter-meta! #'->MyRec1 assoc :doc "My preferred doc string")
{:arglists ([a b]), :doc "My preferred doc string", :line 1, :column 1, :file "NO_SOURCE_PATH", :name ->MyRec1, :ns #object[clojure.lang.Namespace 0x75d0911a "user"]}
user=> (doc ->MyRec1)
-------------------------
user/->MyRec1
([a b])
My preferred doc string
nil
You can change the :doc key of the metadata map of any Var in this way, changing its doc string.
That gives you one doc string per record, but not one per field.
I'm reading chapter 13 of https://www.braveclojure.com the hard copy. It mentions three ways to instantiate a record. MyRecord.
, ->MyRecord
, and map->MyRecord
. However, the https://clojuredocs.org/clojure.core/defrecord mentions the second two and recommends (in the examples) writing your own what looks like a factory function make-MyRecord
. I using the MyRecord.
notation recommended against?
I believe some people really do not like to use any kinds of APIs that rely on positional arguments when the number of those goes over 2 or 3, due to difficulty in people remembering the purpose of that many positions. The MyRecord.
notation would also require an import
statement if you wanted to avoid using the fully qualified name when called from other Clojure namespaces.
The MyRecord. notation is doing Java interop on the implementation details of records - it is preferred to use the generated constructor functions
In my experimentation (map->MyRecord ...)
seems very readable as I'm not relying on positional arguments.
Once I've defined a record MyRecord
how can I ask whether a given object is a MyRecord
?
(instance? MyRecord obj)
Ok, so defrecord doesn't define a trival type predicate for me? That's fine.
no, although we've talked about that
easy for the user to write.
I don't understand the use model of extend-type
. The model in https://slack-redir.net/link?url=https%3A%2F%2Fwww.braveclojure.com is that for each type, you define all the functions specializing on it per protocol. It seems more logical, in my case to turn it 90 degrees.
I.e. for each function in my application, define what that function does for type1 and for type2, next to each other in the code. I.e., I've defined a record, I'd like to define what the function does for MyRecord
, and then what the function does for clojure.lang.Sequential
. Do I need to create 10 different protocols each with a single function?
Or perhaps I don't need a protocol at all, just 10 multi methods which all share the same dispatch function. i.e., to distinguish between MyRecord
and clojure.lang.Sequential
you have n protocols and m types - extend
does 1:1, extend-protocol
extends one protocol to many types. extend-type
extends many protocols to one type (they are nary in different dimensions)
One of the purposes why I'm experimenting with defining a record is because previously I had represented my data as an array of maps. But an array of maps is a sequence. clojure.lan.Sequential
and several times it spent a long time debugging because i was running the sequence code on the array of maps, rather than recognizing it as its own type.
I'm assuming you don't really mean "array" (like Java array)
but really sequence or other sequential collection
basically I'm not sure I understand what you're saying. creating a record to represent a sequential collection seems like a bad idea
alex, when you say "extends one protocol" do you mean a-la-fois extends all 10 functions of the protocol for a type? Or can each call to extend-type
just mention one of the functions? I.e. make 10 calls to extend-type
in different places/files in my code?
each time you extend, you are replacing anything that has been extended for that type before, so you can't extend one method here and one method elsewhere
Alex the fact that it is a sequence is accidental. I'm representing a finite state machine as an array of states, and each transition tells the index of the destination state. Semantically a state machine is not a sequence, it only happens to be because my choice of implementation.
so the second extend is not really an extend, but an unextend-then-extend.
yes (for either extend-type or extend-protocol)
Perhaps I need to use multimethods, as I can place the method definitions anywhere in the code in any order and in any file.
if you want that, that is more the multimethod model
As far as I understand now, I only have two interesting types. MyRecord and everything else.
perhaps 3 cases. MyRecord, sequences, and everthing else is an error, but that 3rd case can be handled directly in the dispatch function.
protocols don't seem very lispy, at least at first glance.
well i'm only a 10 minute protocols-expert at this point in time.
they are designed to tap into what's super optimized on the jvm, so they are definitely coming from a different perspective (type-based first arg dispatch)
Need to collab with a team that has never seen clojure. Best resource to get them started so they can at least read and understand the code? (versus developing new features)
if you post this on reddit, i bet you will get some answers. i think yogthos is active there and he has lots of experience ramping up new-to-clojure coworkers
Is there a lien channel on clojurians?
channels auto complete for me. i can hit cmd-k lein
and it shows me the matching channels
apparently there are many more channels than the ones appearing in my reader.
Has anyone seen a version of the animal guessing game written in Clojure?
How would I do what it looks like I intend the following macro to do?
(defmacro pprint
[& args]
`(do
(map #(println % ": " ~%) '~args)))
That errors with an "Unable to resolve symbol" on the ~%
.I think you'd want ~'% in both places, but maybe better to use the fn form
and you probably don't want a ' on '~args
and in general, I'd try to avoid map
for side effects - run!
prob preferred here
are you trying to print both the name of the arg and the value of it?
What do you mean about having ~'%
in both places? How would that print 2 different things?
Also, without the '
on '~args
, it expands to (arg1 arg2)
and blows up because it tries to call the function arg1
rather than treating it like a list of data to iterate over.
I thought this would be closer, but it still doesn't work. It expands to something that looks correct.
(defmacro pprint
[& args]
`(do
(run! #(println % ": " (eval %)) '~args)))
(let [a 1 b 2]
(macroexpand `(pprint a b)))
;; => (do
;; (clojure.core/run!
;; (fn*
;; [p1__31102__31103__auto__]
;; (clojure.core/println
;; p1__31102__31103__auto__
;; ": "
;; (clojure.core/eval p1__31102__31103__auto__)))
;; '(ezmonic.moniq/a ezmonic.moniq/b)))
(let [a 1 b 2]
(pprint a b))
;; => 1. Caused by java.lang.RuntimeException
;; Unable to resolve symbol: a in this context
you need to think more carefully about what happens at compile time vs runtime
no, you don't want that to be qualified
at compile time you can capture the local names of the symbols (~args), and you want to emit code with those (unqualified) symbols and that then evaluates those symbols at runtime
I think you can use Unquote splicing here
[~@args]
Does anyone have a good tutorial explaining how to use try/catch for error handling? Specifically in Clojure, of course, but I don't have much experience using it in any language either.
As an example, I am prompting a user to enter a number. If it is not a number I just want to loop back up to the start of the function and prompt again until they input it correctly.
Something like
(defn my-fn []
(let [input (read-line)]
(try
(Long/parseLong input)
(catch Exception e (my-fn)
But I am so unclear on the syntax and semantics of such a thing. Unfortunately someone helped me on this before but I lost the code and can't search back for it.
exceptions are kind of annoying to work with. however, some java calls require using them. I still prefer to try to work with values as much as possible. I would probably write my-fn
like:
(defn my-fn []
(let [input (read-line)
num (try
(Long/parseLong input)
(catch NumberFormatException e
nil))]
(if num
num
(recur))))
Ahh, I think that is what I had before. Thank you! So how would you test for a valid number input "your way" using values instead of exceptions?
same as above. basically, making the try/catch as small as possible
ideally, Long/parseLong would return a number and whether or the parse succeeded rather than throwing an exception
ok, ok. And for other problems instead of the exact error like NumberFormatException
can I use Exception
as a catch-all for any errors.
typically, you don’t want to catch Exception
you usually want to be specific as possible. it’s unlikely that your code will know how to generically recover from an unknown exception
often, it’s better to abort than to blindly continue like nothing had happened
Ahh ok. I guess I was asking because in my laziness I usually just re-prompt the user if anything isn't to my liking. haha
I'm currently doing Harvard's CS50 using Clojure and the guidance for many exercises is something like "If user doesn't give you a valid number, just re-prompt until they do"
well, like everything, there’s a always an exception. that’s actually a pretty good example of where catching Exception
and just printing the error makes sense
@ericihli something like this would print in map form if that worked
(defmacro print-args [& args] `(println (zipmap '[~@args] [~@args])))
Thanks. I kept fiddling with it and learned a lot. I had forgotten that syntax quoting expanded things to fully qualified symbols and regular quoting didn't.
Hi Alex, I tried to modify your macro, and I don't understand the macro expansion error. Can you help?
(defmacro print-args [& args] `(map (fn [expr value] (println [expr value])) '[~@args] [~@args]))
When I try to evaluate the following:
(print-args (+ 1 10) (+ 2 20) (+ 3 30 300))
it expands (at least according to cider) as I expect to:
(map
(fn [expr value] (println [expr value]))
'[(+ 1 10) (+ 2 20) (+ 3 30 300)]
[(+ 1 10) (+ 2 20) (+ 3 30 300)])
But I get the error:
Syntax error macroexpanding clojure.core/fn at (clojure-rte:localhost:49674(clj)*:270:19).
(clojure-rte.core/expr clojure-rte.core/value) - failed: Extra input at: [:fn-tail :arity-1 :params] spec: :clojure.core.specs.alpha/param-list
clojure-rte.core/expr - failed: vector? at: [:fn-tail :arity-n :params] spec: :clojure.core.specs.alpha/param-list
I can evaluate the expression which is the printed macro expansion:
(map
(fn [expr value] (println [expr value]))
'[(+ 1 10) (+ 2 20) (+ 3 30 300)]
[(+ 1 10) (+ 2 20) (+ 3 30 300)])
So I'm guessing there is a problem with one of the symbols is different than what I think it is????Perhaps I need a dorun
around the map? But I don't think that is the problem of the macro expansion error
Are there any guide on using web workers with ClojureScript? Like is it possible to connect a repl to a web worker?
There's a couple of examples: https://github.com/jtkDvlp/cljs-workers I've not had a chance to try it yet, but it might be useful :)...
Thanks.
It looks to me like the repl does not call print-method
to print records. Could this be the case? Is that a bug?
there no special exclusion of anything like that so I doubt that is the actual story
there may be default printers for IRecord or eventually everything falls into Object
why do I say that. OK probably I'm just very confused. But here is what I see. When I define a record, and a print-method
for it, then simply allocate the record in the repl it prints as a hash map, rather than printing with my print-method
.
clojure-rte.core> (defrecord Foo [x])
clojure_rte.core.Foo
clojure-rte.core> (defmethod print-method Foo [v w] (.write w (format "#<Foo x=%s>" (:x v))))
#multifn[print-method 0x7665aecc]
clojure-rte.core> (map->Foo {:x 100})
{:x 100}
clojure-rte.core>
I'd expect`#<Foo x=100>` to be printed
this is odd, it works for me using nrepl
you could try also implement print-dup
works as expected for me in clj
too
could repl call pprint
instead of print
for whatever reason?
for those for whom it works, are you using cider? is it possible that cider has its own printer which subverts print-method
?
(defmethod clojure.pprint/simple-dispatch Foo
[obj]
(.write *out* (format "#<Foo x=%s>" (:x obj))))
@UN3BYANJV as neither print-method
nor print-dup
are documented, which one SHOULD I implement if I do not intend the printed representation to be readable by the Clojure reader?
cider definitely has tweaks to the printer (I am not using cider)
I'd say print-method
does explicit print (print (map->Foo {:x 100}))
works?
also try clojure.pprint/simple-dispatch
-- this should work for pprint
clojure-rte.core> (pprint (map->Foo {:x 100}))
{:x 100}
nil
clojure-rte.core> (print (map->Foo {:x 100}))
#<Foo x=100>nil
clojure-rte.core>
pprint
doesn't work, but print
does. Is that normal?I am no expert on this. It seem you have to implement different multimethod for pprint:
(defmethod clojure.pprint/simple-dispatch Foo
[obj]
(.write *out* (format "#<Foo x=%s>" (:x obj))))
> to be readable by the Clojure reader are you trying to create custom tagged literal?
No, I'm not trying to create a tagged literal.
Re pprint
If I implement the clojure.pprint/simple-dispatch
function, I probably should implement the 1-ary and 2-ary versions.
BTW how can I define multiple arity defmethods?
Here is how pprint
seems to be defined
(defn pprint
"Pretty print object to the optional output writer. If the writer is not provided,
print the object to the currently bound value of *out*."
{:added "1.2"}
([object] (pprint object *out*))
([object writer]
(with-pretty-writer writer
(binding [*print-pretty* true]
(binding-map (if (or (not (= *print-base* 10)) *print-radix*) {#'pr pr-with-base} {})
(write-out object)))
(if (not (= 0 (get-column *out*)))
(prn)))))
The https://clojuredocs.org/clojure.pprint/simple-dispatch of simple-dispatch
is not very enlightening.
before diving into anything, try run :
(defmethod clojure.pprint/simple-dispatch Foo
[obj]
(.write *out* (format "#<Foo x=%s>" (:x obj))))
does it fix printing for you?simple-dispatch
takes single argument -- the object to print
or maybe you could try set cider printer fn
I tested this with clj, and it works as advertised. the repl uses print-method
, so it seems cider is confused.
if simple-dispatch takes a single argument, how can it print to a file if pprint is called with a 2nd argument?
I am not using cider so I can't help
(setq cider-repl-use-pretty-printing nil)
I just found this does it change anyting?
re: cider, yes I've opened a thread on the cider channel ...
setting the emacs variable cider-real-use-pretty-printing
works for this case. But this is a bit scary.
I'll experiment further and discuss in the cider Chanel.
thanks for the advice.
maybe unroll to why you say that
(peek (map identity (range 20)))
That raises. Can't peek into a lazy seq, right? Why does (peek (doall (map identity (range 20))))
also fail for the same reason? What am I missing about doall?
what are you missing about peek
?
peek works on instances of IPersistentStack, which are lists, vectors, and queues (not seqs)
doall will force evaluation, but it won’t convert a seq into something besides a seq
if you just want to look at the first thing in a seq, use first
Ah. I see. I thought the problem was that the lazy thing wasn't realized. Not that realizing a lazy seq still gave you a seq and peek didn'k work on seqs.
reading that back, I meant that question with a 😀 not sure if that came across!
generally, I would not use peek/pop unless you're actually using a collection as a stack