编辑“︁
Clojure
”︁(章节)
跳转到导航
跳转到搜索
Template:Editnotice load/content
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
==功能示例== 以下示例均可在Clojure REPL中运行(如,使用Clojure命令行界面工具<ref name="guides/deps_and_cli" />启动的REPL或在REPL.it<ref>{{cite web |url=https://repl.it/l/clojure |website=REPL.it |title=Online Clojure REPL |access-date=2019-07-08 |archive-date=2019-07-09 |archive-url=https://web.archive.org/web/20190709020152/https://repl.it/l/clojure |dead-url=no }}</ref>上提供的在线REPL。) ===简单性=== 由于强调简单性,典型的Clojure程序主要包括函数和简单的数据结构(即列表,向量,映射和集合): <syntaxhighlight lang="clojure"> ;; 一个典型的Clojure程序的入口 (defn -main ; 函数名 [& args] ; 参数向量 (`&`表示可变参数) (println "Hello, World!")) ; 函数体 </syntaxhighlight> ===REPL编程=== 与其他[[Lisp]]一样,Clojure的标志性特征之一是基于[[REPL]]的交互式编程。<ref>{{cite web |url=https://clojure.org/guides/repl/introduction |website=Clojure.org |title=Programming at the REPL: Introduction |access-date=2018-12-04 |archive-date=2018-12-04 |archive-url=https://web.archive.org/web/20181204134219/https://clojure.org/guides/repl/introduction |dead-url=no }}</ref>在以下示例中,<code>;;</code>表示一行注释的开始,而<code>;; =></code>则表示输出: <syntaxhighlight lang="clojure"> ;; 定义一个var (def a 42) ;; => #'user/a ;; 调用名为`+`的函数 (+ a 8) ;; => 50 ;; 调用名为`even?`的函数 (even? a) ;; => true ;; 定义一个函数以返回n除10之余 (defn foo [n] (rem n 10)) ;; => #'user/foo ;; 调用该函数 (foo a) ;; => 2 ;; 打印`rem`的文档字符串(docstring) (doc rem) ;; => ------------------------- clojure.core/rem ([num div]) remainder of dividing numerator by denominator. ;; 打印`rem`的源代码 (source rem) ;; => (defn rem "remainder of dividing numerator by denominator." {:added "1.0" :static true :inline (fn [x y] `(. clojure.lang.Numbers (remainder ~x ~y)))} [num div] (. clojure.lang.Numbers (remainder num div))) </syntaxhighlight> ===运行时可用的名字=== 与Clojure不同,其他语言的编译器会将程序中的名字编译掉使得它们在运行时不可用。而在Clojure中,可以用普通的数据结构对其运行时进行观察: <syntaxhighlight lang="clojure"> ;; 定义一个var (def a 42) ;; => #'user/a ;; 以映射(map)的形式获取在`user`名字空间中捕获的(interned)所有var (ns-publics 'user) ;; => {a #'user/a} ;; 用`#'`(读取器宏)及其关联的、名字空间限定的符号`user/a`引用该var #'user/a ;; => #'user/a ;; 解引用该var(获取其值) (deref #'user/a) ;; => 42 ;; 定义(并附加文档字符串)一个函数以返回n除10之余 (defn foo "返回`(rem n 10)`" [n] (rem n 10)) ;; => #'user/foo ;; 获取var `#'user/foo`的元数据 (meta #'user/foo) ;; => {:arglists ([n]), :doc "返回`(rem n 10)`", :line 1, :column 1, :file "user.clj", :name foo, :ns #namespace[user]} </syntaxhighlight> ===代码即数据(同像性)=== 与其他Lisp类似,Clojure也具有[[同像性]](又称代码即数据)。从下面的示例中可以看到,用Clojure编写代码从而修改代码本身是非常容易的: <syntaxhighlight lang="clojure"> ;; 调用一个函数 (代码) (+ 1 1) ;; => 2 ;; 引用该函数调用 ;;(将代码转换成数据,此处为含一组符号的列表) (quote (+ 1 1)) ;; => (+ 1 1) ;; 获取该列表上的首个元素 ;; (视代码为数据并对其进行操作) (first (quote (+ 1 1))) ;; => + ;; 获取该列表上的最后一个元素 ;; (视代码为数据并对其进行操作) (last (quote (+ 1 1))) ;; => 1 ;; 替换原列表上的符号从而获取一个新列表 ;; (视代码为数据并对其进行操作) (map (fn [form] (case form 1 'one + 'plus)) (quote (+ 1 1))) ;; => (plus one one) </syntaxhighlight> ===富有表现力的数据变换操作符=== 穿梭宏(threading macro,如,<code>-></code>、<code>->></code>等)可以在语法上表达一个数据集在一系列变换间穿梭的抽象: <syntaxhighlight lang="clojure"> (->> (range 10) (map inc) (filter even?)) ;; => (2 4 6 8 10) </syntaxhighlight> 利用变换归纳器也可以更有效地实现该过程: <syntaxhighlight lang="clojure"> (sequence (comp (map inc) (filter even?)) (range 10)) ;; => (2 4 6 8 10) </syntaxhighlight> ===标识及其状态的线程安全管理=== [[线程安全]]的唯一序列号生成器(然而,和许多其他Lisp方言一样,Clojure内部使用其内置的<code>gensym</code>函数): <syntaxhighlight lang="clojure"> (def i (atom 0)) (defn generate-unique-id "每次调用会返回一个唯一数字ID。" [] (swap! i inc)) </syntaxhighlight> ===宏=== <code lang="java">java.io.Writer</code>的一个匿名子类(不写任何内容)和一个宏(使用该类来静音其中打印的所有内容): <syntaxhighlight lang="clojure"> (def bit-bucket-writer (proxy [java.io.Writer] [] (write [buf] nil) (close [] nil) (flush [] nil))) (defmacro noprint "在对给定的`forms`求值的同时静音所有向`*out*`打印的内容。" [& forms] `(binding [*out* bit-bucket-writer] ~@forms)) (noprint (println "Hello, nobody!")) ;; => nil </syntaxhighlight> ===Java互操作=== 作为其主要设计目标之一,Clojure从一开始就将其宿主平台视为其不可分割的一部分。Clojure与Java之间出色的互操作即得益于此: <syntaxhighlight lang="clojure"> ;; 调用一个实例方法 (.toUpperCase "apple") ;; => "APPLE" ;; 调用一个静态方法 (System/getProperty "java.vm.version") ;; => "12+33" ;; 创建`java.util.HashMap`的一个实例 ;; 并加入一些键值对(key-value pairs) (doto (java.util.HashMap.) (.put "apple" 1) (.put "banana" 2)) ;; => {"banana" 2, "apple" 1} ;; 创建`java.util.ArrayList`的一个实例 ;; 并用`clojure.core/map`递增(increment)其元素 (def al (doto (java.util.ArrayList.) (.add 1) (.add 2) (.add 3))) (map inc al) ;; => (2 3 4) ;; 利用Java Swing显示一个消息对话框 (javax.swing.JOptionPane/showMessageDialog nil "Hello, World!") ;; => nil </syntaxhighlight> ===软件事务内存=== 10个线程操纵一个共享数据结构,该结构由100个向量组成,而每个向量包含10个(最初是连续的)唯一数字。每个线程随后在两个随机向量中重复选择两个随机位置并交换它们。通过使用Clojure的[[软件事务内存]]系统,对向量的所有更改都发生在事务中: <syntaxhighlight lang="clojure"> (defn run [nvecs nitems nthreads niters] (let [vec-refs (->> (* nvecs nitems) (range) (into [] (comp (partition-all nitems) (map vec) (map ref)))) swap #(let [v1 (rand-int nvecs) v2 (rand-int nvecs) i1 (rand-int nitems) i2 (rand-int nitems)] (dosync (let [tmp (nth @(vec-refs v1) i1)] (alter (vec-refs v1) assoc i1 (nth @(vec-refs v2) i2)) (alter (vec-refs v2) assoc i2 tmp)))) report #(->> vec-refs (into [] (comp (map deref) (map (fn [v] (prn v) v)) cat (distinct))) (count) (println "Distinct:"))] (report) (->> #(dotimes [_ niters] (swap)) (repeat nthreads) (apply pcalls) (dorun)) (report))) (run 100 10 10 100000) ;; => [0 1 2 3 4 5 6 7 8 9] [10 11 12 13 14 15 16 17 18 19] ... [990 991 992 993 994 995 996 997 998 999] Distinct: 1000 [382 318 466 963 619 22 21 273 45 596] [808 639 804 471 394 904 952 75 289 778] ... [484 216 622 139 651 592 379 228 242 355] Distinct: 1000 nil </syntaxhighlight>
摘要:
请注意,所有对Local Chinese Wikipedia的贡献均可能会被其他贡献者编辑、修改或删除。如果您不希望您的文字作品被随意编辑,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源(详情请见
Project:著作权
)。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)
导航菜单
个人工具
未登录
讨论
贡献
创建账号
登录
命名空间
页面
讨论
大陆简体
不转换
简体
繁體
大陆简体
香港繁體
澳門繁體
大马简体
新加坡简体
臺灣正體
查看
阅读
编辑
查看历史
更多
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息