This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-17
Channels
- # announcements (3)
- # babashka (41)
- # beginners (118)
- # calva (4)
- # cider (22)
- # clj-kondo (4)
- # clj-on-windows (1)
- # clj-together (1)
- # clojure (164)
- # clojure-europe (46)
- # clojure-filipino (1)
- # clojure-indonesia (1)
- # clojure-my (1)
- # clojure-nl (3)
- # clojure-sg (1)
- # clojure-spec (13)
- # clojure-uk (16)
- # clojurescript (18)
- # cloverage (3)
- # conjure (5)
- # core-async (8)
- # cursive (21)
- # datomic (4)
- # deps-new (15)
- # emacs (12)
- # expound (4)
- # fulcro (45)
- # graalvm (32)
- # jobs (1)
- # malli (5)
- # nextjournal (63)
- # off-topic (27)
- # other-languages (3)
- # pathom (27)
- # proletarian (1)
- # rdf (24)
- # re-frame (10)
- # reagent (9)
- # releases (2)
- # shadow-cljs (72)
- # spacemacs (4)
- # timbre (4)
- # tools-deps (29)
- # xtdb (4)
Should 'def' really never be used other than top-level ? I am developing a graphical application and some vars will be intitialised in the main thread with graphics context. So I am declaring lots of vars, then the initialisation function which is called with the context sets the var roots with alter-var-root. I could also use def inside the initialisation function?
I believe it is not quite clojure-conventional, but if it works for your purpose and creates no issues like performance, why not?
Just use intern
if you're dynamically making vars
More strictly speaking, it wouldn't be a good practice because def
creates "a global var with the name of symbol" according to the clojure-docs. Why would we declare global var attached to its namespace within a function or expression. If the purpose is to hold a internal state, it makes a better sense to use let
. For global level state, I would simply use a var that has atom.
In the meantime, Racket
okays define
within function. It is the same as let
though, just syntax diff.
I sometimes do tests which reload app's generated state. And in that case it's sometimes useful to have a def
inside of a defn
:
(defn reload-my-value! []
(def my-stuff _)
)
;;And then generate that value for regular execution:
(reload-my-value!)
You could replace that in your tests with using the with-redefs
macro, which temporarily redefines the vars within a dynamic scope.
I know but the def
bit creates a very large blob and it's also stateless. So I decided to create it only once.
It creates quite a large handler matcher.
I.e. the point of this is to provide code reloading for tests.
As always, it depends: • Are the values you're setting from the main thread immutable values? • Why not set the values outside of the main thread? • Does the state need to be accessed outside of the main thread? • Have you considered using something like https://github.com/stuartsierra/component or https://github.com/tolitius/mount? Also, if you provide more info and context about your use case, we may be able to offer more specific help. • What type of application are you building? • Which GUI library are you using (swing, seesaw, cljfx, etc)?
These values are dependent on the OpenGL context, I am using libgdx library for a game. It looks like this:
(declare texture-a, viewport-b, camera-x)
(defn on-create []
(alter-var-root #'texture-a (texture....))
(alter-var-root #'viewport-b (...))
...
It can be only set during the application-thread because of the context requirement. on-create is called by the application when starting with the right context.
(def on-create []
(def texture-a (texture...))
(def camera-x (camera ...))
(def viewport-b (viewport ...))
There are issues with global state, but for this particular use case there may also be thread-safety issues. I assume that some of these values should not be accessed outside of the main thread.
Not sure how you're consuming libgdx, but their examples seem reasonable for showing how to initialize and deal with state within the context of libgdx, https://libgdx.com/wiki/jvm-langs/using-libgdx-with-clojure
There are no thread -safety issues as the variables are only initialised once ( create is only called once ). Let-ting over the gamestate is not really a possibility for bigger applications
you'd be surprised
are texture, camera, viewport, etc read only? or are they mutable? If they're mutable, are their thread safety issues if they're mutated outside of the main thread?
Generally, I would claim that global state is worse for large applications. For smaller applications, it doesn't really matter as much.
fwiw, it does seem like the type of thing you can refactor later if needed.
@U0ALH6R89 you could also make those dynamic variables and use binding
to give them a value inside the dynamic scope of your application
Funny how much harder I find doing leetcode is in Clojure, but day to day programming working on business problems I find so much easier in Clojure 😛
Oh, does leetcode provide Clojure? When I checked a few months ago, I only saw Racket but no .
https://exercism.org has Clojure tho 😄
I'm sure day-to-day is much easier with Clojure (although I haven't used Clojure in anger yet), but I find it to be easier on Leetcode as well for most problems (compared to Python). Any particular ones you found Clojure difficult to work with @U0K064KQV?
I might just be bad at problem solving algos without mutation and functionally. The ones where say I have to iterate in reverse over an array. Or ones where you need to track the location of things inside an array as well as the value.
For example this one: https://leetcode.com/problems/number-of-visible-people-in-a-queue/
https://leetcode.com/discuss/general-discussion/673522/any-plans-to-support-clojure consider upvoting 🙂
Sorry for disturbing, but they deleted previous one. Please, vote one more time https://leetcode.com/discuss/feedback/2355129/Clojure-support-please!-Interesting-notes-inside
Is it possible to somehow configure the names assigned to the parameters in a class method generated by gen-class
?
You mean the :methods
argument? No, because argument names are not a part of signature.
But the implementation can use any names it wants.
Like in this example with setLocation [String]
and -setLocation [this loc]
: https://clojuredocs.org/clojure.core/gen-class#example-542692d3c026201cdc326fbb
Yeah, the audience of this is potential users of the generated class files who might be using other languages. We’re trying to provide a better experience to our kotlin devs than [Object var1, Object var2]
I think var1
etc don't even come from Clojure - that's just how your viewer, whatever you're using, is assigning names. In bytecode, argument names don't exist at all (unless debugging information is provided, which I don't think is possible to include for gen-class
). And gen-class
doesn't generate anything but bytecode.
That's why you'll see stuff like var1
all over the place when decompiling Clojure class files as Java code.
Same deal in Java:
jshell> String.class.getDeclaredMethods()[5]
$6 ==> public void java.lang.String.getChars(int,int,char[],int)
jshell> String.class.getDeclaredMethods()[5].getParameters()
$7 ==> Parameter[4] { int arg0, int arg1, char[] arg2, int arg3 }
jshell> String.class.getDeclaredMethods()[5].getParameters()[0]
$8 ==> int arg0
jshell> String.class.getDeclaredMethods()[5].getParameters()[0].getName()
$9 ==> "arg0"
Maybe you'll have more luck with it if you rewrite gen-class
in a .java
file and compile it with debug information. Or provide the .java
file as part of the distribution and let clients of other languages figure parameter names themselves.
Maybe some Clojure libraries that serve as alternatives to gen-class
can let you stay in Clojure while creating Java classes with debug information included.
My recommendation if you want to provide an api for other jvm langs is to write Java interfaces in Java, then implement those in Clojure
You can use the Clojure Java API to bootstrap into that with a small amount of Java code (or translate to other langs)
If you makes the Java interfaces, you have a hard target API, all the jvm langs should be able to work to that, you can gen javadoc, etc
I've done this with Java several times, but I think the same principle would apply for Kotlin.
@U064X3EF3 Using the technique https://clojure.org/reference/java_interop#_calling_clojure_from_java, yeah? Then generate classes for that very thin interface? (I ask because I've seen folks run into problems, maybe accidentally, aoting thicker interfaces)
Yeah. I don't know of any issues like that.
The scenario I've seen is a Clojure library that wants to be useable from java. So the lib naively uses gen-class and aots. But then the aoting brings in other classes and the jar ends up with many classes that aren't related to the desired thin interface. And these other classes cause conflicts and issues. (BTW, I'm not suggesting I understand anything here, just trying to learn if this scenario is real).
Well that's not what I'm suggesting. You don't need gen-class at all
You can aot compile your Clojure impl, but you don't even need to do that
(Which means you can still interactively develop in the context of the app)
Yeah, I know, I got that, sorry, I think I'm hijacking this thread, I will go away now.
greetings Clojurians! i have a question about profiling. i have a slow, top level function that calls many deeply nested functions, including some i/o, and i would like to find the bottlenecks. i don't care much about repeatedly profiling individual functions (such as use Tufte) - instead i would like to systematically report back the timing of each nested function call in one journey of the graph when the top level function is called. profiling tools seem like an obvious choice but i'm a little out of the loop. also, i'd like to capture the data from a deployed Ion where it may be tricky to attach a profiler (though i'm not sure). what's a good way to get started? many thanks.
Most notably, https://github.com/clojure-goes-fast/clj-async-profiler seems what you are after
(Not sure how that works with Ions tho)
i'll take a look @UDF11HLKC, thanks for your help
If it's possible to run those functions locally then async profiler is the way to go. I'd also try to separate the IO and CPU parts to figure out if the slowness is due to program structure (blocking and waiting for things sequentially) algorithm (is there a better solution with regards to complexity) or non optimal implementation
coming back to this thread, https://github.com/clojure-goes-fast/clj-async-profiler is pretty great and the flamegraphs are useful, but i'm specifically looking to capture the execution time (not CPU) of each nested function call. any ideas?
I don't do exactly what you want when profiting, but what I do is I compose clj-async-profiler and criterium at the repl
So I profile the benchmarking process, and the result is a flamegraph with relative cpu usage + absolute numbers of total execution time
There are some tracing tools you can use, but they won't instrument all of your code automatically, see mulog for example https://github.com/BrunoBonacci/mulog
hmm. my function graph has lots of i/o so i'm not interesting in stress testing them, just measure a typical journey through it. i started using https://github.com/technomancy/robert-hooke to add a hook with time
to each function in various namespaces, since i want to do this automatically, but it started to become a project. i was hoping a tool existed. darn.
oh this might be what i'm looking for! i'll take a closer look when i'm back on the clock. thanks @UK0810AQ2
Is there any performance difference between #(do-stuff %)
and (fn [one] (do-stuff one))
?
I don't expect so. It is simply IMO a reader macro that end up (fn [gen_name1, ...] body)
- see https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java#L896
On a related note, any idea what is the reasoning for preferring partial
over an anom. fn https://guide.clojure.style/#partial ? @bozhidar?
One argument in favour of partial
is that you immediately know where the argument will be applied. With #()
you can get a lot of complicated permutations
Yeah. Also arguably it can simplify a bit the code and is the "more functional" way of doing things. There's no strong reason to prefer it, though.
But also, partial
is still useful when you have a function with many arguments and you want to bind just one. Compare (partial f 1)
to #(apply f 1 %&)
.
There are still downsides though, like having an extra idiom and having an extra item in your stacktrace that doesn't even point to your code. It also becomes much less obvious how many arguments the resulting function should receive. I myself prefer #()
, except for maybe that case above, which I fortunately almost never need.
With write once, read many times, i rarely think #()
is nicer than (fn [named-argument])
Yeah, I almost always prefer fn these days first, then #(), then rarely partial
#()
usually when it's very small, never use if for things where the code spans multiple lines
So perhaps we should modify the style guide to prefer #() or (fn)? I know partial is the more functional way (that's why I like it) but it is long, you don't know how many arguments it will take, and it is not the Clojure way, according to Rich and Alex. What do you think, Bozhidar? Regarding #(), https://stuartsierra.com/2019/09/11/clojure-donts-short-fn-syntax says "Use #() only for a single function or method call." which resonates with me.
one difference (correct me if I'm wrong) is how (or rather when) higher order functions (partial, comp etal.) evaluate the arguments compared to an anonymous function. I've had several confusing problems related to stuff like (partial satisfies? SomeProtocol)
or using partial with instrumented functions
In your example it shouldn't matter. But if you have something like (partial f (get-val))
as opposed to #(f (get-val) %)
then yeah, there's a difference.
Another potential issue is when you redefine your vars. So if you use alter-var-root
, (partial ...)
won't be affected but #(...)
will be.
my memory is hazy (and I'm having the flu), but I have a recollection that you can accidentally stumble on that "redefining vars" territory without realizing it. I think (again, I may be wrong) enabling instrumentation does it and also extending procotols can "alter" the protocol, whereby it no longer satisfies the value captured by partial.
Oh, hm, that's right. I didn't realize that extend
works differently from using the protocol when calling defrecord
/`deftype`. Thanks!
yes, partial closes over the function value, #() will refer to the var (so you retain the indirection)
partial can also do this of course if you use #'f instead
The one argument I use for partial
is that whenever I see (partial…
I know what’s going on, when I see #(…
or (fn […
I know I need to write the full thing to understand it. In other words. partial
very clearly communicates the intent.
Is there a naming convention to make it clear that a function returns a future or a promise? Like my-fn-f
?
Not really IMO. If appropariate, I include -promise or -f[uture] in the name.
I usually write schemas for input / outputs of my functions, but how to introduce the concept of promises/futures in schemas :thinking_face: I don’t think it’s supported in Prismatic, malli, or spec
no, b/c those are opaque things
It is not really opaque in the sense it is a promise of a data structure shape, I would like to have the same expressivity than what we have with type systems, where you could have a Promise[Account] for the return type of a function
Refactoring ideas?
(condp <= v
10E12 (str (.toPrecision (/ v 10E12) 3) "T")
10E9 (str (.toPrecision (/ v 10E9) 3) "B")
10E6 (str (.toPrecision (/ v 10E6) 3) "M")
10E3 (str (.toPrecision (/ v 10E3) 3) "k")
v)
you might find this cute or terrible
(defn order-of-magnitude
^long [x]
(long (Math/floor (Math/log10 x))))
(def quantifiers
{1 "K"
2 "M"})
(defn quantify
[x]
(get quantifiers (quot (order-of-magnitude x) 3)))
another option
(let [[x s]
(condp <= v
10E12 [ 10E12 "T"]
10E9 [10E9 "B"]
10E6 [10E6 "M"]
10E3 [10E3 "k"]
v)]
(str (.toPrecision (/ v x) 3) s))
looks worse to be honest, but at least there's no repetition
(reduce (fn [v [mag unit]]
(if (<= mag v)
(reduced (str (.toPrecision (/ v mag) 3) unit))
v))
v
[[10E12 "T"] [10E9 "B"] [10E6 "M"] [10E3 "k"]]
@UK0810AQ2 That will blow up on the default condp
clause. ;)
That works only for BigDecimal
. And .toPrecision
is actually from JS. Also converting to a string is not a numerical operation, so it ignores with-precision
in its entirety.
Ah, all right, maybe not then. 🙂 I don't think I've ever had the occasion to use with-precision
, actually.
I usually write schemas for input / outputs of my functions, but how to introduce the concept of promises/futures in schemas :thinking_face: I don’t think it’s supported in Prismatic, malli, or spec
Does clojure support separating a number to make it more readable? e.g., something like 100_000, or 100'000?
Although I'm not entirely sure that there are no values for which it'll end up in a number that's one less than needed...
https://ask.clojure.org/index.php/8511/add-digit-separators-support-to-number-literals if you want to vote
you can probably make a macro which turns symbols like i100_000
into values at compile time :)
not sure you'd retain primitiveness that way
coming back to this thread, https://github.com/clojure-goes-fast/clj-async-profiler is pretty great and the flamegraphs are useful, but i'm specifically looking to capture the execution time (not CPU) of each nested function call. any ideas?
I would like to give a big shout-out and huge "Thank you!" to Sean Corfield (@seancorfield ) for the excellent work on next.jdbc
. In particular, https://cljdoc.org/d/seancorfield/next.jdbc/1.2.659/doc/getting-started/tips-tricks#working-with-json-and-jsonb for getting the JSONB datatype working between CLJ<->Postgres were detailed, complete, and worked on the first try. Wow!
Thanks -- but I can't take any credit for the PG docs: they've all been contributed by PG users (which I'm not). The community are awesome !
is there anything besides java.util.regex.Pattern
that I can be read and does not have value-based equality in Clojure?
Functions.
user=> (read-string (pr-str (fn [] )))
Execution error at user/eval156 (REPL:1).
No reader function for tag object
user=>
user=> #java.lang.Object[]
#object[java.lang.Object 0x6df7988f "java.lang.Object@6df7988f"]
user=>
user=> (read-string "#java.net.Socket[]")
#object[java.net.Socket 0x3241713e "Socket[unconnected]"]
user=>
Aren't functions readable because e.g. (read-string "#(- x)")
? Of course they don't round-trip from being printed to being read in as the same thing, but I didn't think readability required that.
can I back up and ask why you asked for this in the first place?
what if you write a macro that annotates the defined function with its form and insructs print-method to print the form?..
@U064X3EF3 using the read forms (in the case they don’t define a var) as edges in Clerk’s dependency graph and discovering regular expressions being a first thing that makes this seem like a bad idea
seems like giving up control over equality in your primary data representation might generally be suspect
seriously though, that could easily change in 1.12
well, I guess we'd probably use a tagged form for rehydrating vars, so maybe not
but anyways
user=> (type (read-string "#'foo"))
clojure.lang.Cons
user=> (read-string "#'foo")
(var foo)
user=>
he (or she) who controls the reader, controls the world
but back to the matter at hand, seems like there are several ways to handle this - either by wrapping into your own type or using a protocol with default impl but with the ability to override per other cases etc
Not sure whether ##NaN
is in this category you are asking about, or not.
This article mentions the Regex pattern case, ##NaN
, and a few others I'm not recalling at the moment, but not sure whether they are relevant for your use case: https://clojure.org/guides/equality
yeah, that is what it means for the reader to be extendable with tag literals, it can return any type
Not quite directly related to the reader but please don't use java.net.URL
if you can help it, especially not with clojure data structures. It has a hash function that depends on making a DNS lookup so long running processes, systems with inconsistent or fragile internet connections, or also just anything that happens to run around when a dns cache gets evicted can see odd behavior like maps with two keys using "the same" url.
instead of read-string
, you could use something like (memoize read-string)
and guarantee that reading the same form will give you the same value
it was already solved using edamame which supports reading regexes like :regex #(list 're-pattern %)
which is guaranteed to result in the same hashing
went with https://github.com/nextjournal/clerk/commit/07d24a8a350c16c08897ac06744d245decf3ce57. So #"re"
is read as (re-pattern "re")
@U04V15CAJ thanks, https://github.com/nextjournal/clerk/commit/0e4e6b7d69d49a98a621c9a138c1e1fbd93ef057
@U0NCTKEV8 > and that is without going into the most verboten two words in clojure The use of the word verboten has made this to much of a mystery for me. What are these forbidden words? Do they grant grate power but take a terrible toll?