Clojure经典实例(txt+pdf+epub+mobi电子书下载)


发布时间:2020-10-14 17:33:54

点击下载

作者:范德哈特(Luke VanderHart) 诺伊费尔德(Ryan Neufeld)

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Clojure经典实例

Clojure经典实例试读:

前言

本书的首要目标是提供中等长度的 Clojure 代码示例,超越基本知识,关注真实世界的日常应用程序(而不是概念或学术问题)。

与此前的许多其他 Clojure 书籍不同,本书的主题不是语言本身,或它的功能和能力。本书关注开发者面对的具体任务(不论他们使用哪种编程语言),展示如何用 Clojure 来解决这些具体问题。

因此,本书确实不是也做不到包罗万象,因为可能的问题示例有无限多个。但是,我们希望记录大多数程序员会经常遇到的一些比较常见的问题。通过归纳,读者将能够学到一些常见的模式、方法和技术,有助于他们为自己面对的问题设计解决方案。本书如何写成

关于本书,你要了解一件重要的事情:它首先是团队协作的成果。它不是由一两个人写成的,甚至不是一个确定好的团队的成果。相反,它是 60 多个最优秀的 Clojure 程序员协作的结果,他们来自世界各地、各行各业。这些作者每天都在真实的场景中使用 Clojure:从航空航天到社交媒体,从银行业到机器人,从 AI 研究到电子商务。

因此,你会在提供的实例中看到许多差异。有些快速而简要,有些则内容更为丰富,针对 Clojure 的基本原理和实现提供了易于理解的深刻洞见。

我们希望兴趣各异的读者都能从本书中有所获。我们相信,它的用处不仅在于查找具体问题的解决方案,也在于考察 Clojure 能够提供的各种表达能力。在编辑提交的内容时,我们非常吃惊地发现很多概念和技术对我们来说也是新的,希望对读者来说也是新的。

我们在写作和编辑时还发现,要确定我们想介绍的内容的范围是一件很难的事情。每个实例都很棒,可以无限细分,进而涉及多个话题,而每个话题又值得写一个实例、一章甚至一本书。但每个实例也需要保持独立。每个实例应该提供一些有用的、有价值的信息,让读者可以理解并消化。

我们真诚地希望自己很好地平衡了这些目标,也希望你觉得这本书有用而不乏味,内容深刻而不是艰深难懂。读者对象

我们希望所有使用 Clojure 的人都能从本书中学到一些东西。有许多实例介绍的是真正基础的内容,初学者会觉得有用,但还有许多实例探讨的是专业话题,高级开发者会觉得有用,有助于他们开始实践。

但如果你是 Clojure 新手,这可能不是你要看的第一本书,至少不要只看这本书。本书介绍了许多有用的话题,但不像优秀的入门教材那样系统或完整。下面列出了一般的 Clojure 书籍,将它们作为前导教材或补充教材会很有帮助。其他资源

本书内容并不全面,也永远不可能全面。有许多内容要讲,并且由于采用了面向任务的实例,自然就排除了有条理、叙述式地解释整个语言的特点和能力。

