2012-11-06 22 views
39

Chuỗi suy được available in Scala bắt đầu Scala 2.10Nội suy chuỗi trong Scala 2.10 - Làm thế nào để nội suy một biến String?

Đây là ví dụ cơ bản

val name = "World"   //> name : String = World 
val message = s"Hello $name" //> message : String = Hello World 

tôi đã tự hỏi nếu có một cách để làm suy động, ví dụ như sau (không biên dịch, chỉ dành riêng cho mục đích minh hoạ)

val name = "World"   //> name : String = World 
val template = "Hello $name" //> template : String = Hello $name 
//just for illustration: 
val message = s(template)  //> doesn't compile (not found: value s) 
  1. Có cách nào để "tự động" đánh giá một chuỗi như vậy? (hoặc nó đã sai/không thể)

  2. Và chính xác s là gì? nó không phải là một phương pháp def (apparently it is a method on StringContext), và không phải là một đối tượng (nếu nó được, nó sẽ ném một lỗi biên dịch khác với không tìm thấy tôi nghĩ)


Trả lời

29

s thực sự là một phương pháp trên StringContext (hoặc một cái gì đó mà có thể được ngầm chuyển đổi từ StringContext). Khi bạn viết

whatever"Here is text $identifier and more text" 

trình biên dịch desugars nó vào

StringContext("Here is text ", " and more text").whatever(identifier) 

Theo mặc định, StringContext mang đến cho bạn s, f, và raw * phương pháp.

Như bạn có thể thấy, trình biên dịch tự chọn ra tên và đưa nó vào phương thức. Vì điều này xảy ra vào thời gian biên dịch, bạn không thể thực hiện nó một cách hợp lý - trình biên dịch không có thông tin về các tên biến trong thời gian chạy.

Bạn có thể sử dụng các vars, tuy nhiên, để bạn có thể hoán đổi các giá trị bạn muốn. Và phương pháp mặc định s chỉ gọi toString (như bạn mong muốn), do đó bạn có thể chơi các trò chơi như

class PrintCounter { 
    var i = 0 
    override def toString = { val ans = i.toString; i += 1; ans } 
} 

val pc = new PrintCounter 
def pr[A](a: A) { println(s"$pc: $a") } 
scala> List("salmon","herring").foreach(pr) 
1: salmon 
2: herring 

(0 đã được gọi bằng REPL trong ví dụ này).

Đó là điều tốt nhất bạn có thể làm.

* raw bị hỏng và không được dự kiến ​​sẽ được sửa cho đến 2.10.1; chỉ văn bản trước một biến thực sự là thô (không xử lý thoát). Vì vậy, giữ tắt bằng cách sử dụng một cho đến khi 2.10.1 là ra, hoặc nhìn vào mã nguồn và xác định của riêng bạn. Theo mặc định, không có xử lý thoát, do đó việc xác định quy trình của riêng bạn khá dễ dàng.

+1

Một bổ sung nhỏ. Không chỉ có thể sử dụng số nhận dạng. Bất kỳ biểu thức scala hợp lệ có thể được đặt ở giữa $ {}. – pedrofurla

7
  1. Chuỗi suy xảy ra tại thời gian biên dịch, vì vậy trình biên dịch thường không có đủ thông tin để nội suy s(str). Nó mong đợi một chuỗi chữ, according to the SIP.
  2. Dưới Sử dụng nâng cao trong tài liệu bạn đã liên kết, được giải thích rằng biểu thức của biểu mẫu id"Hello $name ." được dịch tại thời gian biên dịch thành new StringContext("Hello", "."). id(name).

Lưu ý rằng id có thể là nội suy do người dùng xác định được giới thiệu thông qua lớp ẩn. Các tài liệu đưa ra một ví dụ cho một người xen vào json,

implicit class JsonHelper(val sc: StringContext) extends AnyVal { 
    def json(args: Any*): JSONObject = { 
    ... 
    } 
} 
1

Điều này vốn dĩ không thể thực hiện được: tên biến cục bộ không có sẵn tại thời gian thực thi - có thể được giữ xung quanh như biểu tượng gỡ lỗi, nhưng cũng có thể bị tước. (Tên biến thành viên là, nhưng đó không phải là những gì bạn mô tả ở đây).

9

Đây là một giải pháp khả thi để # 1 trong bối cảnh của câu hỏi ban đầu dựa trên câu trả lời tuyệt vời Rex

val name = "World"     //> name: String = World 
val template = name=>s"Hello $name" //> template: Seq[Any]=>String = <function1> 
val message = template(name)  //> message: String = Hello World 
+2

Với Scala 2.11.5 dòng thứ hai cho lỗi "thiếu tên kiểu tham số". Tôi nghĩ rằng nó cần phải được viết như 'val template = (tên: Bất kỳ) => s" Xin chào $ name "' hoặc 'def template (tên: Bất kỳ) = s" Xin chào $ name "' – Suma

+0

bạn đã thêm 'val name = "Thế giới" trước đây? Tôi nghĩ nó giúp suy luận kiểu, và nếu không có nó, bạn sẽ thực sự cần phải bao gồm loại tên ... nói cách khác, tôi không biết liệu $ name có che giấu tên tham số hay không ... –

+0

Tôi đã dán cả ba dòng vào một nguồn Scala. Tôi không thể biên dịch nó trừ khi tôi thêm chú thích kiểu vào tham số tên. – Suma