从OOP和FP看苹果Swift语言与Scala比较

如果说,此前的Scala语言是一种函数式编程语言,那么苹果推出的Swift语言无疑是针对Scala提出的挑战。

从语言特性比较上看,Swift语言是将函数作为第一等公民,同时支持类型和数据结构,当Java初学者还在疑惑对象是按值传递还是按引用传递时,Swift干脆显式的区分这两点,类型Class是按引用传递,而数据结构是按值传递,这种清晰的分离反而使得OOP和FP两种都变得更加轻松。见我之前的帖子:伪命题:Java传递的值还是引用?

当我们以函数编程为主时,因为函数编程追求的是贫血对象,也就是对象的方法和属性是分离的,那么在这种情况下,我们就不必委屈使用类型Class作为贫血对象实现,而是直接使用数据结构,算法+数据结构=函数编程,多清晰简单?OOP派的人也不再抨击FP肢解他们的对象。

当我们以面向对象编程为主时,我们使用类型Class,OOP是讲究充血模型,也就是对象方法和属性是混合在一个Class中的。这样OOP派的人也能保全了其面向对象的完整封装性。

所以,从这点来看,虽然Swift和Scala都是FP和OOP的混合,但是Swift要比Scala做得到位,避免了两者混乱。

Swift强于Scala的第二点可能是性能,因为Swift的作者曾经开发过LLVM,对于性能的重视大概是其基因使然,这点就无需多言。

当然,同样作为函数语言,坚持不变性是语言的缺省,可变性是特殊的原则,Swift使用let表示不变性,等同于Scala的val,Swift使用var表示可变。不过一般只有在OOP时,我们使用对象来封装可变性,所以,我的大胆设想是,只有在类型class中才可以使用var,对象之外属于函数编程的天下,函数编程是讨厌可变状态的,因此干脆杜绝var使用,真正发挥函数编程无副作用的特点,这样,语言变量缺省默认都是不变性变量也就是常量,这样的语言是不是更简洁呢?

相关:
苹果Swift语言简要介绍

苹果Swift语言简明教程

[该贴被banq于2014-06-06 07:02修改过]

这是一个谈论Swift函数特性的站点:Functional Swift,源码在Github上。

Swift实现斐波那契数:


// a copy of the f# fib implementation
func fib(n : Int) -> Int {
if n == 0 || n == 1 {
return n
}
else {
return fib(n - 1) + fib(n - 2)
}
}

// A simple print output function
let output = {(n: Array<Int>) -> () in
for (index,value) in enumerate(n) {
println(
"[\(index)] is \(value)")
}
}

// Take an array of Ints, run fib on each in turn, filter just those %2 and then output the result
[1,2,3,4,5,6,7,8,9,10]
|> map(fib)
|> filter({$0 % 2 == 0})
|> output

[该贴被banq于2014-06-06 12:59修改过]

SWIFT IS A LOT LIKE SCALA一文也谈了Swift很多地方类似Scala。并且逐一比较了两者语法。

Swift简直是Scala的方言,Swift从Scala继承了大部分鲜明特征:类型推断, 闭包Closures, 元祖Tuples, 协议Protocols, Extensions, 泛型Generics, Read-Eval-Print-Loop,

但是 Swift运行环境非常不同于Scala,Scala编译到 JVM, 使用垃圾回收, 对象模型和Java透明, Swift是编译到原生native 代码, 使用自动引用计数automatic reference counting, 对象模型和Objective-C集成.

两者具体语法比较可以看英文原文。

[该贴被banq于2014-06-06 16:35修改过]

php是不是一直都是这个样子?

Swift提供了数据结构struct和类Class两种, 数据结构和类一样支持行为,包括方法和初始化,数据结构和类的重要区别是:数据结构按复制方式传递,当你将一个数据结构传递给另外一个变量时,实际是复制了一份,但是类生成的对象进行传递时是按引用传递,传递的是那个对象的地址(当然地址值也是复制)。

Swift Struct代码如下:


struct Card {
 var rank: Rank
 var suit: Suit
 func simpleDescription() -> String {
  return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
 }
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

Swift语言显式地区分了数据结构struct和类Class,而在我们传统语言中,包括Java C# Pthyon Ruby等基本都只有类Class一种对象模型。这就产生了问题。

这个问题我在从数据结构+算法分析ORM的末日已经提到,数据表是一种数据结构,ORM框架是将数据结构转为对象,其实这个对象是贫血对象,也就是只有属性或setter/getter而没有其他业务行为的对象,如:


class Order{
String orderId;
Double money;
..
}

我们使用ORM,是将数据表order中的记录拷贝到这个贫血对象Order中。实际上这个失血对象Order也是一种数据结构,只不过因为语言本身不支持数据结构,所以,我们借用类型Class的对象模型来作为数据结构对象,而且是对Class进行肢解的一种黑客方式(去除了其鲜明特征:行为)。

现在有了Swift的struct,我们实际应该是将数据表order的数值复制到struct中,而且struct是按值传递的,如果你修改了原来的struct,其他复制的不会被改变。数据表实际是一个远程的struct。

从以上分析看出,目前ORM框架包括JPA Hibernate Django Rails的ActiveRecord实际都定位错误了,将类型Class对象模型作为数据结构使用。

以前我们指出ORM末日主要是从抽象泄漏和性能角度提出问题,但是这些问题一般只是在项目复杂时才显露出来,小项目反而体现ORM的快速的特点,但是我们从Swift这个新语言上看到,ORM方向搞错了,应该是structRM才对啊。

ORM在未来面临土崩瓦解,这个词语会成为历史名词。

[该贴被banq于2014-06-07 09:04修改过]

Swift、Scala里看到的都是D语言的影子......