0Pricing
Scala for Backend Engineering & Functional Programming · บทเรียน

เครื่องหมายอัญประกาศและการแทรกโค้ด

โค้ดในฐานะข้อมูล

เครื่องหมายอัญประกาศและการแทรกโค้ด เป็นบทเรียน Scala for Backend Engineering & Functional Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Scala for Backend Engineering & Functional Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน

โค้ดในฐานะข้อมูล

เมตาโปรแกรมมิงใน Scala 3 มองว่า โค้ดเป็นข้อมูล โดย quote จะเก็บส่วนหนึ่งของโค้ดเป็น Expr ส่วน splice จะแทรก Expr กลับเข้าไปในโค้ด

Quote: '{ ... }'

'{ expr } เปลี่ยนนิพจน์ให้เป็น Expr[T] โค้ดจะไม่ถูกรัน แต่จะกลายเป็นค่าที่แมโครนำไปจัดการได้

import scala.quoted.*

def greeting(using Quotes): Expr[String] = '{ "Hello, " + "world" }

Splice: ${ ... }

${ expr } จะแทรก Expr เข้าไปใน quote ที่ครอบอยู่ เพื่อเชื่อมส่วนของโค้ดที่สร้างขึ้นเข้าด้วยกัน Quote และ splice เป็นการดำเนินการที่ผกผันกัน

import scala.quoted.*

def doubled(x: Expr[Int])(using Quotes): Expr[Int] = '{ ${ x } * 2 }

การ Splice ค่าที่ถูกยกขึ้น

ภายใน quote คุณสามารถ splice ค่าที่ถูกยกขึ้นด้วย Expr(...) เพื่อฝังค่ายามคอมไพล์ลงในโค้ดที่สร้างขึ้นได้

import scala.quoted.*

def addN(x: Expr[Int], n: Int)(using Quotes): Expr[Int] =
  '{ ${ x } + ${ Expr(n) } }

การสร้างโค้ดแบบเรียกซ้ำ

แมโครสร้างนิพจน์ที่ซับซ้อนได้ด้วยการผสาน quote และ splice ในลูปหรือการเรียกซ้ำ เช่น การคลี่การยกกำลังให้เป็นการคูณซ้ำ ๆ

import scala.quoted.*

def pow(x: Expr[Double], n: Int)(using Quotes): Expr[Double] =
  if (n == 0) '{ 1.0 } else '{ ${ x } * ${ pow(x, n - 1) } }

การจับคู่รูปแบบบน Quote

คุณสามารถ แยกโครงสร้างโค้ดได้ด้วยการจับคู่กับรูปแบบของ quote วิธีนี้จะตรวจสอบรูปร่างของนิพจน์เพื่อปรับให้เหมาะสมหรือเขียนใหม่

import scala.quoted.*

def optimize(e: Expr[Int])(using Quotes): Expr[Int] = e match {
  case '{ ($a: Int) + 0 } => a
  case _                  => e
}

Type[T] และชนิดที่ใส่ไว้ใน Quote

เช่นเดียวกับที่ Expr[T] เก็บนิพจน์ไว้ Type[T] ก็เก็บชนิดไว้เช่นกัน ใช้ '[T] เพื่อ quote ชนิด และใช้ given Type[T] เพื่อ splice ชนิดในตำแหน่งที่ต้องการชนิด

import scala.quoted.*

def typeName[T](using t: Type[T], q: Quotes): Expr[String] =
  Expr(Type.show[T])

API ของ reflect

สำหรับงานระดับล่าง quotes.reflect จะเปิดเผยต้นไม้ไวยากรณ์นามธรรม (Term, Symbol, TypeRepr) ทำให้คุณตรวจสอบหรือสร้างโค้ดที่เกินกว่าที่ quote จะแสดงได้โดยตรง

import scala.quoted.*

def show(e: Expr[Any])(using q: Quotes): Expr[String] = {
  import q.reflect.*
  Expr(e.asTerm.show)
}

การแปลงไปกลับระหว่างระดับ

แปลง Expr เป็น Term ด้วย asTerm และแปลงกลับด้วย asExpr / asExprOf[T] วิธีนี้เชื่อม API ของ quote ระดับสูงเข้ากับ API ของการสะท้อน

import scala.quoted.*

def ident[T: Type](e: Expr[T])(using q: Quotes): Expr[T] = {
  import q.reflect.*
  e.asTerm.asExprOf[T]
}

ตัวอย่างเทียบเท่าขณะรันไทม์

แมโครยกกำลังแบบเรียกซ้ำด้านบนจะขยายเป็นการคูณธรรมดา ตัวอย่างขณะรันไทม์ที่ทำงานได้ในตัวเองนี้แสดงผลลัพธ์เดียวกับที่โค้ดที่สร้างขึ้นจะให้

object Main {
  def pow(x: Double, n: Int): Double =
    if (n == 0) 1.0 else x * pow(x, n - 1)
  def main(args: Array[String]): Unit = {
    println(pow(3.0, 2)) // 9.0
  }
}

Quote และ Splice เป็นการดำเนินการที่ผกผันกัน

โปรดจำความสัมพันธ์แบบคู่กันนี้ไว้: '{ } ยกโค้ดขึ้นเป็น Expr ส่วน ${ } นำ Expr กลับลงไปเป็นโค้ด การซ้อนทั้งสองอย่างให้ถูกต้องคือหัวใจของการสร้างแมโคร

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ตัวดำเนินการ splice ${ x } ทำอะไรเมื่ออยู่ภายใน quote

สรุป

คุณได้เรียนรู้เรื่อง quote และ splice:

  • '{ } quote โค้ดให้เป็น Expr[T]
  • ${ } splice Expr เข้าไปในโค้ด
  • การจับคู่รูปแบบของ quote เพื่อแยกโครงสร้างโค้ด
  • Type[T] และ API ของ reflect

ถัดไป: แมโครภาคปฏิบัติ

คำถามที่พบบ่อย

บทเรียน “เครื่องหมายอัญประกาศและการแทรกโค้ด” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “เครื่องหมายอัญประกาศและการแทรกโค้ด” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ 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 ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “เครื่องหมายอัญประกาศและการแทรกโค้ด” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม

ได้ บทเรียน Scala for Backend Engineering & Functional Programming ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เมธอด Inline
  2. พื้นฐานมาโคร
  3. เครื่องหมายอัญประกาศและการแทรกโค้ด
  4. มาโครเชิงปฏิบัติ
← กลับไปที่ Scala for Backend Engineering & Functional Programming