Skip to content

関数

Onionでは def キーワードで名前付き関数(メソッド)を定義します。ラムダ式(匿名関数)もサポートしています。

基本的な関数定義

def greet(name: String): String = "Hello, " + name + "!"

val message: String = greet("Alice")
println(message)  // "Hello, Alice!"

式ボディ(=)と文ボディ({ })の両方が使えます:

def square(x: Int): Int = x * x           // 式ボディ

def max(a: Int, b: Int): Int {            // 文ボディ
  if a > b { return a }
  return b
}

デフォルト引数と名前付き引数

パラメータにデフォルト値を設定できます。呼び出し側は省略したり名前を指定して渡せます:

def greet(name: String, greeting: String = "Hello"): String {
  return greeting + ", " + name
}

greet("kota")                         // Hello, kota
greet("kota", "Yo")                   // Yo, kota
greet(greeting = "Hi", name = "kota") // 名前付き引数(順序自由)

可変長引数(Varargs)

末尾の Type... パラメータで可変個の引数を配列として受け取ります:

def join(parts: String...): String {
  var r = ""
  foreach p: String in parts { r = r + p }
  return r
}

join("a", "b", "c")   // "abc"
join(existingArray)   // 配列をそのまま渡せる

拡張メソッド(Extension Methods)

extension ブロックで既存の型(Javaクラスを含む)にメソッドを追加できます:

extension String {
  def shout(): String { return this.toUpperCase() + "!" }
}

println("hello".shout())   // HELLO!

末尾再帰の最適化

末尾位置の自己再帰呼び出しはコンパイラが自動的にループに変換します。大きな深さでもスタックオーバーフローが起きません:

def factorialTail(n: Int, acc: Int): Int {
  if n <= 1 { return acc }
  return factorialTail(n - 1, n * acc)  // 末尾呼び出し → ループに最適化
}

def factorial(n: Int): Int = factorialTail(n, 1)

println(factorial(1000))  // スタックオーバーフローなし

高階関数

関数を引数として受け取ったり返したりできます:

def applyTwice(f: (Int) -> Int, value: Int): Int {
  val temp: Int = f.call(value)
  return f.call(temp)
}

val increment: (Int) -> Int = (x: Int) -> { return x + 1; }
val result: Int = applyTwice(increment, 5)  // 7

staticメソッド

クラスレベルのメソッドは static で定義し、:: でアクセスします:

class MathUtils {
  public:
    static def square(x: Int): Int = x * x
    static def cube(x: Int): Int = x * x * x
}

println(MathUtils::square(5))  // 25
println(MathUtils::cube(3))    // 27

次のステップ