2011-12-16 30 views

Trả lời

32

Các "ảo" Mẫu trình khớp là một viết lại của khớp hiện có. Động lực để thực hiện điều này là hỗ trợ ảo hóa kết hợp mẫu cho các DSL nhúng đa hình, không liên quan đến 2,10.

Như Iulian nói trong các ý kiến ​​dưới đây: Nó rất giống với cách cho-comprehensions được biên soạn: thay vì trực tiếp tạo mã, họ được dịch sang foreach, map, filter, vv mẫu phù hợp có thể sau đó được dịch sang một loạt của các cuộc gọi phương thức, các DSL đó có thể ghi đè lên. Việc thực hiện mặc định sẽ tôn trọng ngữ nghĩa hiện tại và thách thức là làm cho nó hiệu quả như hiện tại. Có vẻ như Adriaan rất gần với mục tiêu này. Việc triển khai 'ảo hóa' đơn giản hơn và sửa một số lỗi trong quá trình triển khai hiện tại.

"DSL đa hình nhúng" là ý tưởng rằng người ta có thể viết chương trình trong scala không được phép chạy trên JVM. Tức là, scalac sẽ tạo ra một đầu ra mô tả những gì chương trình đang làm. Điều này sau đó có thể được biên dịch lại dựa trên một kiến ​​trúc cụ thể. Những thứ như vậy have been talked about at ScalaDays 2011.

Việc viết lại này cuối cùng sẽ trở thành đối sánh mẫu scala chuẩn. Mẫu phù hợp cũ là (như tôi hiểu nó) không thể duy trì.

+0

Tôi không chắc chắn rằng "trình ghép mẫu ảo là để hỗ trợ ảo hóa khớp mẫu" không phải là điều tôi không thể đoán được. Có lẽ bạn có thể giải thích những gì phù hợp với mô hình ảo hóa thực sự là? –

+24

Nó rất giống với cách biên dịch được biên dịch: thay vì tạo mã trực tiếp, chúng được dịch thành 'foreach',' map', 'filter', vv. có thể ghi đè lên. Việc thực hiện mặc định sẽ tôn trọng ngữ nghĩa hiện tại và thách thức là làm cho nó hiệu quả như hiện tại. Có vẻ như Adriaan rất gần với mục tiêu này. Việc triển khai 'ảo hóa' đơn giản hơn và sửa một số lỗi trong quá trình triển khai hiện tại. –

+0

Xin chào Iulian - nếu chỉ tôi mới có thể trao giải "câu trả lời được chấp nhận" cho bình luận của bạn! –

8

Đáng buồn thay, câu trả lời hiện có (duy nhất) thấp về các bit ngon ngọt và các liên kết trên bình luận bị hỏng. Vì vậy, hãy để tôi cố gắng thêm một ít nước vào đây, vì nếu không có lý do nào khác, tham chiếu của riêng tôi khi tôi thực sự quyết định làm điều gì đó với nó trong tương lai, xem câu trả lời này nằm trên đầu mỗi tìm kiếm google tôi làm.

Trình so khớp mẫu ảo hóa, như đã đề cập, được viết lại cách trình biên dịch Scala xử lý đối sánh mẫu. Nó phục vụ nhiều mục đích, với phần "ảo hóa" của nó có nghĩa là nó là một phần của nỗ lực scala ảo hóa. Nỗ lực đó hơi ngược lại với các macro: nó lấy những thứ "chạy" tại thời gian biên dịch, và di chuyển sau đó để chạy thời gian.

Ví dụ, với sự hiện diện của định nghĩa thích hợp trong phạm vi, một tuyên bố như thế này:

if (false) 1 else 2 

thay vì được biên soạn cho các chi nhánh và literals bytecode, hoặc thậm chí tối ưu hóa để các literal "2", trên thực tế được biên soạn như tuyên bố sau:

__ifThenElse(false, 1, 2) 

Hãy xem scala virtualized wiki để biết thêm thông tin và một số ví dụ về điều này có thể hữu ích cho.

