Archive

Archive for the ‘Scala’ Category

Scala: 方法名约定

August 7th, 2010 leeing 2 comments

Scala中没有操作符但是支持运算符重载,方法的最后一个字符也对优先级有影响,它决定了方法调用的目标。

Scala的这个约定在熟悉之后你会发现它提高了流畅性,例如,如果想要将一个值添加到一list中,可以写作:value::list,尽管可以读为:“value被附加到list上”,这个方法的目标实际上list而参数是value,也就是说list.::(value)。

如果方法名以冒号结尾,那调用目标是操作符后面的实例,在下一个例子中,^() 是一个定义在类Cow中的方法,而 ^:() 是一个定义在Moon中的方法:

class Cow {
	def ^(moon: Moon) = println("Cow jumped over the moon")
}
class Moon {
	def ^:(cow: Cow) = println("This cow jumped over the moon too")
}

调用如下:

val cow = new Cow
val moon = new Moon
cow ^ moon
cow ^: moon

Read more…

Categories: Scala Tags:

Scala : “运算符” 重载

April 26th, 2010 leeing No comments

运算符带了双引号,这是因为从技术上来说,Scala 并没有所谓的“运算符”,在这里是指重载符号,如+ ,+- 等等。
在 Scala 中,事实上这些是方法的名字。但是由于 Scala 并不需要点来分隔对象引用和方法名,因而看起来像是运算符。调用 ref1+ref2 其实与 ref1.+(ref2)是等同的,调用的其实是 ref1 的+()方法。

举例如下:

class Complex(val real: Int, val imaginary: Int) {
    def +(operand: Complex) : Complex = {
        new Complex(real + operand.real, imaginary + operand.imaginary)
    }
    override def toString() : String = {
        real + (if (imaginary < 0) "" else "+") + imaginary + "i"
    }
}
val c1 = new Complex(1, 2)
val c2 = new Complex(2, -3)
val sum = c1 + c2
println("(" + c1 + ") + (" + c2 + ") = " + sum)

运行结果:

(1+2i) + (2-3i) = 3-1i

再次强调,Scala 并不存在运算符,所以没有定义运算符优先级,但是同时又定义了方法的优先级。方法的第一个字符用来决定它们的优先级,如果两个同等优先级的字符在同个表达式中出现,那左边的优先。

Read more…

Categories: Scala Tags:

Scala : 交互式应用程序,函数组合

April 26th, 2010 leeing No comments

函数和交互式应用程序

回调(callback)在交互式应用程序中是很常见的。例如一个按钮被点击,并进行一个特定的动作。在Web 应用程序中创建回调是尤其困难的,除非你拥有像Scala这样强大的工具。下面创建一个方法,它生成一个随机的String,以作为一个全局唯一的标识符(GUID)。

scala> def randomName() = "I"+ scala.util.Random.nextLong.abs
randomName: ()java.lang.String

然后定义一个通用的JavaScript trait, 我们不需要刷新它,假设它包含可以在浏览器中运行的JavaScript 命令。

scala> trait JavaScript
defined trait JavaScript

下面用一个能生成 JavaScript的函数来创建一个Map 以关联GUID:

