惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Hackread – Cybersecurity News, Data Breaches, AI and More
C
Check Point Blog
Hacker News: Ask HN
Hacker News: Ask HN
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
WordPress大学
WordPress大学
P
Proofpoint News Feed
V
Visual Studio Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
N
Netflix TechBlog - Medium
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 聂微东
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 叶小钗
Cisco Talos Blog
Cisco Talos Blog
S
Schneier on Security
T
Threat Research - Cisco Blogs
腾讯CDC
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
The Hacker News
The Hacker News
Google DeepMind News
Google DeepMind News
Microsoft Security Blog
Microsoft Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
GbyAI
GbyAI
N
News | PayPal Newsroom
L
LINUX DO - 最新话题
酷 壳 – CoolShell
酷 壳 – CoolShell
P
Palo Alto Networks Blog
T
Tenable Blog
S
Secure Thoughts
T
Threatpost
V2EX - 技术
V2EX - 技术
大猫的无限游戏
大猫的无限游戏
Martin Fowler
Martin Fowler
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Vercel News
Vercel News
罗磊的独立博客
P
Privacy & Cybersecurity Law Blog
Engineering at Meta
Engineering at Meta
小众软件
小众软件
Google DeepMind News
Google DeepMind News
N
News and Events Feed by Topic
Y
Y Combinator Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Cybersecurity and Infrastructure Security Agency CISA
P
Proofpoint News Feed
L
Lohrmann on Cybersecurity
P
Privacy International News Feed
H
Heimdal Security Blog
量子位
B
Blog

Jark's Blog

Flink 1.16:Hive SQL 如何平迁到 Flink SQL Flink CDC 如何简化实时数据入湖入仓 基于 Flink SQL 构建流批一体的 ETL 数据集成 Nexmark: 如何设计一个流计算基准测试? Demo:基于 Flink SQL 构建流式应用 Flink 1.9 实战:使用 SQL 读取 Kafka 并写入 MySQL Flink SQL 编程实践 如何从小白成长为 Apache Committer? 聊聊Blink开源和Flink社区近况 Flink 小贴士 (7): 4个步骤,让 Flink 应用达到生产状态 Flink 小贴士 (6): 使用 Broadcast State 的 4 个注意事项 Flink 小贴士 (5): Savepoint 和 Checkpoint 的 3 个不同点 Flink 小贴士 (4): 如何选择状态后端 Flink 小贴士 (3): 轻松理解 Watermark 一文了解 Apache Flink 核心技术 Flink 零基础实战教程:如何计算实时热门商品 5分钟从零构建第一个 Flink 应用 Flink 小贴士 (2):Flink 如何管理 Kafka 消费位点 Flink小贴士 (1):确定Flink作业所需资源大小时要考虑的6件事 Flink在美团的实践与应用 我在阿里的这两年 Flink 原理与实现:Aysnc I/O Flink 原理与实现:Table & SQL API Flink 原理与实现:Session Window Flink 原理与实现:Window 机制 Flink 原理与实现:数据流上的类型和操作 Flink 原理与实现:如何生成 JobGraph Flink 原理与实现:理解 Flink 中的计算资源 Flink 原理与实现:如何生成 StreamGraph Flink 原理与实现:架构和拓扑概览 Flink 原理与实现:内存管理 Flink 原理与实现:如何处理反压问题 Flink官方文档翻译:安装部署(集群模式) Flink官方文档翻译:安装部署(本地模式) 迟到的2015年终总结 高效Macbook开发之道(工具篇) Clojure学习笔记(三):并发与引用 Clojure学习笔记(二):语法 Thrift 实践 Thrift 入门 Metrics 是个什么鬼 之入门教程 使用Redis和SQLAlchemy对Scrapy Item去重并存储 使用Scrapy定制可动态配置的爬虫 编程方式下运行 Scrapy spider 读《程序员必读的职业规划书》 Spark 下操作 HBase(1.0.0 新 API) HBase 集群安装部署 Spark On YARN 集群安装部署 Git 常用技能
Clojure学习笔记(一):数据结构
WuChong · 2015-11-06 · via Jark's Blog

