『阿男的编程本质论』*11 Eval,Macro,Preprocessor,Homoiconicity(四)*

『阿男的编程本质论』*11 Eval,Macro,Preprocessor,Homoiconicity(四)*

最后我们说说Haskell。Haskell并不是Homoiconic的语言,而且Haskell也不需要Macro。为什么呢?因为Haskell有自己非常完善的类型系统的设计,而且Haskell的function都是Lazy-Evaluation的。

我们使用Clojure的macro,也等于是Lazy-Evaluation,因为我们传入macro的参数即便是代码,实际上也是做为list数据来对待,而parser不会马上做语法分析。只有macro完全展开以后,才会做语法分析。因此macro的展开这一步是本身是一次parsing,展开后的代码再进行一次parsing,这两次的parsing是一样的,并没有什么不同,这和C语言那种macro进行文本替换的方式是不同的。因此我们的macro在展开时的错误就是代码本身的错误,这就让错误信息很准确,分析错误也就变得更容易。

Haskell则是采取了完全不同的设计使得Haskell里面并不需要macro。为什么这么说呢?因为首先Haskell的function全部是lazy evaluated的,其次Haskell的function是可以被当作参数来传递的。有了这两点,Haskell语言本身即可以实现lisp macro所起到的"模版"的功能,因为我们可以通过定义各种函数来实现很多抽象的概念。比如下面这段Haskell代码^1

Prelude> doif x y = if x then (Just y) else Nothing

上面的代码定义了一个函数叫做doif,这个函数接受两个参数xy,其中x是判断条件,而y是根据条件可能的结果。JustNothing都是Maybe类型的monad,你如果不回Haskell语言可以先不管含义。我们看看doif函数的类型定义:

Prelude> :t doif
doif :: Bool -> a -> Maybe a

可以看到doif接受的第一个参数xBool类型的数据,这个是Haskell通过if判断出来的。if需要一个Bool类型的参数做为判断。然后第二个参数的类型是a,是个类型参数,也就是说y可以是任何东西,可以是数据,也可以是函数,等等。

最后,返回结果是Maybe a,就是把a封装在Maybe里面。你不需要知道Maybe是什么,但理解它是个盒子的种类就行了。这个盒子里可以是空的,用Nothing代表,也可以装着东西,用Just ...代表,我们这里参数是y,因此可能装的就是Just y。我们用用看这个doif

Prelude> doif (1 == 2) "Yes 1 == 2 :-)"
Nothing

我们使用doif判断x,也就是1==2是否成立,如果成立,那么我们的y,也就是Yes 1 == 2 :-)将被装进Just盒子里面返回。注意Haskell允许我们把(1 == 2)这个表达式做为参数传递,因为这个表达式的执行结果会返回True或者False。

我们再看doif判断为True的使用:

Prelude> doif (1 == 1) "Yes 1 == 1"
Just "Yes 1 == 1"

注意这是阿男要说的Haskell的第一个特点:表达式,函数都可以作为参数传递,这叫做First-Class Function

第二个特点:作为参数的表达式或者函数不会被执行后传入函数,而是传入后执行。也就是说,因为我们调用doif,导致了doif需要第一个参数,导致了第一个参数被解析。如果参数是表达式或者函数,此时表达式才被解析和运行,这叫做Lazy Evaluation

因此Haskell本身的设计免去了macro的需求,而是用First-Class FunctionLazy Evaluation使得我们可以定义所需功能。

转载于:https://my.oschina.net/u/3195023/blog/826331

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值