[英]Clojure : loading dependencies at the REPL
我最近了解到(感謝技術),在 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 中做事的指導方針是什么 --- 與在普通 clojure 源文件中做事相比? 假設我們可以從 LEININGEN 項目的根目錄加載我們的 repl,因此至少 jars 將在磁盤上的依賴項子目錄中可用。
我將從高級到您的特定問題:
REPL 或 Read-Eval-Print Loops 是 LISP 設計的核心:
因此,當您在 REPL 中輸入文本時,它會通過每個步驟來處理您的輸入並將輸出返回到您的終端。
首先是一些clojure閱讀器形式。 這將非常簡短,我鼓勵您閱讀或觀看( 第 1 部分、 第 2 部分)。
clojure 中的符號是可以表示特定值(如變量)的形式。 符號本身可以作為數據傳遞。 它們類似於 c 中的指針,只是沒有內存管理的東西。
前面有冒號的符號是關鍵字。 關鍵字類似於符號,但關鍵字的值始終是其自身——類似於字符串或數字。 它們與 Ruby 的符號相同(也以冒號為前綴)。
表單前面的引用告訴評估者保持數據結構不變:
user=> (list 1 2)
(1 2)
user=> '(1 2)
(1 2)
user=> (= (list 1 2) '(1 2))
true
盡管引用不僅僅適用於列表,但它主要用於列表,因為 clojure 的評估器通常會將列表作為類似函數的調用來執行。 使用'
是引用宏的簡寫:
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
還有很多要引用的,但這超出了這個范圍。
至於 require 語句,我假設您以以下形式找到前者:
(ns my.namespace
(:require [clojure.set :as set]))
ns
是一個宏,它將 :require 表達式轉換為您描述的后一種形式:
(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 中使用ns
,而只使用require
和use
函數。 但是在文件中,使用ns
宏來做這些事情。
區別在於require
是用於導入代碼的函數,而:require
是關鍵字。
記住當您將關鍵字用作函數時會發生什么:
=> (type :require)
clojure.lang.Keyword
=> (:require {:abc 1 :require 14})
14
它在地圖中查找自己。 因此,當您將[clojure.set :as set]
傳遞給關鍵字時,它會嘗試將其計算為向量,但失敗了,因為它不知道clojure.set
是什么。 Clojure 文檔說:
關鍵字為一個參數(映射)的 invoke() 實現 IFn,並帶有可選的第二個參數(默認值)。 例如 (: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)))
ns
宏:當你輸入:
(ns some-great-ns
:require my-form)
您使用:require
引用,在其中說明您想從給定的命名空間中使用什么。 相當於寫:
(in-ns 'some-great-ns)
(require 'my-form)
請注意,在ns
形式中(與in-ns
函數調用不同),您不必用'
引用您的符號。 您永遠不必在ns
引用符號。
require
功能如前所述,可以在某些給定的命名空間中運行:( (require 'some-great-ns)
,以便您可以使用它。 要使用它,您必須使用完全限定名稱,除非您在需要命名空間后立即使用: refer
function: (refer 'some-great-ns)
。
您可以將這兩個功能合二為一: (use 'some-great-ns)
。 現在你不需要寫: (some-great-ns/my-form
)。 簡單地說: my-form
。
當然,您也可以在宏引用和函數中使用:as
、 :exclude
、 :only
和:rename
關鍵字。
(:require)
引用中要求多個庫,如下所示:(ns my-great-namespace.core
(:require [some-other-ns.a.b :as ab]
[some-other-other-ns.c.d :as cd]))
在function
編寫中你應該寫兩行:
(in-ns my-great-namespace.core)
(require 'some-other-ns.a.b :as 'ab)
(require 'some-other-other=ns.c.d :as 'cd)
require
引用還允許您引用名稱,例如:(ns my-great-namespace.core
(:require [some-other-ns.a.b :refer [some-func]]))
你應該在什么地方做:
(in-ns my-great-namespace.core)
(require 'some-other-ns.a.b)
(refer 'some-other-ns.a.b :only ['some-func])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.