This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-10-01
Channels
- # aws (37)
- # babashka (7)
- # babashka-sci-dev (2)
- # beginners (75)
- # biff (7)
- # calva (85)
- # cider (9)
- # clj-kondo (26)
- # clj-yaml (1)
- # clojure (45)
- # clojure-europe (4)
- # clojure-norway (1)
- # clojure-spec (3)
- # clojure-uk (2)
- # clojurescript (3)
- # core-typed (2)
- # cursive (12)
- # fulcro (3)
- # humbleui (5)
- # jobs (8)
- # malli (1)
- # meander (3)
- # membrane (1)
- # portal (50)
- # squint (15)
- # vim (1)
I’m trying to use var-get
to make a copy of a macro, but I don’t understand why it’s failing. It works well with function.
Am I doing it wrong or there is no way to do this for macro?
The problem here is that in order for something to be used as a macro, the containing var itself must be marked as a macro. def
does not create a copy of a var with all the internal flags - it creates a completely new var.
You can see how Clojure itself marks an existing var as a macro: (. (var defn) (setMacro))
.
So, try adding (.setMacro #'my-doseq)
right after that def
.
ha, that works! I wonder are there any clojure way to this? using with-meta doesn’t seem to work.
I’m writing a small library that will change the implementation of a core function. And I want to be able to fall back to the original implementation.
That is a "clojure way" - after all, clojure.lang.Var
is a part of Clojure. :) It's just that it requires interop to use it.
> I’m writing a small library that will change the implementation of a core function
And why is that needed, if I may ask? For some instrumentation or something else?
ah I want to change the behavior a bit.
Specifically I’m working on adding a new macro testing-only
and intern it into clojure.test
so you can use it like clojure.test/testing-only
.
This is meant to be used as a drop-in replacement so if a deftest
has a testing-only
in it, it’ll run, well only the body of testing-only
and ignores the others testing
.
In order to do this, I need to change the implementation of clojure.test/testing
a bit, so I want to preserve the original implementation so users can just opt-out if they want to.
But why? Why not just make a library where a user would simply have to e.g. replace the imports of clojure.test
with, say, ngoc-khuat.test
and be done with it?
In other words, you're trying to do magic. And magic is bad. It's incomparably better to just make a user do a trivial step once in a life time of a project than to add some magic that will be absolutely impenetrable to someone who doesn't intimately know your library and that it's being used on that particular project.
I imagine the overall need is to be able to easily re-run a particular testing
block without running the whole deftest
.
If that's the case, you can create your own namespace that's completely separate from clojure.test
and, when you have a need to re-run a testing
block, you just put a :require
of that namespace under the :require
vector of clojure.test
with shadowing testing
with a no-op macro and adding testing-only
macro that just uses clojure.test/testing
.
This way, there's exactly 0 magic and the usage seems to be just as easy.
You’re right, I don’t like magic either.
But this is meant to be used as debugging tool and should not be committed.
Something you just plug it into ~/.clojure/deps.edn
and leave it there.
My use case is I often have jumped between different tests file, and I think it’s will be convenient if you can just add -only
on testing
and it should just works.
> If that’s the case, you can create your own namespace that’s completely separate from clojure.test
I’m not following this, could you elaborate?
Before:
(ns my-proj.test
(:use [clojure.test]))
(deftest hello
(testing "a" ...)
(testing "b" ...))
After:
(ns my-proj.test
(:use [clojure.test] [ngoc-khuat.test]))
(deftest hello
(testing "a" ...)
(testing-only "b" ...))
Haven't tried it myself but I'm 80% certain that it'll work.An alternative option might be to add some data reader tag that you put in front of (deftest ...)
that removes all the (testing ...)
blocks apart from ones marked with some other data reader tag.
Just as a demonstration (not sure why the X
line is printed twice though):
user=> (set! *data-readers* {`x (fn [data] (println "X" data) (concat data '(3)))})
#:user{x #object[user$eval177$fn__178 0x71178a52 "user$eval177$fn__178@71178a52"]}
user=> #user/x (+ 1 2)
X (+ 1 2)
X (+ 1 2)
6
Of course, in your use-case you don't want to call set!
that way. Instead, you'd put a data_readers.clj
file somewhere on your classpath set with ~/.clojure/deps.edn
.
This will not work for my case because I need to redefine the testing
macro as well, and get testing already refers to #'clojure.testing
error.
FWIW, inorder this to affect users will have to call a function (ngockhuat.test/install!)
to take affect tho.
hmm, I haven’t thought about using reader, maybe I can play with that
> not sure why the X
line is printed twice though
Hmm, must be something with how the default clj
REPL works. A REPL window in Cursive doesn't print the line twice.
But in any case, it shouldn't affect anything.
Is there a way to have clojure.edn/read-string
not throw an exception upon encountering a regex literal?
I don’t think so. But fwiw, https://github.com/cljdoc/cljdoc-shared/blob/53c113e375df94d50cf96c6f2c1b3842dc0e9b35/src/cljdoc_shared/analysis_edn.clj#L1-L34.
Thanks, I don't think that helps with reading untrusted string input though which is what I need
looks like edamame supports reading regexes: https://github.com/borkdude/edamame#parser-options
Where did the following reader implementation come from? I've been reading the source and can't seem to track it down
(defrecord Foo [x])
(tests
(def x (->Foo 1))
(pr-str x) := "#dustin.scratch.Foo{:x 1}"
(read-string "#dustin.scratch.Foo{:x 1}") := x) ; where in clojure internals was this defined?
;✅✅
Guess I might as well ask. What is a “Ctor”?
I know they are unhappy when I try to use undefined protocols
Constructor
I think here it just means defrecord reader
This final test can never work, right? (for safety i guess) Why is global tag registration allowed in CLJS then?
(tests
"#uri literals in clojure runtime readers are auto-wired from data_readers.cljc (unsafe)"
#?@(:clj ((clojure.core/read-string "#uri \"\"") := x))
"#uri literals are not auto-wired in cljs reader (it uses JS runtime and therefore is an EDN reader for safety)"
;
#?@(:cljs ((cljs.reader/read-string "#uri \"\"")
:throws js/Error ; No reader function for tag uri.
(contains? (set (keys @cljs.reader/*tag-table*)) 'inst) := true
(contains? (set (keys @cljs.reader/*tag-table*)) 'uri) := false))
"cljs userland can globally register an EDN tag reader, but it's probably a bad idea"
#?@(:cljs ((cljs.reader/register-tag-parser! 'uri ->URI)
(clojure.edn/read-string "#uri \"\"") := x))
"Clojure userland can not globally register an EDN tag reader"
#?@(:clj ((clojure.edn/read-string "#uri \"\"") :throws RuntimeException)))
HOWTO install #uri
reader extension in Clojure/Script
Can I get a code review on this please?
It was hard fought knowledge (this is my third time in 6 years going through this exercise and the first time I think i fully understand it)
every clojure project eventually needs this so I would like to put it somewhere where folks can find it –
perhaps ask clojure? where should I put it?
https://gist.github.com/dustingetz/89a8333b8e5bf73b0f527d865d53079a
I thought Clojure reserved all unqualified reader extension names for itself? (so users should always qualify reader extension names)
Can I just say of "every clojure project eventually needs this" that I've never needed this in over a decade of Clojure production work? 🙂
Yes that is true, IMO this should be in core (http://java.net.URI and transit URI are not my types); this is why we chose an unqualified tag
we think this should be in core, in alignment with clojure.core/uri?
being hardcoded to java.net.URI
and goog.Uri
, they are not userland types
I still would go with a qualified tag even if you don't own the type: this makes it possible for folks to find out where this comes from and won't override a hypothetical future built-in implementation
if a builtin is provided this impl becomes superseded and should be removed
this is also likely the exact impl that core would provide
The problem is that you can't easily undo overriding built-in tags if people have data_readers.cljc
stuff on their classpath that override
Ah so if this extension ends up bundled as a transitive dependency in some lib
Yes. So even if you wish to remove it, as you know, software isn't killed that easily
thanks, good argument