标签 Haskell 下的文章

翻译《七周七语言》的那些事儿

今天在互动出版网看到《七周七语言:理解多种编程范型》一书已经开卖了。看到自己参与翻译的第一本书出版了,心中还是很愉悦的,因为自己的辛苦付出终于有了结果。

一、缘起

能够参与到这本书的翻译完全是机缘巧合。记得2011年初我启动了一个《Programming in Haskell》的公共翻译项目,可是由于欠缺版权的考虑,中途不得不终止了该书的翻译。当时经dreamhead介绍联系到图灵刘江总编,希望人邮能 引进版权以促成该书的翻译,但刘总编考虑到该书是有关Haskell这门"小众"语言的,引进后受众面小,书很可能卖不出去,商业价值不高(后得知该书作 者Graham Hutton博士已经在与某出版社谈中文版版权的事宜了,并已经委托其一位同事进行中文版的翻译工作了)。不过刘总编说图灵当时已经引进了《Seven Languages in Seven Weeks》一书的中文版权,但第一译者戴玮因工作学习繁忙,可能无法按期完成全部翻译,问我是否愿意参与翻译。我的最初目标就是翻译一本英文技术书籍, 有这样的机会,而且书还可以在国内出版,于是我就欣然接下了这个翻译工作。

二、翻译过程

经过试译审核,顺利与图灵签订了翻译合同,我将负责翻译该书的PrologScalaHaskell三个章节。正式翻译是在2011年春节后开始的, 为了能在合同规定的第一个时间点交稿,我连续N天翻译到凌晨下半夜,工作日中午午休时间也在抓紧时间翻译,周末也不放松。因为是第一次翻译,生怕自己翻译 的不好,于是对原书中的每句话都字斟句酌,仔细揣摩。另外虽说此书是一本技术书籍,但作者给每门编程语言都赋予了一部电影中的典型人物角色,并用电影中的 情节或人物角色的特征作为章节的导引,这使得每章的开篇十分难于翻译,特别是当我不熟悉语言所对应的那部影片中的那个角色时,翻译更是举步维艰。为此,我 特意看了一遍"雨人(Rain Man)"和"星际旅行(Star Trek)",重温了"剪刀手爱德华(Edward Scissorhands)",为的就是能够更精确地定位本书作者所要表达的意思。Scala一章的第一稿提交后,我收到了图灵编辑不错的反馈。于是再接 再励,在2011年4月末交了全部初稿,5月中旬完成了中耕校对;2012年3月份完成排后稿的校对。

三、关于翻译方法和心得

这是我第一次参与翻译项目,说实在的真没有资格谈什么翻译方法,我也不是什么专业翻译人员。但在这本书的翻译过程中还是有若干经验和教训可以与大家分享的。

* 心态

我认识的参与过技术书籍翻译的朋友都说:翻译不是为了赚钱(那些以翻译为谋生手段的职业翻译除外),这点我深表认同。翻译工作是一件枯燥、辛苦甚至是费力 不讨好(出版后可能被拍砖)的工作。因此翻译前就要摆正心态,弄清楚自己为何要翻译,有了良好心态,才会有持续不断的动力,否则译着译着人就容易产生懈 怠,进度和质量都会下降,你需要这样一种战胜懈怠并持续下去的手段。

* 你是翻译质量的决定者

不要过于期望诸多编辑朋友会拿出百分百的时间对你的翻译内容进行校对,出版社的编辑们太忙了,一个人估计要至少负责10本以上书籍的出版工作,因此你才是翻译质量的决定者,从开始翻译的那一刻你就要保持高质量水准。

* 第一遍就要保持高质量,不要期待你能回头做二次翻译

第一遍翻译时,务必保证按顺序逐字逐句的高质量的翻译,一次到位;遇到难点也不要跳过,而是要集中精神搞定这个难点;否则你就会发现你积蓄的难点越来越 多,严重影响你后续翻译的情绪和心理。不要有回头做全面二次翻译的想法,因为你会发现那基本不可行,二次翻译时你会发现你的思路严重受制于第一次翻译的思 路,因此不仅不会提高什么质量,还会使你变得更加烦躁,严重影响翻译进度。

* 前后一致

保持前后章节的术语、句型等翻译的一致性。这点在翻译和校对时都要重点关注。

* 除了认真还是认真

不是所有人都是翻译天才,大部分译者,特别是技术书籍的译者,可能只是那个领域的从业人员(比如我),在翻译能力上存在不足。但万事就怕认真,认真可以尽量袮补在能力上不足,也是出品高质量译文的必要条件。

四、关于《七周七语言》一书

