Basic 语法
为了理解Clojure的基本语法,让我们首先看一个简单的Hello World程序。
Hello World作为一个完整的程序
在完整的Clojure程序中写下“Hello world”。 以下是一个例子。
例子 (Example)
(ns clojure.examples.hello
(:gen-class))
(defn hello-world []
(println "Hello World"))
(hello-world)
关于上述程序需要注意以下事项。
该程序将写在一个名为main.clj的文件中。 扩展名“clj”是clojure代码文件的扩展名。 在上面的示例中,文件名称为main.clj。
'defn'关键字用于定义函数。 我们将在另一章中详细介绍函数。 但是现在,知道我们正在创建一个名为helloworld的函数,它将具有我们的主要Clojure代码。
在我们的Clojure代码中,我们使用'println'语句将“Hello World”打印到控制台输出。
然后我们调用hello-world函数,然后运行'println'语句。
上述程序产生以下输出。
输出 (Output)
Hello World
声明的一般形式
任何语句的一般形式都需要在大括号中进行评估,如以下示例所示。
(+ 1 2)
在上面的示例中,整个表达式用大括号括起来。 上述语句的输出为3. +运算符的作用类似于Clojure中的一个函数,用于添加数字。 值1和2被称为parameters to the function 。
让我们考虑另一个例子。 在这个例子中,'str'是用于连接两个字符串的运算符。 字符串“Hello”和“World”用作参数。
(str "Hello" "World")
例子 (Example)
如果我们结合上述两个语句并编写程序,它将如下所示。
(ns clojure.examples.hello
(:gen-class))
(defn Example []
(println (str "Hello World"))
(println (+ 1 2)))
(Example)
输出 (Output)
上述程序产生以下输出。
Hello World
3
Namespaces
命名空间用于定义Clojure中定义的模块之间的逻辑边界。
当前命名空间
这定义了当前Clojure代码所在的当前名称空间。
语法 (Syntax)
*ns*
例子 (Example)
在REPL命令窗口中,运行以下命令。
*ns*
输出 (Output)
当我们运行上面的命令时,输出将推迟,具体取决于当前命名空间。 以下是输出的示例。 Clojure代码的命名空间是 -
clojure.examples.hello
(ns clojure.examples.hello
(:gen-class))
(defn Example []
(println (str "Hello World"))
(println (+ 1 2)))
(Example)
在Clojure中要求声明
Clojure代码打包在库中。 每个Clojure库都属于一个名称空间,类似于Java包。 您可以使用“Require”语句加载Clojure库。
语法 (Syntax)
(require quoted-namespace-symbol)
例子 (Example)
以下是此语句的使用示例。
(ns clojure.examples.hello
(:gen-class))
(require ‘clojure.java.io’)
(defn Example []
(.exists (file "Example.txt")))
(Example)
在上面的代码中,我们使用'require'关键字导入命名空间clojure.java.io,它具有输入/输出功能所需的所有功能。 由于我们没有所需的库,我们可以在上面的代码中使用'file'函数。
Clojure中的评论
注释用于记录您的代码。 单行注释使用;; 在任何位置。 以下是一个例子。
例子 (Example)
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(println "Hello World"))
(Example)
Delimiters
在Clojure中,可以使用弯曲或方括号括号来分割或分隔语句。
例子 (Example)
以下是两个例子。
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(println (+ 1 2 3)))
(Example)
输出 (Output)
上述程序产生以下输出。
6
例子 (Example)
以下是另一个例子。
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(println [+ 1 2 3]))
(Example)
输出 (Output)
上述程序产生以下输出。
[#object[clojure.core$_PLUS_ 0x10f163b "clojure.core$_PLUS_@10f163b"] 1 2 3]
Whitespaces
可以在Clojure中使用空格来分割语句的不同组件,以便更清晰。 这可以在逗号(,)运算符的帮助下完成。
例如,以下两个语句是等效的,两个语句的输出都是15。
(+ 1 2 3 4 5)
(+ 1, 2, 3, 4, 5)
尽管Clojure忽略了逗号,但它有时会使用它们来让程序员更容易阅读。
例如,如果你有一个如下所示的哈希映射(def a-map {:a 1:b 2:c 3})并在REPL窗口中询问它的值,Clojure会将输出打印为{:a 1, :b 2,:c 3}。
结果更容易阅读,特别是如果您正在查看大量数据。
Symbols
在Clojure中,符号等同于其他编程语言中的标识符。 但与其他编程语言不同,编译器将符号视为实际的字符串值。 由于符号是值,因此符号可以存储在集合中,作为参数传递给函数等,就像任何其他对象一样。
符号只能包含字母数字字符和'* +! /。 : - _?' 但不能以数字或冒号开头。
以下是符号的有效示例。
tutorial-point!
TUTORIAL
+tutorial+
Clojure项目结构
最后,我们来谈谈Clojure项目的典型项目结构。 由于Clojure代码在Java虚拟机上运行,因此Clojure中的大多数项目结构与您在java项目中找到的类似。 以下是Eclipse中Clojure项目的示例项目结构的快照。
关于上述程序结构,需要注意以下关键事项。
demo_1 - 这是放置Clojure代码文件的包。
core.clj - 这是主要的Clojure代码文件,它将包含Clojure应用程序的代码。
Leiningen文件夹包含运行任何基于Clojure的应用程序所需的文件,如clojure-1.6.0.jar。
pom.properties文件将包含诸如groupId,artifactId和Clojure项目版本之类的信息。
project.clj文件包含有关Clojure应用程序本身的信息。 以下是项目文件内容的示例。
(defproject demo-1 "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {
:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"
}
:dependencies [[org.clojure/clojure "1.6.0"]])