This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-11-11
Channels
- # announcements (3)
- # babashka (62)
- # beginners (58)
- # calva (40)
- # cider (3)
- # clj-kondo (75)
- # cljdoc (14)
- # clojars (8)
- # clojure (110)
- # clojure-australia (6)
- # clojure-europe (38)
- # clojure-hungary (1)
- # clojure-india (4)
- # clojure-italy (1)
- # clojure-nl (3)
- # clojure-spec (4)
- # clojure-uk (3)
- # clojurescript (45)
- # conjure (4)
- # cursive (35)
- # data-science (1)
- # datomic (11)
- # events (2)
- # exercism (4)
- # figwheel-main (4)
- # fulcro (103)
- # graphql (16)
- # helix (1)
- # holy-lambda (16)
- # honeysql (1)
- # introduce-yourself (3)
- # jobs (1)
- # keyboards (2)
- # lsp (4)
- # malli (11)
- # membrane-term (3)
- # mount (2)
- # nextjournal (2)
- # off-topic (53)
- # pathom (30)
- # pedestal (2)
- # portal (22)
- # rdf (1)
- # re-frame (7)
- # reagent (3)
- # reitit (5)
- # remote-jobs (6)
- # shadow-cljs (20)
- # sql (8)
- # tools-build (10)
- # vim (4)
- # xtdb (12)
Is hickory abandoned? https://github.com/davidsantiago/hickory There are many unaddressed issues and pull requests. If I look at davidsantiago
’s activity on github, he made 0 contributions this year, and 1 contribution last year. Anyone know more?
Seems so. I’ve been using it, but have replaced most of that I used it for with my own stuff.
I can’t figure out how to get the REPL to tell me the version of cider-nrepl that is loaded. I asked here, since my google-fu was not enough to find the answer out there: https://ask.clojure.org/index.php/11268/tools-deps-how-list-dependencies-and-their-versions-from-repl
Guess one option would be to parse it from (System/getProperty "java.class.path")
.
I hope you’re both considering to answer at http://ask.clojure.org. 😃
(-> (System/getProperty "java.class.path")
(clojure.string/split #":")
(->> (map #(clojure.string/replace % #"^/Users/pez/.m2/repository" ""))))
A bit brute, but does the work.FWIW, if you care about Windows compatibility, you might want to use
instead of :
.
You could also probably use the tools.deps.alpha API to get the information if you don't mind the dependency.
advice question ... I have something that works but it doesn't feel as clean as I think it should be ...
(seq (reduce (fn [form param]
(conj form (keyword param) param))
['prn] '[x y]))
=> (prn :x x :y y)
I don’t know what you are doing, but if you want to generate a code based on same data macro sounds good.
the idea was to produce pairs of kw / value so that it's obvious which variable is being referenced
you might want to care about the actual form that gets passed in rather than converting it to a keyword, like this maybe?
(defmacro prn-debug [& forms]
`(do ~@(map #(list `prn :debug (list `quote %) :> %) forms)))
(let [x 1 y 2]
(prn-debug x (+ x y)))
;; outputs:
;; x :> 1
;; (+ x y) :> 3
I guess you might also want to care about the return value, so you can wrap it around things?? maybe like this??
(defmacro prn-debug [& forms]
`(first ~(mapv #(list `doto % (list `->> (list `prn :debug (list `quote %) :>))) forms)))
which should output the same thing, but return the value of the first one?? Or are you imaging wrapping it round a defn
/ fn
or something so it prints the args and then does whatever?thanks @U0P0TMEFJ that is indeed a powerful option
the bigger picture is to enable code changes during a conform
/ unform
round trip for ns, def and defn ... and then eventually others though that's a good enough start 🙂
the actual goal is to to pass any registered functions the conformed data for the forms they are interested in and have an API that can make life easier for the authors of the functions. But those functions must return data that can be subject to unform
(def sample-xform-declaration
{:defn.params.prn
{:enabled? false
:ui {:label "Print parameters"
:control :checkbox}
:joins [{:ns-regex #"repl.*"
:form-types #{:defn :defn-}}]
:actions [xform-sample-f-prn]}})
and the :ui
part would control whether or not the specific xform is enabled ... like I say, very early sketch
the macro for prn-debug
is definitely more general than my code so I'll give it some thought
so it's some kind of advice / interceptor framework type thing? When I've written things like that in the past, I've regretted writing things like regex-filter
and ended up putting a transducer there, so you can compose filters together and write (remove #(re-matches #"regex" %))
for not, and so on ... so I'd recommend starting with that instead of :ns-regex
and :form-types
.. cos you might want to match all the forms that have some metadata or match some name or something - you can always write
:form-filter (filter (comp #{`defn `defn-} first))
or something? Then you're just reading forms from a file and filtering them with whatever matches before passing it to the action, and you get to name the filters and can easily join them together ... you get a sorta query language for very little effort ... just a thought 😉are you planning on getting in the way of loading files, so you're adding your own code processing layer in code loading? or altering the var contents after it's loaded? cos you're going to have to keep track of what order these transformations get applied, especially if you want to undo them 😉
it's early days ... if you're interested you can read more https://github.com/repl-acement/editors
although it's a bit broken now, this provides an approximate demo of how the transforms should work
work to do ... undo the transform (the fun bit), support multi-arity functions (straightforward)
the code is at https://github.com/repl-acement/repl-acement (like I say, currently broken ... I really should stop committing to main)
ah ... so you're expecting to be in the way of people actually evaluating code, as some new tooling?? So you can just store the original form and a sequence of transforms as metadata on the var and apply them from scratch every time, right? That seems like the easiest way to implement undo, by not implementing it 😜
I might have some free time to help out, but not this weekend ... I'll keep an eye on your repo and ping you if you want any help?
(defmacro when-let-all [bindings & body]
(let [local? (->> bindings (partition 2) (map first)
(tree-seq (fn [x] (and (not (string? x)) (seqable? x))) seq)
set)]
`(let ~bindings
(when (and ~@(->> bindings destructure (partition 2) (map first) (filter local?) distinct))
~@body))))
that might help?@U0P0TMEFJ there is some room for discussion about whether the transformations are durable or not ... something like tracing maybe just for the session but might also be useful on a production app and these kind of transforms reduce the labour of adopting logging frameworks. They could also be the basis for more extensive refactoring which would be retained. How undo operates is an open question tbh ... could be done by scrubbing back time but other work is lost then and that's not nice so there has to be some sort of means to select history in a granular manner
apropos destructuring ... I'm currently relying on the clojure.core.specs
to help me out for the defn
specs so I'll see how that macro works with that data
I know that I could avoid it altogether using pprint
or tap
but that's something else 🙂
@takis_ I'll be looking into the data.json thing, but so far ai haven't been able to repro. Could your elaborate a bit on your environment and such? Perhaps in #data-json or on the ticket?
A question about reading custom objects (org.joda.time.DateTime) in the REPL. The problem: I want to easily print and then read the printed version of collections containing joda time objects. Example - while debugging or when logging stuff floating through the app I may get this on stdout:
{:created-at #object[org.joda.time.DateTime 0x58053a61 "2021-11-10T17:31:01.000Z"]}
(possibly including multiple such things in a way larger map)
Now I want to read this stuff in the REPL - but I cannot because the reader doesn't know how to read / instantiate such things.
So I added data_readers.clj
{object my.ns/joda-time-data-reader}
which references this:
(ns ...
(:require
[clj-time.format :as tf]))
(defn joda-time-data-reader [[class-symbol _objid date-time-string :as value]]
(if (= "org.joda.time.DateTime" (name class-symbol))
(tf/parse date-time-string)
(throw (ex-info "Unsupported #object instance" {:value value}))))
But I still cannot read these things in the repl - an attempt to do so gives me an error:
;; Syntax error compiling fn* at (src/my/ns.clj:1:8458).
;; Can't embed object in code, maybe print-dup not defined: 2021-11-10T17:31:01.000Z
So without really knowing what is print-dup
used for I find this https://groups.google.com/g/clojure/c/scAjN7_Xig0
and do something similar for the DateTime object
(defmethod print-dup org.joda.time.DateTime
[dt stream]
(.write stream (format "#=(org.joda.time.DateTime. %s %s %s %s %s %s %s)"
(.year dt)
(.monthOfYear dt)
(.dayOfMonth dt)
(.hourOfDay dt)
(.minuteOfhour dt)
(.secondOfMinute dt)
(.millisOfSecond dt))))
This finally seems to work.
but it even works if i just do this
(defmethod print-dup org.joda.time.DateTime
[dt stream]
nil)
My questions:
• Is there a better way to achieve my goal?
• Did I introduce some problems with my solution that I'm not aware of?
• In which scenarios I need a valid print-dup
implementation? Will the dummy version suffice?I think you're looking for tagged literals. https://clojure.org/reference/reader#tagged_literals Rather than defining print-dup
to print with the rather undesirable #=(,,,)
form, you could always define a #joda/DateTime
or something that you print it and read it as?
Is there a difference though?
Here I'm defining the reader function for #object
(built-in tagged literal). Will it be any different if I use my own?
should be relevant https://github.com/clj-time/clj-time/commit/e5c9cce321e923464a3480ae04e4a43abdd4fc7e https://stuartsierra.com/download/2011-11-10-clojure-next-steps.pdf
What are these performance warning, case has int tests but tested expression is not primitive
warnings?
is this just that I'm using a case
expression with ints?
I noticed these in one of my libraries today when I turned on reflection warnings
It has a boxed int probably:
user=> (case 1 1 1)
1
user=> (case (Integer. 1) 1 1)
Performance warning, NO_SOURCE_PATH:1:1 - case has int tests, but tested expression is not primitive.
1
And boxing can happen when there are no type annotations:
user=> (defn x [a] a)
#'user/x
user=> (case (x 1) 1 1)
Performance warning, NO_SOURCE_PATH:1:1 - case has int tests, but tested expression is not primitive.
1
user=> (defn x ^long [a] a)
#'user/x
user=> (case (x 1) 1 1)
1
ah, okay. thanks
What's the performance difference between a type hint for a primitive, and calling the associated primitive cast function?
Depends where you put it and which hint :) Do you have more context?
In particular ^long and ^double are special in function param/return hints
Right, this is as the first argument to a case
expression in order to suppress the performance warning
Well ,should really be long first of all
Clojure literal integers are longs
Yeah, I've been casting to long
If the expression is a literal number, they cant carry meta
It's the result of calling first
on a collection getting thrown around the stack by an Error.
So type hinting it would be wrong then, it's not a primitive
So I would use long cast
alright, thanks
The return type of that is known as prim long
makes sense
e.g. ^int x
vs (int x)
Hard to give an exact number, since that's dependent on the machine. Conceptually, the conversion happens at runtime and the type hint is an indication to the compiler about how to produce more efficient code. All else being equal, pushing work to the compiler is generally going to be faster overall.
haven't looked at the code for int
but I strongly suspect that, if x
is already a primitive int, it just returns it with a type hint – making the latter just a more roundabout way to do the former
More or less I'm just looking for if ^int will result in a cast in the resulting bytecode and if the function call overhead from int
will be optimized away, which I guess criterium is the way to test that
Type hints are not casts
They result in casts to primitives if it's the correct boxed type
which is guaranteed to be the case here
or at least that was my understanding
You're right, my mistake, it does can generate a cast.
user=> (defn ^long f [] "this is totes a number, I promise")
#'user/f
user=> (f)
Execution error (ClassCastException) at user/f (REPL:1).
class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')
This is a special case
Oh really? interesting
Only for long or double type hint
And it's not a cast, it's generating a method in bytecode that really returns a long
But the exception here would suggest that, while the method's signature really returns a long, the body attempts to cast the string, right?
I believe what you see above is not a cast but a typecheck ensuring that type (don't remember the exact bytecode name)
I'd have to look at the bytecode to be sure
The Clojure compiler may insert a cast here, don't remember
seems to walk like a cast and quack like a cast, at least
user=> (defn ^long f [] (int 100))
#'user/f
user=> (f)
100
user=> (defn ^long f [] (Long. 100))
#'user/f
user=> (f)
100
user=> (defn ^long f [] (Integer. 100))
#'user/f
user=> (f)
100
You are also in the space of auto promotion and auto boxing, you just can't tell from this
Type hints are mostly useful for allowing the right interp method to be selected
You really want an explicit conversion here
More of a regex question than a #clojure question, I guess (happy to be redirected to the proper location for such questions), but it's sort of Clojure-specific in as much as my ultimate target is a regex that's compatible with instaparse
.
Anyway, here's my question. I'm trying to use lazy matchers in a regex to achieve matches against a string up to, but not including a specific pattern - if it's present. Otherwise I want the whole thing. I've managed to kind of do this using multiple non-capturing groups:
(let [re #"(.*?)(?:(?:🔚)?)"]
(println "regex" (.toString re))
(println "matches?" (re-matches re "text with ending🔚"))
(println "matches?" (re-matches re "text without ending")))
; => regex (.*?)(?:(?:🔚)?)
; => matches? [text with ending🔚 text with ending]
; => matches? [text without ending text without ending]
the second match in both is what I'm after. Is there a way to specify the regex in a way that only returns those matches? I'm a relative novice w/ regex so I definitely don't have a good feel for how capturing/non-capturing groups work.re-matches
always returns the full string match in the 0 position and captured groups after that in the order they appear
and nil
if it doesn't match
most commonly, you destructure the return to grab what you want
(let [re #"(.*?)(?:(?::end:)?)"
[_ text] (re-matches re s)]
...do stuff with text, often includes a nil check for a match
)
the #"(.*?)(?:(?:🔚)?)"
regex seems to work with re-matches
but not with the way instaparse
https://github.com/Engelberg/instaparse/blob/4d1903b059e77dc0049dfbc75af9dce995756148/src/instaparse/gll.cljc#L745:
(let [m (re-matcher #"(.*?)(?:(?:🔚)?)" "text with ending🔚")]
(do
(.matches m)
(.group m)
))
; => "text with ending🔚"
seems like I wasn't prototyping my regex using the right method, and I may need to narrow down the behavior of the groups so it works properly with the .group
method.I managed to experiment towards a solution for this problem that appears to work for both instaparse
and for re-seq
in a relatively unambiguous way:
(re-seq #"^.*?(?=🔚|$)" "text with ending🔚")
; => ("text with ending")
(re-seq #"^.*?(?=🔚|$)" "text ")
; => ("text ")