2012-11-06 12 views
39

文字列補間available in Scalaこれは基本的な例Scala 2.10での文字列補間 - 文字列変数を補間する方法は?

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

動的補間を行うための方法、例えば、存在する場合、私は思っていたであるスカラ2.10

開始されます次

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. 「動的」というような文字列を評価する方法はあります(単に例示目的のために、コンパイルされませんか)? (またはそれは本質的に間違っている/できない)

  2. 正確にはsとは何ですか? それは(それがあった場合、それは私が考えるを見つけていないとは異なるコンパイルエラーを投げているだろう)


答えて

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

sは実際StringContextのメソッド(または暗黙的にStringContextから変換することができるもの)です。あなたは

whatever"Here is text $identifier and more text" 

を書くとき、コンパイラはデフォルトで

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

にそれをdesugars、StringContextf、あなたにsを与え、raw *メソッド。

ご覧のとおり、コンパイラは名前を選択してメソッドに渡します。これはコンパイル時に発生するため、実行時に変数名に関する情報をコンパイラには持っていません。

しかし、varsを使用することで、必要な値に入れ替えることができます。 (あなたが期待される)あなたは

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は既にこの例ではREPLで呼ばれた)のようなゲームをプレイすることができますので、デフォルトs方法はただtoStringを呼び出します。

これは、できる限りのことです。

* rawは壊れており、2.10.1までは固定されていません。変数の前のテキストのみが実際には生である(エスケープ処理なし)。だから、2.10.1が出るまでそれを使わないでください。あるいは、ソースコードを見て自分自身を定義してください。デフォルトでは、エスケープ処理はないので、独自の定義は非常に簡単です。

+1

一つの少量の添加です。識別子だけでなく、任意の有効なスカラ式を$ {}の間に入れることができます。 – pedrofurla

7
  1. 文字列補間方法デフ(apparently it is a method on StringContext)、およびでないオブジェクトではありませんコンパイル時に発生するので、コンパイラは通常、s(str)を補間するのに十分な情報を持っていません。文字列リテラル、according to the SIPが必要です。
  2. の下にある詳細な使用の文書では、id"Hello $name ."という形式の式がコンパイル時にnew StringContext("Hello", "."). id(name)に翻訳されていると説明されています。

idは、暗黙のクラスによって導入されたユーザー定義の補間器です。ドキュメントはjson補間のための例を示し、

1

ローカル変数名は実行時には使用できません。デバッグシンボルとして保持されますが、削除されている可能性もあります。 (メンバ変数の名前は、あなたがここで説明しているものではありません)。ここで

9

はレックスの優れた回答に基づいて元の質問の文脈で第1位に可能な解決策は、

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

Scala 2.11.5では、2行目に "missing parameter type name"というエラーが表示されます。 "Hello $ name" 'または' def template(name:Any)= s "Hello $ name" ' – Suma

+0

あなたは' val 'を追加しましたか?名前= "世界"の前に?私はそれが型推論に役立つと思うし、それがなければ実際に名前の型を含める必要がある...言い換えれば、$ nameがパラメータ名をシャドーイングしているかどうかわからない... –

+0

私は貼り付けた3行すべてをScalaソースに追加します。私はnameパラメータに型名を追加しない限りコンパイルできません。 – Suma

関連する問題