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 |
ค่าตัวแปร |
Goodval x = 5 Bad x=6 |
ค่าคงที่ |
var x: Double = 5 |
type ที่ชัดเจน |
ฟังก์ชัน | |
Gooddef f(x: Int) = { x*x } Bad def f(x: Int) { x*x } |
กำหนดฟังก์ชัน ซ้อนความผิดพลาด : ไม่มีการ return Unit ของฟังก์ชัน; เป็นสาเหตุให้เกิดข้อผิดพลาดได้ |
Gooddef 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) |
การผูกโครงสร้างข้อมูลใหม่ : ด้วยรูปแบบการจับคู่ |
Badvar 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) |
Badval v42 = 42 Some(3) match { case Some(v42) => println("42") case _ => println("Not 42") } |
“v42” ถูกตีความว่าเป็นชื่อที่ตรงกับค่า Int และแสดงค่า “42” |
Goodval v42 = 42 Some(3) match { case Some(`v42`) => println("42") case _ => println("Not 42") } |
“v42” กับ backticks ถูกตีความว่าเป็น v42 val ที่มีอยู่และ แสดงค่า “Not 42” |
Goodval 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 |
Badnew 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) |