Scala Cheatsheet

Scala Cheatsheet

Language
Contributed by Brendan O’Connor

ขอบคุณ Brendan O’Connor, สำหรับ cheatsheet นี้มีวัตถุประสงค์เพื่ออ้างอิงอย่างง่ายสำหรับโครงสร้างประโยคของ Scala, Licensed by Brendan O’Connor under a CC-BY-SA 3.0 license.

ตัวแปร  
var x = 5 ค่าตัวแปร
Good
val x = 5
Bad
x=6
ค่าคงที่
var x: Double = 5 type ที่ชัดเจน
ฟังก์ชัน  
Good
def f(x: Int) = { x*x }
Bad
def f(x: Int) { x*x }
กำหนดฟังก์ชัน
ซ้อนความผิดพลาด : ไม่มีการ return Unit ของฟังก์ชัน;
เป็นสาเหตุให้เกิดข้อผิดพลาดได้
Good
def f(x: Any) = println(x)
Bad
def f(x) = println(x)
กำหนดฟังก์ชัน
ไวยกรณ์ผิดพลาด : จำเป็นต้องกำหนดค่าสำหรับทุกๆ arg
type R = Double นามแฝงของ type
def f(x: R) vs.
def f(x: => R)
call-by-value
call-by-name (lazy parameters)
(x:R) => x*x ฟังก์ชันที่ไม่ระบุชื่อ
(1 to 5).map(_*2) vs.
(1 to 5).reduceLeft( _+_ )
ฟังก์ชันที่ไม่ระบุชื่อ : ตำแหน่งของขีดล่างตรงกับตำแหน่งของ arg
(1 to 5).map( x => x*x ) ฟังก์ชันที่ไม่ระบุชื่อ : เพื่อใช้ arg สองครั้งต้องตั้งชื่อ
Good
(1 to 5).map(2*)
Bad
(1 to 5).map(*2)
ฟังก์ชันที่ไม่ระบุชื่อ : เชื่อม infix method ใช้ 2*_. แทน
(1 to 5).map { x => val y=x*2; println(y); y } ฟังก์ชันที่ไม่ระบุชื่อ : block style จะ return ส่วนสุดท้าย
(1 to 5) filter {_%2 == 0} map {_*2} ฟังก์ชันที่ไม่ระบุชื่อ : pipeline style. (หรือวงเล็บด้วย).
def compose(g:R=>R, h:R=>R) = (x:R) => g(h(x))
val f = compose({_*2}, {_-1})
ฟังก์ชันที่ไม่ระบุชื่อ : เพื่อส่งค่าหลาย block จะต้องใส่วงเล็บด้านนอก
val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd currying, ไวยกรณ์ที่ชัดเจน
def zscore(mean:R, sd:R) = (x:R) => (x-mean)/sd currying, ไวยกรณ์ที่ชัดเจน
def zscore(mean:R, sd:R)(x:R) = (x-mean)/sd currying, ไวยกรณ์ sugar, แต่ในกรณีนี้
val normer = zscore(7, 0.4) _ จะต้องต่อท้ายด้วยขีดล่างเพื่อเอาบางส่วน, เวอร์ชัน sugar เท่านั้น
def mapmake[T](g:T=>T)(seq: List[T]) = seq.map(g) type ทั่วไป
5.+(3); 5 + 3
(1 to 5) map (_*2)
ฝัง sugar
def sum(args: Int*) = args.reduceLeft(_+_) ตัวแปรที่มีความยาว
แพคเกจ  
import scala.collection._ import ทั้งหมด
import scala.collection.Vector
import scala.collection.{Vector, Sequence}
เลือก import
import scala.collection.{Vector => Vec28} เปลี่ยนชื่อ import
import java.util.{Date => _, _} import ทั้งหมดจาก java.util ยกเว้น Date
package pkg ที่เริ่มต้นของไฟล์
package pkg { ... }
ประกาศแพคเกจ
โครงสร้างข้อมูล  
(1,2,3) การเขียน tuple
var (x,y,z) = (1,2,3) การผูกโครงสร้างข้อมูลใหม่ : ด้วยรูปแบบการจับคู่
Bad
var x,y,z = (1,2,3)
ซ้อนความผิดพลาด : เป็นการแทนค่าทั้ง tuple
var xs = List(1,2,3) list (แก้ไขไม่ได้)
xs(2) ระบุตำแหน่งด้วยวงเล็บ
1 :: List(2,3)  
1 to 5 เหมือนกับ 1 until 6
1 to 10 by 2
ระยะ sugar
() (วงเล็บว่าง) สมาชิกเดียวของ Unit type (เหมือน void ใน C++/Java)
โครงสร้างควบคุม  
if (check) happy else sad เงื่อนไข
if (check) happy เหมือนกับ
if (check) happy else ()
เงื่อนไข sugar
while (x < 5) { println(x); x += 1} ทำซ้ำ while
do { println(x); x += 1} while (x < 5) ทำซ้ำ do while
import scala.util.control.Breaks._
breakable {
for (x <- xs) {
if (Math.random < 0.1) break
}
}
หยุด (slides)
for (x <- xs if x%2 == 0) yield x*10
เหมือนกับ
xs.filter(_%2 == 0).map(_*10)
ทำความเข้าใจ for : filter/map
for ((x,y) <- xs zip ys) yield x*y
เหมือนกับ
(xs zip ys) map { case (x,y) => x*y }
ทำความเข้าใจ for : การเชื่อมโยงโครงสร้างใหม่
for (x <- xs; y <- ys) yield x*y
เหมือนกับ
xs flatMap {x => ys map {y => x*y}}
ทำความเข้าใจ for : ข้ามผลคูณ
for (x <- xs; y <- ys) {
println("%d/%d = %.1f".format(x, y, x/y.toFloat))
}
ทำความเข้าใจ for : คำอธิบายประเภทจำเป็น sprintf-style
for (i <- 1 to 5) {
println(i)
}
ทำความเข้าใจ for : ทำซ้ำโดยรวมขอบเขตบน
for (i <- 1 until 5) {
println(i)
}
ทำความเข้าใจ for : ทำซ้ำโดยละเว้นขอบเขตบน
จับคู่รูปแบบ  
Good
(xs zip ys) map { case (x,y) => x*y }
Bad
(xs zip ys) map( (x,y) => x*y )
ใช้ case ใน arg ของฟังก์ชันสำหรับ จับคู่รูปแบบ (pattern maching)
Bad
val v42 = 42
Some(3) match {
case Some(v42) => println("42")
case _ => println("Not 42")
}
“v42” ถูกตีความว่าเป็นชื่อที่ตรงกับค่า Int และพิมพ์ “42”
Good
val v42 = 42
Some(3) match {
case Some(`v42`) => println("42")
case _ => println("Not 42")
}
“v42” กับ backticks ถูกตีความว่าเป็น v42 val ที่มีอยู่และ
พิมพ์ “Not 42”
Good
val UppercaseVal = 42
Some(3) match {
case Some(UppercaseVal) => println("42")
case _ => println("Not 42")
}
UppercaseVal ถือว่าเป็น val ที่มีอยู่ไม่ใช่ตัวแปรรูปแบบใหม่
เพราะมันเริ่มต้นด้วยตัวอักษรตัวพิมพ์ใหญ่ ดังนั้นค่าที่มีอยู่ใน
UppercaseVal จะถูกตรวจสอบเทียบกับ 3 และพิมพ์ “Not 42”
การใช้งาน object  
class C(x: R) เหมือนกับ
class C(private val x: R)
var c = new C(4)
ตัวสร้างพารามิเตอร์ - x มีเฉพาะในคลาส body เท่านั้น
class C(val x: R)
var c = new C(4)
c.x
ตัวสร้างพารามิเตอร์ - กำหนดสมาชิกสาธารณะโดยอัตโนมัติ
class C(var x: R) {
assert(x > 0, "positive please")
var y = x
val readonly = 5
private var secret = 1
def this = this(42)
}
ตัวสร้างเป็นคลาส body
ประกาศเป็นสมาชิกสาธารณะ
ประกาศสมาชิก get ค่าได้ แต่ set ค่าไม่ได้
ประกาศเป็นสมาชิกส่วนตัว
ตัวสร้างอื่นๆ
new{ ... } คลาสที่ไม่ระบุตัวตน
abstract class D { ... } กำหนดคลาสนามธรรม (ไม่สามารถสร้างได้)
class C extends D { ... } กำหนดคลาสที่สืบทอดมา
class D(var x: R)
class C(x: R) extends D(x)
การสืบทอดและตัวสร้างพารามิเตอร์ (สิ่งที่อยากได้:
โดยอัตโนมัติจะส่งพารามิเตอร์ขึ้นโดยอัตโนมัติ)
object O extends D { ... } กำหนด singleton (เหมือนโมดูล)
trait T { ... }
class C extends T { ... }
class C extends D with T { ... }
traits
อินเตอร์เฟซที่มีการดำเนินการ ไม่มีพารามิเตอร์ของตัวสร้าง mixin-able
trait T1; trait T2
class C extends T1 with T2
class C extends D with T1 with T2
หลาย traits
class C extends D { override def f = ...} ต้องประกาศ method override
new java.io.File("f") สร้าง object
Bad
new List[Int]
Good
List(1,2,3)
ชนิดความผิดพลาด: ชนิดนามธรรม
แทนที่, ธรรมเนียม: factory ที่เรียกได้เงาสะท้อนของ type
classOf[String] ดูข้อมูลของคลาส
x.isInstanceOf[String] เช็ค type (ขณะ runtime)
x.asInstanceOf[String] แปลง type (ขณะ runtime)
x: String ascription (ขณะ compile time)
bafrjaplpt-brzh-cnthru

Contributors to this page: