clojure - क्लोजर: आरईपीएल पर निर्भरता लोड हो रहा है




read-eval-print-loop (2)

मैंने हाल ही में सीखा (टेक्नोमेंसी के लिए धन्यवाद), जो कि REPL पर है ---

यह विफल रहता है:

user=> (:require [clojure.set :as set])
java.lang.ClassNotFoundException: clojure.set (NO_SOURCE_FILE:24)

जबकि यह सफल होता है:

user=> (require '[clojure.set :as cs]) 
nil

clojure.set वर्ग लोड करने पर।

संदर्भ: पूर्व पंक्ति को नामांकित स्रोत फ़ाइल से कॉपी किया गया था।

मेरा प्राथमिक प्रश्न यह है: हमने क्या परिवर्तन किया है: स्वैप करके: और 'वर्ण, जो अब बाद वाली कमांड की सफलता के लिए अनुमति देता है?

मेरा दूसरा सवाल है, सामान्य रूप से - REPL में चीजों को करने के लिए दिशानिर्देश क्या हैं --- सामान्य क्लोजर सोर्स फाइलों में चीजों को करने की तुलना में? यहां मान लें कि हम अपने उत्तर को एक LEININGEN परियोजना की जड़ से लोड कर सकते हैं, इसलिए कम से कम जार निर्भरता उप निर्देशिका में डिस्क पर उपलब्ध होंगे।


अंतर यह है कि require एक फ़ंक्शन है जिसका उपयोग कोड आयात करने के लिए किया जाता है, जबकि :require एक कीवर्ड है।

याद रखें कि जब आप एक फ़ंक्शन के रूप में किसी कीवर्ड का उपयोग करते हैं तो क्या होता है:

=> (type :require)
clojure.lang.Keyword
=> (:require {:abc 1 :require 14})
14

यह नक्शे में ही दिखता है। इसलिए जब आप एक कीवर्ड के लिए [clojure.set :as set] पास करते हैं, तो यह मूल्यांकन करने की कोशिश कर रहा है कि एक वेक्टर, और विफल रहता है क्योंकि यह नहीं जानता कि clojure.set क्या है। क्लोजर डॉक्स कहते हैं:

कीवर्ड एक तर्क (एक मानचित्र) के इनवोक () के लिए वैकल्पिक दूसरा तर्क (एक डिफ़ॉल्ट मान) के साथ लागू करते हैं। उदाहरण के लिए: (mykey my-hash-map: none) का अर्थ होता है जैसे (get my-hash-map: mykey: none)।

आप ns मैक्रो द्वारा भ्रमित हो सकते हैं:

(ns foo.bar
  (:refer-clojure :exclude [ancestors printf])
  (:require (clojure.contrib sql sql.tests))    ;; here's :require!
  (:use (my.lib this that))
  (:import (java.util Date Timer Random)
           (java.sql Connection Statement)))

मैं आपकी विशेष समस्या के लिए उच्च-स्तर से नीचे जाऊँगा:

कैसे क्लोजर (या LISPs) आम तौर पर काम करते हैं

REPLs, या रीड-एवल-प्रिंट लूप्स कोर के प्रमुख हैं कि कैसे LISPs डिज़ाइन किए गए हैं:

  • पाठक पात्रों की एक धारा को डेटा संरचनाओं में परिवर्तित करता है (जिसे रीडर फॉर्म्स कहा जाता है)।
  • मूल्यांकनकर्ता पाठक रूपों का संग्रह करता है और उनका मूल्यांकन करता है।
  • प्रिंटर मूल्यांकनकर्ता के परिणामों का उत्सर्जन करता है।

इसलिए जब आप एक REPL में पाठ दर्ज करते हैं, तो यह आपके इनपुट को संसाधित करने और आउटपुट को आपके टर्मिनल पर वापस करने के लिए इन चरणों में से प्रत्येक के माध्यम से जाता है।

पाठक प्रपत्र

पहले कुछ, क्लोजर रीडर रूपों। यह अत्यंत संक्षिप्त होगा, मैं आपको इसके बारे में read या देखने के लिए प्रोत्साहित करता हूं ( भाग 1 , भाग 2 )।

क्लोजर में एक प्रतीक रूप है जो एक विशेष मूल्य (एक चर की तरह) का प्रतिनिधित्व कर सकता है। प्रतीक खुद को डेटा के रूप में चारों ओर से पार किया जा सकता है। वे सी में संकेत के समान हैं, बस स्मृति प्रबंधन सामान के बिना।

इसके सामने एक बृहदान्त्र के साथ एक प्रतीक एक कीवर्ड है । कीवर्ड उस अपवाद के प्रतीक के समान हैं जो किसी कीवर्ड का मान हमेशा स्वयं होता है - तार या संख्या के समान। वे रूबी के प्रतीकों के समान हैं (जो कॉलन के साथ भी उपसर्ग हैं)।

प्रपत्र के सामने एक उद्धरण मूल्यांकनकर्ता को डेटा संरचना को छोड़ने के लिए कहता है:

user=> (list 1 2)
(1 2)
user=> '(1 2)
(1 2)
user=> (= (list 1 2) '(1 2))
true

हालाँकि उद्धृत करना केवल सूचियों से अधिक पर लागू हो सकता है, यह मुख्य रूप से सूचियों के लिए उपयोग किया जाता है क्योंकि क्लोजर का मूल्यांकनकर्ता सामान्य रूप से फ़ंक्शन-जैसे इनवोकेशन के रूप में सूचियों को निष्पादित करेगा। ' का प्रयोग शॉर्टहैंड टू द मैक्रो:

user=> (quote (1 2)) ; same as '(1 2)
(1 2)

मूल रूप से उद्धृत करना डेटा संरचना को वापस करने के लिए निर्दिष्ट करता है और निष्पादित करने के लिए वास्तविक कोड नहीं। तो आप प्रतीकों को उद्धृत कर सकते हैं जो प्रतीक को संदर्भित करता है।

user=> 'foo ; not defined earlier
foo

और उद्धरण पुनरावर्ती है। तो अंदर के सभी डेटा को भी उद्धृत किया गया है:

user=> '(foo bar)
(foo bar)

उद्धरण के बिना (foo bar) के व्यवहार को प्राप्त करने के लिए, आप इसे निकाल सकते हैं:

user=> (eval '(foo bar)) ; Remember, foo and bar weren't defined yet.
CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:1)
user=> (def foo identity)
#'user/foo
user=> (def bar 1)
#'user/bar
user=> (eval '(foo bar))
1

उद्धृत करने के लिए बहुत कुछ है, लेकिन वह इस दायरे से बाहर है।

की आवश्यकता होती है

जैसा कि बयानों की आवश्यकता है, मैं मान रहा हूं कि आपने पूर्व को निम्न रूप में पाया है:

(ns my.namespace
    (:require [clojure.set :as set]))

ns एक macro जो रूपांतरित करेगा: आपके द्वारा वर्णित बाद के रूप में अभिव्यक्ति की आवश्यकता है:

(require '[clojure.set :as set])

साथ में कुछ नेमस्पेसिंग का काम। REPL में ns के डॉक्स मांगते समय मूल बातें वर्णित हैं।

user=> (doc ns)
-------------------------
clojure.core/ns
([name docstring? attr-map? references*])
Macro
  Sets *ns* to the namespace named by name (unevaluated), creating it
  if needed.  references can be zero or more of: (:refer-clojure ...)
  (:require ...) (:use ...) (:import ...) (:load ...) (:gen-class)
  with the syntax of refer-clojure/require/use/import/load/gen-class
  respectively, except the arguments are unevaluated and need not be
  quoted. (:gen-class ...), when supplied, defaults to :name
  corresponding to the ns name, :main true, :impl-ns same as ns, and
  :init-impl-ns true. All options of gen-class are
  supported. The :gen-class directive is ignored when not
  compiling. If :gen-class is not supplied, when compiled only an
  nsname__init.class will be generated. If :refer-clojure is not used, a
  default (refer 'clojure) is used.  Use of ns is preferred to
  individual calls to in-ns/require/use/import:

REPL उपयोग

सामान्य तौर पर, REPL में ns का उपयोग न करें, और केवल require और use कार्यों का use करें। लेकिन फ़ाइलों में, उन सामानों को करने के लिए ns मैक्रो का उपयोग करें।





read-eval-print-loop