scala> var callbacks: Map[String, () => JavaScript] = Map()
callbacks: Map[String,() => JavaScript] = Map()
scala> def register(f: () => JavaScript) = {
| val name = randomName
| callbacks += name -> f
| <button onclick={"invokeServerCall("""+name+""")"}>ClickMe</button>
| }
register: (f: () => JavaScript)scala.xml.Elem

当用户点击按钮时,会用 GUID 创建一个Ajax HTTP 请求,Servlet 在map中查找GUID,如果GUID存在,这个函数就会被调用并将JavaScript则返回给浏览器,这个功能的代码类型于:

Scala> def handleAjax(guid: String): HttpResponse =
functionMap.get(guid).map(f => f()) match {
case Some(javaScript) => JavaScriptResponse(javaScript)
case _ => Http404Response()
}

上面的代码是 Lift 框架的简化版本,可以看到,这种写法可以让程序员更关注于业务逻辑。

Read more…

Categories: Scala Tags:

Scala : 作用域中的变量,容器

April 25th, 2010 leeing No comments

Functions Bound to Variables in Scope

函数被绑定到创建函数时所在的作用域内中的变量,这样就允许承载状态,例如首先声明一个名为 foo 的变量:

scala> val foo = "dog"
foo: java.lang.String = dog

下面创建一个引用了这个变量的函数:

scala> val whoTo = (s: String) => s+" "+foo
whoTo: (String) => java.lang.String = <function1>

调用这个函数:

scala> whoTo("I love my")
res0: java.lang.String = I love my dog

scala> whoTo("I walk my")
res1: java.lang.String = I walk my dog

函数可以绑定于vars 或 vals ,甚至可以修改vars,首先,创建一个var strs,它是一个 List[String]:

然后创建一个以String为参数并返回String的函数,并且它能修改strs:

scala> var strs: List[String] = Nil
strs: List[String] = List()

scala> val strF = (s: String) => {strs ::= s; s+" Registered"}
strF: (String) => java.lang.String = <function1>

调用这个函数:

scala>  strF("a")
res2: java.lang.String = a Registered

scala> strF("b")
res3: java.lang.String = b Registered

scala> strs
res4: List[String] = List(b, a)

把这个函数作为参数:

scala> List("p", "q", "r").map(strF)
res5: List[java.lang.String] = List(p Registered, q Registered, r Registered)

scala> strs
res6: List[String] = List(r, q, p, b, a)

可以看到每一步都正确地更新了 strs。

Read more…

Categories: Scala Tags:

Scala : Partial Functions 和 Type Parameters

April 21st, 2010 leeing No comments

方法和函数是不同的,在Scala中,除了方法以外,一切都是一个实例。方法被附加到实例之上,并且被实例所调用。Function是实现了 FunctionNN trait (NN是指参数的个数,在 Scala 2.8 的文档中可知,NN 的取值范围是 1~22)的实例。在运行时函数没有什么特别的地方,但在编译阶段,有一些方式可以让编写一个函数使用很少的代码。

Partial Functions

Partial function 是只有部份参数被 apply 的函数,在Scala中,可以从方法中来构建 partially applied function:

scala> def plus(a: Int, b: Int) = "Result is: "+(a + b)
plus: (a: Int,b: Int)java.lang.String

scala> val p = (b: Int) => plus(42, b)
p: (Int) => java.lang.String =

partial function 允许你基于已有的方法或函数来构建新的函数,参数可以用不同的括号来分组:

scala> def add(a: Int)(b: Int) = "Result is: "+(a + b)
add: (a: Int)(b: Int)java.lang.String

这样,就可以用下面的語法来调用:

scala> add(1)(2)
res1: java.lang.String = Result is: 3

通过这个語法,你可以传递一个独立于其它参数的代码快作为参数:

scala> add(1){
| val r = new java.util.Random
| r.nextInt(100)
| }
res2: java.lang.String = Result is: 15

同时,也允许很容易地将一个方法提升为一个partially applied function:

scala> def w42(f: Int => String) = f(42)
w42: (f: (Int) => String)String

scala> w42(add(1))
res5: String = Result is: 43

最后,也可以通过partially applying一个方法将它转换为一个函数:

scala> def f2 = add(1) _
f2: (Int) => java.lang.String

此时,这个函数也能被传递给另一个方法:

scala> w42(f2)
res6: String = Result is: 43

Type Parameters

方法可以拥有类型参数:类型参数定义了其它的类型或方法的返回值类型。但注意函数不能接收类型参数,一个的参数和返回值必须在函数定义时创建。

Read more…

Categories: Scala Tags: