উত্তর:
ডট্রেসও রয়েছে, যা আপনাকে নির্বাচিত ফাংশনগুলির ইনপুট এবং আউটপুটগুলি দেখার অনুমতি দেয়।
(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
Clojure 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
।
এই এসও প্রশ্নের গৃহীত উত্তর: অগ্রগতি প্রতিবেদনের জন্য আইডোম্যাটিক ক্লোজার? সিকোয়েন্স অপারেশনগুলি ডিবাগ করার সময় খুব সহায়ক।
এরপর কিছু যা হয় বর্তমানে লম্বাচওড়া কথা-clojure সঙ্গে বেমানান 'র REPL কিন্তু খুব ভাল উল্লেখ করার নয়: debug-repl
। আপনি এটি স্ট্যান্ডেলোন রিপ্লেল এ ব্যবহার করতে পারেন যা লেনিনজেন ( lein repl
) এর সাথে উদাহরণস্বরূপ পাওয়া সহজ ; এবং যদি আপনি কমান্ড লাইন থেকে আপনার প্রোগ্রামটি চালু করছেন, তবে এটি ঠিক নিজের টার্মিনালে এটির নিজস্ব আরএপিএল আনতে চলেছে। ধারণাটি হ'ল আপনি debug-repl
ম্যাক্রোটিকে আপনার পছন্দ মতো যে কোনও জায়গায় ফেলে দিতে পারেন এবং প্রোগ্রামের প্রয়োগটি সেই স্থানে পৌঁছালে এটির নিজস্ব আরএইপিএল আনতে পারে, সমস্ত স্থানীয় লোকের সাথে এই সম্পর্কিত লিঙ্কের একটি দম্পতি: ক্লোজার ডিবাগ-রিপ্লিজ , ক্লোজার ডিবাগ -রেপল ট্রিকস , কীভাবে ডিবাগ- রেপ্লিট (ক্লোজার গুগল গ্রুপে), ক্লোজারগুলিতে ডিবাগ-রেপ্লিট হয় ।
ক্লঞ্জার কোডের সাথে কাজ করার সময় স্ল্যামকের বিল্ট-ইন ডিবাগারকে দরকারী করার জন্য সোয়াঙ্ক-ক্লোজার একটি পর্যাপ্ত কাজ করে - লক্ষ্য করুন যে কীভাবে স্ট্যাকট্রেসের অপ্রাসঙ্গিক বিটগুলি গ্রে গ্রেড করা হয়েছে তাই কোডটি ডিবাগ হওয়ার ক্ষেত্রে প্রকৃত সমস্যাটি খুঁজে পাওয়া সহজ। একটি বিষয় মনে রাখবেন যে "নাম ট্যাগ" ছাড়াই বেনাম ফাংশনগুলি স্ট্যাকট্রেসে মূলত তাদের সাথে কোনও কার্যকর তথ্য সংযুক্ত থাকে না; যখন একটি "নাম ট্যাগ" যুক্ত করা হয়, এটি স্ট্যাকট্রেসে প্রদর্শিত হয় এবং সমস্ত কিছু আবার ভাল হয়:
(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
ব্যবহার করে আপনি সমস্ত স্থানীয় বাইন্ডিংয়ের সাথে নিজেকে একটি আরএপিএল এ নামানোর জন্য কোড সন্নিবেশ করতে পারেন :
(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))))
তারপরে এটি ব্যবহার করতে, আপনি যেখানেই Repl শুরু করতে চান সেখানে এটি প্রবেশ করুন:
(defn my-function [a b c]
(let [d (some-calc)]
(debug-repl)))
আমি এটি আমার ব্যবহারকারী.এলজে রেখেছি যাতে এটি সমস্ত রিপল সেশনে উপলব্ধ।
"Repl ব্যবহার করার সময় ক্লোজার কোডটি ডিবাগ করার সর্বোত্তম উপায়"
সামান্য বাম-ক্ষেত্র, তবে 'রিপল পুনরায় ব্যবহার করুন'
আমি এক বছরেরও বেশি সময় ধরে শখের ক্লোজার লিখছি এবং কোনও ডিবাগিংয়ের সরঞ্জামের বড় প্রয়োজন অনুভব করিনি। আপনি যদি নিজের ফাংশনগুলি ছোট রাখেন, এবং প্রতিটিই প্রত্যাশিত ইনপুটগুলি দিয়ে আরপিএলে চালান এবং ফলাফলগুলি পর্যবেক্ষণ করেন তবে আপনার কোডটি কী আচরণ করছে তার একটি সুন্দর পরিষ্কার চিত্র পাওয়া সম্ভব should
আমি আবিষ্কার করি একটি চলমান অ্যাপ্লিকেশনে স্ট্যাট পর্যবেক্ষণের জন্য একটি ডিবাগার সবচেয়ে দরকারী useful Clojure অপরিবর্তনীয় ডেটা স্ট্রাকচার (কোনও পরিবর্তনযোগ্য রাষ্ট্র নয়) সহ কার্যকরী শৈলীতে লিখতে সহজ (এবং মজাদার) করে তোলে। এটি একটি ডিবাগারের প্রয়োজনকে ব্যাপকভাবে হ্রাস করে। একবার আমি জানতে পারলাম যে সমস্ত উপাদানগুলি আমার প্রত্যাশা অনুযায়ী আচরণ করে (জিনিসগুলির ধরণের দিকে বিশেষ মনোযোগ দেওয়া) তখন বড় আকারের আচরণ খুব কমই সমস্যা হয় is
আপনি যদি ইমাস / স্লাইম / সোয়াঙ্ক ব্যবহার করেন, তবে REPL এ চেষ্টা করুন:
(defn factorial [n]
(cond (< n 2) n
(= n 23) (swank.core/break)
:else (* n (factorial (dec n)))))
(factorial 30)
এটি আপনাকে এলআইএসপি এর আওতায় নিয়ে যাওয়ার মতো একটি সম্পূর্ণ স্ট্যাক ট্রেস দেয় না, তবে আশেপাশে পোকার জন্য এটি ভাল।
এটি এর সূক্ষ্ম কাজ:
http://hugoduncan.org/post/2010/swank_clojure_gets_a_break_with_the_local_environment.xhtml
যেমন উপরে একটি মন্তব্যে উল্লেখ করা হয়েছিল।
ইন্টেলিজিজের জন্য একটি দুর্দান্ত ক্লোজার প্লাগইন রয়েছে যাকে বলা হয় ক্রুসিভ । অন্যান্য জিনিসের মধ্যে এটি একটি আরপিএল সরবরাহ করে যা আপনি ডিবাগ মোডে চালাতে পারেন এবং আপনার ক্লোজার কোডটি দিয়ে যেতে পারেন ঠিক যেমন জাভা হিসাবে।
আমি পিটার ওয়েস্টমাকটের উত্তরটি দ্বিতীয় করব যদিও আমার অভিজ্ঞতায় কেবলমাত্র আমার কোডের টুকরোগুলি আরপিএলে চালানো বেশিরভাগ সময়ই যথেষ্ট পরিমাণে ডিবাগ করার জন্য form
Leiningen
, এটি দেখায়:Error running 'ring server': Trampoline must be enabled for debugging
ring
বা মনে হয় lein
- সম্ভবত একটি পৃথক প্রশ্ন পোস্ট করার উপযুক্ত?
২০১ of সাল পর্যন্ত আপনি ক্লাবজুর / স্ক্রিপ্টের জন্য একটি সাধারণ ডিবাগিং লাইব্রেরি ডাবক্স ব্যবহার করতে পারেন যা আপনার Repl পাশাপাশি আপনার ব্রাউজারের কনসোলের সাথে একত্রে কাজ করে। আপনি আপনার কোডে ছিটানো dbg
(ডিবাগ) বা clog
(কনসোল.লগ) ম্যাক্রোগুলি করতে পারবেন এবং সহজেই আপনার আরপিএল এবং / অথবা কনসোলে মুদ্রিত পৃথক ফাংশনগুলির ফলাফলগুলি পর্যবেক্ষণ করতে পারেন।
প্রকল্পের রেডমি থেকে :
বেসিক ব্যবহার
এটি একটি সহজ উদাহরণ। ম্যাক্রো ডিবিজি একটি মূল ফর্মটি মুদ্রণ করে এবং আরপিএল উইন্ডোতে মূল্যবান মানটি প্রিন্ট করে। তারপরে কোড প্রয়োগের ক্ষেত্রে হস্তক্ষেপ না করে মানটি ফিরিয়ে দেয়।
আপনি যদি ডিবিজি দিয়ে কোডটি এভাবে মুড়ে রাখেন,
(* 2 (dbg (+ 10 20))) ; => 60
নীচে REPL উইন্ডোতে মুদ্রিত করা হবে।
রিপল আউটপুট:
dbg: (+ 10 20) => 30
নেস্টেড ডিবিজি
ডিবিজি ম্যাক্রো নেস্ট করা যায়।
(dbg (* 2 (dbg (+ 10 20)))) ; => 60
রিপল আউটপুট:
`dbg: (+ 10 20) => 30`
dbg: (* 2 (dbg (+ 10 20))) => 60
হুগো ডানকান এবং সহযোগীরা রিটজ প্রকল্পের সাথে আশ্চর্যজনক কাজ চালিয়ে যান । রিটজ-এনআরপিএল একটি এনআরপিএল সার্ভার যা ডিবাগ ক্ষমতা সহ। ওয়াচ হুগো এর Clojure মধ্যে debuggers Clojure / সংযোগমূলক অব্যয় 2012 আলাপ কর্ম এটি দেখতে, ভিডিও স্লাইডের কিছু পাঠযোগ্য নয়, তাই আপনার কাছ থেকে স্লাইড দেখতে চাইতে পারেন এখানে ।
কাস্টম রিডার ম্যাক্রো প্রয়োগ করে এমন স্পাইস্কোপ ব্যবহার করুন যাতে আপনার ডিবাগ কোডটি প্রোডাকশন কোডও হয় https://github.com/dgrnbrg/spyscope
জাভা থেকে আগত এবং একটিগ্রহের সাথে পরিচিত হয়ে আমি কাউন্টার ক্লকওয়াইজ (ক্লোজার ডেভেলপমেন্টের জন্য এক্সপ্লিট প্লাগইন) যা অফার করে তা পছন্দ করি: http://doc.ccw-ide.org/docamentation.html#_debug_clojure_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)])