2. Pure Function - Gaoey/scala-diary GitHub Wiki

a pure function is one that lacks side effects

A pure function is modular and composable because it separates the logic of the computation itself from “what to do with the result” and “how to obtain the input”

Pure Function จะมีคุณสมบัติเรียกว่า Referential transparency

Referential transparency and purity

การเรียก function ด้วย arguments แบบเดิม จะได้ค่ากลับมาเป็นค่าเดิมเสมอ

An expression e is referentially transparent if, for all programs p, all occurrences of e in p can be replaced by the result of evaluating e without affecting the meaning of p. A function f is pure if the expression f(x) is referentially transparent for all referentially transparent x.

ตัวอย่างที่ไม่ใช่ RT เช่นฟังก์ชันที่ยุ่งเกี่ยวกับ Input/Output หรือฟังก์ชันที่ยุ่งเกี่ยวกับเวลา และ การrandom

RT บังคับให้ค่าคงที่ทุกอย่างในฟังก์ชันทำหน้าที่แทน โดยค่าที่ส่งคืน จะส่งคืนตามชนิดผลลัพธ์ของฟังก์ชัน ข้อจำกัดนี้ช่วยให้โหมดการให้เหตุผลเรียบง่ายและเป็นธรรมชาติต่อการประเมินผลโปรแกรม ซึ่งเรียกว่าแบบจำลองการทดแทน (Substitution model)

Example โดยวิธีแบบ substitutions model

// RT
// code version 1
val x = "Hello, World"
val r1 = x.reverse
val r2 = x.reverse
// r1 and r2 are the same

// code version 2 - ลองแทน param ด้วยค่าที่ใส่มา
val r1 = "Hello, World".reverse
val r2 = "Hello, World".reverse
// r1 and r2 are the same

version 1 and version 2 totally the same

// Non-RT
// code version 1
val x = new StringBuilder("Hello") -> 
// x: java.lang.StringBuilder = Hello
val y = x.append(", World")
// y: java.lang.StringBuilder = Hello, World
val r1 = y.toString
val r2 = y.toString
// r1 and r2 are the same -> "Hello, World"

// code version 2 - ลองแทน param ด้วยค่าที่ใส่มา
val x = new StringBuilder("Hello")
val r1 = x.append(", World").toString
val r2 = x.append(", World").toString
// r1 and r2 are NOT the same
// r1 -> "Hello, World"
// r2 -> "Hello, World, World"

เวลาเขียน code ให้ดูว่ามีคุณสมบัติ RT หรือไม่ โดยลองใช้วิธี substitutions model


RT คือ we can replace it with a corresponding value without changing the program's behaviour.

  • you can do that with pure functions because they always return same value as long as the inputs are same.

ยกตัวอย่าง Math.sqrt(4.0) = 2.0 ตลอดไหม คำตอบคือใช่ ตราบใดที่ ใส่ 4 เข้าไปใน fn จะคืนค่า 2 เสมอ

ดังนั้น sqrt เป็น pure function เพราะมีคุณสมบัติ RT

ยกตัวอย่างที่ไม่ใช่ rt

scala> val g = 10
scala> def notRT(i:int): Int = {
   g = i+g
   return g
}

scala> val v1 = notRT(5)
v1: Int = 15

scala> val v2 = notRT(5)
v2: Int = 20

v1 !== v2 ทั้งๆที่เรียก notRT(5) เหมือนกัน จึงไม่ใช่ Pure function