Fork me on GitHub
#clojure
<
2022-11-15
>
Yehonathan Sharvit01:11:47

What should I do after I remove a failing test to let the REPL know that I don't want this test to run again? The problem is that even though the test is removed, it is still part of the run time! Therefore (clojure.test/run-tests)fail forever 😞

hiredman02:11:33

deftest interns a var like def does, so all the normal namespace manipulation stuff can be used

hiredman02:11:56

I am usually really lazy and just comment out the body of the test and leave the deftest in place so it redefs as an empty test

Yehonathan Sharvit02:11:58

I just found

(remove-ns (ns-name *ns*))

Yehonathan Sharvit02:11:13

It seems to do the job 🙂

skylize02:11:56

That will clean the whole namespace. Fine if that works for you, but (ns-unmap *ns* 'foo-test) is more direct to your issue.

Eugen11:11:29

I don't know where to ask better so I decided to ask here: is there interest in adding a slf4j 2 factory to clojure tools.logging ? slf4j 2 changed how it discovers implementation - now it uses java ServiceLoader (standard) facilities. I don't think the old way of loading is working https://github.com/clojure/tools.logging#selecting-a-logging-implementation

dpsutton14:11:53

i think the best place to ask this is on http://ask.clojure.org . It will get the attention it needs there

kwladyka17:11:32

Do you use java.util.logging (JUL) as a main logger after Java 11 (JUL: changed in Java 9 if I remember?) for your applications? Personally I found it the simplest choice for all my custom needs. All log framework are good as long as I didn’t want to do custom JSON structure logging. I tried to implement it in each log framework about 2-3 years ago and I did it with really high effort. It was like rocket science and literally each of this solution had a lot of troubles. Maybe today it is not the case anymore. For example compilation didn’t work for Clojure, because of some conflicts of files and the framework developers said they will fix it, but it is not the priority in any meaning. It was a long time ago, so I can’t precisely recall all issues, but I remember all this issues were really bad. After this chaotic prolog I want to share my thoughts: java.util.logging works really great and I think there is negative opinion from the past which people repeat, but this is not true anymore since Java 9 / 11. JUL deserve for more respect :) Do you agree / disagree? Why?

phill17:11:49

JUL is both (1) an interface that receives messages to log, and (2) the custodian and writer of a file. Let's stipulate that JUL does a lousy job in both its roles. But the proliferation of slightly-improved loggers AND 99,999 slightly-lossy adapters every-which-way among them and JUL suggests that application integrators forgo nearly all the improvements to the (1) interface, and the net improvements of alternative loggers are in the disposal of messages to a file or whatever.

kwladyka18:11:20

@U0HG4EHMH This is my poor english, but it is not clear for me you are saying + or - for using JUL 🙂 > Let’s stipulate that JUL does a lousy job in both its roles. Can you extend? I don’t write to file, but to STDOUT in cloud world.

kwladyka18:11:54

But if you mean JUL is like a base version for logging and frameworks are extended logging with ready to go solutions, then sure it is true.

kwladyka18:11:40

At the same time I have feeling (like with all frameworks) if you want to do something custom, then framework start to be frustrating experience and better do it with JUL.

kwladyka18:11:21

and so far I didn’t find anything in JUL what I need and can’t do. Maybe even faster, than reading framework log documentation heh

skuttleman17:11:20

Ran into some surprising behavior on clojure 1.11 when destructuring lazy sequences. Anyone know anything about this? I hope it's just a bug.

(let [{:keys [a]} [{:a :b}]]
    a)
;; => nil (this is what I expect)

(let [{:keys [a]} (lazy-seq [{:a :b}])]
    a)
;; => :b (would expect nil here too or an exception)
On clojure 1.10.3 the latter throws IllegalArgumentException.

Alex Miller (Clojure team)17:11:50

this is a consequence of the new trailing map support

Alex Miller (Clojure team)17:11:02

so, not a bug, new intended behavior

Alex Miller (Clojure team)17:11:59

at least I suspect that's the case, this is kind of a weird combination of things?

skuttleman17:11:27

> this is kind of a weird combination of things? I'm not sure what you mean by that. It seems like the semantics of destructuring are now different for lists/lazy-seqs than for vectors. Heretofore I've been treating all sequential types the same when it comes to destructuring, but apparently I can't do that anymore.

Alex Miller (Clojure team)17:11:41

that associative destructuring of a sequential thing does anything outside the case of & args is not anything that has ever been documented. what do you expect it to even mean to do associative destructuring on a sequential collection of one element?

Alex Miller (Clojure team)18:11:30

in 1.10 previous, that had no meaning. in 1.11, a lone element in this case is treated as a map on which to destructure

Alex Miller (Clojure team)18:11:08

it having this effect only on a seq? is a result of the expectation here being that it's used for & args (which are always a seq)

skuttleman18:11:46

> what do you expect it to even mean to do associative destructuring on a sequential collection of one element? My only expectation was that associative destructuring on lists/vectors/lazy-seqs would all work the same.

Alex Miller (Clojure team)18:11:08

associative destructuring on lists/vectors/lazy-seqs is not defined

skuttleman18:11:32

> associative destructuring on lists/vectors/lazy-seqs is not defined I don't think this is true anymore. I think associative destructuring on lazy seqs has now been defined.

