When working with looping over strings, should I be using first
and rest
heavily or use a [Buffered]Reader? Does using a reader and passing it around means that we're now in mutable land? I'm trying to parse html something like Selmer / Mustache. Selmer is using a reader
and passing it around, but I'm wondering if there are other ways to do something like that?
not a pro but, I don't think there is a significant performance benefit for the trouble involved -- not sure how it's implemented under the hood but i reckon it's probably close to optimal. Check out how other projects do it -- hiccup, selmer as you mentioned, maybe enlive by cgrand can point you in the best direction.
using strings via the seq api is a bad idea, the slowdown is significant
if you are just reading you can use indexing and subs
, and just keep track of indexes
Thanks will try the subs
approach, I was mainly concerned if passing around a reader
is like an anti pattern or not. I've seen it being used at multiple places so I guess it's fine.
• The fn
macro distinguishes between the two syntaxes: (fn name? [params*] exprs*)
vs (fn name? ([params*] exprs*) +)
.
What is the correct way in closure to distinguish between [something ...]
and (something ...)
especially when writing macros ?
When I look at https://github.com/clojure/clojure/blob/clojure-1.10.1/src/clj/clojure/core.clj#L4513 it seems, on line 4525 that the function vector?
is used to distinguish these two cases.
This would seem to mean that I can use vector in my code or any structure that implements IPersistentVector
. Is that true?
Is there a naming convention for functions which I intend to only be used within a file or from within the implementation of a group of functions? In common lisp it is customary to name such functions starting with a %
. other namespaces which import this namespace can use such a function, but the naming convention implies they shouldn't.
If I make such a function a local function, than I cannot write test cases for it, so it is better for development purposes to make it a top level function.
Is there a word clojure programmers use to describe the type of destructuring which happens with a let
or fn
like this: ?
(let [[[a b] [c [d]]]] some-data] ...)
In Common Lisp it is referred to as destructuring but that name unfortunately is very long, resulting in very long function names such as destructuring-bind
which sometimes gets abbreviated in literature as dsb
which is very terse.When you say “local” do you mean “defn-“? You can still write tests for those fn’s, you just have to call the var instead of the name:
(#’foo/my-private-fn)
Can someone please remind me how to figure out which dispatch value a defmulti is returning. My program is triggering some error in the dispatch that I cannot figure out. If I have the values from the call site, I'd like to know what the code in defmulti returned, or whether it encountered an error while trying to figure that out?
You can use get-method
with the method and dispatch value to see which dispatch fn would get called
not sure if that's what you're looking for exactly
yes but how can I get the dispatch value?
There is some function, I seem to recall, for debugging purpose, which will give you back the dispatch value.
yes, prefix the function with -
, i.e (defn -foo [] ...)
. note that this is just a convention and is not recognized by the compiler in any way
unaware of an extant term, might I suggest "pickpocketing" ... at least I can sort of grok it right away
it is called “destructuring” in clojure as well: https://clojure.org/guides/destructuring
user=> (vector? '(1 2 3))
false
user=> (list? [1 2 3])
false
but most code should not care about whether something is a list or a vector
Is it prefers
you're talking about? https://clojuredocs.org/clojure.core/prefers that's the closest something I could locate right now
True. There are very few data structures built into Clojure that implement IPersistentVector, and none that I am aware of that can be written as literal expressions in code other than clojure.lang.PersistentVector. The other I know of you can create a vector of Java primitive values using (vector-of :byte 1 2 3)
, but there is no literal syntax for that, so not useful in macros.
There is also the notion of a private function, written (defn- private-foo ...)
, or (defn ^:private private-foo ...)
. Those can be called from outside of the namespace where they are defined, e.g. useful in namespaces containing test code for such functions, but you must use syntax like #'some.namspace/private-foo
to refer to them in namespaces other than the one where they are defined.
If you defined the multimethod yourself, then you know what the dispatch function is, and can call it on any object you want.
If you are asking "for an arbitrary multimethod, is there a way I can call its dispatch function, even if I do not know what that happens to be?", then I don't know of any Clojure function included in core that can do that, but there is a Java field named dispatchFn
in the object with class clojure.lang.MultiFn
that is public, and so you can use Java interop to get it.
user=> (defn foo [x] (inc x))
#'user/foo
user=> (defmulti mymm "blarg" foo)
#'user/mymm
user=> mymm
#object[clojure.lang.MultiFn 0x68ad99fe "clojure.lang.MultiFn@68ad99fe"]
user=> (.dispatchFn mymm)
#object[user$foo 0x1755e85b "user$foo@1755e85b"]
user=> foo
#object[user$foo 0x1755e85b "user$foo@1755e85b"]
user=> (identical? foo (.dispatchFn mymm))
true
user=> ((.dispatchFn mymm) 5)
6
I probably have misunderstood, but why would a function be written just to destructure a value? I would name the function on the logic or purpose I needed destructured values for. If destructure was part of the name, would also the type of destructuring (positional, associative) be used? This seems a very low level and brittle approach. What if the function changed it's arguments and didn't destructure, or changed the type of destructuring, the name would no longer be relevant.
Not sure that I agree. I write tests for my private functions, making testing the public functions easier. Especially when I write the private functions first, and write the public functions when I get the private ones all working.
It is of course your right to disagree and take a different approach. I've rarely seem to use a distinction of public and private functions, the distinction seems largely irellevant, especially compared to the approach I used to take with Java and Scala. I usually have functions and helper functions, occasionally spinning off the very generic helper functions into their own namespace (which would then require refactoring the tests if they had them). I tend to write tests when I have evolved a sufficient understanding of the constraints around the 'public' functions which form the API for each namespace. The design of this API is usually more important to the overall design and should be supported by valuable tests. I tend not to write tests for everything, especially if it is tested elsewhere. When exploring a design I may write funcitons that become helper functions, used by others. However, at that stage of uncertanty I typically would not write unit tests (or not many) as the design would not be concrete enough to put into unit tests that would be stable enough to feel useful. I have found that exploring design choices in the REPL and codifying data models in spec provide an effective way to evolve my understanding of the challenge at hand. An of course just spending a good detail of time away from the computer thinking about the problem in detail (hamock time). Once specific design descisons are made then they can also be codified in test, using clojure.spec generative testing to provide a more diverse set of test data Naturally I do not have a shared set of experiences with all developers and of course you should take an approach that you find effective.
@andy.fingerhut I recall that there's an easier way. What you've done is factor out the dispatch function from the defmulti. There's a way, I just have forgotten what it is, to ask the system to call the dispatch function and give you the value back, without actually dispatching.
Is there a way to escape the spaces in main-opts
in deps.edn
? They seem to always break the argument, even when they are in the quotes...
For example :main-opts ["--param={:a 1}"]
is always intepreted as ["--param={:a" "1}"]
It seems to be a reported problem: https://clojure.atlassian.net/browse/TDEPS-56
Has there been any fixes? Are they any work-arounds?
"--param={:a,1}"
should work
unless we're all talking past each other using dispatch value/function to mean different things, as best I can tell from https://github.com/clojure/clojure/blob/clojure-1.10.1/src/jvm/clojure/lang/MultiFn.java at least, the return value of dispatchFn is always immediately used to lookup the associated fn, it isn't stored anywhere besides the method cache or exposed elsewhere.
Oh, I see. I thought there was a more clojurey way
(defmulti xyzzy (fn [x y] 42))
I see I can evaluate the following ((.dispatchFn xyzzy) 1 2)
to get back 42.It would be nice if that were documented with defmulti
Commas are whitespace in Clojure, so are used instead of spaces that would otherwise need to be managed on the command line. For example, https://github.com/practicalli/clojure-deps-edn/blob/live/deps.edn#L314
I added https://clojuredocs.org/clojure.core/defmulti#example-5f70f927e4b0b1e3652d73c3. Did I use the correct description?
That looks correct to me. I wouldn't be surprised if it might be somewhat different for ClojureScript, but http://ClojureDocs.org tends to be focused on Clojure/JVM anyway.
@jason358 Thanks! What if the param requires a space?
@jr0cket What if the param requires a space? Here is an example I ran into: --error-format="::error file={{file}}::{{message}}"
I was thinking
:main-opts ["-m" "antq.core" '"--error-format=::error file={{file}}::{{message}}"']
I will try find time to look at this option for antq, I’m just using the default and piping it into an org file to give an interactive table
@jr0cket Single quotes in edn do not "surround" they are syntactic sugar for (quote ...). If you meant :main-opts ["-m" "antq.core" "'--error-format=::error file={{file}}::{{message}}'"]
then no, it does not work...
I believe single quotes should work on the command line or in a script, but haven't had chance to test
@jr0cket Yes, it works in command line, but I was wondering if I could include it in the :main-opts
. I mean for antq I can probably just make a Makefile or bash file and include the param, but I was wondering if :main-opts
itself supports spaces or not. It seems not ...
In this case, --error-format
is an arbitrary string that could have spaces them
I don't know. It looks like your problem is with shell, splitting at spaces, not with edn. So I'd suggest trying some standard shell escaping approaches (like \\
or "--param='{:a 1}'"
)
I believe strings are surrounded with single quotes. Does that help?