Clojure 是一种运行在 Java 平台上的 LISP 方言,LISP 是一种以表达性和功能强大著称的编程语言。

; 分号作为注释的开始
; clojure 用括号把元素括起来,元素之间用空格隔开。clojure 解释器把第一个元素当做是函数或者宏调用,其他的元素都作为参数
; 下面这个函数用于设置当前的命名空间
(ns myclojure)
; 一些简单的例子:
(str "Hello" " " "World") ; => "Hello World"
(+ ) ; =>
(- ) ; =>
(* ) ; =>
(/ ) ; =>
;  比较使用 "="
(= ) ; => true
(= ) ; => false
; 逻辑运算
(not true) ; => false
; 嵌套预算
(+ (- )) ; = + ( - ) =>
; defn 定义一个函数
; doseq 类似 for 循环
(defn Example []
(doseq [n [ ]]
(println n)))
(Example)
; 使用let 来创建临时绑定
(let [a b ]
(> a b)) ; => false
; clojure 把布尔值、字符串、数字、向量、列表转化为 java 对象
(class ) ; 整形字面值默认是 java 中的 Long 类型
(class .); 浮点字面值对应着 java 中的 Double 类型
(class ""); 字符串总是用双引号括起来,并且对应着 java 中的 Sring 类型
(class false) ;布尔值对应着 java 中的 Boolean 类型
(class nil); null值被称为 nil
(class [ ]) ; => clojure.lang.PersistentVector
(class '(1 2 3)) ; => clojure.lang.PersistentList
; 如果想创建一列数据字面值, 使用一个单引号 ' 来防表达式被解析执行
'(+ 1 2) ; => (+ 1 2) ;这里没有返回3
; (上面表达式和(quote (+ )) 等价,不过更简洁 ; 可以运算一个引用列表
(eval '(+ 1 2)) ; => 3
;书写一个列表如( )一样简单, 但是我们不得不把它“引”(前面加个单引号)起来
;这样就能防止解释器把它当做一个函数来解析
;另外,(list ) 和 '(1 2 3) 等价
;列表和向量都是集合:
(coll? '(1 2 3)) ; => true
(coll? [ ]) ; => true ; 只有列表是序列.(序列是有顺序的)
(seq? '(1 2 3)) ; => true
(seq? [ ]) ; => false ; 序列是列表一种逻辑上的接口,可以懒加载.
; "懒" 意味着可以定义无穷序列,就像下面一样:
(range ) ; => ( )
(range) ; => ( ...) (一个无穷序列)
(take (range)) ; ( ) ; 使用cons 来追加一个元素到列表或者向量的头部
(cons [ ]) ; => ( )
(cons '(1 2 3)) ; => (4 1 2 3) ; 使用conj追加一个元素到列表的头部,或者向量的尾部,
(conj [ ] ) ; => [ ]
(conj '(1 2 3) 4) ; => (4 1 2 3) ; 使用concat来连接列表和向量
(concat [ ] '(3 4)) ; => (1 2 3 4) ; 使用filter, map 来进行列表计算
(map inc [ ]) ; => ( )
(filter even? [ ]) ; => () ; 使用reduce 来进行化繁为简 (map/reduce 思想就来自于lisp)
(reduce + [ ])
; = (+ (+ (+ ) ) )
; => ; Reduce 可以使用一个初始值
(reduce conj [] '(3 2 1))
; = (conj (conj (conj [] ) ) )
; => [ ] ; 使用 fn 来创建一个函数。所有的函数都有返回值,就是它的最后一个表达式
(fn [] "Hello World") ; => fn ; (你需要额外的括号去调用它)
((fn [] "Hello World")) ; => "Hello World" ;你可以使用def来创建变量
(def x )
x ; => ; 将函数赋值给一个变量
(def hello-world (fn [] "Hello World"))
(hello-world) ; => "Hello World" ; 你可以使用defn来简化定义过程
(defn hello-world [] "Hello World") ;[] 是函数的参数列表
(defn hello [name]
(str "Hello " name))
(hello "Steve") ; => "Hello Steve" ; 你也可以使用下面这种简写方式
(def hello2 #(str "Hello " %))
(hello2 "Fanny") ; => "Hello Fanny" ; 你可以创建拥有可变参数的函数
(defn hello3
([] "Hello World")
([name] (str "Hello " name)))
(hello3 "Jake") ; => "Hello Jake"
(hello3) ; => "Hello World" ; 函数允许将参数打包成列表 (有点类似python中的*)
(defn count-args [& args]
(str "You passed " (count args) " args: " args))
(count-args ) ; => "You passed 3 args: (1 2 3)" ; 你可以将普通参数和列表参数混合使用
(defn hello-count [name & args]
(str "Hello " name ", you passed " (count args) " extra args"))
(hello-count "Finn" )
; => "Hello Finn, you passed 3 extra args" (class {:a :b :c }) ; => clojure.lang.PersistentArrayMap ; 关键字类似字符串,但是做了一些性能上的优化
(class :a) ; => clojure.lang.Keyword ; Maps 的键可以是任意类型,但是通常推荐使用keywords
(def stringmap (hash-map "a" , "b" , "c" ))
stringmap ; => {"a" , "b" , "c" } (def keymap (hash-map :a :b :c ))
keymap ; => {:a , :c , :b } (不保证顺序) ; 从一个map中检索一个值,可以直接把这个map当做函数调用(这个NB)
(stringmap "a") ; =>
(keymap :a) ; => ; 关键字也可以当做函数来调用,从一个map中检索值(这个更NB)
(:b keymap) ; => ; stings 可没有这个功能,所以下面会抛出异常。(这也是为什么推荐使用keywords)
;("a" stringmap)
; => Exception: java.lang.String cannot be cast to clojure.lang.IFn ; 检索一个不存在的值会返回nil
(stringmap "d") ; => nil ; 使用assoc 向一个map中添加新的键值对。
(assoc keymap :d ) ; => {:a , :b , :c , :d } ; 请记住, clojure 类型是不可变的!
keymap ; => {:a , :b , :c } ; 使用dissoc 来删除key(可以删除多个)
(dissoc keymap :a :b) ; => {:c } (class #{ }) ; => clojure.lang.PersistentHashSet
(set [ ]) ; => #{ } ; 使用con来添加新值
(conj #{ } ) ; => #{ } ; 使用disj删除原有值
(disj #{ } ) ; => #{ } ; 直接将set当做函数来测试是否包含某个值(NB)
(#{ } ) ; => (有就返回原有的值)
(#{ } ) ; => nil (没有就返回nil) ; clojure.sets 命名空间包含更多的函数 ; clojure中的逻辑结构都是宏, 看起来也没什么不同
(if false "a" "b") ; => "b"
(if false "a") ; => nil ; 执行多条语句,返回最后一条语句
(do
(print "Hello")
"World") ; => "World" (prints "Hello") ; 所有的函数都包含一个隐式的do
(defn print-and-say-hello [name]
(print "Saying hello to " name)
(str "Hello " name))
(print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff") ; let绑定也是
(let [name "Urkel"]
(print "Saying hello to " name)
(str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel") ; 使用“use”来获得一个模块中所有的函数
(use 'clojure.set) ; 现在我们可以使用集合操作
(intersection #{ } #{ }) ; => #{ } 求交集
(difference #{ } #{ }) ; => #{} 求差集 ; 你可以只导入一个函数子集(例如下面只包含交集函数)
(use '[clojure.set :only [intersection]]) ; 使用reqire来导入一个模块
(require 'clojure.string) ; 使用/从一个模块中调用函数
(clojure.string/blank? "") ; => true ; 你可以在导入模块的时候自定义名称
(require '[clojure.string :as str])
(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst."
; (#"" denotes a regular expression literal) ; 你可以使用":require" 从一个命名空间中引入模块(use也可以,但是别这么做)
; 如果你使用:require的话,就没必要把模块“引”(前面加个单引号)起来了.
(ns test
(:require
[clojure.string :as str]
[clojure.set :as set])) ; Java
;;;;;;;;;;;;;;;;; ; java 拥有一个庞大的各种用途的标准库,你一定迫不及待想学习如何在clojure中使用这些库 ; 使用import类引入java模块(这个还好没变化)
(import java.util.Date) ; 你也可以从一个命名空间中引入
(ns test
(:import java.util.Date
java.util.Calendar)) ; 类名字后加个”."用来创建一个对象
(Date.) ; <a date object> ; 使用. 来调用方法. 或者使用“.方法名"简写的方式
(. (Date.) getTime) ; <a timestamp>
(.getTime (Date.)) ; 和上面一样哦 ; 使用/ 来调用静态方法
(System/currentTimeMillis) ; <a timestamp> (system is always present) ; 使用 doto 来处理可变的类,所有的函数始终用最初的那个对象值,最后还是返回最初的那个对象 (import java.util.Calendar)
(doto (Calendar/getInstance)
(.set )
.getTime) ; => A Date. set to -- ::

clojure 语法的更多相关文章

  1. Clojure语法学习-循环

    do和块语句 在Scala中,花括号{}括起来的语句构成一个block,它的值就是最后一个语句的值. scala> val a = { | println("a") | 1} ...

  2. clojure基础入门(一)

    最近在看storm的源码,就学习分享下clojure语法. 阅读目录: 概述 变量 运算符 流程控制 总结 概述 clojure是一种运行在JVM上的Lisp方言,属于函数式编程范式,它和java可以 ...

  3. 优雅的函数式编程--Clojure概述

    欢迎转载,转载请注明出处,徽沪一郎. 楔子 由于阅读storm源码的原因,头一次接触到Clojure.没有花特别的时间来研究clojure语法,只是在一些特殊的用法时,才查了一下clojure官网的文 ...

  4. Clojure——学习迷宫生成

    背景 初学clojure,想着看一些算法来熟悉clojure语法及相关算法实现. 找到一个各种语言生成迷宫的网站:http://rosettacode.org/wiki/Maze_generation ...

  5. Clojure学习笔记(一)——介绍、安装和语法

    什么是Clojure Clojure是一种动态的.强类型的.寄居在JVM上的语言. Clojure的特性: 函数式编程基础,包括一套性能可以和典型可变数据结构媲美的持久性数据结构 由JVM提供的成熟的 ...

  6. Clojure学习02:语法

    相比我们传统的 c ,java ,python ,javascript等,Clojure的语法比较特别,初一看,还可能会有些不适应. 本文来介绍下Clojure的语法特点. 一.表达式 所有的Cloj ...

  7. clojure的语法糖

    语法糖很多, 就是奔这个“懒” 来用clj的. 但是,在常见的书里(<Clojure编程><Clojure编程乐趣2>)都对很多基本语法,用法都介绍不全, 不细.看书看得很累. ...

  8. Markdown编辑器语法指南2

    人的一切痛苦, 本质上都是对自己的无能的愤怒. --王小波 1 Markdown编辑器的基本用法 1.1 代码 如果你只想高亮语句中的某个函数名或关键字,可以使用 `function_name()` ...

  9. MorkDown 常用语法总结

    推荐一款很好用的markdown编辑器:http://www.typora.io/ 基本技巧: 代码高亮 如果你只想高亮语句中的某个函数名或关键字,可以使用``实现 通常编辑器根据diamagneti ...

随机推荐

  1. Luogu P5339 [TJOI2019]唱、跳、rap和篮球

    题目 设\(f_i\)表示从\((a-4i,b-4i,c-4i,d-4i)\)中选\(n-4i\)个排队的方案数. 那么我们可以容斥,答案为\(\sum\limits_{i=0}^{lim}(-1)^ ...

  2. 偶遇com组件 .rc 文件 not found .tlb文件问题:

    好久木有弄com组件来,记忆已经模糊了,今天遇见一个编译问题,折腾了半天,mark一下: xxx_x64.rc(273): error RC2135: file not found: xxx.tlb ...

  3. 思维体操: HDU1287破译密码

    破译密码 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  4. P3588 [POI2015]PUS(拓扑排序+线段树)

    P3588 [POI2015]PUS 对于每个$(l,r,k)$,将$k$个位置向剩下$r-l-k+1$个位置连边,边权为$1$,这样就保证$k$个位置比剩下的大 先给所有位置填$1e9$保证最优 然 ...

  5. Timer的利用

    package 第十一章; import java.util.*; import java.util.TimerTask; public class TimerTest { /** * @param ...

  6. 前端开发HTML&CSS入门——具体是做什么的

    软件开发,一提起来感觉这个感觉这个词范围很大很广,说起来也很笼统.不知所云,开发的到底是什么?或者说开发的具体内容是什么?以前我们讲软件开发主要是分前端和后端,那前端和后端又是什么那?你可以这么通俗的 ...

  7. FPGA异步时钟系统中信号处理之单比特信号

    有些东西当你习以为常而不去深思熟虑的时候,致命的错误就会因此埋下!      FPGA开发中难免会遇到跨时钟域处理的问题,而对于单比特信号,我会不假思索的回答:打两拍不久解决了吗?但是事实时,这佯作的 ...

  8. 025-Cinder服务-->安装并配置一个本地存储节点(ISCSI)

    一:Cinder提供块级别的存储服务,块存储提供一个基础设施为了管理卷,以及和OpenStack计算服务交互,为实例提供卷.此服务也会激活管理卷的快照和卷类型的功能,块存储服务通常包含下列组件:cin ...

  9. AGC007题解

    发现自己思维能力又跟不上了...做题有点吃力...所以回归AGC刷题计划... AGC040506都写了一部分题然后懒得补全了,所以从07开始做吧.大概是从C开始. C 这也太人类智慧了吧... 我先 ...

  10. 【LuoguP4770】[NOI2018] 你的名字

    题目链接 题意简述 给定一个串 \(S\) 多组询问 , 每次给定一个串 \(T\) 和一个 区间 \([l,r]\) 求串\(T\) 有多少个本质不同的子串 满足不是 \(S[l...r]\) 的子 ...