Cで高階関数を書くには……関数ポインタかっ!と思い出したのはいいもの書き方をすっかり忘れていて死んだ、という話。SICP の Exercise 1.32 を参照。

(define (accumulate combiner null-value term next a b)
  (if (> a b)
      null-value
      (combiner (term a)
                (accumulate combiner null-value term next (next a) b))))

;; 1-10 の総和
(accumulate + 0 (lambda (x) x) (lambda (x) (+ x 1)) 1 10)
;; 1-10 の階乗
(accumulate * 1 (lambda (x) x) (lambda (x) (+ x 1)) 1 10)

引数の順番はちょっと変えた。まあこれはいいとして。Cで書くとこんな感じ?

#include
int accumulate(int (*combiner)(int, int), int null_value, int (*term)(int), int (*next)(int), int a, int b)
{
  if(a > b)
    return null_value;
  else
    return (*combiner))*1(;
}

int com1(int a, int b){ return a+b;}
int com2(int a, int b){ return a*b;}
int f(int a){ return a;}
int inc(int a){ return a+1;}

int main()
{
  printf("%d\n", accumulate(com1, 0, f, inc, 1, 10));
  printf("%d\n", accumulate(com2, 1, f, inc, 1, 10));
  return 0;
}

感想

  • 関数ポインタの書式が覚えられない
  • セミコロンをつけないといけないのがめんどくさい
  • ちょっと使いたいだけなのに関数を定義しないといけないのがめんどくさい
  • ((〜)) を表示したいときは ))*2(( って書かないといけないってのは酷い仕様だと思った(←はてなの話!?)

ちなみに Python だとこんな感じ。

def accumulate(combiner, null_value, term, next, a, b):
  if a > b:
    return null_value
  else:
    return combiner(term(a), accumulate(combiner, null_value, term, next, next(a), b))

print accumulate(lambda x, y: x+y, 0, lambda x: x, lambda x: x+1, 1, 10)
print accumulate(lambda x, y: x*y, 1, lambda x: x, lambda x: x+1, 1, 10)

といった具合に SICP の問題を色々な言語で書いてみると意外と楽しいということがわかったのでこれからも書いたり書かなかったりしていきたい。あと、SICP のことを「しくぴー」と読(呼)んで萌え擬人化していきたい。いきたくない。

*1:*term)(a), accumulate(combiner, null_value, term, next, (*next)(a), b

*2: