hao对《七周七语言》的笔记(15)

七周七语言
  • 书名: 七周七语言
  • 作者: [美] Bruce A. Tate
  • 副标题: 理解多种编程范型
  • 页数: 246
  • 出版社: 人民邮电出版社
  • 出版年: 2012-5-8
  • 第8页 序章
    获得任何新技能的第一步,是先别想着独立解决什么,而是重复一遍前人已竟之事,这是掌握一门技能最快的方法。用一门新语言上手编程的过程,与其说是投入大量时间反复实践,试图理解语言背后蕴含的深奥原理,还不如说是让分号、逗号各就各位,同时读懂出错时系统反馈的千奇百怪的错误信息。 只有不断提高编程水平,让自己超越先输入代码、再等待编译成功的枯燥阶段,你才有能力思考程序语言中各种语法结构的含义。跨过输入、运行程序的门槛后,你会有如释重负的感觉,因为潜意识将接管余下的工作。意识刚琢磨出分号放哪儿,潜意识就已明白了表面结构下的深层含义。这样下去,你终会有所顿悟,理解某个程序逻辑的更深层含义,某种语言结构如此特殊的原因,等等。对几门语言均略知一二,这其实是一项相当实用的技能,因为我常常发现,网上的某个程序有助于解决手头问题,却没法直接拿来使用,还得针对问题稍作调整才行。这程序用什么语言写的都有可能,所以懂点儿Python、Ruby什么的就非常管用。每门语言都自有一套惯用法。它们各有所长,亦各有所短。通过学习各种不同的编程语言,你会明白,哪门语言最适宜解决自己当下关注的问题。
    引自 序章

    2014-06-18 21:17:41 回应
  • 第19页 简介
    术语“语法糖”是由英国计算机科学家Peter Landin首次提出的。该术语指的是为编程语言添加某种语法,这种语法虽对语言本身功能并无实质影响,但为程序员编程提供了便利,比如C语言用a[i]表示*(a+i)、用for表示循环等语法。语法糖是本书重点关注的主题之一。 语言的类型模型----强类型(Java)或弱类型(C语言),静态类型(Java)或动态类 型(Ruby)。语言的类型模型会改变你对问题的处理方式,还会控制语言的运行方式。 语言的编程范型-----是面向对象(object-oriented,OO)、函数式、过程式,还是它 们的综合体?本书介绍的语言涵盖了4种编程范型,有些语言还由几种范型组合而成。你 将看到一门基于逻辑的编程语言(Prolog)、两门完全支持面向对象思想的语言(Ruby和Scala)、四门带有函数式特性的语言(Scala、Erlang、Clojure和Haskell)及一门原型语言(Io)。这里有Scala这样的多范型(multiparadigm)语言,也有Clojure这种多方法(multimethod)语言,后者甚至允许你实现自定义范型。 怎样和语言交互-----语言可编译也可解释,可以有虚拟机也可以没有。在本书中,如果某 门语言带交互命令行,将先通过交互命令行探索这门语言,当我们处理规模较大的项目 时,还会转而采用文件编程。我们接触的项目不会特别大,因此无需深入研究打包 (packaging)模型。 语言的判断结构(decision construct)和核心数据结构是什么-----或许你会惊讶,在作判断时,居然如此多的语言都用到了与if和while的各种变型都不相同的结构。你会见识到 Erlang的模式匹配,还有Prolog的合一(unification)①。至于数据结构,集合(collection)在任何语言中都扮演着至关重要的角色。对Smalltalk和Lisp这类语言,集合刻画了语言特征,而在C++和Java等语言中,集合更可谓无所不在,它们决定着用户体验,若没了它们,语言势必成为一盘散沙。因此,无论用哪一类语言,都必须全面、透彻地理解集合。 哪些核心特性让这门语言与众不同------有些语言支持并发编程的高级特性,有些语言提供独一无二的高级结构,比如Clojure的宏(marco)和Io的消息解释(message interpretation);有些语言包含性能强劲的虚拟机,如Erlang的BEAM,它能让Erlang构建的容错分布式系统远远快于其他语言;有些语言提供专门针对特定问题的编程模型,比如利用逻辑规则解决约束问题。
    引自 简介

    七种语言高票当选的理由

    Ruby。这门面向对象语言高票当选,因为它不仅好用,而且好读。我曾经考虑过不介绍 任何一门面向对象语言,但我又想在其他编程范型与面向对象编程之间作一些比较,因 此,至少介绍一门面向对象语言还是有必要的。相比于大多数程序员的日常用法,我想 把它挖掘得更深入一些,以揭示设计者的良苦用心。我最终决定重点介绍Ruby元编程 (metaprogramming),因为它可以用来扩展Ruby的语法。对于Ruby榜上有名的结果,我还是相当认可的。 Io。和Prolog一样,Io也是本书颇具争议的语言。它虽与商业成功无缘,但其兼具简单性 和语法一致性的并发结构,却是十分重要的思想。它的最简语法(minimal syntax)功能 强大,与Lisp的相似性也颇能给人留下几分印象。Io不仅和JavaScript一样同为原型语言,还有着独一无二、韵味无穷的消息分发机制,因此在众多编程语言之中,它也占有小小的一席之地。 Prolog。没错,Prolog年事已高,但它仍然威力无穷。它能轻松解出数独问题,这着实让 我大开眼界。用Java或C语言时,有些难题我殚精竭虑方能解决,用Prolog却能干净利落 地搞定。承蒙Erlang发明者Joe Armstrong出手相助,我得以深刻体会到Prolog之妙,而且也正是深受Prolog影响,Erlang才得以问世。如果你此前从未用过Prolog,我保证,它定会带给你惊喜。 Scala。作为运行于Java虚拟机上的新一代语言,Scala为Java系统引入了强大的函数式思想,同时也并未丢弃面向对象编程。回顾历史,我发现C++和Scala有着惊人的相似之处,因为从过程式编程过渡到面向对象编程期间,C++同样起到了举足轻重的作用。当你真正融入Scala社区之后,你就会明白,为什么对于函数式语言程序员来说,Scala是异端邪说,而对于Java开发者来说,Scala是天降福音。 Erlang。作为名单上历史最悠久的语言之一,Erlang不仅是一门函数式语言,而且在并发、分布式编程、容错等诸多方面都有优异表现,真是想不火都难。CouchDB(新兴的基于云的数据库)的创始人就选择了Erlang,并且义无反顾地一直用它,只要花上点时间了解这门分布式语言,你就会明白原因所在。在Erlang帮助下,设计带有并发、分布式、容错等特征的应用程序将变得无比简单。 Clojure。这又是一门Java虚拟机语言,但正是这门Lisp方言,彻底颠覆了我们在Java虚拟机上并发编程的思考方式。它是本书唯一在版本数据库中使用同一种策略管理并发的语言。作为Lisp方言,Clojure或许拥有本书所有语言中最灵活的编程模型,因此绝不缺乏号召力。与其他Lisp方言不同的是,它不会带那么多括号,还有众多Java库和在各平台上的广泛部署作为坚强后盾。 Haskell。它是本书唯一的纯函数式语言,这也意味着,它根本不存在可变状态:只要使 用相同的输入参数,去调用相同的函数,就会返回相同的输出。在所有强类型语言中, Haskell拥有最令人称羡的类型模型。和Prolog一样,它也需要你花一些时间理解,但你得到的回报绝对物超所值。
    引自 简介

    超越语言语法的极限。

    2014-06-18 21:33:32 回应
  • 第28页 Ruby
    作为Ruby的发明者,Matz并不担心编程语言的执行效率,而是把精力放在了提高程序员的编程效率上。 从语言的角度看,Ruby出身于所谓的脚本语言家族,是一种解释型、面向对象、动态类型的语言。解释型,意味着Ruby代码由解释器而非编译器执行。动态类型,意味着类型在运行时而非编译时绑定。从这两方面看,Ruby采取的策略是在灵活性和运行时安全之间寻找平衡点。面向对象,意味着Ruby支持封装(把数据和行为一起打包)、类继承(用一棵类树来组织对象类型)、多态(对象可表现为多种形式)等特性。 Ruby作者最喜欢Ruby的技术点是,我最喜欢的是“代码块”(block)。代码块即是一种易于控制的高阶函数,也为DSL(Domain-Specific Language,领域特定语言)及其他特性的实现提供了极大的灵活性。
    引自 Ruby

    本书中所有代码都是在互交式界面中执行的。(python用户就知道了)

    以上的代码告诉我们: 第一,它告诉你,Ruby是解释执行的。确切地说,Ruby几乎总是解释执行的,但也有开发者正着手开发虚拟机,想把Ruby代码编译成字节码再执行;第二,我没在代码里声明任何变量①;第三,即使我没让Ruby返回任何值,这几行代码也都具有各自的返回值②。实际上,每条Ruby代码都会返回某个值。此外,你还至少看见了两种形式的字符串。单引号包含的字符串表示它将不加改动地直接解释,双引号包含的字符串则会引发字符串替换。字符串替换是Ruby解释器所做的一种求值。在上面的示例中,Ruby把变量language的返回值替换进了字符串。
    引自 Ruby

    Ruby的编程模型 看到这里,原来Lua是原型语言啊,原型语言用对象而不用类来作为定义对象甚至继承的基础。

    Ruby是一门纯面向对象语言,虽然在代码最后的列表中,我省略了一些方法,但已经充分说明了问题。在Ruby中,一切皆为对象,就连每个单独的数字①也不例外。通过此例,我们可以看出,数字是Fixnum类型的对象,且调用methods方法可返回方法数组(Ruby用方括号表示数组)。实际上,我们可以用“.”符号调用对象具有的任意方法。
    引自 Ruby

    判断

    鸭子类型

    2014-06-18 22:10:43 回应
  • 第31页 Ruby

    第二天

    散列表

    =>前面的名称应该就是键了吧,后面应该就是所谓的“值”了。

    所谓一等参数,即可将代码块作为参数直接传递给函数(也就相当于将函数作为参数传递给函数),而无需包装在其他结构中传递。 在Ruby中,参数名之前加一个“&”,表示将代码块作为闭包传递给函数。
    引自 Ruby

    定义类

    到目前为止,还没有什么难以理解的内容。对象是从类派生出来的。4的类是Fixnum,Fixnum 继承自Integer,而Integer又继承自Numeric,最终,Numeric继承自Object。 所有的事物,归根结底都继承自Object。一个Class同时也是一个Module。Class的实例将作为对象的模板。在我们的例子中,Fixnum是Class的一个实例,而4又是Fixnum的一个实例。每一个类同时也是一个对象。
    引自 Ruby
    说到底,Ruby中的一切事物都有一个共同祖先——Object。
    引自 Ruby

    编写Mixin

    面向对象语言利用继承,将行为传播到相似的对象上。但对象若想继承并不相似的多种行 为,一方面可通过允许从多个类继承(多继承)而实现,另一方面也可借助于其他解决方案。 过往经验表明,多继承不仅复杂,且问题多多。Java采用接口解决这一问题,而Ruby采用的是 模块。模块是函数和常量的集合。如果在类中包含了一个模块,那么该模块的行为和常量也会 成为类的一部分。
    引自 Ruby

    模块,可枚举和集合

    元编程,说白了就是“写能写程序的程序”。
    引自 Ruby

    实际上对以上的话我可以理解为,用程序生产出程序?就比如用cmake的语言来生成makefile的语言,因为makefile的语言更加复杂。这样的方式就是更加抽象和提炼问题的本质。不知道是不是可以这样理解?

    2014-06-19 13:35:29 回应
  • Ruby

    开放类

    看看这段代码到底做了些什么。你想要一把削铁如泥的匕首,而Ruby正是将这样一把匕首递 到你手中,于是,你得以开放String和NilClass两个类,对它们进行了重定义。利用重定义, 我们甚至能让Ruby完全瘫痪,比如重定义Class.new方法。对于开放类来说,这里的权衡主要考 虑了自由。有这种随时重定义任何类或对象的自由,我们就能写出极为通俗易懂的代码。不过你 也要明白,自由越大、能力越强,担负的责任也越重。
    引自 Ruby

    实现用于领域编程的特定语言时,开放类特别有用,其中一种常用情况,是通过语言表示业 务领域的度量单位,例如,考虑下面这个以英寸为距离单位的API:

    使用开放类就可以像上面那样采用最简单的语法轻松实现用英寸表示的距离。
    引自 Ruby

    使用method_missing Ruby找不到某个方法时,会调用一个特殊的调试方法显示诊断信息。该特性不仅让Ruby更 易于调试,有时还能实现一些不易想到的有趣行为。只需要覆盖method_missing方法,我们就 可以实现这些行为。思考一下,如何编写一个表示罗马数字的API。或许你觉得可以用方法调用 轻松实现这个API,类似Roman.number_for "ii"。说实话,这样做也不坏,毕竟没有括号、分 号什么的捣乱,不过用Ruby,我们能做得更漂亮:

    这段代码十分简明,是将method_missing方法用于实践的极佳示例。我们先是覆盖了 method_missing方法。通过该方法的参数列表,可获得未找到方法的名称和参数,这个例子中, 我们只对名称感兴趣。首先,我们把名称转换为字符串;然后,iv和ix这样的特殊数字形式①, 将被替换为更容易计数的字符串;最后,是对罗马数字进行计数,并将计数结果与数字的值相乘。 这个API比前面提到的那个简单得多,对比一下Roman.i和Roman.number_for "i"就能看出来。 然而,这样做也要付出代价:我们写的类调试起来会比过去困难得多,因为Ruby再也不会告 诉你找不到某个方法!我们当然想严格检查错误,确保方法接受了正确的罗马数字。但如果不熟 悉method_missing方法的上述用法,想找到Roman类如何实现ii方法都会很困难,更别说检查 错误了。尽管如此,method_missing方法仍然是你武器库中的一把利器。只是在用它的时候一 定要三思而行。
    引自 Ruby

    模块

    说到Ruby最流行的元编程方式,非模块莫属。仅在模块中写上寥寥数行代码,就可以实现 def或attr_accessor关键字的功能。你还可以通过一些令人惊叹的方式扩展类定义,其中一种 技术是设计自己的DSL(domain-specific language,领域特定语言),再用DSL定义自己的类②。该DSL在模块中定义各种方法,这些方法添加了对类进行管理所必需的全部方法和常量。
    引自 Ruby

    首先,用常见的超类(superclass)剖析程序示例。从下面的程序中,你将会了解到我们稍后 用元编程编写的将是什么样的类。这程序很简单——根据类名,打开相应的CSV文件:

    这个基础类定义了4个方法:headers和csv_contents是两个仅返回实例变量值的访问器, initialize初始化读取结果,而read承担了这个类的大部分工作——打开文件,读取表头,把 表头切分成一个个字段,再循环各行,把每一行的内容放入数组。这个读取CSV文件的类,因为 没处理引号之类的特殊情况①,所以功能实现并不完整,但其思路不难理解。 下面的代码还是读取CSV文件,但这回,用一个叫做宏(macro)的模块方法添加类行为。宏 经常根据环境变化改变类行为。在示例中,宏开放类,并把所有与CSV文件相关的行为复制到类中。
    引自 Ruby
    元编程发生在acts_as_csv宏当中,它对我们想添加到目标类上的所有方法都调用了 define_method。现在,当目标类调用acts_as_csv时,宏代码会为目标类定义4个方法。 所以说,acts_as_csv宏不过是添加了一些方法,而这些方法本可以通过继承轻松添加。这 样设计看来改进不大,但好戏还在后面。我们看看在模块中,同样的行为是如何实现的:
    引自 Ruby
    只要某个模块被另一模块包含,Ruby就会调用该模块的included方法。记住,类也是模块。 在ActsAsCsv模块的included方法中,我们扩展了名为base的目标类(即RubyCsv类)。该模块还 为RubyCsv类添加了类方法。其中,acts_as_csv是唯一的类方法。接下来,acts_as_csv方法又 打开了RubyCsv类,并在类中包含了所有实例方法。如此这般,我们就写了一个会写程序的程序。 所有这些元编程技术的有趣之处在于,程序可以根据它应用时的状态而改变。ActiveRecord 利用元编程,动态添加与数据库中的列有相同名称的访问器。有些XML框架如builder,可允许 用户通过method_missing方法定义自定义标签,以提供更加美观的语法。当代码的语法变得更 美观,阅读代码的读者也就不必在语法问题上大伤脑筋,从而能更好地理解代码本身表达的意图。 这正是Ruby的威力所在。
    引自 Ruby

    Ruby的优劣

    Ruby的纯面向对象可以让你用一致的方式来处理对象。鸭子类型根据对象可提供的方法,而 不是对象的继承层次,实现了更切合实际的多态设计。Ruby的模块和开放类,使程序员能把行为 紧密结合到语法上,这大大超越了类中定义的传统方法和实例变量。 Ruby作为脚本语言或带有合理扩展需求的Web开发语言而言,可以说是相当理想的。它的生 产力很强,但其中某些提高生产力的特性使得Ruby难以编译,在性能上也有所损失。 Rails现已成为有史以来最成功的Web开发框架之一,其设计理念以广为人知的模型—视图— 控制器(model-view-controller)范型为基础。 Ruby的最大弱点就是性能。没错,Ruby是越来越快了。在某些应用场景中,1.9版甚至比过 去快了10倍之多。Evan Phoenix写的新虚拟机Rubinius初步实现了用即时编译器(just-in-time compiler)编译Ruby代码。用这种方法观察大段代码在企业中应用的模式,以判断哪些代码可能 多次使用。这对于Ruby的运行方式来说相当合适,因为Ruby语法提供的线索通常不足以完成编 译。别忘了,类的定义任何时间都可能改变。 Matz也十分清楚,他写Ruby是为了改善程序员的体验,而不是优化语言的性能。Ruby正是 凭借它的许多特性(比如开放类、鸭子类型、method_missing等),击败了可编译并由此提升性 能的语言。 并发和面向对象编程: 面向对象编程有一个重大弱点:该编程模型成立的一切前提条件,都建立在一种思想(围绕 状态包装一系列行为)的基础之上,但通常,状态是会发生改变的。于是,程序中存在并发时, 这种编程策略就会引发严重问题。最好的情况下,Ruby会产生大量的资源竞争;最坏的情况下, 面向对象语言几乎无法在并发环境下调试程序,也无法可靠地测试程序。在我写这本书的时候, Rails团队刚开始解决如何有效地管理并发的问题。 类型安全: 我是鸭子类型的坚定支持者。在这种类型策略下,你通常可用简洁而清晰的代码对事务进行 完美地抽象。但使用鸭子类型也是有代价的。静态类型可提供一整套工具,可以更轻松地构造语 法树,也因此能实现各种IDE(集成开发环境)。对Ruby来说,实现IDE就困难得多,而且直到现 在,也没几个人真正用IDE开发Ruby程序。①我多次从心底哀叹Ruby没有一个IDE形式的调试器。 我想,有类似体验的人不会只有我一个。
    引自 Ruby
    2014-06-28 10:02:25 回应
  • 第60页 Io
    如同Lua、JavaScript一样,Io是一种原型语言,这意味着每个对象都是另一个对象的复制品。用Io的时候,你不必既操心类又操心对象。你只需和对象打交道,必要时把对象复制一下就行。这些被复制的对象就叫做原型。学习Io库的阶段,花的时间就要多一些了,因为这门语言的复杂性和丰富性,统统来自于库的设计。
    引自 Io

    打开解释器,输入经典的hello world > "Hello World" print Hello World ==> Hello World 你完全能看出这段代码是怎么做到这点的。你发送了print消息给字符串"Hi ho, Io",接 收者在左边,消息在右边。这里没有任何语法糖,你不过是把消息发送给对象而已。 在Ruby中,你可对某个类调用new创建一个新对象。通过定义类,可以创建一个新的对象种类。而Io不区分类和对象。你可通过复制现有对象创建新对象。现有对象就是原型:

    Object是根对象。我们发送clone消息过去,它会返回一个新对象。我们把这个返回的新对 象赋值给Vehicle。这里的Vehicle不是类,也不是用来创建对象的模板,它只是个对象,是一个基于Object原型的对象。
    引自 Io

    我们可以继续用Vehicle做一些交互:

    对象、原型和继承

    方法

    列表和映射 Io包含了几种类型的集合。列表(list)是任意类型对象的有序集合,所有列表的原型都是List 对象。而Map对象是键值对的原型,称为映射(map),如同Ruby的散列表一样。我们可以像下面这样创建列表:

    true、false、nil以及单例

    Io语言作者的语录:

    其他语言会开辟一些语法捷径,这产生了额外的转换规则。当你用某门语言编程时, 你的脑子里必须有相应的语法转换器,语言越复杂,脑子里的转换器就会越多,转换器的工作越 重,你的工作也就越重。 Io的灵活性可能会让它面对很多常见用途时速度较慢。不过,Io在某些方面也有速度 优势[如:协程(coroutine)、异步套接字、SIMD①支持等],这也使得Io相比于那些采用传统线 程(每个套接字并发或非SIMD向量运算时产生)编写的程序要快得多,即便这程序是用C语言编 写的,也同样如此。 Io较少的语法会使快速检查代码变得更加困难,对这一点,我也颇有微词。然而,我用Lisp 也发现了同样问题,因此这也是可以理解的。额外的语法的确有利于速读代码。不过,新用户有 时一开始会抱怨Io的语法实在太少,但在大多数情况下,他们都会渐渐喜欢上这一点。 这些年来,我听说过各种各样关于Io的传闻,比如用在卫星上,用作路由配置语言,还用作电子游戏的脚本语言。皮克斯动画公司也用Io,他们还写了一条关于Io的博客文章。
    引自 Io
    2014-06-28 11:00:37 回应
  • 第70页 Io

    条件和循环

    运算符

    消息

    反射

    2014-06-29 17:25:59 回应
  • 第78页 Io

    领域特定语言

    Io的method_missing

    并发

    Io的优劣

    1. 占用空间 Io占用的空间很小。大多数Io应用程序的产品都是嵌入式系统。虽然Io这门语言个头小,但 其功能强大且相当灵活,所以应用在嵌入式领域也就合情合理。Io的虚拟机也易于移植到不同的 操作环境当中。 2. 简单 Io的语法极为简洁,学习它花不了多少时间。一旦你理解了它的核心语法,剩下的就是学习 库是如何组织的了。就我的经验而言,在使用这门语言的头两个月中,我能够学会元编程,这速 度已经相当快了。在Ruby中,我达到同样程度所花的时间要更长一点。而Java,我花了很多个月,才对元编程有所了解。 3. 灵活 Io的鸭子类型和自由度,能让你在任何时间改变任何对象的任何槽。Io这一自由宽松的特点, 意味着你可以为了适应自己的应用环境而改变Io的基本规则。通过改变forward槽,随便在哪儿添 加代理都非常容易。你也可以直接改变核心语言结构的槽,从而覆盖这些语言结构。你甚至可以 快速创建出自己想要的语法。 4. 并发 与Java和Ruby不同的是,Io的并发结构非常与时俱进。actor、future和协程使得Io编写多线程 应用程序要容易得多,而且写出来的程序更易于测试且拥有更出色的性能。Io也花了很多心思考 虑可变数据和如何避免它们的问题。这些特征作为其核心库的组成部分,使我们轻松地认识到什 么是健壮的并发模型。后面学习其他语言时,我们还会进一步巩固这些并发概念。你将在Scala、 Erlang和Haskell中再见到actor。 不足之处: 1. 语法 Io几乎没什么语法糖。简单的语法就像一把双刃剑。一方面,简单的语法使Io清晰易懂,但 为此付出的代价是,简单的语法常常使Io难以用简短的方式表达艰深的概念。换句话说,你会 发现自己很容易明白某个程序如何用Io写出来,但与此同时,你也很难明白某个程序到底做了 些什么。我们可以拿Ruby作个对比。刚开始,你可能会觉得Ruby代码array[-1]让人迷惑不解,因 为你并不理解这个语法糖:-1是数组最后一个元素的缩写形式。你还应该知道,[]是获取数组 指定下标值的方法。一旦理解了这些概念,阅读代码就会轻松许多。但Io所做的权衡恰恰相反。 刚开始不用知道太多,但在理解那些用语法糖表达起来轻松自如的概念时,或许就没那么容易了。平衡语法糖是件困难的事,加得过多,会导致语言不易学习,难以记住使用方法;加得过少,在代码的表达方式上花的工夫就要多一些,而且很可能要费大量精力排错。说到底,语法不过是个喜好问题,Matz喜好丰富的语法糖,Steve就不这么想。 2. 社区 当前,Io社区的规模非常小。Io不像其他语言那样,总能找到合适的库。想找到Io程序员就 更难了。通过使用设计良好的C接口(它可以和各种各样的语言交互),以及非常容易记忆的语法,这些问题可在某种程度上得到缓和。优秀的JavaScript程序员能在短时间内学会Io。但较小的社区的确是个缺点,也是阻碍功能强大的新语言不断发展的主要因素。今后,Io要么就作出一个杀手级的应用,吸引大家接受这门语言,或者是保持小众代言人的身份,继续陪太子读书。 3. 性能 脱离其他问题——如并发或应用程序设计——谈论性能通常是不明智的,但我必须指出,对 于那些未经琢磨且为单线程服务的程序来说,Io有不少能拖慢其执行速度的特性。这个问题通过 Io的并发结构可得到一定程度的缓解,但你仍然要记住Io在性能上的这种局限性。
    引自 Io
    2014-06-29 17:37:54 回应
  • 第90页 Prolog
    Io和Ruby被称为命令式语言(imperative language)。命令式语言就像是一本烹饪食谱,你需要精确地告诉计算机如何去完成一项工作。更高级别的命令式语言可能会给你带来更多杠杆效力,即将多个比较长的步骤合并为一个步骤。不过从根本上说,你其实是在列出原料的购物清单,并描述烤蛋糕的详细步骤。 Prolog是一门声明式编程语言(decalarative language)。你向Prolog提供一些事实(fact)和推论(inference),并让它为你推断。它更像是一名手艺高超的糕点师。说出你喜欢的蛋糕的特征,让糕点师挑选原料并按照你提供的规则为你烤出蛋糕。有了Prolog,你无需知道如何做,计算机会为你作出推断。 Prolog是最早的逻辑编程语言之一。你使用纯逻辑设置断言,Prolog判定它们是否为真。你可以在断言中留出空白,Prolog将尝试填充这些空白并使那些不完整的事实变为真。
    引自 Prolog

    关于Prolog

    Prolog是一门逻辑编程语言,它于1972年由Alain Colmerauer和Phillipe Roussel开发完成,在自然语言处理领域颇受欢迎。现在,从调度系统到专家系统,这门备受尊重的语言为各类问题提供了编程基础。你可以使用这门基于规则的语言来表达逻辑和提出问题。和SQL一样,Prolog基于数据库,但是其数据由逻辑规则和关系组成;和SQL一样,Prolog包含两个部分:一部分用于描述数据,而另一部分则用于查询数据。在Prolog中,数据以逻辑规则的形式存在,下面是基本构建单元。  事实。事实是关于真实世界的基本断言。(Babe是一头猪,猪喜欢泥巴。)  规则。规则是关于真实世界中一些事实的推论。(如果一个动物是猪,那么它喜欢泥巴。)  查询。查询是关于真实世界的一个问题。(Babe喜欢泥巴吗?) 事实和规则被放入一个知识库(knowledge base)。Prolog编译器将这个知识库编译成一种适于高效查询的形式。
    引自 Prolog

    Prolog不同方言有点不一样。 GNU prolog是一个实现版本 基本概况

    在一些语言中,大写字母如何使用完全由程序员自行决定。不过在Prolog中,第一个字母的大小写是有着重要意义的,如果一个词以小写字母开头,它就是一个原子(atom)——一个类似Ruby符号(symbol)的固定值,如果一个词以大写字母或下划线开头,那么它就是一个变量。变量的值可以改变,原子则不能。让我们用一些事实来构建一个简单的知识库吧。把下面内容敲入到一个编辑器中:
    引自 Prolog

    地图着色问题

    2014-06-29 20:12:18 回应
  • 第110页 Prolog

    递归

    当你使用递归子目标时,你需要小心。因为每个递归的子目标都会使用栈空间,最终你很可能会耗尽栈空间。声明式语言通常使用一种称为尾递归优化(tail recursion optimization)的技术来解决这个问题。如果你将一个递归的子目标放到递归规则的末尾,Prolog会通过丢弃调用栈来优化这次调用,并保持内存占用不变。这里的调用就是一个尾递归,因为递归子目标ancestor(Z, Y)是递归规则中的最后一个目标。如果你的Prolog程序因耗尽栈空间而崩溃的话,那么就应该知道是时候使用尾递归对程序进行优化了。
    引自 Prolog

    列表和元组

    列表和元组是Prolog的重要组成部分。你可以像[1, 2, 3]这样指定一个列表,像(1, 2, 3) 这样指定一个元组。列表是变长容器,而元组则是定长容器。当你从合一的角度考虑时,列表和 元组都会变得更加强大。
    引自 Prolog

    合一

    记住,当Prolog对变量进行合一操作时,它会尝试使左右两侧相匹配。如果两个元组拥有的 元素数量相同且每个元素可以合一,则它们就可以匹配。
    引自 Prolog

    列表与数学运算

    在两个方向上使用规则

    解决数独问题

    八皇后问题 首先,看看查询应该是什么样子的。我们将每个皇后表示为(Row, Col),一个包含行和列 号的元组。棋盘是一个元组的列表。如果我们有一个合法的棋盘,eight_queens(Board)会返 回成功。我们的查询像下面这样:

    Prolog的优劣

    2014-07-06 10:22:38 回应