Tôi đã nói, tuy nhiên, trình ghép mẫu khớp được phục vụ cho nhiều mục đích. Một mục tiêu rất quan trọng khác là biến mã spaghetti là mẫu matcher cũ, đầy đủ hoặc đặc biệt và góc trường hợp và lỗi, thành một cái gì đó có thể được lý luận, mở rộng và cải thiện dễ dàng hơn. Điều này viết lại cố định rất nhiều vấn đề mà mọi người chỉ cần đi qua các danh sách các vấn đề chạy mã mẫu cho các vấn đề liên quan đến phù hợp với mô hình và đánh dấu các vấn đề là "cố định" khi họ làm việc. Nó có lỗi mới của riêng nó, nhưng trên một quy mô nhỏ hơn nhiều.

Hiện tại, có rất ít thông tin về cách trình ghép mẫu mới hoạt động, nhưng về cơ bản, nó chuyển thành một vài cuộc gọi phương thức được "triển khai" trong trình biên dịch với đơn lẻ Option. Điều đó sau đó đi vào một giai đoạn tối ưu hóa sản xuất bytecode tối ưu.

Có thể giới thiệu trình kết nối của riêng bạn, mặc dù nó bị khóa phía sau cờ -Xexperimental. Hãy thử đoạn mã sau, sao chép từ bộ kiểm tra của Scala, có và không có cờ rằng:

trait Intf { 
type Rep[+T] 
type M[+T] = Rep[Maybe[T]] 

val __match: Matcher 
abstract class Matcher { 
    // runs the matcher on the given input 
    def runOrElse[T, U](in: Rep[T])(matcher: Rep[T] => M[U]): Rep[U] 

    def zero: M[Nothing] 
    def one[T](x: Rep[T]): M[T] 
    def guard[T](cond: Rep[Boolean], then: => Rep[T]): M[T] 
    def isSuccess[T, U](x: Rep[T])(f: Rep[T] => M[U]): Rep[Boolean] // used for isDefinedAt 
} 

abstract class Maybe[+A] { 
    def flatMap[B](f: Rep[A] => M[B]): M[B] 
    def orElse[B >: A](alternative: => M[B]): M[B] 
} 

implicit def proxyMaybe[A](m: M[A]): Maybe[A] 
implicit def repInt(x: Int): Rep[Int] 
implicit def repBoolean(x: Boolean): Rep[Boolean] 
implicit def repString(x: String): Rep[String] 

def test = 7 match { case 5 => "foo" case _ => "bar" } 
} 

trait Impl extends Intf { 
type Rep[+T] = String 

object __match extends Matcher { 
    def runOrElse[T, U](in: Rep[T])(matcher: Rep[T] => M[U]): Rep[U] = ("runOrElse("+ in +", ?" + matcher("?") + ")") 
    def zero: M[Nothing]            = "zero" 
    def one[T](x: Rep[T]): M[T]          = "one("+x.toString+")" 
    def guard[T](cond: Rep[Boolean], then: => Rep[T]): M[T]   = "guard("+cond+","+then+")" 
    def isSuccess[T, U](x: Rep[T])(f: Rep[T] => M[U]): Rep[Boolean] = ("isSuccess("+x+", ?" + f("?") + ")") 
} 

implicit def proxyMaybe[A](m: M[A]): Maybe[A] = new Maybe[A] { 
    def flatMap[B](f: Rep[A] => M[B]): M[B]       = m + ".flatMap(? =>"+ f("?") +")" 
    def orElse[B >: A](alternative: => M[B]): M[B]     = m + ".orElse("+ alternative +")" 
} 

def repInt(x: Int): Rep[Int] = x.toString 
def repBoolean(x: Boolean): Rep[Boolean] = x.toString 
def repString(x: String): Rep[String] = x 
} 

object Test extends Impl with Intf with App { 
    println(test) 
} 

Kết quả mà không có cờ chỉ là những gì bạn mong muốn:

scala> Test.main(null) 
bar 

Với -Xexperimental, tuy nhiên, thay thế phù hợp với "động cơ" được biên soạn:

scala> Test.main(null) 
runOrElse(7, ?guard(false,?).flatMap(? =>one(foo)).orElse(one(bar))) 

Xem thêm, để biết thêm thông tin, scaladocs cho PatternMatchingMatchMonadInterface.

Tuyên bố từ chối trách nhiệm: phần trên được trích xuất và chạy từ phiên bản Scala trên nhánh chính, sau 2.10.0, do đó có thể có sự khác biệt. Tôi thấy mình buồn bã thiếu trong một môi trường 2.10.0 hoặc 2.10.1 tinh khiết để kiểm tra nó ra, mặc dù.

Các vấn đề liên quan