見出し画像

Retro-gaming and so on

継続受け渡しスタイル

「継続」と言う機能はScheme及びScheme系言語特有の機能だ(例外的に継続を持ってるプログラミング言語はRubyくらいしかないだろう・・・と言う事は「権威ある公式仕様」を持ってる言語で唯一「継続」を持ってるのはRubyだ、って事かもしんない)。
ただし、「継続受け渡しスタイル」(CPS)でプログラムを記述する、と言う事自体はラムダ式が使える言語なら基本何でも出来る。なんせ、「継続受け渡しスタイル」と厳つい名称は付いてるが、本質的にはCPSは単なる高階関だから、だ。
従って、Racketで

(define (map1 proc xs k)
 (if (null? xs)
  (k '())
  (map1 proc (cdr xs) (lambda (u)
            (k (cons (proc (car xs)) u))))))

こう書ける物は、いつぞや見せたが、Pythonでも

def map1(proc, xs, k):
 if xs == []:
  return k([])
 else:
  return map1(proc, xs[1:], lambda u:
        k([proc(xs[0])] + u))

と書ける。
当然、OCamlでも記述可能だ。

let rec map1 proc xs k = match xs with
  [] -> k []
 | first::rest -> map1 proc rest (fun u -> k ((proc first)::u))

Pythonのラムダ式はreturnが要らないし、LispやOCamlは「値を返す」仕様になってるからいいが、割にJavaScriptはマジメで、無名関数でもreturnが入らないとならない。

function map1(proc, xs, k) {
 if (!xs.length) {
  return k([]);
 } else {
  return map1(proc, xs.slice(1), (u) => {return k([proc(xs[0])].concat(u))});
 }
}

Rubyもちとメンド臭い。枠組みは同じだし、基本「必ず返り値を返す」仕様を持ってるんだが、メソッドを呼び出す際にはcallが必要になる。

def map1(proc, xs, k)
 if xs.empty?
  k.call([])
 else
  map1(proc, xs[1..-1], -> (u) {k.call([proc.call(xs[0])] + u)})
 end
end


  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最近の「プログラミング」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事