要更线性、彻底地了解 Clojure 及其特点,我们推荐下面的书。● 《Clojure 编程:Java 世界的 Lisp 实践》(O'Reilly,2012),

作者是 Chas Emerick、Brian Carper 和 Christophe Grand。这是

一本全面的、用于一般目的的 Clojure 好书,关注语言和常见任

务,面向 Clojure 的初学者。● 《Clojure 程序设计(第 2 版)》(Pragmatic Bookshelf,

2012),作者是 Stuart Halloway 和 Aaron Bedra。这是第一本关

于 Clojure 的书,为 Clojure 语言提供了清晰全面的介绍和指

导。● Practical Clojure(Apress,2010),作者是 Luke

VanderHart 和 Stuart Sierra。它简明扼要地解释了 Clojure 是什

么,它的特点是什么。● 《Clojure 编程乐趣》(Manning,2011),作者是 Michael

Fogus 和 Chris Houser。这是一本比较高级的教材,真正深入到

Clojure 的主题和原理。● ClojureScript: Up and Running(O'Reilly,2012),作者是

Stuart Sierra 和 Luke Vander Hart。虽然本书和这里列出的其他

Clojure 书籍主要或全部在探讨 Clojure 本身,但

ClojureScript(一种 Clojure 方言,能编译成 JavaScript)已经得

到了相当的发展。这本书介绍了 ClojureScript,以及如何使用它,

并探讨了 ClojureScript 和 Clojure 之间的相似与不同。

最后,你应该看看本书的源代码,它们可以从 GitHub 自由下载(https://github.com/clojurecookbook/clojure-cookbook">https://github.com/clojurecookbook/clojure-cookbook)。网上选择的实例比印刷版本更多,我们仍在接受新实例的“拉取请求”(pull request),也许某天会加入本书的下一版。本书结构

本书的章节主要是依据主题对实例进行分组,而不是严格的分类。一个实例完全有可能适用于不止一个章节,在这种情况下,我们试着根据我们的猜测,将它放在大部分读者首先会去寻找的地方。

实例包含三个主要部分和一个次要部分:问题、解决方案、讨论和参阅。实例的问题陈述提出了任务或要克服的障碍。它的解决方案解决了问题,展示了特定的技术或库,能够高效地完成该任务。讨论完善了相关知识,探讨了解决方案和相关注意事项。最后,参阅部分向读者指出了一些附加的资源或相关实例,帮助你采用描述的解决方案。各章简介

本书由以下几章构成。● 第 1 章“原生数据”和第 2 章“复合数据”介绍了 Clojure

内建的原生和复合数据结构,解释了许多常见的(以及不太常见

的)使用方式。● 第 3 章“广义计算”包含了一些有用的主题,广泛适用于

许多不同的应用领域和项目,从协议这样的 Clojure 特征,到可

选的编程范式,例如用 core.logic 实现逻辑编程,或用

core.async 实现异步协作。● 第 4 章“本地 I/O”包含了程序在运行时与本地计算交互的

所有方式。这包括读写标准输入输出流,创建并操作文件,序列

化和反序列化文件等。● 第 5 章“网络 I/O 和 Web 服务”包含了类似第 4 章的主

题,但探讨的是通过网络的远程通信。它包括的实例涉及各种网

络通信协议和库。● 第 6 章“数据库”展示了连接和使用各种数据库的技术和

工具。特别关注了 Datomic 数据库,它共享了 Clojure 背后关于

值、状态和标识的哲学,并扩展到了持久存储的领域。● 第 7 章“Web 应用”深入探讨了 Clojure 最常见的应用领

域:构建和维护动态网站。它全面介绍了 Ring(Clojure 中最流

行的 HTTP 服务器库),以及 HTML 模板和渲染的工具。● 第 8 章“性能与开发效率”解释了拥有 Clojure 程序之后还

需要做些什么,介绍了打包、分发、性能剖析、日志的常见模式,

将正在进行的任务与应用的生命周期关联起来。● 第 9 章“分布式计算”关注云计算以及在重量级分布式数

据处理中使用 Clojure。特别关注了 Cascalog,它是一个声明式

Clojure 接口,面向 Hadoop MapReduce 框架。● 最后但同样重要的是第 10 章“测试”介绍了各种技术,来

确保代码和数据的完整性和正确性:从传统的单元测试和集成测

试,到更全面的产生式测试和模拟测试,甚至还有可选的编译时

验证,利用 core.typed 实现静态类型。软件获取

若要按照本书的实例操作,你需要正确安装 Java 开发工具(JDK)和 Clojure 事实上的构建工具 Leiningen。我们推荐第 7 版 JDK,但至少需要第 6 版。对于 Leiningen,至少是第 2.2 版。

如果你还没安装 Java(或者希望升级),请访问 Java 下载页面(http://www.oracle.com/technetwork/java/javase/downloads/index.htmlhttp://www.oracle.com/technetwork/java/javase/downloads/index.html),按提示下载并安装 Java JDK。

要安装 Leiningen,请遵循 Leiningen 网站(href="http://leiningen.org/">http://leiningen.org/)的安装指南。如果已经安装了 Leiningen,通过执行 lein upgrade 命令来取得最新版本。如果不熟悉 Leiningen,请访问使用指南(https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.mdhttps://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md),了解更多信息。

你不需要手工安装的就是 Clojure 本身,因为 Leiningen 将随时根据需要,替你安装。要验证安装,就运行 lein repl 来检查 Clojure 的版本:$ lein repl# ...user=> *clojure-version*{:major 1, :minor 5, :incremental 1, :qualifier nil} 某些实例在 GitHub 上提供了一些在线材料。如果你的系统上没有安装 Git,请按照安装指南(https://help.github.com/articles/set-up-githttps://help.github.com/articles/set-up-git)操作,以便能将 GitHub 代码库签出到本地。

某些实例(如数据库实例),需要进一步安装软件。在这种情况下,实例将包含安装工具的额外信息。本书约定

在这本全是解决方案的书中,你会发现其中有不少代码。Clojure 源代码使用等宽字体,像这样:(defn add [x y] (+ x y))

如果 Clojure 表达式被求值并返回,该值将以注释的形式给出,跟在一个箭头后面,就像它出现在命令行中一样:(add 1 2);; -> 3

在合适的时候,代码示例可能略去或省略返回值注释。最常见的两种情况就是在定义函数 /var 时和缩短较长的输出时:;; 这会返回#'user/one,但你真的关心吗?(def one 1)(into [] (range 1 20));; -> [1 2 ... 20]

如果表达式产生输出到 STDOUT 或 STDERR,就会有注释说明(分别用 *out* 或 *error*),跟着就是每行输出的注释:(do (println "Hello!")(println "Goodbye!"));; -> nil;; *out*;; Hello!;; Goodbye!REPL会话

看到 REPL 驱动开发目前正在流行,因此本书就成为了 REPL 驱动的。REPL(读取、求值、打印、循环)是交互式的提示符,对表达式求值并打印出结果。Bash 提示符、irb 和 python 提示符都是 REPL 的例子。本书中几乎每个实例,都是为在 Clojure REPL 中运行而设计的。

虽然 Clojure REPL 传统上显示为 user=> ...,但本书希望读者能够复制粘贴实例中所有的例子,并看到标示的结果。因此,例子中省略了 user=> 并以注释的方式给出了输出,让事情变得更容易。如果你在计算机旁,这就特别有帮助:只要复制粘贴代码示例,不用担心遇到不能执行的代码。

如果例子只适用于 REPL 的环境,我们将保留传统的 REPL 风格(带上 user=>)。下面两个例子分别是只适用于 REPL 的例子和它的简化版本。

只适用于 REPL:user=> (+ 1 2)3user=> (println "Hello!")Hello!nil

简化版本:(+ 1 2);; -> 3(println "Hello!");; *out*;; Hello!控制台/终端会话

控制台会话(例如,shell 命令)用等宽字体表示,行开始的美元符号($)表示 shell 提示符。输出打印前面没有($):$ lein versionLeiningen 2.0.0-preview10 on Java 1.6.0_29 Java HotSpot(TM) 64-Bit Server VM

命令行末的反斜杠(\)告诉控制台,命令将在下一行继续。我们的金童 lein-tryClojure 不以它的扩展标准库而闻名。不像 Perl 或 Ruby 这样的语言,Clojure 的标准库相对比较小。Clojure 选择了简单和强大。因此 Clojure 是一种有许多库的语言,但不是内建的库(好吧,Java 除外)。因为本书中这么多解决方案都依赖于第三方库,所以我们开发了 lein-try(https://github.com/rkneufeld/lein-tryhttps://github.com/rkneufeld/lein-try)。Leiningen 是 Clojure 事实上的项目工具,lein-try 是 Leiningen(http://leiningen.org/http://leiningen.org/)的一个小插件,让你快速而容易地尝试各种 Clojure 库。要使用 lein-try,请确保安装了 Leiningen,然后将你的用户特性描述文件(~/.lein/profiles.clj)编辑成下面的样子:{:user {:plugins [[lein-try "0.4.1"]]}}现在,在项目内外都可以使用 lein try 命令来启动 REPL,访问任何你喜欢的库:$ lein try clj-time#...user=>长话短说:只要可能,在用第三方库的实例中,你会看到要求执行 lein-try 命令。在 3.4 节中,有一个用 lein-try 尝试实例的例子。如果实例不能通过 lein-try 运行,我们会努力提供足够的指令,说明如何在你的机器上运行该实例。排版约定

本书使用下面的字体约定。● 楷体新术语第一次出现时使用楷体,目的是强调。● 等宽字体用于函数名、方法名和参数,用于数据类型、类和命名空间,

在例子中表示输入和输出,在正则文本中表示字面代码。● 等宽黑体用于表示命令,你应该在命令行中照样输入。● < 可取代的值 >路径、命令、函数名中的元素,应该由用户提供的值来取代

尖括号及其中的内容。

库的名称符合两种惯例之一:具有适当名称的库用普通字体(如 Hiccup 或 Swing),而名称与代码符号相似的库用等宽字体(如 core.async 或 clj-commons-exec)。这个符号表示提示或建议。这个符号表示一般注释。这个符号表示警告或注意。使用代码示例

补充材料(代码示例、练习等)可以在 https://github.com/clojure-cookbook/clojure-cookbookhttps://github.com/clojure-cookbook/clojure-cookbook 下载。

本书的目的是帮助你完成工作。一般来说,如果示例代码出现在本书中,就可以在你的程序和文档中使用它,不需要联系我们获得许可,除非你打算复制大量的代码。例如,写一个程序,用到本书中的几段代码,不需要获得许可。而销售或分发 O'Reilly 图书的示例 CD-ROM,确实需要许可。回答问题时摘录本书并引用示例代码,不需要获得许可。在你的产品文档中包含本书的大量示例代码,则确实需要许可。

我们感谢你说明来源,但这不是必须的。来源说明通常包括标题、作者、出版商和 ISBN。例如:“Luke VanderHart 和 Ryan Neufeld 所著 Clojure Cookbook (O'Reilly). Copyright 2014 Cognitect, Inc., 978-1-449-36617-9.”

如果你觉得你对代码的使用超出了合理的范围或上述允许的情况,可随时联系我们:permissions@oreilly.com.®Safari Books Online

Safari Books Online(http://www.safaribooksonline.comhttp://www.safaribooksonline.com)是应运而生的数字图书馆。它同时以图书和视频的形式出版世界顶级技术和商务作家的专业作品。技术专家、软件开发人员、Web 设计师、商务人士和创意专家等,在开展调研、解决问题、学习和认证培训时,都将 Safari Books Online 视作获取资料的首选渠道。对于组织团体、政府机构和个人,Safari Books Online 提供各种产品组合和灵活的定价策略。用户可通过一个功能完备的数据库检索系统访问 O'Reilly Media、Prentice Hall Professional、Addison-Wesley Professional、Microsoft Press、Sams、Que、Peachpit Press、Focal Press、Cisco Press、John Wiley & Sons、Syngress、Morgan Kaufmann、IBM Redbooks、Packt、Adobe Press、FT Press、Apress、Manning、New Riders、McGraw-Hill、Jones & Bartlett、Course Technology 以及其他几十家出版社的上千种图书、培训视频和正式出版之前的书稿。要了解 Safari Books Online 的更多信息,我们网上见。联系我们

请把对本书的意见和疑问发送给出版社。

美国:

O'Reilly Media, Inc.

1005 Gravenstein Highway North

Sebastopol, CA 95472

中国:

北京市西城区西直门南大街 2 号成铭大厦 C 座 807 室(100035)

奥莱利技术咨询(北京)有限公司

O'Reilly 的每一本书都有专属网页,你可以在那儿找到本书的相关信息,包括勘误表、示例代码以及其他信息。本书的网站地址是:

http://oreil.ly/clojure-ckbkhttp://oreil.ly/clojure-ckbk

对于本书的评论和技术性问题,请发送电子邮件到:bookquestions@oreilly.com

要了解更多 O'Reilly 图书、培训课程、会议和新闻的信息,请访问以下网站:

http://www.oreilly.comhttp://www.oreilly.com

我们在 Facebook 的地址如下:http://facebook.com/oreillyhttp://facebook.com/oreilly

请关注我们的 Twitter 动态:http://twitter.com/oreillymediahttp://twitter.com/oreillymedia

我们的 YouTube 视频地址如下:http://www.youtube.com/oreillymediahttp://www.youtube.com/oreillymedia致谢

如果没有 Clojure 社区中许多人的无私奉献,本书不可能写成。超过 65 个 Clojure 开发者响应号召,提交实例,审读,并为本书的方向提供了建议。归根到底,这是一本属于社区的书,我们只是很荣幸能够将内容组织到一起。这些贡献者是:● Adam Bard,adambard on GitHub● Alan Busby,thebusby on GitHub● Alex Miller,puredanger on GitHub● Alex Petrov,ifesdjeen on GitHub● Alex Robbins,alexrobbins on GitHub● Alex Vzorov,0rca on GitHub● Ambrose Bonnaire-Sergeant,frenchy64 on GitHub● arosequist● Chris Allen,bitemyapp on GitHub● Chris Ford,ctford on GitHub● Chris Frisz,cjfrisz on GitHub● Clinton Begin,cbegin on GitHub● Clinton Dreisbach,cndreisbach on GitHub● Colin Jones,trptcolin on GitHub● Craig McDaniel,cpmcdaniel on GitHub● Daemian Mack,daemianmack on GitHub● Dan Allen,mojavelinux on GitHub● Daniel Gregoire,semperos on GitHub● Dmitri Sotnikov,yogthos on GitHub● Edmund Jackson,ejackson on GitHub● Eric Normand,ericnormand on GitHub● Federico Ramirez,gosukiwi on GitHub● Filippo Diotalevi,fdiotalevi on GitHub● fredericksgary● Gabriel Horner,cldwalker on GitHub● Gerrit,gerritjvv on GitHub● Guewen Baconnier,guewen on GitHub● Hoàng Minh Th ng,myguidingstar on GitHub● Jason Webb,bigjason on GitHub● Jason Wolfe,w01fe on GitHub● Jean Niklas L'orange,hyPiRion on GitHub● Joey Yang,joeyyang on GitHub● John Cromartie,jcromartie on GitHub● John Jacobsen,eigenhombre on GitHub● John Touron,jwtouron on GitHub● Joseph Wilk,josephwilk on GitHub● jungziege● jwhitlark● Kevin Burnett,burnettk on GitHub● Kevin Lynagh,lynaghk on GitHub● Lake Denman,ldenman on GitHub● Leonardo Borges,leonardoborges on GitHub● Mark Whelan,mrwhelan on GitHub● Martin Janiczek,Janiczek on GitHub● Matthew Maravillas,maravillas on GitHub● Michael Fogus,fogus on GitHub● Michael Klishin,michaelklishin on GitHub● Michael Mullis,mmullis on GitHub● Michael O'Church,michaelochurch on GitHub● Mosciatti S.,siscia on GitHub● nbessi● Neil Laurance,toolkit on GitHub● Nurullah Akkaya,nakkaya on GitHub● Osbert Feng,osbert on GitHub● Prathamesh Sonpatki,prathamesh-sonpatki on GitHub● R. T. Lechow,rtlechow on GitHub● Ravindra R. Jaju,jaju on GitHub● Robert Stuttaford,robert-stuttaford on GitHub● Russ Olsen,russolsen on GitHub● Ryan Senior,senior on GitHub● Sam Umbach,sumbach on GitHub● Sandeep Nangia,nangia on GitHub● Steve Miner,miner on GitHub● Steven Proctor,stevenproctor on GitHub● temacube● Tobias Bayer,codebrickie on GitHub● Tom White,dribnet on GitHub● Travis Vachon,travis on GitHub● Stefan Karlsson,zclj on GitHub

最大的贡献者值得特别感谢:Adam Bard、Alan Busby、Alex Robbins、Ambrose BonnaireSergeant、Dmitri Sotnikov、John Cromartie、John Jacobsen、Robert Stuttaford、Stefan Karlsson 和 Tom Hicks。这些杰出的开发者一起几乎贡献了本书三分之一的实例。

感谢我们的技术复查者 Alex Robbins、Travis Vachon 和 Thomas Hicks。在大约 11 个小时或更短的时间内,这几位先生查遍了本书,寻找技术错误。普通的技术复查者只会提交文本的问题描述,这几位则做得更多,常常提交拉取请求(pull request),修复了他们报告的所有错误。总之,和他们一起工作很开心,因为他们的参与,本书变得好了很多。

最后,感谢我们的雇主 Cognitect,让我们有时间完成本书,同时感谢所有的同事,他们提出了建议和反馈,而且最棒的是,他们提供了更多的实例!Ryan Neufeld

首先,非常感谢 Luke,是他最先提出了这本书的主意。我非常感激他邀请我加入,一起编写。人们说学习某样东西最好的方法就是写一本关于它的书,此言不虚。编写这本书确实丰富了我的 Clojure 技能,使我的水平提升到了另一个层次。

而且最重要的是,我要感谢家人,他们容忍我完成写书的过程。让这件事顺利起步是无比艰巨的任务,没有妻子 Jackie 和女儿 Elody 的爱和支持,这不可能完成。如果不是侵占了她们无数的夜晚、周末和休假时间,我不可能编写完这本书。Luke VanderHart

首先,我要感谢合著者 Ryan,他工作非常努力,参与编写了这本书。

同时,我在 Cognitect 的同事提供了许多想法和思路,最重要的是有一个很好的委员会,探讨在编写和编辑过程中出现的许多问题。非常感谢他们,同时也感谢他们提供机会,让我整天写 Clojure 代码,天天如此。第 1 章原生数据1.0 简介

对于处理困难的问题,Clojure 是一门极好的语言。它的简单工具让软件开发者一层一层地建立抽象,直到能够轻松地处理世界上最难的一些问题。像化学一样,每个了不起的 Clojure 程序都归结为简单的原子,即原生类型。

很久以前,Clojure 就站在 Java 巨人的肩上,它利用了 Java 虚1拟机(JVM) 中提供的一组极好的类型,这些类型经过了实践的检验:字符串、数值类型、日期、通用唯一标识符(UUID),只要说得出的,Clojure 都有。本章探讨 Clojure 的原生类型,以及如何完成常见任务。

1JVM 是执行 Java 字节码的地方。Clojure 编译器以 JVM 为目标,生成能运行的字节码。因此,你可以任意使用所有原生 Java 类型。字符串

几乎所有编程语言都知道如何处理字符串,Clojure 也不例外。除了一些差别之外,Clojure 提供了像大多数其他语言一样的能力。下面是一些应该了解的关键差别。

首先,Clojure 字符串基于 Java 的 UTF-16 字符串。不需要在文件中添加注释来说明字符串的编码方式,也不需要担心在转换过程中丢失了字符。Clojure 程序已经准备好与英文字符之外的世界通信。

其次,Clojure 不像 Perl 或 Ruby 拥有较大的字符串程序库,其内建的字符串操作库相当精练。初看起来这可能有点奇怪,但 Clojure 喜欢简单的、可组合的工具,Clojure 中有许多集合操作函数,都能很好地处理字符串,因为它们也是集合!由于这个原因,Clojure 的字符串库小得出人意料。在 clojure.string 命名空间中,可以找到很小一组专门针对字符串的函数。

Clojure 也利用了它的宿主平台(JVM),没有重复 java.lang.String 类已实现的功能。在 Clojure 中使用 Java 互操作并不是一种失败的尝试,因为语言的设计就是为了便于互操作,使用内建的字符串方法通常和调用 Clojure 的函数一样方便。

我们建议在必要的时候,“require as”clojure.string 命名空间。2盲目地 :use 一个命名空间总是令人气恼的 ,常常导致冲突或混乱。所以我们更喜欢给它取别名为 str 或 s,而非在所有东西前面加上 clojure.string,那有点奇怪:

2用了 use,就在项目的命名空间中引入了许多新的符号,又没有留下线索表明它们来自哪里。这通常让代码维护者感到困惑和沮丧。我们强烈建议不要用 use。(require '[clojure.string :as str])(str/blank? "");; -> true数值类型

对于数值类型,Clojure 和 Java 之间的差异比较大。但这不一定是坏事。虽然 Java 的数值类型可能非常快或具有任意的精度,但数值整体上没有一组精美的接口。Clojure 把 Java 的各种数值类型统一成为一致的包,每个困难的地方都有解决的办法。

本章中关于数值类型的实例,将展示如何利用这些设计,实现期望的速度、精度或表达能力。日期

在 Java 生态系统中,日期和时间的历史长而曲折。需要 Date、Time、DateTime 或 Calendar 吗?谁知道呢。为什么这些 API 都那么不稳定?本章中的实例应该能够阐明何时使用恰当的内建类型,如何使用,以及若内建类型不够用(或者非常难用),何时去寻找外部库。1.1 改变字符串的大小写

作者:Ryan Neufeld问题

需要改变一个字符串的大小写。解决方案

用 clojure.string/capitalize 来大写字符串中的第一个字符。(clojure.string/capitalize "this is a proper sentence.");; -> "This is a proper sentence."

如果需要改变所有字符的大小写,请用 clojure.string/lower-case 或 clojure.string/upper-case:(clojure.string/upper-case "loud noises!");; -> "LOUD NOISES!"(clojure.string/lower-case "COLUMN_HEADER_ONE");; -> "column_header_one"讨论

大小写函数只影响字母。虽然函数 capitalize、lower-case 和 upper-case 可能会改动字母,但标点符号或数字会保持不变:(clojure.string/lower-case "!&$#@#%^[]");; -> "!&$#@#%^[]"

Clojure 对所有字符串都使用 UTF-16 编码,因此它对什么是字母的定义是相当宽泛的,包括有重音的字母。例如短句“Hurry up, computer!”,它包含字母 e,翻译成法语时会有锐音(é)和长音(ê)记号。由于这些特殊的字符都被视为字母,大小写函数可以对它们进行相应的改变:(clojure.string/upper-case "Dépêchez-vous, l'ordinateur!");; -> "DÉPÊCHEZ-VOUS, L'ORDINATEUR!"参阅● clojure.string 命名空间的 API 文档(http://clojure.github.io/

clojure/clojure.string-api.htmlhttp://clojure.github.io/clojure/

clojure.string-api.html)。● java.lang.String 的 API 文档(http://docs.oracle.com/

javase/7/docs/api/java/lang/String.htmlhttp://docs.oracle.com/

javase/7/docs/api/java/lang/String.html)。1.2 清除字符串中的空白字符

作者:Ryan Neufeld问题

需要清除字符串中的空白字符。解决方案

使用 clojure.string/trim 函数来删除字符串首尾的所有空白字符:(clojure.string/trim " \tBacon ipsum dolor sit.\n");; -> "Bacon ipsum dolor sit."

要处理字符串内部的空白字符,需要有点创造性。使用 clojure.string/replace 来修正字 符串内部的空白字符:;; 将空白字符压缩为一个空格(clojure.string/replace "Who\t\nput all this\fwhitespace here?" #"\s+" " ");; -> "Who put all this whitespace here?";; 将Windows 风格的换行替换成Unix 风格的换行(clojure.string/replace "Line 1\r\nLine 2" "\r\n" "\n");; -> "Line 1\nLine 2"讨论

什么构成了 Clojure 中的空白字符?回答取决于功能:有些比另一些更自由,但可以放心地假定空格( )、制表符(\t)、换行(\n)、回车(\r)、走行(\f)和垂直制表符(\x0B)都会被当成空白字符。在 Java 的正则表达式实现中,这一组字符由 \s 匹配。

Ruby 和其他语言将字符串操作函数放在核心命名空间,Clojure 不同,它将 clojure.string 命名空间放在 clojure.core 之外,因此不能够直接使用。常用的技巧是将 clojure.string 引入为 str 或 string 这样的简写形式,让代码更简明:(require '[clojure.string :as str])(str/replace "Look Ma, no hands" "hands" "long namespace prefixes");; -> "Look Ma, no long namespace prefixes"

有时候,也许不需要把字符串两边的空白字符都删掉。如果只是想删除字符串左边或右边的空白字符,请分别使用 clojure.string/triml 或 clojure.string/trimr。(clojure.string/triml " Column Header\t");; -> "Column Header\t"(clojure.string/trimr "\t\t* Second-level bullet.\n") ,;; -> "\t\t* Second-level bullet."参阅● 1.3 节“利用部件构建字符串”。1.3 利用部件构建字符串

作者:Ryan Neufeld问题

有多个字符串、值或集合,需要合并成一个字符串。解决方案

使用 str 函数来连接多个字符串和(或)值:(str "John" " " "Doe");; -> "John Doe";; str 也适用于变量,或其他任何值(def first-name "John")(def last-name "Doe")(def age 42)(str last-name ", " first-name " - age: " age);; -> "Doe, John - age: 42"

使用 apply 带 str,将值的集合连接成一个字符串:;; 将一系列字符还原成一个字符串(apply str "ROT13: " [\W \h \y \v \h \f \ \P \n \r \f \n \e]);; -> "ROT13: Whyvhf Pnrfne";; 或者将一些行还原成一个文件(如果行都有换行符)(def lines ["#! /bin/bash\n", "du -a ./ | sort -n -r\n"])(apply str lines);; -> "#! /bin/bash\ndu -a ./ | sort -n -r\n"讨论

Clojure 的 str 就像一个好的 Unix 工具:它做一件事,做得很好。如果向 str 提供一个或多个参数,它会对参数调用 Java 的 .toString() 方法,将每个结果加在后面。如果提供 nil 作为参数或不带参数调用,str 会返回代表字符串身份的值,即空串。

对于字符串连接,Clojure 采用了相当自由的方式。(apply str ...)没有什么专门针对字符串的东西。它只是使用了高阶函数 apply,模拟用变长参数调用 str。

这个 apply:(apply str ["a" "b" "c"])

在功能上等价于:(str "a" "b" "c")

既然 Clojure 在连接字符串时没有什么限制,我们就可以自由发挥,利用 Clojure 提供的大量操作函数。例如,从一行抬头和几行数据中构造逗号分隔的值(CSV)。这个例子特别适合 apply,因为可以在前面加上抬头,不用将它插在 rows 集合的前面:;; 利用一行抬头字符串和几行数据来构造CSV(def header "first_name,last_name,employee_number\n")(def rows ["luke,vanderhart,1","ryan,neufeld,2"])(apply str header (interpose "\n" rows));; -> "first_name,last_name,employee_number\nluke,vanderhart,1\nryan,neufeld,2"

如果要做的事情不是太特别,apply 和 interpose 可能有些繁琐。要连接简单的字符串,通常用 clojure.string/join 更容易。join 函数接受一个集合和一个可选的分隔符。带分隔符时,join 返回的字符串是集合的所有元素,中间用该分隔符分隔。不带分隔符时,它返回所有元素挤在一起的字符串,类似于(apply str coll)的返回:(def food-items ["milk" "butter" "flour" "eggs"])(clojure.string/join ", " food-items);; -> "milk, butter, flour, eggs"(clojure.string/join [1 2 3 4]);; -> "1234"参阅● 1.6 节“格式化字符串”。● clojure.string 命名空间的 API 文档(http://clojure.github.io/

clojure/clojure.string-api.htmlhttp://clojure.github.io/clojure/

clojure.string-api.html)。● java.lang.String 的 API 文档(http://docs.oracle.com/

javase/7/docs/api/java/lang/String.htmlhttp://docs.oracle.com/

javase/7/docs/api/java/lang/String.html)。1.4 将字符串作为字符序列

作者:Ryan Neufeld问题

需要处理字符串中的单个字符。解决方案

对字符串使用 seq,得到它包含的字符序列:(seq "Hello, world!");; -> (\H \e \l \l \o \, \space \w \o \r \l \d \!)

但是,并非每次想处理字符串中的字符时,都要调用 seq。以序列为参数的所有函数,都会自动将字符串强制转换成字符序列:;; 计算每个字符在字符串中出现的次数(frequencies (clojure.string/lower-case "An adult all about A's"));; -> {\space 4, \a 5, \b 1, \d 1, \' 1, \l 3, \n 1, \o 1, \s 1, \t 2, \u 2};; 字符串中的每个字母都是大写的吗?(defn yelling? [s] (every? #(or (not (Character/isLetter %)) (Character/isUpperCase %)) s))(yelling? "LOUD NOISES!");; -> true(yelling? "Take a DEEP breath.");; -> false讨论

在计算机科学中,“字符串”意味着“字符序列”,Clojure 对字符串就是这么处理的。因为 Clojure 字符串背后就是字符序列,所以在需要集合的地方,都可以用字符串替代。如果这样做,字符串就会被解释为一个字符集合。(seq string) 没有什么特别的。seq 函数只是返回一个字符集合的序列,这些字符组成了这个字符串。

更常见的是,在对字符串中的字符做了某种工作之后,希望将这个集合恢复成一个字符串。对字符集合使用 apply 和 str,将它们还原成字符串:(apply str [\H \e \l \l \o \, \space \w \o \r \l \d \!]);; -> "Hello, world!"参阅● 1.3 节“利用部件构建字符串”。● 1.5 节“字符与整数的转换”。1.5 字符与整数的转换

作者:Ryan Neufeld问题

需要将字符转换成对应的 Unicode 编码值(整数值),或反过来。解决方案

用 int 函数将字符转换成它的整数值:(int \a);; -> 97(int \ø);; -> 248(int \a) ; 希腊字母alpha;; -> 945(int \u03B1) ; 希腊字母alpha(按编码值);; -> 945(map int "Hello, world!");; -> (72 101 108 108 111 44 32 119 111 114 108 100 33)

用 char 函数返回整数编码值对应的字符:(char 97);; -> \a(char 125);; -> \}(char 945);; -> \a(reduce #(str %1 (char %2)) "" [115 101 99 114 101 116 32 109 101 115 115 97 103 101 115]);; -> "secret messages"讨论

Clojure 继承了 JVM 强大的 Unicode 支持。所有字符串都是 UTF-16 字符串,所有字符都是 Unicode 字符。前面 256 个 Unicode 编码值与 ASCII 码相等,这很方便,让标准的 ASCII 文本很容易处理。但是,Clojure 像 Java 一样,没有对 ASCII 码进行任何特殊处理,字符和整数之间的一一对应表明,编码值直接延伸到整个 Unicode 空间。

例如,表达式 (map char (range 0x0410 0x042F)) 列出所有的斯拉夫语大写字母,它们处于 Unicode 的这个范围:(\А \Б \В \Г \Д \Е \Ж \З \И \Й \К \Л \М \Н \О \П \Р \С \Т \У \Ф \Х \Ц \Ч \Ш \Щ \Ъ \Ы \Ь \Э \Ю)

char 和 int 函数的主要用处,是将一个数字强制转换成 java.lang.Integer 或 java.lang.Character 的实例。Integer 和 Character 最终都是数字编码的,尽管 Character 还支持一些额外的文本相关方法,要先转换成真正的数字类型,才能用于数学表达式。参阅● Unicode Explained(http://oreil.ly/unicode-explainedhttp://

oreil.ly/unicode-explained), 作 者 Jukka K. Korpela (O'Reilly),

真正全面地探讨了 Unicode 和国际化的工作原理。● 1.4 节“将字符串作为字符序列”,详细讨论了处理构成字

符串的字符。● 1.15 节“解析数字”。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载