束縛

まだ教科書読み初めたばっかだけど、勉強のログを取ることは重要ということで、適当に記録してく。

束縛

「○○変数の束縛」というように使うようだ。Ocamlの場合は、代入というのではなく「束縛」というらしい。
束縛はletを使う。束縛された変数を使用して計算を行うことができる

以降、「#」で始まる行は入力を表し、他はインタープリタからの出力を表す。

# let pi = 3.1415926535;;
val pi : float = 3.1415926535
# 2.0 *. pi *. 4.0;; (* 半径4の円周 *)
- : float = 25.132741228

関数

関数についても束縛というのだそうだ。

# let enshu r = 2.0 *. pi *. r;;
val enshu : float -> float = <fun>
# enshu 4.0
- : float = 25.132741228

匿名関数

他の言語では無名関数と呼ばれていたりもする。
letで定義しているのは、実際にはfunを使用した式の略式記法なのだそうだ。

# let enshu = fun n -> 2.0 *. pi *. n;;
val enshu : float -> float = <fun>
# enshu 4.0;;
- : float = 25.132741228

perlでやると、

use constant PI => 3.1415926535;
my $enshu = sub{
  my ($r) = @_;
  2.0 * PI * $r;
};
$enshu->(4.0);

匿名関数(無名関数)が使えると何がうれしいかというと、関数を引数にする関数を作れるということかな。

カリー化

引数の一部を束縛した関数を返す。
まだよくわかっていないけど、複数の引数を渡したい場合などで、一部の引数のみ先に処理し、次の引数を処理する為の関数を返すというのがカリー化という認識。

なお、Ocamlでは、引数は一つしか渡せない。複数の引数を渡したいときにはタプル(組)を使用する。

カリー化を使わないconcat
# let concat (s1,s2) = s1 ^ s2 ^ s1;;
val concat : string * string -> string = <fun>
# concat ("abc","def");;
- : string = "abcdefabc"

perlでは

my $concat = sub{
  my ($s1,$s2) = @_;
  "$s1$s2$s1";
};
$concat->("abc","def");
カリー化を使うconcat
let concat_curry s1 = fun s2 -> s1 ^ s2 ^ s1;;
val concat_curry : string -> string -> string = <fun>
# (concat_curry "abc") "def";;
- : string = "abcdefabc"

perlでは、第一引数を束縛し、次に渡された第一引数を処理するクロージャを返す。

my $concat_curry = sub{
  my ($s1) = @_;
  sub{
    my ($s2) = @_;
    "$s1$s2$s1";  
  }
};
$concat_curry->("abc")("def");

Ocamlでもperlでもカリー化した関数と通常の関数とでは呼び出し方法が違う。