从本书的中文名字,你也许会将其与"21天学会C语言"之类的捷径书籍混为一谈,但本书的初衷与那些捷径书籍显然不同。本书意在让你在短时间内了解到多种 编程语言的范式和主要特性,并做简单的对比了解。书的作者也许并不期望你在看完某种语言后就彻底学会了这门语言,那显然不是本书的意图。如今也许是另一个 编程语言百家争鸣的时代,新的语言层出不穷,作者试图帮助大家在如此繁多的语言当中找到一些适合你投资、学习和使用的有前途的编程语言。

书的最终版本我也没有拿到,我也只是看了我所翻译的那三章,因此书的内容好坏我也不能妄加评论。这里是Amazon.com上关于此书的一些书评(中文翻译版),另外从本书获得了2011年Jolt大奖可以看出本书还是被业内专家一致看好的。

个人感觉出版的有些晚了,如果能与Jolt大奖的公布同步推出也许效果会更好。书的最终纸质版本我也没有拿到,尚不知书的印刷质量如何,另外翻译的质量如何还得需要大家评判。

最后十分感谢翻译过程刘江、杨海玲 、傅志红、李松峰、丁晓昀等各位老师对我的帮助。

Common Lisp初学点滴

Common Lisp是一门Interactive语言,比较容易上手。无论你是用CLISPSBCL还是Clozure CL,你都可以很快地写出一个"Hello, World"程序出来。不过千万不要因此低估了Common Lisp,前人的经验表明:Common Lisp是门庞大且复杂的语言,其学习曲线可并不低。要想真正掌握它,需要你有持续的热情、足够的耐心和不断的练习。我接触Common Lisp时间也不长,是个地地道道的初级选手。这段时间看了些书,做了一些练习,这里把我初学Common Lisp过程中的点点滴滴记录下来,以备忘。

俗话说:工欲善其事,必先利其器。Common Lisp开发者们也有着自己一套高效的开发工具。目前无论是在Windows还是在Linux或是其他平台上,最受Lisper们推崇的工具组合是Emacs+ Slime(The Superior Lisp Interaction Mode for Emacs)。鼎鼎大名的Emacs这里就不说了,Slime对于很多非Lisp开发者来说是一个陌生的名字,我们可以把它看成是一种专门为Lisper们提供的一个嵌入到Emacs中的IDE,通过它我们可以在Emacs编辑器中直接进行Lisp代码的求值,编译,宏扩展,符号定义的查找,名字的自动补全以及在线文档查询等操作。我平时开发更多使用的是另外一种编辑神器-VIM,幸运的是已经有人将Slime移植到了Vim下,Slime摇身一变,变成了Slimv(The Superior Lisp Interaction Mode for Vim)。由于接触时间较短,我目前尚不确定在功能上Slimv是否完全等同于Slime。不过就目前来看,Slimv的确让Vim下Common Lisp代码的编写变的高效了许多。

Slimv的安装极其简单:将Slimv包下载到你的$HOME/.vim下(这里以Linux下的安装为例),直接解压即可。Slimv首先为Vim提供了一种名为Paredit Mode(.vim/doc/paredit.txt )的编辑模式,这种模式专门针对Lisp代码源文件,诸如以.lisp为后缀名的文件。该编辑模式保证内容中所有括号、方括号以及双引号均平衡出现,即成对匹配。当你敲入"(",该模式会自动补充对应的")";删除半个括号时,另半个括号也被自动删除。初次使用Paredit mode很不习惯,特别是不知如何在括号的外层再包裹一层括号,也就是将(list 1 2)变为((list 1 2))。每次在(list 1 2)开始处输入"(",都会得到"()(list 1 2)"。后来才在Stackoverflow上觅到答案:原来先输入"\"再输入"("时,Slimv不会自动补充")",通过这种方式可以在括号的外围再加上一层括号了,在Lisp实际编程过程当中,嵌套括号的情况还是很多的。

打开一个名为xx.lisp的源文件,Slimv就会自动发挥作用。在Vim的命令模式下,敲入",c",Slimv会自动启动Swank Server,这个Server运行着一个Common Lisp的REPL,接收并处理嵌入在Vim中的Slimv client端发出的求值、编译、调试等请求,保存你在Vim中与REPL的session内容。Slimv同时会在Vim里创建一个REPL窗口,不过这仅是用来等待你的输入,真正的求值等操作是在Swank Server完成的。

Slimv会自动Detect你已安装的Common Lisp实现,在我的已经安装过Clisp和SBCL的系统中,Slimv优先选择了SBCL。 关于Slimv,这里不再多说什么了,因为其作者已经编写了一份很详尽的Tutorial在这里,有兴趣的朋友可以参考之。