发表于   |   分类于 编程语言   |  

最近学习了Clojure,好记性不如烂笔头,把一些知识点记录了下来。原本想放在一篇文章里的,谁知太长了,只好分成了三篇,本文是第一篇。由于是笔记,比较杂乱,建议阅读前先系统地学习Clojure(比如 Clojure - Function Programming for JVM),然后用本笔记知识梳理。

概述

Clojure是一个动态类型的,运行在JVM(JDK5.0以上),并且可以和java代码互操作的函数式语言。这个语言的主要目标之一是使得编写一个有多个线程并发访问数据的程序变得简单。

Clojure的发音和单词closure是一样的。Clojure之父是这样解释Clojure名字来历的

“我想把这就几个元素包含在里面: C (C#), L (Lisp) and J (Java). 所以我想到了 Clojure, 而且从这个名字还能想到closure;它的域名又没有被占用;而且对于搜索引擎来说也是个很不错的关键词,所以就有了它了.”

基本类型

Boolean

true, false

常用函数:

  1. not
  2. and
  3. or

Nil

nil,只有false与nil会被计算为false,其它的都为true

常用函数:

  1. nil?

Character

字符的表示要在前面加反斜杠 \a \b \c

Number

数字1, 2

常用函数:

  1. +, -, *
  2. /(分数形式),quot(商),rem(余数)
  3. inc,dec
  4. min, max
  5. =,<,<,>,>=
  6. zero?,pos?,neg?,number?

String

字符串,如 “hello”

常用函数

  1. str: 拼接多个字符串
  2. subs: 子字符串(0为开始下标)
  3. string?

KeyWord

关键字,常用于Map中的key,:tag:doc

Symbol

变量名,一个命名空间中唯一。如(def x 1),就申请了一个'user/x的Symbol。

集合

list, vector, set, map

clojure中的任何变量都是不变的,当对一个变量进行修改时,都会产生一个新的变量(clojure会使用共享内存的方式,只会消耗很小的内存代价)。有点像scala中的val哦。

  • count
    返回集合里面的元素个数

    (count [19 "yellow" true]) ; -> 3
  • reverse
    把集合里面的元素反转

    (reverse [1 2 3]) ; -> (3 2 1)
  • map
    对一个集合内的每个元素都调用一个指定的方法。每个元素调用方法后的返回值再构成一个新的集合返回。

    ; 使用匿名函数对每个元素加3
    (map #(+ % 3) [2 4 7]) ; -> (5 7 10)
    ; 函数可以有多个参数,则指定多个集合,执行次数取决于个数最少的集合长度
    (map + [2 4 7] [5 6] [1 2 3 4]) ; -> (8 12)
  • apply
    把集合里的所有元素都作为函数参数做一次调用,并返回这个函数的返回值。

    (apply + [2 4 7]) ; -> 13
  • conj & cons
    conj (conjoin), 添加一个元素到集合里面去。如果是list类型,则新元素插到队头;如果是vector类型,则新元素插到队尾。

    cons (construct),也是添加一个元素到集合里面去。只不过新元素都会在队头。返回类型都会变成seq。

    ; 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 5) ; -> [1 2 3 4 5]
    (conj '(1 2 3) 4 5 6) ; -> (6 5 4 1 2 3)

常用的集合操作

;从集合中取一个元素
(def stooges ["Moe" "Larry" "Curly" "Shemp"]) (first stooges) ; -> "Moe"
(second stooges) ; -> "Larry"
(last stooges) ; -> "Shemp"

;从集合中取多个元素
(nth stooges 2) ; indexes start at 0 -> "Curly" (next stooges) ; -> ("Larry" "Curly" "Shemp") (butlast stooges) ; -> ("Moe" "Larry" "Curly") (drop-last 2 stooges) ; -> ("Moe" "Larry")
; 得到包含多于3个字符的名字.
(filter #(> (count %) 3) stooges) ; -> ("Larry" "Curly" "Shemp")
(nthnext stooges 2) ; -> ("Curly" "Shemp")

;一些谓词操作
(every? #(instance? String %) stooges) ; -> true
(not-every? #(instance? String %) stooges) ; -> false
(some #(instance? Number %) stooges) ; -> nil
(not-any? #(instance? Number %) stooges) ; -> true

Lists

Lists 相当于Java中的LinkedList。

  • 创建

    (def stooges (list "Moe" "Larry" "Curly"))
    (def stooges (quote ("Moe" "Larry" "Curly")))
    (def stooges '("Moe" "Larry" "Curly"))
  • some
    检测一个集合中是否包含某个元素,需要跟一个谓词函数和一个集合。

    (some #(= % "Moe") stooges) ; -> true
    (some #(= % "Mark") stooges) ; -> nil
    ;在Lists搜索一个元素是线性低效的,在set里搜索就容易且高效多了
    (contains? (set stooges) "Moe") ; -> true
  • into
    把两个集合里面的元素合并成一个新的大list

    (into [1 2] [3 4]) ; -> [1 2 3 4]
    (into '(1 2 3) '(4 5 6)) ; -> (6 5 4 1 2 3)

Vectors

类似于数组。这种集合对于从最后面删除一个元素,或者获取最后面一个元素是非常高效的(O(1))。这意味着对于向vector里面添加元素使用conj被使用cons更高效。

  • 创建

    (def stooges (vector "Moe" "Larry" "Curly"))
    (def stooges ["Moe" "Larry" "Curly"])
  • get
    获取vector里面指定索引的元素,从map中取value也是用的get。get 和 nth 有点类似。

    ; Usage: (get map key) , (get map key not-found)
    (get stooges 1 "unknown") ; -> "Larry"
    (get stooges 3 "unknown") ; -> "unknown"
  • assoc
    可以对 vectors 和 maps进行操作。替换指定索引的元素。

    (assoc stooges 2 "Shemp") ; -> ["Moe" "Larry" "Shemp"]
  • subvec
    获取一个给定vector的子vector。

      ; Usage: (subvec v start) , (subvec v start end)
    (subvec stooges 1) ; -> ["Larry" "Curly"]
    (subvec stooges 1 2) ; -> ["Larry"]
    ```

    ### Sets

    Sets 是一个包含不重复元素的集合。Clojure 支持两种不同的set: 排序的(sorted-set)和不排序的(hash-set)。

    - 创建

    ```clojure
    (def stooges (hash-set "Moe" "Larry" "Curly")) ; not sorted
    (def stooges #{"Moe" "Larry" "Curly"}) ; same as previous
    (def stooges (sorted-set "Moe" "Larry" "Curly"))
  • contains?
    是否包含某元素。可以操作在set和map上。

    (contains? stooges "Moe") ; -> true
    (contains? stooges "Mark") ; -> false

Sets 自己也可以作为一个函数。当以这种方式来用的时候,返回值要么是这个元素,要么是nil。 这个比起contains?函数来说更简洁。

(stooges "Moe") ; -> "Moe"
(stooges "Mark") ; -> nil
(println (if (stooges person) "stooge" "regular person"))
  • disj
    去掉给定的set里面的一些元素,返回一个新的set。

    (def more-stooges (conj stooges "Shemp")) ; -> #{"Moe" "Larry" "Curly" "Shemp"}
    (def less-stooges (disj more-stooges "Curly")) ; -> #{"Moe" "Larry" "Shemp"}

Maps

Maps 保存从key到value的a对应关系 — key和value都可以是任意对象。和set类似,map也分为排序的(sorted-hash)和不排序的(hash-map)。

  • 创建

    (def colors (hash-map :red 1, :yellow 9, :blue 4, :black 3)) 
    (def colors {:red 1, :yellow 9, :blue 4, :black 3})
    ; -> {:red 1, :yellow 9, :blue 4, :black 3} 语法糖,和上面的是一样的
    (def colors_sort (sorted-map :red 1, :yellow 9, :blue 4, :black 3))
    ; -> {:black 3, :blue 4, :red 1, :yellow 9} 可以看到这是排序了的

    Map可以作为它的key的函数,同时如果key是keyword的话,那么key也可以作为map的函数。下面是三种获取:red所对应的值的方法。

    (get colors :red)
    (colors :green)
    (:red colors)
  • contains? & keys & vals
    contains? 用来检测某个key存不存在。keys 和 vals 可以获得map中的键集合和值集合。

    (contains? colos :red) ; -> true
    (keys colors) ; -> (:yellow :red :blue :black)
    (vals colors) ; -> (9 1 4 3)
  • assoc & dissoc
    assoc 会创建一个新的map,同时添加任意对新的key-value对, 如果某个给定的key已经存在了,那么它的值会被更新。

    dissoc 会创建一个新的map,同时去掉了给定的那些key。

    (assoc colors :red "red" :white "white")
    ; -> {:white "white", :yellow 9, :red "red", :blue 4, :black 3}
    (dissoc colors :red :white )
    ; -> {:yellow 9, :blue 4, :black 3}
  • 遍历
    遍历map可以使用宏doseq,把key bind到color, 把value bind到v。name函数返回一个keyword的字符串名字。

    (doseq [[color v] colors]
    (println (str "The value of " (name color) " is " v ".")))

输出为:

The value of yellow is 9.
The value of red is 1.
The value of blue is 4.
The value of black is 3.

或者使用Destructing

  • 内嵌
    map的值也可以是一个map。

    (def person {
    :name "Mark Volkmann"
    :address {
    :street "644 Glen Summit"
    :city "St. Charles"
    :state "Missouri"
    :zip 63304}
    :employer {
    :name "Object Computing, Inc."
    :address {
    :street "12140 Woodcrest Executive Drive, Suite 250"
    :city "Creve Coeur"
    :state "Missouri"
    :zip 63141}}})

为了获取这个人的employer的address的city的值,我们一般有三种方法。

; 使用get-in函数
(get-in person [:employer :address :city])
; 宏 -> 本质上是调用一系列的函数,前一个函数的返回值作为后一个函数的参数.
(-> person :employer :address :city)
; reduce 函数接收一个需要两个参数的函数, 一个可选的value以及一个集合。
(reduce get person [:employer :address :city])

修改一个内嵌的key值,我们可以使用assoc-in或者update-in,不同之处在于update-in的新值是通过一个给定的函数来计算出来的。

(assoc-in person [:employer :address :city] "Clayton")
(update-in person [:employer :address :zip] str "-1234") ; :zip "63141-1234"

StructMaps

StructMaps 和普通map类似,它的作用其实是用来模拟java里面的javabean。

  • 定义

    (def vehicle-struct (create-struct :make :model :year :color))
    (defstruct vehicle-struct :make :model :year :color) ; 简洁的写法
  • 实例化

    使用struct函数实例化一个StructMap对象,相当于java里面的new关键字。提供给struct的参数的顺序必须和定义时提供的keyword的顺序一致,后面的参数可以忽略。如果忽略,那么对应key的值就是nil。

    (def vehicle (struct vehicle-struct "Toyota" "Prius" 2009))
  • accessor
    accessor 函数可以创建一个类似java里面的getXXX的方法, 它的好处是可以避免hash查找, 它比普通的hash查找要快。

    (def make (accessor vehicle-struct :make)) ; 注意使用的是def而不是defn
    (make vehicle) ; -> "Toyota"
    (vehicle :make) ; 效果一样只是慢些
    (:make vehicle) ; 效果一样只是慢些

hoxis wechat