欢迎进入clojure的世界。 ? 变量 Clojure中的变量可以def关键字来声明: ? clojure数据类型是弱类型,对应java中的object,然后通过变量名直接调用。...函数 clojure中以函数为第一类对象,其小括号后面第一个元素被Clojure解释器当成一个函数或宏,其后面的都会被当成参数。...加参数后,再次调用需要传入值,如果不传会报异常。 ? 下面在函数内部使用a函数参数,如果想要拼接的话,可以在内部使用str函数,用它返回的值当成Get函数的参数: ?...注意if是不是函数或宏,而是叫做special form(特殊形式),而且没有else,用空白或换行即表示else,不用显式return,clojure会将最后一个表示的值作为函数的返回值。...宏(macro) Clojure中几乎所有的函数和宏都是用Clojure代码实现的,关于宏后面再说。
2 3 } java.util.Set Nil 保留符号nil在Clojure程序中有特殊的意义:它的意思是“空”或“空值”。...如果一个值有可能是nil,你就需要考虑代码中的这种特殊情况,以避免这个操作会产生一个java.lang.NullPointerException错误。 nil和Java中的Null是相同的。...(char 97) -> \a Keywords 关键字是Clojure中唯一特殊的的原始数据类型。主要目的是提供非常高效的存储和相等判断。...请阅读12章里在宏里使用quote来实现复杂的元编程的详细讨论。 ---- 列表是以单向链接列表的形式来实现的,在这一点上有利有弊。...你要么显示地引用,要么使用ns形式的:use子句将其包含到你的命名空间里。请查阅第二章。 clojure.set/union 集合的并函数union接收任意数量的参数,每个参数都是一个集合。
Clojure源码托管在:github 在线练习编译环境: himera learnclojure.clj 示例: ; 分号作为注释的开始 ; Clojure 用一种把元素用括号括起来的像列表一样的方式来书写...,元素之间用空格隔开 ; clojure 解释器会把第一个元素当做是函数或者宏调用,其他的都作为参数 ; 下面这个函数用于设置当前的命名空间 (ns test) ; 更多基本的例子: ; str 函数会用它所有的参数创造一个字符串...; 从一个map中检索一个值,可以直接把这个map当做函数调用(这个NB) (stringmap "a") ; => 1 (keymap :a) ; => 1 ; 关键字也可以当做函数来调用,从一个...2 3} 4) ; => nil (没有就返回nil) ; clojure.sets 命名空间包含更多的函数 ; 一些有用的形式 ;;;;;;;;;;;;;;;;; ; clojure中的逻辑结构都是宏...:only [intersection]]) ; 使用reqire来导入一个模块 (require 'clojure.string) ; 使用/从一个模块中调用函数 (clojure.string
但是没有改变lisp中 "代码也是数据" 的哲学. Clojure 语言在直觉和观感上比历史上的lisp更易于阅读....2 函数也是一种数据类型 在Lisp语言中,函数与整数或字符串一样,也属于数据类型的一种。它有自己的字面表示形式(literal representation),能够储存在变量中,也能当作参数传递。...在读取期运行代码,使得用户可以重新调整(reprogram)Lisp的语法; 在编译期运行代码,则是Lisp宏的工作基础; 在运行期编译代码,使得Lisp可以在Emacs这样的程序中,充当扩展语言(extension...最常用的做法就是使用宏。 术语"宏"在Lisp语言中,与其他语言中的意思不一样。Lisp宏无所不包,它既可能是某样表达式的缩略形式,也可能是一种新语言的编译器。...直接调用Java方法,不去发明一套新的调用语法,努力规避Java语言中繁琐的地方(doto,箭头宏等等)。
为了更加具体描述 Clojure 运行原理,会分两篇文章来介绍。 本文为第一篇,涉及到的主要内容有:编译器工作流程、Lisp 的宏机制。...Compiler.java Compiler 类主要有三个入口函数: compile,当调用clojure.core/compile时使用 load,当调用clojure.core/require、clojure.core.../use时使用 eval,当调用clojure.core/eval时使用 这三个入口函数都会依次调用 macroexpand、analyze 方法,生成Expr对象,compile 函数还会额外调用...是否为一个宏,而这又是通过检查var是否为一个函数,并且元信息中macro是否为true。...Clojure 里面通过defmacro函数创建宏,它会调用var的setMacro函数来设置元信息macro为true。
clojure macro宏在运行之前机械展开,定义宏相当于给语言增加新特性,写宏的*原则*: 能写成函数就不要用宏(因为写宏没有写函数简单直观,容易写错,需要先在 REPL 中测试一番) ...只有不得不用时才用宏(性能要求高时比函数调用快,或者需要“代码数据”相互转换) 精心设计的宏调用比函数调用更 DSL(如实现控制结构、传递 Java方法) 宏与函数 ;; 宏正确写法 (defmacro...10 (+ 5 2)) (println (macroexpand-1 '(op 5 + 2 * 10))) ;; (* 10 (+ 5 2)) (println (clojure.walk...;; 2 (println (macroexpand-1 '(op2 5 + 2 * 10))) ;; 2 (println (clojure.walk...with-mongo 是定义的函数,后面传递的是参数,使用 ~' 修饰直接翻译过去,即字符串传字符串,:dict 键值也传键值 with-dict 传递多个参数给body,其中 dbname tbname 在
在 Clojure 众多的 Web 框架中,Ring 以其简单统一的 HTTP 抽象模型脱颖而出。...Compojure 里面使用了大量宏来简化路由的定义,像上面例子中的GET、not-found等。...在使用 GET 等这类宏定义 handler 时,会调用wrap-route-matches 来包装真正的处理逻辑,逻辑如下: (defn- wrap-route-matches [handler method...一个 App 中的 middleware 调用顺序非常重要,因为不同的 middleware 之间 request map 与 response map 是相互依赖的,所以在定义 middleware...Ring 与其说是一个框架,不如说是由各个短小精悍的函数组成的 lib,充分展示了 Clojure 语言的威力,通过函数的组合定义出一套完整的 HTTP 抽象机制,通过宏来实现“路由”特定领域语言,极大简化了路由的定义
Clojure使用Java方法 Clojure有个很强大的功能,就是你可以使用Lisp语言风格无缝调用java api(java interop).这无疑是如虎添翼....调用一个Java对象的方法 语法: .method-name object-value args ... user=> (.toUpperCase "hello,clojure") "HELLO,CLOJURE...user/eval1266 (form-init7793881567968869401.clj:1) user=> (new String "Clojure") "Clojure" 连续调用一个对象的方法...我们在Clojure中这样来写 user=> (doto (java.util.Stack.) #_=> (.push "Hello!")...#inst "2016-06-28T15:21:43.048-00:00" 访问一个类的内部类 用如下形式: package.class-name$inner-class
ASM 生成可运行在 JVM 中的 bytecode。...交互 defrecord、deftype生成同名的类,proxy、reify生成匿名的类 需要明确一点,只有在 AOT 编译时,Clojure 才会在本地生成 .class 文件,其他情况下生成的类均在内存中...我们知道 Clojure 里面很多“函数”其实是用宏实现的,宏在编译时会进行展开,生成新代码,上面代码中的ns、defn都是宏,展开后(在 Cider + Emacs 开发环境下,C-c M-m)可得...源码,只有在 RT.java 的 makeClassLoader 函数 里面有new DynamicClassLoader语句,继续通过 Intellj 的 Find Usages 发现有如下三处调用...另外,JVM 7 中增加了 invokedynamic 指令,可以让运行在 JVM 上的动态语言通过实现一个 CallSite (可以认为是函数调用)的 MethodHandle 函数来帮助编译器找到正确的实现
除了最基本的圆括号()外,方括号[]与花括号{}在 Clojure 用的也比其他 Lisp 方言中多。...《The Joy of Clojure》一书中有简单介绍,不过我觉得初学者可以完全不用去关心实现的细节,在遇到性能问题时在考虑去优化。...这也就意味我们或多或少需要了解这些宿主语言,比如 Clojure 里面没有提供直接操作文件系统、网络的类库,而是采用间接的方法去调用其宿主语言的相应类库。...Emacs + Cider 的组合相比 Intellj + Cursive 最大的优势就是对宏的支持,Cider 提供了对宏展开的快捷键,但在 Cursive 中我没找到,不过宏也是比较高级的功能,初学者应用用不到...nrepl Clojure 的 REPL 可以连接到远程服务器上的进程中,直接对进程中的函数或变量进行修改,这是非常便利的,对于很多运行时的错误可以采用这种方式解决,Emacs 与 Intellj 里面都提供了连接远程
读取和写入文件 数据一般都是存储在纯文本文件当中,存储的形式多种多样。本文,我会介绍如何在Clojure中读取和写入这些数据。 1....with-open宏 with-open宏用于自动关闭打开的文件。...惰性序列在repl中什么时候变现(realizes)? 惰性序列是用(lazy-seq [& body] )宏创建出来的。lazy-seq仅在需要的时候才会去调用它的body。...with-open是宏,我们使用clojure.walk/macroexpand-all展开下: (clojure.walk/macroexpand-all '(with-open [rdr...也就是说,我们在求值with-open时,rdr中第一行的内容会被(line-seq )给抓住了。
数组的组件类型为type(如果指定了type),或aset中第一个元素的类型(如果aset不为空),或Object。aset中所有元素的类型必须兼容数组的组件类型。...amap, areduce amap 宏 (amap a idx ret expr) 用表达式expr映射数组a。...Clojure数组专题到此为止,之后会继续以专题的形式总结其他的API。...之前没注意这个,在《The Joy Of Clojure》中看到。.../into-array ([aseq] [type aseq]) Returns an array with components set to the values in aseq.
对于 Clojure,我目前在 sf 上有一套视频课程,供参考。 为了方便大家使用 cljs 开发插件,我整理了一份模板,供大家参考。...在 dev 过程中,推荐设置 cljsbuild 的 optimizations 为 none,以便得到最快的编译速度; 在 release 过程中,可以将其设置为 advanced,来压缩、优化 js...Clojure,一般需要单独把宏定义在一个文件里面,然后在 cljs 里面用(:require-macros [my.macros :as my]) 这样的方式去引用,而且宏定义的文件名后缀必须是 clj...由于宏编译与 cljs 编程在不同的时期,所以如果宏写错了,就需要把 repl 杀掉重启来把新的宏 feed 给 cljs,这点也比较痛苦,因为 repl 的启动速度实在是有些慢。...这一点在 Clojure 里面虽然也存在,但是 Clojure 里面一般 repl 开了就不关了,直到电脑重启。
另外,为了更好地在emacs中编写Clojure,还需要cider-mode和clojure-mode的支持,这时候就不得不编辑init.el文件,本着KISS (keep it simple, stupid...简单点说,就是防止在package-initialize之后重复加载包,因为可能会影响性能。 模块化 如果把什么东西都揉到init.el文件中,这个文件一定会很快变得臃肿不堪。...在emacs中按下c-h i获取主话题(topic)的菜单,然后点击Elisp进入它的操作指南。重点查看Evaluation和Byte Compilation两个章节。...当你正在编译文件的时候,包中宏就会原地展开,然后被eval-when-compile宏加载进内存并被编译成字节码,供后续解析器执行。...配置完毕后,使用(provide 'init-clojure)将模块以这样的名字暴露给其它客户端调用。
我就想啊,论函数式编程,舍Clojure其谁?而且我在Clojure很少能写出loop... recur这样偏底层的循环代码。话不多说,撸起袖子开工。...Clojure 解法 转换数据格式 原题中给的是json的格式,不适合在Clojure中处理,所以我们手工转换成需要的形式,如下: 清单1-1 数据定义 (def rooms [{:room-id...它的文档描述如下: (doc juxt) -> clojure.core/juxt [f] [f g] [f g h] [f g h & fs] Added in 1.1 Takes a set...中判断集合是否为空较为常用的手法(seq ),如果集合非空,那么返回集合本身;反之,返回nil,nil在逻辑上是false。...照这个思路,在我的程序当中使用(first )取map的第一个元素并不会出错。
一、创建函数: fn: fn是一个宏,用于定义一个简单的函数,如下: user=> (fn [] "hello") #<user$eval375$fn__376 user$eval375...") ; 一个参数 "my name is clojure" user=> (defn f1 [& a] (str a)) ;定义变参函数 #'user/f1 user=> (f1...->:宏-> 我们也称为 “thread” 宏,它本质上是调用一系列的函数,前一个函数的返回值作为后一个函数的参数,返回最后一次函数调用的值,比如下面两行代码的作用是一样的: user=> (.toUpperCase...println 1)")) ;str函数返回字符串 "(println 1)" user=> (read-string "(println 1)") ;而read-string函数用于从字符串中读取对象...>=) true 参考推荐: clojure 学习
Clojure的contrib包中实现了对现有JDBC的封装,在wiki上有连接,该页面上包含了对不同的数据库的连接方法和基本的操作,但是这个页面上没有提供足够的信息,足够一个初学者能够使用Clojure...其次,在和MySQL的操作中,我们需要两个库,一个是clojure.contrib,另外一个是mysql-connector-java-xxx.jar。...接着,在需要使用sql库的地方要导入这些库 在ns宏中加载如下内容:(:use [clojure.contrib.sql :as sql :only ()]),这样在本文件中就可以直接使用sql作为前缀...示例 创建表 fruit,并插入两条记录,然后条件查询和全部查询 1) 在project.clj 中,添加sql依赖: (defproject myClojure "0.1.0-SNAPSHOT"...注:所有的sql操作都需要在with-connection宏下包裹着 参考推荐: Clojure SQL 基础 Clojure 连接mysql Connecting Clojure and MySQL
由于宿主环境的不同,因此只能与宿主环境无关的Clojure代码可以在JVM和JSVM间共享,并且cljs也未能完全实现clj中的所有语言特性,更何况由于JSVM是单线程因此根本就不需要clj中STM等特性呢...|:=$&] 末尾字符不能是: 以:为首字符则解释为Keyword 命名空间 cljs中每个symbol无论是函数还是绑定,都隶属于某个具体的命名空间之下,因此在每个.cljs的首行一般为命名空间的声明...docstrings就是Document String,用于描述函数、宏功能。...return dividend - divisor * Math.trunc(dividend/divisor) } 至于次方,开方和对数等则要调用JS中Math所提供的方法了!...; 调用JS函数,以下两种形式是等价的。但注意第二种,第一个参数将作为函数的上下文,和python的方法相似。
Clojure里面是不支持变量的。...注意:如果这些表达式里面有调用别的函数,那么这个函数是无法利用let创建的这个binding的。...宏 binding 跟let 类似, 但是它创建的本地binding会暂时地覆盖已经存在的全局binding....这个binding可以在创建这个binding的form以及这个form里面调用的函数里面都能看到。但是一旦跳出了这个binding 那么被覆盖的全局binding的值会回复到之前的状态。...入门教程 Clojure 基本语法
领取专属 10元无门槛券
手把手带您无忧上云