Git Product home page Git Product logo

Comments (13)

bhb avatar bhb commented on August 24, 2024 1

Thanks for the feedback and for using Expound! 😄

Unfortunately, alter-var-root doesn't always work either: namely, in the case of using spec and Expound inside the Clojure REPL. I've had questions about this - users try to use alter-var-root and then are surprised when it doesn't work (but set! does work in this case). As a result, I think it's good to mention both alter-var-root and set! and discuss when they are appropriate (and probably default to set!, since it's appropriate for most use cases).

The README currently includes this section:

If you are enabling Expound in a non-REPL environment, remember that set! will only change s/explain-out in the current thread. If your program spawns additional threads (e.g. a web server), you can set s/explain-out for all threads with (alter-var-root #'s/explain-out (constantly expound/printer)). This won't work (and is not necessary) in CLJS.
Using set! will also not work within an uberjar.

Unfortunately, it sounds like you still got bitten by this, so the docs should probably be reorganized or rewritten to be clearer. I suspect other users will run into similar problems. In your opinion, what would be a good way to improve the docs here?

from expound.

bhb avatar bhb commented on August 24, 2024

Thanks for reporting this! What version of Clojure and clojure.spec are you using?

from expound.

bhb avatar bhb commented on August 24, 2024

Are you running this at the REPL or in some other way?

from expound.

devth avatar devth commented on August 24, 2024

1.9.0-alpha17. Strangely, it works in tests and in the REPL but fails when run from a -main inside an Uberjar.

from expound.

bhb avatar bhb commented on August 24, 2024

Thanks for the info! The following works

  1. lein new expound-client-command-line
  2. Add :main expound-client-command-line.core to project.clj
  3. Edit src/expound_client_command_line/core.clj to be
(ns expound-client-command-line.core
  (:require [clojure.spec.alpha :as s]
            [expound.alpha :as expound]))

(s/def ::name string?)

(defn -main []
  (set! s/*explain-out* expound/printer)
  (s/explain ::name 1))

I will see if I can reproduce with an uberjar.

from expound.

bhb avatar bhb commented on August 24, 2024

@devth I can reproduce with an uberjar. Unfortunately, I've been looking for a concise explanation of why this won't work with an uberjar and I haven't found anything yet, but my googling may be failing me. I'd be happy to add a note to the instructions, but I'd like to have a link or at least an explanation.

Can you talk more about your use case? In most cases, I would not expect the final uberjar artifact to be using expound (it's generally a dev-time library). I suppose one could use expound to, say, display error messages for an API, but in this case, would using binding be sufficient to localize the effect of changing *explain-out*?

from expound.

devth avatar devth commented on August 24, 2024

@bhb thanks. I was partly trying to figure out why set! didn't work and whether I was just missing something. The set! docs weren't super clear, and now they're all the more confusing.

Keeping it in an uberjar was for convenience and we would have removed it eventually. I'll remove it now instead. And yes, binding would be perfectly usable in an uberjar since there's a natural entrypoint to bind from.

from expound.

athos avatar athos commented on August 24, 2024

Dynamic vars have to be bound with binding before you set! values to them.
But, in most cases you don't have to do it yourself in the REPL for dynamic vars defined in Clojure core because Clojure REPL does that for you before getting started (cf. https://github.com/clojure/clojure/blob/master/src/clj/clojure/main.clj#L71-L89).

In this case, I think something like the following should work:

(binding [s/*explain-out* expound/printer]
  (s/explain ::name 1))

Note that this might not work if the body of the binding form would be executed in other thread.

from expound.

bhb avatar bhb commented on August 24, 2024

@athos Ah, thank you for the explanation! This all makes more sense now.

@devth Thanks again for reporting this. I certainly did not understand all the subtleties of using set!. But since set! works in the contexts that I would expect clients to use Expound (namely, at dev time), I'm leaning towards leaving the documentation as-is for now. If this continues to be a source of confusion, I'll reconsider modifying the documentation to either only recommend using binding or adding a note about when set! won't work.

from expound.

aisamu avatar aisamu commented on August 24, 2024

We just got bitten by that as well, might be useful to point it out in the docs!
We're using it in dev and testing only - but we use tomcat during testing, so our artifact is an uberjar.

Would alter-var-root be a valid alternative? It looks like Pallet used it at some point:
(From https://stackoverflow.com/a/16448108/7182237, pasting for convenience)

(defn force-slf4j
 "The repl task brings in commons-logging, which messes up our logging
  configuration. This is an attempt to restore sanity."
  []
 (binding [*ns* (the-ns 'clojure.tools.logging.slf4j)]
   (alter-var-root
    #'clojure.tools.logging/*logger-factory*
    (constantly (clojure.tools.logging.slf4j/load-factory)))))

from expound.

aisamu avatar aisamu commented on August 24, 2024

Unfortunately, alter-var-root doesn't always work either

Oh, :(
At least the failure mode is not so bad (set! throws an exception and halts tomcat), and if I'm in a REPL I imagine I can rebind it myself.

To be fair, I went straight to the orchestra section and completely missed this paragraph. Even now, knowing it was there, I still had a bit of trouble finding it.

It might be the case that the title could have been more elaborate (e.g. just like "Using orchestra", we could have "Using expound as the default printer for clojure.spec/orchestra"), or perhaps we need a reference on the orchestra section (e.g. "The same binding restrictions apply (explain-out link)").

I think it's good to mention both alter-var-root and set! and discuss when they are appropriate (and probably default to set!, since it's appropriate for most use cases).

I agree that it might be useful to have them described in more detail - either with a more explicit section or with comments in the code snippets.

Thanks for both the quick response and this glorious lib!

from expound.

bhb avatar bhb commented on August 24, 2024

(e.g. "The same binding restrictions apply (explain-out link)")

Good idea! I'll leave this open as a doc issue - I may also explore whether I can just figure out an API that doesn't require users dive into the details of set! and alter-var-root entirely by intelligently installing Expound. We'll see.

from expound.

bhb avatar bhb commented on August 24, 2024

Closing with #142

from expound.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.