มาโครเชิงปฏิบัติ
กรณีใช้งาน
มาโครเชิงปฏิบัติ เป็นบทเรียน Scala for Backend Engineering & Functional Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Scala for Backend Engineering & Functional Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน
แมโครในโลกจริง
นอกเหนือจากตัวอย่างง่าย ๆ แล้ว แมโครยังช่วยแก้ปัญหาที่เป็นรูปธรรม เช่น การเก็บบริบทของซอร์ส การสร้างคลาสชนิด การตรวจสอบค่าลิเทอรัล และการสร้างโค้ดโดยไม่ต้องเขียนโค้ดประกอบซ้ำซ้อน
กรณีใช้งาน: assert พร้อมข้อความ
แมโครสามารถเก็บ ข้อความต้นฉบับ ของเงื่อนไขที่ไม่ผ่าน เพื่อนำไปสร้างข้อความของการยืนยันที่ช่วยอธิบายปัญหาได้โดยอัตโนมัติ
import scala.quoted.*
inline def myAssert(inline cond: Boolean): Unit =
${ assertImpl('cond) }การเก็บซอร์สโค้ด
ภายในแมโคร cond.show (ผ่าน API ของ reflect) จะคืนค่าซอร์สจริงของนิพจน์ ซึ่งคุณสามารถ splice เข้าไปในข้อความข้อผิดพลาดได้
import scala.quoted.*
def assertImpl(cond: Expr[Boolean])(using q: Quotes): Expr[Unit] = {
import q.reflect.*
val src = Expr(cond.asTerm.show)
'{ if (!${ cond }) throw new AssertionError("failed: " + ${ src }) }
}กรณีใช้งาน: การตรวจสอบขณะคอมไพล์
ตรวจสอบลิเทอรัล เช่น นิพจน์ประจำหรือหมายเลขพอร์ต ขณะคอมไพล์ เพื่อไม่ให้ค่าที่ไม่ถูกต้องไปถึงช่วงรันไทม์
import scala.quoted.*
inline def port(inline n: Int): Int = ${ portImpl('n) }ยุติการทำงานเมื่ออินพุตไม่ถูกต้อง
ดึงค่าลิเทอรัลออกมา ตรวจสอบค่า แล้วเรียก report.errorAndAbort เมื่อค่าไม่ถูกต้อง วิธีนี้เปลี่ยนข้อผิดพลาดขณะรันไทม์ให้เป็นข้อผิดพลาดขณะคอมไพล์
import scala.quoted.*
def portImpl(n: Expr[Int])(using q: Quotes): Expr[Int] = {
import q.reflect.*
val v = n.valueOrAbort
if (v < 1 || v > 65535) report.errorAndAbort("invalid port")
n
}กรณีใช้งาน: การสร้างคลาสชนิด
แมโคร (มักใช้ร่วมกับ inline และ scala.deriving.Mirror) สามารถสร้างอินสแตนซ์ของคลาสชนิด เช่น ตัวเข้ารหัส JSON สำหรับคลาสแบบกรณีใด ๆ โดยแทบไม่ต้องเขียนโค้ดประกอบ
import scala.deriving.Mirror
trait Show[T] { def show(t: T): String }
inline def derived[T](using Mirror.Of[T]): Show[T] = ???การใช้ Mirror
Mirror เปิดเผยชนิดและป้ายกำกับของฟิลด์ในผลิตภัณฑ์ขณะคอมไพล์ เมื่อใช้ร่วมกับ inline คุณจะวนซ้ำผ่านฟิลด์ต่าง ๆ เพื่อสร้างอินสแตนซ์ได้
import scala.deriving.*
import scala.compiletime.*
inline def labels[T](using m: Mirror.ProductOf[T]): List[String] =
constValueTuple[m.MirroredElemLabels].toList.map(_.toString)กรณีใช้งาน: การบันทึกข้อมูลพร้อมตำแหน่ง
แมโครสามารถอ่าน Position จาก API ของ reflect เพื่อแนบชื่อไฟล์และหมายเลขบรรทัดไปกับข้อความบันทึก โดยไม่เสียค่าใช้จ่ายขณะรันไทม์
import scala.quoted.*
def posImpl(using q: Quotes): Expr[String] = {
import q.reflect.*
val p = Position.ofMacroExpansion
Expr(s"${p.sourceFile.name}:${p.startLine + 1}")
}กรณีที่ไม่ควรใช้แมโคร
แมโครมีประสิทธิภาพสูง แต่ดูแลรักษาและแก้จุดบกพร่องได้ยาก ควรใช้ฟังก์ชันธรรมดา เมธอดแบบ inline หรือการสร้างโดยใช้ given ก่อน และเลือกใช้แมโครเมื่อวิธีเหล่านั้นไม่สามารถแสดงความต้องการได้เท่านั้น
การทดสอบแมโคร
ทดสอบ พฤติกรรมที่สร้างขึ้น เช่นเดียวกับโค้ดทั่วไป และทดสอบให้อินพุตที่ไม่ถูกต้องทำให้คอมไพล์ไม่ผ่าน โดยใช้เครื่องมืออย่าง typeCheckErrors จากชุดเครื่องมือทดสอบขณะคอมไพล์
ตัวอย่างเทียบเท่าขณะรันไทม์
แมโครตรวจสอบขณะคอมไพล์ให้ผลเช่นเดียวกับการตรวจสอบขณะรันไทม์ที่ทำงานได้ในตัวเองนี้ แต่ข้อผิดพลาดจะเกิดขึ้นระหว่างคอมไพล์แทนที่จะเกิดขณะรันไทม์
object Main {
def port(n: Int): Int = {
require(n >= 1 && n <= 65535, "invalid port")
n
}
def main(args: Array[String]): Unit = {
println(port(8080)) // 8080
}
}ตรวจสอบความเข้าใจอย่างรวดเร็ว
ข้อได้เปรียบหลักของการตรวจสอบลิเทอรัลด้วยแมโครแทนการตรวจสอบขณะรันไทม์คืออะไร
สรุป
คุณได้สำรวจกรณีใช้งานจริงของแมโคร:
assertที่เก็บซอร์ส- การตรวจสอบขณะคอมไพล์ด้วย
errorAndAbort - การสร้างคลาสชนิดผ่าน
Mirror - การบันทึกข้อมูลที่รู้ตำแหน่ง
- เวลาที่ควรหลีกเลี่ยงแมโครและวิธีทดสอบแมโคร
คุณเรียนจบหลักสูตรเมตาโปรแกรมมิงและแมโครแล้ว
เรียนรู้ Scala ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 39
- บทเรียน
- 143
คำถามที่พบบ่อย
บทเรียน “มาโครเชิงปฏิบัติ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “มาโครเชิงปฏิบัติ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Scala for Backend Engineering & Functional Programming ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “มาโครเชิงปฏิบัติ”
กรณีใช้งาน คุณปฏิบัติ Scala for Backend Engineering & Functional Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Scala for Backend Engineering & Functional Programming บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “มาโครเชิงปฏิบัติ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม
ได้ บทเรียน Scala for Backend Engineering & Functional Programming ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เมธอด Inline
- พื้นฐานมาโคร
- เครื่องหมายอัญประกาศและการแทรกโค้ด
- มาโครเชิงปฏิบัติ