作者godfat (godfat 真常)
看板PLT
标题Re: [闲聊] Scala 超短介绍(续1)
时间Mon Aug 17 12:00:48 2009
※ 引述《Schelfaniel (Schelfaniel)》之铭言:
: def 是定义函式,它的格式是
: def 函式名称(函数传入值 : 型别) : 传回值型别 = { 内容 }
^^^^^^^^^^^^
有等号的话,回传是 type inference 决定
: 但是传回值型别,其实有时候 编译器 可以判断时可以省略的
: 而後面的 = 在没有传回值型别时可以省略,所以就变成
: def 函式名称(函数传入值 : 型别) { 内容 }
^^ 没有等号的话,回传一律是 Unit
scala 定义 function/method 的写法一堆,这边讲得似乎不太清楚。
用举例的应该比讲解快...
def f: Int = 10
其实这相近於 val f: Int = 10, 因为呼叫他时也不能加括号。
在 scala 里,如果 function/method 定义没有 parameter 的括号,
则呼叫时不能给括号。
f // 回传 10
f() // error: f of type Int does not take parameters
但是如果当初写:
def f(): Int = 10
f // ok
f() // ok
也就是说括号可打可不打。我不知道这样设计的理由是什麽...
def f = {return 123} // error:
// method f has return statement; needs result type
def f = {123} // ok, 大括号有打跟没打一样,return type 由
// type inference 决定
def f {return 123} // ok, 但没有加 = 的结果是,return type 一律是 Unit
// 这边呼叫 f 并不会回传 123
def f {123} // 同上
def f: Int {123} // error: illegal start of declaration
也就是说,有加 = 的话,return type 由 type inference 决定。
有写 type 的话,要和 type inference 结果符合。
但如果没加 = 的话,不管回传是什麽,一律忽略,回传 Unit.
: 为什麽不用 <> 来表示样板呢?
: 因为 Scala 中,有内建 XML 型别的 val a = <test>test</test> 这是可以过的,
: 所以它样板全部改用 [] 来定义,而原本阵列等使用 [] 的,
: 则变为和函数用的 () 一样。
原来是这样啊? XD 这也难怪 D 用了奇怪的符号,而 C++ 为了这个 <>
parser 搞半天,出现一堆诡异的状况...
而 scala 把 () 和 apply method 绑在一起,其实也满清楚的。
ruby 是把 [] 和 call method 绑在一起,有时候看起来怪怪的。
而 ruby 1.9 更引进了这种:
f.() === f[] === f.call
混着乱用的话,应该会出现很难看懂的状况。
: 眼细的人可能会注意到 (函数传入值:型别)(函数传入值:型别) 这样两个定义,
这跟 curried function 有关,不过我觉得 scala 这个有点难用,
不知道是不是有搞错什麽...
: 而第二个是程式区块,型别是 T => Unit ( 输入 T ,而输出 Unit 表示不输出 )
Unit 是表示不关心他的结果,但还是有结果,那个结果就是 Unit,
这个 Unit 只有一个唯一的 instance, 是 ()
因此任何 return type 是 Unit 者,必然是回传 ()
可以看成 OOP 中的 singleton
: Scala 把 A 拆成两项,一个 object 一个 class。
其实这个 object 和 class 本身应该是没关系的,
只是可以用同一个名字,因此看起来会像是 java static 似的?
: 注意的是这边 Scala 预设下 public,
: 而 object 中的 count 如果设 private 会让 class A 也读不到,
因为其实是无关的东西,正好同名,才会出现这样的状况(吧?)
: 其实,在对物件导向的初学者讲解 static 时,常常会有人弄不懂,
: 不管是说 static 是属於 class 的,而非属於 instance 的,
: 或是说 static 时不用传入 this,但 instance 时需要传入 this。
我觉得这来自 C 的包袱... C++ 为了少用 keyword,
避免占用 programmer 可用的字眼,所以常常重复利用 keyword.
因此 static 就被这样拿来用了。接着 Java 又为了跟 C++ 相似,
所以继续拿 static 来用...
我一直觉得应该换个名字。虽然他相对於 method, 确实是 static.
但仍然觉得这个名字乍看之下,很难让人理解。
: 而这边 Scala 就乾脆拆成两个定义,静态的放 object,动态的放 class,
这样讲似乎有点怪,因为 object 应该比较像是 singleton,
倒不是动态静态的差别。例如:
class Base{
def f = "Base"
}
class Derived extends Base{
override def f = "Derived"
}
object Derived extends Base{
override def f = "object Derived"
}
val base: Base = Derived
base.f // 回传 object Derived
画成继承树是像这样:
Base
/ \
Derived object Derived (singleton)
两者其实没有关系,而且都是动态的。
: 其次是 class A 的部份,咦??建构子呢??
: 其实 Scala 中,直接包在 class 的部份就算是建构子了,
: 这边我们连建构子的宣告定义都省了,就直接把内容包在 class 中,
: 看起来也清爽多了吧。
需要 overloading constructor 的话,用 def this(...) = ...
: 另外 Scala 的阵列和 Java 有点不同。
: Java:
: int[] a = new int[10];
: Scala:
: var a : Array[Int] = new Array[Int](10)
这比较是因为 scala 没有 primitive, 应该跟 java ArrayList 等相比
: 型态可省略
: var a = new Array[Int](10)
type inference
: Java 程式师要转为 Scala 程式师,并不是很大的障碍,
: 这障碍其实感觉比 C 转到 C++ 还来得小。
我不觉得咧 XD
Java 很单纯,但 Scala 性质很多,语法也很多变。
也许可以这样说:
对於很熟悉 Java 的人,转到 Scala 会比
对於很熟悉 C 的人,转到 C++ 来得容易些。
对於不够熟的人的话... Scala 应该会晕头转向 XD
--
Nobody can take anything away from him.
Nor can anyone give anything to him.
What came from the sea,
has returned to the sea.
Chrono Cross
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 220.128.121.85