<前页 1 2 后页>

hao的其他笔记  · · · · · ·  ( 全部427条 )

P2P网络技术原理与C++开发案例
5
大话移动通信
1
图解网络硬件
1
写给大家看的C++书
1
Orange'S
1
虚拟机
1
大规模C++程序设计
10
Linux Shell脚本攻略
3
HTTP权威指南
3
C++ API设计
8
C++语言的设计和演化
5
构建嵌入式LINUX系统
3
链接器和加载器
1
Windows网络与通信程序设计
2
Windows核心编程(第5版)
16
C++GUI Qt4编程
3
图解TCP/IP (第5版)
12
Python学习手册
5
编写可读代码的艺术
14
你一定爱读的极简欧洲史
2
短码之美
1
程序员的自我修养
17
美国纽约摄影学院摄影教材(上)
2
Win32多线程程序设计
8
竹林蹊径
4
鸟哥的Linux私房菜
4
Linux/Unix设计思想
6
程序设计语言的形式语义
1
Windows驱动开发技术详解
9
你必须知道的495个C语言问题
5
Windows内核原理与实现
44
PCI Express 体系结构导读
3
程序员的数学
5
深入浅出 MFC 第二版
2
并发的艺术
4
群和它的图象表示
1
C语言接口与实现
1
致命元素
2
深入解析Windows操作系统
51
Linux C编程一站式学习
13
淘宝技术这十年
1
高效程序的奥秘
1
花田半亩
1
于丹:重温最美古诗词
1
诛仙8(大结局)
1
深入理解计算机系统(原书第2版)
9
C和指针
9
寒江独钓
5
Windows程序设计
9
数据结构与算法分析
11
80X86汇编语言程序设计教程
3
琢石成器
30
数学分析教程
1
操作系统概念(第六版)
12
算法竞赛入门经典
10
C++反汇编与逆向分析技术揭秘
12