jay*_*100 36 clojure read-eval-print-loop
我最近学到了(感谢技术),在REPL ---
这失败了:
user=> (:require [clojure.set :as set])
java.lang.ClassNotFoundException: clojure.set (NO_SOURCE_FILE:24)
Run Code Online (Sandbox Code Playgroud)
虽然这成功了:
user=> (require '[clojure.set :as cs])
nil
Run Code Online (Sandbox Code Playgroud)
在加载clojure.set类时.
上下文:前一行是从命名空间源文件复制的.
我的主要问题是:通过交换:和'字符,我们所做的改变是什么,现在允许后一个命令成功?
我的第二个问题是,一般来说 - 与在普通的clojure源文件中做事相比,REPL做事的准则是什么?这里假设我们可以从LEININGEN项目的根目录加载我们的repl,因此至少可以在依赖项子目录的磁盘上使用这些jar.
Jef*_*eff 50
我会从高级到你的特定问题:
REPL或Read-Eval-Print循环是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
Run Code Online (Sandbox Code Playgroud)
虽然引用可以应用于不仅仅是列表,但它主要用于列表,因为clojure的求值程序通常会将列表作为类函数调用来执行.使用'是报价宏的简写:
user=> (quote (1 2)) ; same as '(1 2)
(1 2)
Run Code Online (Sandbox Code Playgroud)
引用基本上指定要返回的数据结构,而不是要执行的实际代码.所以你可以引用符号的符号.
user=> 'foo ; not defined earlier
foo
Run Code Online (Sandbox Code Playgroud)
引用是递归的.所以里面的所有数据也被引用:
user=> '(foo bar)
(foo bar)
Run Code Online (Sandbox Code Playgroud)
要获得(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
Run Code Online (Sandbox Code Playgroud)
引用还有很多,但这超出了这个范围.
至于require语句,我假设您以以下形式找到前者:
(ns my.namespace
(:require [clojure.set :as set]))
Run Code Online (Sandbox Code Playgroud)
ns是一个宏,它将:require表达式转换为您描述的后一种形式:
(require '[clojure.set :as set])
Run Code Online (Sandbox Code Playgroud)
随着一些命名空间的工作.在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:
Run Code Online (Sandbox Code Playgroud)
一般情况下,不要ns在REPL中使用,只需使用require和use函数.但是在文件中,使用ns宏来做那些事情.
Mat*_*ick 13
不同之处在于它require是用于导入代码的函数,而是:require一个关键字.
请记住将关键字用作函数时会发生什么:
=> (type :require)
clojure.lang.Keyword
=> (:require {:abc 1 :require 14})
14
Run Code Online (Sandbox Code Playgroud)
它在地图上看起来很自己.因此,当您传递[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)))
Run Code Online (Sandbox Code Playgroud)