जवाबों:
डॉट्रेस भी है, जो आपको चयनित कार्यों के इनपुट और आउटपुट को देखने की अनुमति देता है।
(use 'clojure.contrib.trace)
(defn fib[n] (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
(dotrace [fib] (fib 3))
उत्पादन का उत्पादन:
TRACE t4425: (fib 3)
TRACE t4426: | (fib 2)
TRACE t4427: | | (fib 1)
TRACE t4427: | | => 1
TRACE t4428: | | (fib 0)
TRACE t4428: | | => 0
TRACE t4426: | => 1
TRACE t4429: | (fib 1)
TRACE t4429: | => 1
TRACE t4425: => 2
2
क्लोजर 1.4 में, dotrace
स्थानांतरित हो गया है:
आपको निर्भरता की आवश्यकता है:
[org.clojure/tools.trace "0.7.9"]
(require 'clojure.tools.trace)
और आपको फ़ंक्शन परिभाषा में ^: डायनेमिक जोड़ने की आवश्यकता है
(defn ^:dynamic fib[n] (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
तब बॉब एक बार फिर आपके चाचा हैं:
(clojure.tools.trace/dotrace [fib] (fib 3))
TRACE t4328: (fib 3)
TRACE t4329: | (fib 2)
TRACE t4330: | | (fib 1)
TRACE t4330: | | => 1
TRACE t4331: | | (fib 0)
TRACE t4331: | | => 0
TRACE t4329: | => 1
TRACE t4332: | (fib 1)
TRACE t4332: | => 1
TRACE t4328: => 2
user=> (use 'closure.contrib.trace) java.io.FileNotFoundException: Could not locate closure/contrib/trace__init.class or closure/contrib/trace.clj on classpath: (NO_SOURCE_FILE:0)
मेरे पास थोड़ा डीबगिंग मैक्रो है जो मुझे बहुत उपयोगी लगता है:
;;debugging parts of expressions
(defmacro dbg[x] `(let [x# ~x] (println "dbg:" '~x "=" x#) x#))
आप इसे वहां डाल सकते हैं जहाँ आप देखना चाहते हैं कि क्या चल रहा है और कब:
;; Examples of dbg
(println (+ (* 2 3) (dbg (* 8 9))))
(println (dbg (println "yo")))
(defn factorial[n] (if (= n 0) 1 (* n (dbg (factorial (dec n))))))
(factorial 8)
(def integers (iterate inc 0))
(def squares (map #(dbg(* % %)) integers))
(def cubes (map #(dbg(* %1 %2)) integers squares))
(take 5 cubes)
(take 5 cubes)
clojure.tools.trace/trace
।
मेरी पसंदीदा विधि println
कोड पर सभी में से एक उदार छिड़काव है ... उन्हें चालू करना और बंद करना#_
पाठक मैक्रो के लिए आसान है (जो पाठक को निम्नलिखित रूप में पढ़ता है, फिर दिखावा यह कभी नहीं देखा है)। या आप एक मैक्रो का विस्तार करने के लिए या तो पारित शरीर का उपयोग कर सकते हैं या nil
कुछ विशेष चर के मूल्य के आधार पर कह सकते हैं *debug*
:
(defmacro debug-do [& body]
(when *debug*
`(do ~@body)))
एक साथ (def *debug* false)
वहाँ में, यह करने के लिए विस्तार होगा nil
। के साथ true
, यह body
एक में लिपटे करने के लिए विस्तार करेंगे do
।
इस SO प्रश्न का स्वीकृत उत्तर: प्रगति रिपोर्टिंग के लिए मुहावरेदार क्लोजर? अनुक्रम ऑपरेशन डिबगिंग जब बहुत उपयोगी है।
तो फिर वहाँ जो कुछ है वर्तमान में स्वांक-clojure के साथ असंगत है आरईपीएल, लेकिन बहुत अच्छा उल्लेख करने के लिए नहीं है: debug-repl
। आप इसे एक स्टैंडअलोन आरईपीएल में उपयोग कर सकते हैं, जो कि लेनिंगन ( lein repl
) के साथ प्राप्त करना आसान है ; और यदि आप अपने प्रोग्राम को कमांड लाइन से लॉन्च कर रहे हैं, तो यह आपके टर्मिनल में अपने ही REPL को लाने जा रहा है। विचार यह है कि आप अपनी debug-repl
पसंद के अनुसार मैक्रो को ड्रॉप कर सकते हैं और इसे अपने स्वयं के REPL तक ला सकते हैं जब प्रोग्राम का निष्पादन उस बिंदु तक पहुंचता है, सभी स्थानीय लोगों के साथ गुंजाइश आदि में प्रासंगिक लिंक के एक जोड़े: क्लोजर डिबग-उत्तर , क्लोजर डिबग। -प्ले ट्रिक , कैसे 'एक डिबग- रिप्लाई (क्लोजर गूगल ग्रुप पर), क्लोर्ज पर डिबग-रिप्लाई ।
Swank-clojure एक पर्याप्त काम करता है SLIME के अंतर्निहित डिबगर को क्लोजर कोड के साथ काम करते समय उपयोगी बनाने पर - ध्यान दें कि स्टैकट्रेस के अप्रासंगिक बिट्स को कैसे निकाला जाता है इसलिए कोड डिबग किए जाने में वास्तविक समस्या का पता लगाना आसान है। एक बात का ध्यान रखें कि "नाम टैग" के बिना अनाम फ़ंक्शन स्टैक्ट्रेस में दिखाई देते हैं, जो मूल रूप से उनके साथ जुड़ी कोई उपयोगी जानकारी नहीं है; जब एक "नाम टैग" जोड़ा जाता है, तो यह स्टैकट्रेस में दिखाई देता है और सब फिर से ठीक हो जाता है:
(fn [& args] ...)
vs.
(fn tag [& args] ...)
example stacktrace entries:
1: user$eval__3130$fn__3131.invoke(NO_SOURCE_FILE:1)
vs. ^^
1: user$eval__3138$tag__3139.invoke(NO_SOURCE_FILE:1)
^^^
आप एलेक्स ओस्बोर्न काdebug-repl
उपयोग करते हुए सभी स्थानीय बाइंडिंग के साथ खुद को एक REPL में ड्रॉप करने के लिए कोड भी डाल सकते हैं :
(defmacro local-bindings
"Produces a map of the names of local bindings to their values."
[]
(let [symbols (map key @clojure.lang.Compiler/LOCAL_ENV)]
(zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols)))
(declare *locals*)
(defn eval-with-locals
"Evals a form with given locals. The locals should be a map of symbols to
values."
[locals form]
(binding [*locals* locals]
(eval
`(let ~(vec (mapcat #(list % `(*locals* '~%)) (keys locals)))
~form))))
(defmacro debug-repl
"Starts a REPL with the local bindings available."
[]
`(clojure.main/repl
:prompt #(print "dr => ")
:eval (partial eval-with-locals (local-bindings))))
फिर इसका उपयोग करने के लिए, जहाँ भी आप प्रारंभ करना चाहते हैं, उसे डालें:
(defn my-function [a b c]
(let [d (some-calc)]
(debug-repl)))
मैं इसे अपने user.clj में चिपकाता हूँ, इसलिए यह सभी REPL सत्रों में उपलब्ध है।
"उत्तर का उपयोग करते समय क्लूज कोड को डीबग करने के सर्वोत्तम तरीके"
थोड़ा-सा बायाँ क्षेत्र, लेकिन 'REPL iteself का उपयोग करते हुए'।
मैं एक वर्ष से अधिक समय से हॉबी क्लोजर लिख रहा हूं और किसी भी डीबगिंग टूल की बहुत आवश्यकता महसूस नहीं हुई है। यदि आप अपने कार्यों को छोटा रखते हैं, और प्रत्येक को REPL पर अपेक्षित इनपुट के साथ चलाते हैं और परिणामों का निरीक्षण करते हैं, तो आपके कोड का व्यवहार कैसा है, इसकी स्पष्ट रूप से स्पष्ट तस्वीर होना संभव है।
मुझे लगता है कि डिबगर एक चल रहे एप्लिकेशन में स्टेट देखने के लिए सबसे उपयोगी है। क्लोजर को अपरिवर्तनीय डेटा संरचनाओं (कोई बदलते राज्य) के साथ एक कार्यात्मक शैली में लिखना आसान (और मजेदार!) बनाता है। यह बड़े पैमाने पर डिबगर की आवश्यकता को कम करता है। एक बार जब मुझे पता है कि सभी घटक व्यवहार करते हैं जैसा कि मैं उम्मीद करता हूं (चीजों के प्रकार पर विशेष ध्यान देना) तो बड़े पैमाने पर व्यवहार शायद ही कभी एक समस्या है।
यदि आप emacs / slime / swank का उपयोग करते हैं, तो REPL में यह प्रयास करें:
(defn factorial [n]
(cond (< n 2) n
(= n 23) (swank.core/break)
:else (* n (factorial (dec n)))))
(factorial 30)
यह आपको एक पूर्ण स्टैक ट्रेस नहीं देता है जैसे आप LISP के तहत प्राप्त करेंगे, लेकिन यह चारों ओर poking के लिए अच्छा है।
यह ठीक काम है:
http://hugoduncan.org/post/2010/swank_clojure_gets_a_break_with_the_local_environment.xhtml
जैसा कि ऊपर एक टिप्पणी में उल्लेख किया गया था।
IntelliJ के लिए Cursive नामक एक उत्कृष्ट Clojure प्लगइन है । अन्य बातों के अलावा, यह एक REPL प्रदान करता है जिसे आप डिबग मोड में चला सकते हैं और अपने Clojure कोड के माध्यम से कदम उठा सकते हैं जैसे आप जावा जैसे।
मैं पीटर वेस्टमाकॉट का जवाब दूंगा, हालांकि मेरे अनुभव में आरईपीएल में सिर्फ मेरे कोड के टुकड़े चल रहे हैं, अधिकांश समय डिबगिंग का पर्याप्त रूप है।
Leiningen
, यह दिखाता है:Error running 'ring server': Trampoline must be enabled for debugging
ring
या lein
शायद एक अलग प्रश्न पोस्ट करने के लायक है?
2016 के रूप में आप डीबक्स का उपयोग कर सकते हैं , क्लॉजुर / स्क्रिप्ट के लिए एक सरल डिबगिंग लाइब्रेरी जो आपके उत्तर के साथ-साथ आपके ब्राउज़र के कंसोल के साथ मिलकर काम करती है। आप अपने कोड में dbg
(डीबग) या clog
(कंसोल.लॉग) मैक्रोज़ को छिड़क सकते हैं और अपने आरईपीएल और / या कंसोल पर मुद्रित व्यक्तिगत कार्यों आदि के परिणामों का आसानी से निरीक्षण कर सकते हैं।
परियोजना की रीडमी से :
मूल उपयोग
यह एक सरल उदाहरण है। मैक्रो dbg एक मूल रूप प्रिंट करता है और REPL विंडो पर मूल्यांकित मान को सुंदर प्रिंट करता है। फिर यह कोड निष्पादन के साथ हस्तक्षेप किए बिना मान लौटाता है।
यदि आप इस तरह से dbg के साथ कोड को लपेटते हैं,
(* 2 (dbg (+ 10 20))) ; => 60
निम्नलिखित को REPL विंडो में प्रिंट किया जाएगा।
REPL उत्पादन:
dbg: (+ 10 20) => 30
नेस्टेड डी.बी.जी.
Dbg मैक्रो को नेस्टेड किया जा सकता है।
(dbg (* 2 (dbg (+ 10 20)))) ; => 60
REPL उत्पादन:
`dbg: (+ 10 20) => 30`
dbg: (* 2 (dbg (+ 10 20))) => 60
ह्यूगो डंकन और सहयोगी रिट्ज परियोजना के साथ अद्भुत काम करना जारी रखते हैं । Ritz-nrepl डिबग क्षमताओं के साथ एक एनआरईपीएल सर्वर है। वीडियो में इसे देखने के लिए क्लूजुर / कॉनज 2012 में क्लोजर में ह्यूगो के डिबगर्स को देखें, वीडियो में कुछ स्लाइड्स पढ़ने योग्य नहीं हैं, इसलिए आप यहां से स्लाइड देखना चाहते हैं ।
Spyscope का उपयोग करें जो एक कस्टम रीडर मैक्रो को कार्यान्वित करता है ताकि आपका डिबग कोड भी उत्पादन कोड https://github.com/dgrnbrg/spyscope हो
जावा से आ रहा है और ग्रहण से परिचित होने के नाते, मुझे पसंद है कि क्या काउंटरक्लॉकवाइज (क्लोजर डेवलपमेंट के लिए ग्रहण प्लगइन) की पेशकश करनी है: http://doc.ccw-ide.org/documentation.html#_debug_cwjure_code
यहाँ जटिल let
रूपों डिबगिंग के लिए एक अच्छा मैक्रो है:
(defmacro def+
"def with binding (def+ [{:keys [a b d]} {:a 1 :b 2 :d 3}])"
[bindings]
(let [let-expr (macroexpand `(let ~bindings))
vars (filter #(not (.contains (str %) "__"))
(map first (partition 2 (second let-expr))))
def-vars (map (fn [v] `(def ~v ~v)) vars)]
(concat let-expr def-vars)))
डीफ़-लेट का फ़ंक्शन संस्करण, जो लेट्स को डीफ़ की श्रृंखला में बदल देता है। कुछ श्रेय यहां जाता है
(defn def-let [aVec]
(if-not (even? (count aVec))
aVec
(let [aKey (atom "")
counter (atom 0)]
(doseq [item aVec]
(if (even? @counter)
(reset! aKey item)
(intern *ns* (symbol @aKey) (eval item)))
; (prn item)
(swap! counter inc)))))
उपयोग: सामग्री को उद्धरण के साथ उद्धृत करने की आवश्यकता है, जैसे
(def-let '[a 1 b 2 c (atom 0)])