Java で以下のコードにてgreeting()を呼び出すと、
public String hello() { return "HELLO"; } public void print(String s) { System.out.println(s); } public void greeting() { print(hello()); }
最初に hello() メソッドが呼ばれ、その結果の HELLO という文字列が print() の引数として渡されます。
同じようにScalaにて。
def hello() = "HELLO" def print(s : String) = { println(s) } def greeting() = print(hello())
greeting() を呼び出すと、まぁ、同じように HELLO を出力します。
ここで Scala では print を以下のように書くことができます。
def print(s : => String) = { println(s) }
この場合も同じように HELLO が出力されますが、なにが違うのでしょうか。
コードを以下のように変更して greeting() を呼び出すと、
def hello() = { println("in hello()") "HELLO" } def print(s : => String) = { println("print() start") println(s) println("print() end") } def greeting() = print(hello())
以下のような結果が得られます。
print() start in hello() HELLO print() end
最初に print() が呼び出され、その後で hello() が呼び出されています。
なにが起きたかというと、print() 関数に、hello() という関数が s という名前のコードブロックとして渡されています。print() 関数は、何かわからないけど結果が String となるコードブロックの s を受け取って、自身の中でコードブロックを実行しているのです。
以下のように、変数と型の間に => を記述すると Call-by-name(名前渡し) の宣言となり、引数のメソッドの実行を遅らせることができます。
def print(s : => String) = ・・
ログ出力時などで、
if(log.isDebugEnable()) { log.debug(hoge() + "hoge"); }
などと書かなくてすむようになったりします。