zoukankan      html  css  js  c++  java
  • clojure 语法

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

    ; 分号作为注释的开始
    ; clojure 用括号把元素括起来,元素之间用空格隔开。clojure 解释器把第一个元素当做是函数或者宏调用,其他的元素都作为参数
    ; 下面这个函数用于设置当前的命名空间
    (ns myclojure)
    ; 一些简单的例子:
    (str "Hello" " " "World") ; => "Hello World"
    (+ 2 1) ; => 3
    (- 2 1) ; => 1
    (* 2 2) ; => 4
    (/ 2 1) ; => 2
    ;  比较使用 "="
    (= 1 1) ; => true
    (= 2 1) ; => false
    ; 逻辑运算
    (not true) ; => false
    ; 嵌套预算
    (+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2
    ; defn 定义一个函数
    ; doseq 类似 for 循环
    (defn Example [] (doseq [n [
    0 1 2]] (println n))) (Example)
    ; 使用let 来创建临时绑定
    (let [a 1 b 2]
      (> a b)) ; => false
    ; clojure 把布尔值、字符串、数字、向量、列表转化为 java 对象
    (class 1) ; 整形字面值默认是 java 中的 Long 类型
    (class 1.); 浮点字面值对应着 java 中的 Double 类型
    (class ""); 字符串总是用双引号括起来,并且对应着 java 中的 Sring 类型
    (class false) ;布尔值对应着 java 中的 Boolean 类型
    (class nil); null值被称为 nil
    (class [1 2 3]) ; => clojure.lang.PersistentVector
    (class '(1 2 3)) ; => clojure.lang.PersistentList
    ; 如果想创建一列数据字面值, 使用一个单引号 ' 来防表达式被解析执行
    '(+ 1 2) ; => (+ 1 2) ;这里没有返回3
    ; (上面表达式和(quote (+ 1 2)) 等价,不过更简洁
    
    ; 可以运算一个引用列表
    (eval '(+ 1 2)) ; => 3
    ;书写一个列表如(1 2 3)一样简单, 但是我们不得不把它“引”(前面加个单引号)起来
    ;这样就能防止解释器把它当做一个函数来解析
    ;另外,(list 1 2 3) 和 '(1 2 3) 等价
    ;列表和向量都是集合:
    (coll? '(1 2 3)) ; => true
    (coll? [1 2 3]) ; => true
    
    ; 只有列表是序列.(序列是有顺序的)
    (seq? '(1 2 3)) ; => true
    (seq? [1 2 3]) ; => false
    
    ; 序列是列表一种逻辑上的接口,可以懒加载.
    ; "" 意味着可以定义无穷序列,就像下面一样:
    (range 4) ; => (0 1 2 3)
    (range) ; => (0 1 2 3 4 ...) (一个无穷序列)
    (take 4 (range)) ;  (0 1 2 3)
    
    ; 使用cons 来追加一个元素到列表或者向量的头部
    (cons 4 [1 2 3]) ; => (4 1 2 3)
    (cons 4 '(1 2 3)) ; => (4 1 2 3)
    
    ; 使用conj追加一个元素到列表的头部,或者向量的尾部,
    (conj [1 2 3] 4) ; => [1 2 3 4]
    (conj '(1 2 3) 4) ; => (4 1 2 3)
    
    ; 使用concat来连接列表和向量
    (concat [1 2] '(3 4)) ; => (1 2 3 4)
    
    ; 使用filter, map 来进行列表计算
    (map inc [1 2 3]) ; => (2 3 4)
    (filter even? [1 2 3]) ; => (2)
    
    ; 使用reduce 来进行化繁为简  (map/reduce 思想就来自于lisp)
    (reduce + [1 2 3 4])
    ; = (+ (+ (+ 1 2) 3) 4)
    ; => 10
    
    ; Reduce 可以使用一个初始值
    (reduce conj [] '(3 2 1))
    ; = (conj (conj (conj [] 3) 2) 1)
    ; => [3 2 1]
    
    ; 使用 fn 来创建一个函数。所有的函数都有返回值,就是它的最后一个表达式
    (fn [] "Hello World") ; => fn
    
    ; (你需要额外的括号去调用它)
    ((fn [] "Hello World")) ; => "Hello World"
    
    ;你可以使用def来创建变量
    (def x 1)
    x ; => 1
    
    ; 将函数赋值给一个变量
    (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 " %1))
    (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 1 2 3) ; => "You passed 3 args: (1 2 3)"
    
    ; 你可以将普通参数和列表参数混合使用
    (defn hello-count [name & args]
      (str "Hello " name ", you passed " (count args) " extra args"))
    (hello-count "Finn" 1 2 3)
    ; => "Hello Finn, you passed 3 extra args"
    
    
    (class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap
    
    ; 关键字类似字符串,但是做了一些性能上的优化
    (class :a) ; => clojure.lang.Keyword
    
    ; Maps 的键可以是任意类型,但是通常推荐使用keywords
    (def stringmap (hash-map "a" 1, "b" 2, "c" 3))
    stringmap  ; => {"a" 1, "b" 2, "c" 3}
    
    (def keymap (hash-map :a 1 :b 2 :c 3))
    keymap ; => {:a 1, :c 3, :b 2} (不保证顺序)
    
    ; 从一个map中检索一个值,可以直接把这个map当做函数调用(这个NB)
    (stringmap "a") ; => 1
    (keymap :a) ; => 1
    
    ; 关键字也可以当做函数来调用,从一个map中检索值(这个更NB)
    (:b keymap) ; => 2
    
    ; stings 可没有这个功能,所以下面会抛出异常。(这也是为什么推荐使用keywords)
    ;("a" stringmap)
    ; => Exception: java.lang.String cannot be cast to clojure.lang.IFn
    
    ; 检索一个不存在的值会返回nil
    (stringmap "d") ; => nil
    
    ; 使用assoc 向一个map中添加新的键值对。
    (assoc keymap :d 4) ; => {:a 1, :b 2, :c 3, :d 4}
    
    ; 请记住, clojure 类型是不可变的!
    keymap ; => {:a 1, :b 2, :c 3}
    
    ; 使用dissoc 来删除key(可以删除多个)
    (dissoc keymap :a :b) ; => {:c 3}
    
    (class #{1 2 3}) ; => clojure.lang.PersistentHashSet
    (set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3}
    
    ; 使用con来添加新值
    (conj #{1 2 3} 4) ; => #{1 2 3 4}
    
    ; 使用disj删除原有值
    (disj #{1 2 3} 1) ; => #{2 3}
    
    ; 直接将set当做函数来测试是否包含某个值(NB)
    (#{1 2 3} 1) ; => 1  (有就返回原有的值)
    (#{1 2 3} 4) ; => 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 #{1 2 3} #{2 3 4}) ; => #{2 3}  求交集
    (difference #{1 2 3} #{2 3 4}) ; => #{1}   求差集
    
    ; 你可以只导入一个函数子集(例如下面只包含交集函数)
    (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 2000 1 1 0 0 0)
      .getTime) ; => A Date. set to 2000-01-01 00:00:00
  • 相关阅读:
    GB/T 38863-2020 干部网络培训 平台数据接口技术要求
    SF/T 0023-2019 全国公证综合管理信息系统技术规范
    JTS/T 198-3-2019 水运工程施工信息模型应用标准
    GA/T 467-2019 居民身份证验证安全控制模块接口技术规范
    JR/T 0192-2020 证券期货业移动互联网应用程序安全规范
    JR/T 0191-2020 证券期货业软件测试指南 软件安全测试
    C 实战练习题目85
    C 实战练习题目84
    C 实战练习题目83
    C 实战练习题目82
  • 原文地址:https://www.cnblogs.com/weiweifeng/p/7489752.html
Copyright © 2011-2022 走看看