Alex Miller (Clojure team)18:11:11

no, it's still undefined

Alex Miller (Clojure team)18:11:40

if you're doing a thing that's undefined, you don't get to have expectations :)

Alex Miller (Clojure team)18:11:38

what's defined for sequential collections is sequential destructuring, and nothing has changed there

flowthing18:11:35

A colleague brought up this issue at work a couple of days ago, and I’ve bumped into it myself multiple times. I think the main problem is that the new behavior is particularly confusing when you’re refactoring a function that used to accept one map into one that accepts a seq of maps. It’s easy to remain under the illusion that everything works fine, even though it doesn’t. For example:

(defn make-move
  [{:keys [name move]}]
  (printf "%s uses %s!\n" name move))

(def pikachu {:name "Pikachu" :type :electric :move "Thunder Shock"})

(make-move pikachu) ;; Pikachu uses Thunder Shock!

;; Then, you realize make-move must accept a seq of Pokémon instead of just
;; one, but forget to update the function.
;;
;; You make a callsite that gives make-move a lazy seq:
(make-move (map #(select-keys % [:name :move]) [pikachu])) ;; Pikachu uses Thunder Shock!

(make-move [pikachu]) ;; null uses null!
On 1.10.3, you at least get this:
(make-move (map #(select-keys % [:name :move]) [pikachu]))
;; Execution error (IllegalArgumentException) at user/make-move (REPL:1).
;; No value supplied for key: {:name "Pikachu", :move "Thunder Shock"}
If the seq has more than one map, though, the result is the same on both 1.10.3 and 1.11.1:
(def charmander {:name "Charmander" :type :fire :move "Ember"})

(make-move (map #(select-keys % [:name :move]) [pikachu charmander]))
;; null uses null!
I do understand that the behavior is as undefined as ever on 1.11.1 and that the new behavior is more confusing than the old one is mostly an unfortunate side effect of the trailing map change, though.

flowthing18:11:00

(The silly map ... select-keys thing is just meant to illustrate how a callsite might end up passing a lazy seq to the function.)

flowthing18:11:04

The difference between lazy and non-lazy seqs is also unfortunate, because when you start debugging the function at the REPL, the first thing you’re going to try might be something like (make-move [pikachu]), and then you’re doubly confused about the different end result.

Alex Miller (Clojure team)18:11:48

it's not lazy vs non-lazy, it's seq? vs not seq?

flowthing18:11:22

Ah, indeed. 👍

pez22:11:27

How can I avoid the (quote ...) after read-string here?

(comment 
  (str '(defn foo [s] (println "Foo" s)))
  ;; => "(defn foo [s] (println \"Foo\" s))"

  (-> "'(defn foo [s]\n (println \"Foo\" s))"
      read-string ; => '(defn foo [s] (println "Foo" s))
      str)
  ;; => "(quote (defn foo [s] (println \"Foo\" s)))"
  )

hiredman22:11:38

(str '(defn foo [s] (println "Foo" s))) is basically (str (eval '(defn foo [s] (println "Foo" s))))

hiredman22:11:56

and that is why it removes the quote

pez22:11:40

Hmmm, I actually need this in ClojureScript, where I don't have eval...

hiredman22:11:05

then don't quote things

pez22:11:38

It's not as if I can choose...

hiredman22:11:00

' is short hand for (quote ...)

hiredman22:11:18

the data you are reading contains the quote, so that is what you get when you read it

hiredman22:11:55

(quote ...) is just a two element seq, where the first element is the symbol quote

pez22:11:32

I know. It's not me quoting things. I'm reading a file where some items are quoted and need a string representation that will print exactly as it ”looks” in the file.

pez22:11:12

Maybe this can't be done with ClojureScript?

pez23:11:39

Thanks, @U0NCTKEV8! 🙏 For now I'll update the README of the project and inform that quoted code is not supported. 😃

mkvlr07:11:37

@U0ETXRFEW no need for eval, can also use second:

(->> "'(defn foo [s]\n (println \"Foo\" s))"
       read-string ; => '(defn foo [s] (println "Foo" s))
       (clojure.walk/postwalk #(cond-> % (and (seq? %) (= 'quote (first %))) second)))
  ;; => (defn foo [s] (println "Foo" s))

👍 1
pez09:11:49

Wonderful, @U5H74UNSF! 🙏 ❀ It works!

pez09:11:53

Of course I have a second requirement that the single-quote should be kept in the resulting string. After some trial 'n horror I think I nailed that too:

(defn- single-quote-second
  [x]
  (if (symbol? (second x))
    (symbol (str \' (second x)))
    (str \' (second x))))
(And use this one instead of the vanilla second, of course.)

pez09:11:43

The horror part of this last exercise was that I first tried with an anonymous function, but that yields totally different results! I get the compiled JavaScript code instead...

facepalm 1
skylize18:11:19

Of course now you have the opposite problem, don't you? If I am following correctly, a literal (quote ...) will also be turned into ' now. And what about ` ?

skylize18:11:09

Would it be too much overhead to check the original string for what type of quote was used?

skylize18:11:56

Maybe a custom reader that builds that in?

pez21:11:37

You are right, of course, @U90R0EPHA. Now I have the reverse problem. ...

pez21:11:29

I'm doing something similar to what pprint does.