3 ms·
Another trick is to define temporary inline vars. If I have some Ring handler, it can be quite annoying to construct a request by hand. Instead, I can do someth
by oskarth 9y ago
Another trick is to define temporary inline vars. If I have some Ring handler, it can be quite annoying to construct a request by hand. Instead, I can do something like:
(defn foo-handler [{{:strs [authorization]} :headers :as req}]
(def *req req)
(def *auth authorization)
...)
Then fire off a request in my browser and simply proceed to play around with `req` and `auth` in my editor/REPL, which is where I am running my local server from.
- lvh 9y agoFor people used to Scheme (or most other programming languages, I guess): note that def will create a var in the current namespace, not a locally-scoped variable. In Scheme, or e.g. in Python, a define or = in the same spot as that def would get you a local var. In Clojure, the idiomatic way to do the same thing is normally a let or something -- but using def here makes it easy to access from a REPL running in that namespace. (A var is a Clojure thing that holds a value. If you've ever had like a "fully qualified path" to a class or object and had to describe it as a string or whatever, that concept is a first-class thing in Clojure, and called a var.)
- lispm 9y ago> For people used to Scheme (or most other programming languages, I guess) That's what LISP did since shortly after the last dinosaurs got killed by humans.
- dragandj 9y agoThis is a terrible advice, and is not even necessary. Even println debugging is better than this. Not only defs are abused contrary to their intended use, they are difficult to distinguish from legitimate defs, and thus some may (and will!) slip away into the wild.
- oskarth 9y ago> Even println debugging is better than this. Print debugging is great. A carefully placed print statement is something many great programmers swear by [1], despite the existence of "sophisticated" debuggers (see footnote in OP). This is a complement to this when you want to play around with the data directly. > Not only def's are abused contrary to their intended use, they are difficult to distinguish from legitimate defs, and thus some may (and will!) slip away into the wild. Never been an issue for me. It's just an extension and morphing of playing around with data in a standalone REPL. The temporary defs are never used in actual code logic, the prefix character makes it clear it is purely for exploration. Is it a dirty hack? Yes, but one might argue that's partly what Lisp is too: The most intelligent way to misuse a computer - Dijkstra (paraphrasing) Lisp Some unsolicited feedback: you might want to consider that there is more than one way to skin a cat. If you want to understand the trade-offs of solutions people find, you might find it useful to not dismiss solutions outright. Especially something as universally useful like print debugging, considering how many people use it. Instead, a more useful question to ask yourself is: why do experienced programmers use print debugging when they are aware of the existence of debuggers? That might expand your worldview, as opposed to categorizing these people as "doing it wrong". See Worse is Better etc. 1: From this lovely quote by Brian Kernighan: The most effective debugging tool is still careful thought, coupled with judiciously placed print statements.
- dreish 9y agoWhy not define debug-req and debug-auth as atoms before this function, and set them with (reset! debug-req req) etc.?
- dm3 9y agoThis actually looks pretty handy. Not sure why you'd think it's so terrible - how else would you capture a request in a variable to play with it in the REPL? I think a lot of the constraints can be relaxed during the development phase.
- lispm 9y agoThere are many ways one would do that in various Lisps during development. For example a dynamic variable could be accessible in the debug repl: CL-USER 56 > (defvar *bar*) *BAR* CL-USER 57 > (defun foo (baz) (let ((*bar* (* 1000 baz))) (break) *bar*)) FOO CL-USER 58 > (foo 5) Break. 1 (continue) Return from break. 2 (abort) Return to level 0. 3 Return to top loop level 0. Type :b for backtrace or :c <option number> to proceed. Type :bug-form "<subject>" for a bug report template or :? for other options. CL-USER 59 : 1 > *bar* 5000 The value of a lexical variable can be retrieved. CL-USER 60 : 1 > :l baz Value of BAZ is: 5 CL-USER 61 : 1 > * 5 In something like McCLIM or SLIME I would print the object to a listener and the window system remembers the value. In some other Lisp I would call (inspect foo) instead of (print foo) and the inspected values would be available in a stack of inspectors. Alternatively I would trace the functions, and the tracer would record the passed and returned objects.