我在读的Common Lisp书籍主要有两本:一本是"黑客与画家"的作者Paul Graham编写的"ANSI Common Lisp",另外一本则是Peter Seibel的"Practical Common Lisp"(据说该书的中文译本已由binghe完成)。这一周多来,我快速地浏览了Peter Seibel的"Practical Common Lisp",除了惊奇于一些之前未曾接触过的特殊语法结构(如Closure)之外,也感叹于Common Lisp的复杂,数不尽的function, macro和special operator让我有些迷失和混淆。另外Peter Seibel自称书中有关macro的例子都很初级,但就是这样初级的macro也是甚难以理解的。关于macro的深入领会,我看只能指望Paul Graham的大作:"ANSI Common Lisp"和"on lisp"了。

另外一本名为"Common Lisp Quick Reference"的小书也值得一看,不过更适合Common Lisp老手查阅手册时使用。

浏览完"Practical Common Lisp“后,继续精读"ANSI Common Lisp",并且对其中的习题也不放过。这些练习估计很初级,不过对于我这个初级选手来说正合适。刚刚看完第二章(Welcome to Lisp),这里将我的习题答案放到这里,供大家批评指正:

练习1.
(a) 14
(b) (1 5)
(c) 7
(d) (NIL 3)

练习2.
[1]> (cons 'a '(b c))
(A B C)
[2]> (cons 'a (cons 'b (cons 'c nil)))
(A B C)
[3]> (cons 'a (list 'b 'c))
(A B C)

练习3.
[1]> (defun my-fourth (x)
          (car (cdr (cdr (cdr x)))))
MY-FOURTH
[2]> (my-fourth '(1 2 3 4 5))
4

练习4.   
[1]> (defun my-max (x y)
         (if (> x y) x y))
MY-MAX
[2]> (my-max 5 6)
6
[3]> (my-max 7 6)
7

以上方案只适用于整数等适用>进行比较的类型,下面是一个更加通用的版本:

[1]> (defun my-max1 (x y comp_func)
         (if (funcall comp_func x y) x y))
MY-MAX1
[2]> (defparameter *cf* (lambda (x y) (if (> x y) t nil)))
*CF*
[3]> (my-max1 5 6 *cf*)
6
[4]> (my-max1 7 6 *cf*)
7
[5]> (defparameter *ccf* (lambda (x y) (if (char> x y) t nil)))
*CCF*
[6]>  (my-max1 #\c #\b *ccf*)
#\c
[7]> (my-max1 #\c #\d *ccf*)
#\d

练习5.
(a) enigma函数的功能是找出list中是否有值为nil的元素,如果有,返回T;否则返回nil
(b) mystery函数的功能是返回x在y列表中的位置(下标)

练习6.
(a) x = car
(car (car (cdr '( a (b c) d ) ) ) )

(b) x = or
(or 13 (/ 1 0))
注:短路求值,后一项在13为t的情况下不被求值,避免了divide by 0错误

(c) x = apply

注意funcall与apply的区别
(funcall function arg1 arg2 …)
==  (apply function arg1 arg2 … nil)
==  (apply function (list arg1 arg2 …))

练习7.
(defun have-list-param-p (x)
  (let ((result nil))
    (dolist (obj x)
      (if (listp obj)
        (setf result t)))
    result))

[1]> (load "list_param.lisp")
;; Loading file list_param.lisp …
;; Loaded file list_param.lisp
T
[38]> (have-list-param-p '(1 2 3))
NIL
[39]> (have-list-param-p '(1 (2 3) 4))
T

练习8.
(a)
iterative solution:
(defun print_dots (number-of-dots)
  (do ((i 1 (+ i 1)))
    ((> i number-of-dots))
    (format t ".")))

recursive solution:
(defun print_dots (number-of-dots)
  (let  ((i number-of-dots))
     (if (> i 1)
        (print_dots (- number-of-dots 1)))
     (format t ".")))

练习9.
(a) 问题所在:remove返回一个新的lst,原来的lst如果包含nil,则+会提示nil is not a number
修改后:
(defun summit (lst)
  (setf lst (remove nil lst)) 
  (apply #'+ lst))

(b) 问题所在:导致无穷递归,提示Program stack overflow. RESET
修改后:
(defun summit (lst)
  (if lst (+ (or (car lst) 0) (summit (cdr lst))) 0))
     
Common Lisp与Haskell不同,Common Lisp并非纯函数式编程语言,其中包含了诸多命令式(imperative)的元素,这样对于习惯了命令式编程的初学者来说,在学习过程中就不会感觉到过于剧烈的思维跳跃了。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats