ちょっとだけ

tutorial を見て、べき乗な手続きを試してみた。
べき乗の一番簡単な実装としては

  • b の 1 乗は b
  • b の n 乗は b * b^(n - 1)

となるんですが、erlang では上記の直球な記述が可能。

-module(tut0).
-export([expt/2]).

expt(B, 1) ->
    B;
expt(B, N) ->
    B * expt(B, N - 1).

これでイケる。SICP にある逐次平方なソレの解を erlang でどう書くのか、は微妙。組み込み、な手続きはどうすれば分かるのか。

ちなみに以下だと Warning が出る。

-module(tut0).
-export([expt/2]).

expt(B, 0) ->
    1;
expt(B, N) ->
    B * expt(B, N - 1).

こんな感じ。

1> c(tut0).
./tut0.erl:4: Warning: variable 'B' is unused
2>

google 先生に探してもらってたら剰余演算子は rem との事。もう少し時間がありそうなので実装を考えてみよ。

で、逐次平方なソレですが、再帰ループする。何故だ。

(define (square n)
  (* n n))
(define (exptFast b n)
  (cond ((= 0 n) 1)
	((even? n) (square (exptFast b (/ n 2))))
	(else
	 (* b (exptFast b (- n 1))))))

を書きかえてみたのが以下。ループしている模様。(一部のみ)
# ちなみに square な手続きを作ったり、
# lambda みたいの (無名関数?) を使ったりしてますが駄目

-module(tut0).
-export([test/2]).

test(_, 0) ->
    1;
test(X, Y) when Y rem 2 == 0 ->
    N = test(X, Y / 2),
    N * N;
test(X, Y) ->.
    X * test(X, Y - 1).

面倒臭いのでもう少し SICP 継続かな。(何

さらに追記

jmkさんからコメントを頂いた。動く。

これでも

-module(tut0).
-export([test/2]).

test(_, 0) ->
    1;
test(X, Y) when Y rem 2 == 0 ->
    square(test(X, Y div 2));
test(X, Y) ->
    X * test(X, Y - 1).

square(X) ->
    X * X.

動くしこれでも

-module(tut0).
-export([expt/2]).
-export([exptFast/2]).
-export([max/2]).
-export([test/2]).

test(_, 0) ->
    1;
test(X, Y) when Y rem 2 == 0 ->
    S = fun(N) -> N * N end,
    S(test(X, Y div 2));
test(X, Y) ->
    X * test(X, Y - 1).

動く事を確認。

/ と div の差ですが、コメント頂いた通り、_/ 2 すると整数でなくなるので 0 のマッチングに失敗し、止まりません。_との事。駄目な実装だと

1> tut0:test(2,2).

でループしていた。試してみると

1> 1 rem 2.
1
2> 2 / 2.
1.00000
3> 2 / 2 rem 2.

=ERROR REPORT==== 3-May-2007::20:11:57 ===
Error in process <0.70.0> with exit value: {badarith,[{erl_eval,eval_op,3},{shell,exprs,6},{shell,eval_loop,3}]}

** exited: {badarith,[{erl_eval,eval_op,3},
                      {shell,exprs,6},
                      {shell,eval_loop,3}]} **
4> 1.00000 rem 2.

=ERROR REPORT==== 3-May-2007::20:12:29 ===
Error in process <0.73.0> with exit value: {badarith,[{erl_eval,eval_op,3},{shell,exprs,6},{shell,eval_loop,3}]}

** exited: {badarith,[{erl_eval,eval_op,3},
                      {shell,exprs,6},
5>

失敗したまま、続くのか。tutorial 微妙、ってかきちんと仕様を確認せずにヤッてるのがダウトと言えるかも (を

またまた追記

jmkさんの Programming Erlang の訳は本を買わんと見れんのか。とほほ、と言いつつ referecnce を見つけた。(見つけてた?)

バージョン微妙?