0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

fluorite-7 日本語チュートリアル Part 4 変数と関数

Last updated at Posted at 2020-06-20

チュートリアルトップ

←前回 次回→

このパートでは、関数を生成して名前を付けることを扱います。

レッスン1 変数

fluorite-7では、変数名: 値; 式という形で変数を宣言し、使用します。

$ fl7 'x: 10; x * 7'
70

var: valは変数を宣言しつつ代入を行います。
fluorite-7では、変数は宣言時に必ず代入を行う必要があります。

変数はいくつでも宣言できます。

$ fl7 'x: 10; y: x * 7; y * 10'
700

レッスン2 変数のスコープ

変数は、宣言された部分より後の箇所からのみ利用できます。
また、括弧で囲われた内部で宣言された変数は、外部からは見えません。

次の式では括弧の中で宣言されたxを括弧の外側から参照して、ストリーマを生成しようとしていますが、括弧の外ではxは未定義の識別子になるため、同内容の文字列がそのまま現れています。

$ fl7 '(x: 10; 5), x'
5
x

この場合、式を変形してxの宣言を括弧から取り外すことでxが見えるようになります。

$ fl7 'x: 10; 5, x'
5
10

レッスン3 変数に代入できる値

変数には、式の結果であれば何でも代入できます。
fluorite-7では変数に型が存在しません。

$ fl7 'x: [123, 456, 789]; x[2], x[1], x[0]'
789
456
123

同様にストリーマを変数に入れることもできます。

$ fl7 'x: 1 .. 5; [x], x'
1,2,3,4,5
1
2
3
4
5

変数に入れられたストリーマは、使われるたびに同じ順序で値を返却します。
つまり、ストリーマは何度でも使いまわすことができます
これが、ストリーマが単に「ストリーム」と呼ばれていない理由です。

レッスン4 関数の生成

fluorite-7では、「引数名->式」という形で関数を生成できます。
この演算子をラムダ演算子と呼びます。

$ fl7 'x -> x * 10'
[FluoriteFunction]

xでも10でもxxxxxxxxxxとかでもなく、[FluoriteFunction]という何かよくわからない文字が出ました。
関数を出力しようとすると、[FluoriteFunction]と出力されます。

これだけでは何が生成されたのか分からないため、次のレッスンに進みましょう。

レッスン5 関数の適用

関数は、「関数(引数)」という形で使用します。

$ fl7 '(x -> x * 10)(7)'
70

「xを与えたらxを10倍して返す関数」に対して、7を与えました。
関数は7をxとして受け取り、関数の本文ではxで表される7を10倍にして返しました。
関数から帰ってきた70がソースコードの値となり、70が出力されました。

レッスン6 関数への命名

fluorite-7の関数は、「値」の一種です。
そのため、変数に入れることができます。

$ fl7 'f: x -> x * 10; f(7)'
70

変数fに対してx -> x * 10で表される関数を割り当てて、fに格納された関数をf(7)という形で呼び出しています。
fluorite-7では、変数に入れられて名前で呼ぶことができるようになった関数が名前付き関数です。
逆に言うと、関数自体には名前はなく、変数に入れることで初めて名前で呼べるようになります。

レッスン7 高階関数

関数は引数として値を受け取れます。
関数は値の一種です。
そのため、関数に関数を渡すこともできます。

$ fl7 'doubleFunc: f -> x -> f(f(x)); doubleFunc(x -> x * 10)(7)'
700

いきなり複雑になりました。
整形してみます。

doubleFunc: f -> (
  x -> f(f(x))
);
doubleFunc(x -> x * 10)(7)

関数doubleFuncは、関数fを受け取る関数で、戻り値はx -> f(f(x))で表される関数です。
x -> f(f(x))は何かというと、値xを受け取ったら、関数fを2回適用して返す関数です。
ということは、doubleFuncは「値を入れたら値を加工して返す関数」で呼び出すことができ、それを更に「値」で呼び出すことができます。
それがdoubleFunc(x -> x * 10)(7)です。
x -> x * 10は「値を入れたら値を10倍して返す関数」で、doubleFunc(x -> x * 10)は「値を入れたら値を10倍してまた10倍して返す関数」です。
それに7を入力しているので、7を2回10倍した700が得られます。

レッスン8 複数の引数

関数は引数を0個や複数個取ることもできます。

$ fl7 'f: () -> 10; f, f()'
[FluoriteFunction]
10

$ fl7 'f: (x; y) -> x * y; f, f(4; 5)'
[FluoriteFunction]
20

関数の引数は、カンマ,ではなくセミコロン;で区切ります。
列挙演算子,で区切って並べたものは一つの値であるストリーマです。
ストリーマを受け取る関数に対しては、ストリーマの要素を,で区切って与えます。

$ fl7 'sum: _ -> +_; sum(4, 6)'
10

レッスン9 関数の引数の書き方

さて、ラムダ演算子の左辺の書き方は少々特殊です。
以下のものはすべて同じ意味です。

(x; y) -> x * y
(x, y) -> x * y
x, y -> x * y

まず、ラムダ演算子の左辺は,区切りでもかまいません。
また、引数が0個の場合を除いて、それを取り囲む括弧は省略できます。
これにより、関数の宣言部分では括弧をすべて省略することができます。

$ fl7 'mul: a, b -> a * b; mul(4; 6)'
24

関数に関連する演算子の結合優先度は、以下の通りです。

  • ↑高優先度
  • その他の算術演算子 + -
  • 列挙演算子 ,
  • ラムダ演算子 ->
  • 変数宣言演算子 :
  • 文の区切り ;
  • ↓低優先度

これにより、まず関数の本文の列挙要素が一番先に結合し、その次に列挙部分が結合し、そのあとで関数になり、そして変数になり、そのあとで;によって変数宣言が完了します。
実はラムダ演算子の左辺にもこの優先度が適用されています。
そのため、,で区切られた引数の羅列のあとに->が適用され、括弧が不要となります。

レッスン10 クロージャ

記述された場所から参照できる変数を本文の中から参照することができる関数をクロージャと呼びます。
fluorite-7の関数はすべてクロージャです。

$ fl7 '(x: 10; () -> x)()'
10

関数を使うと、変数をスコープ外から参照できます。

レッスン11 再帰関数

実は変数宣言演算子:で宣言した変数は、:の右辺からもアクセスすることができます。
これを使うと、再帰関数を作ることができます。

$ fl7 'f: n -> n === 0 ? 1 : n * f(n - 1); f(6)'
720
f: n -> n === 0
  ? 1
  : n * f(n - 1);
f(6)

これは階乗を計算する再帰関数です。
a === 0 ? b : cの意味は、aが0であればbを使用し、そうでなければcを使用するという意味です。

まとめ

  • 変数を宣言するにはvar: val;と書く。
  • 括弧の中でも変数を宣言できる。
  • 変数はそれを取り囲むもっとも内側の括弧の以降の部分から利用できる。
  • ストリーマを何度も使うことができる。
  • 関数はargs -> formulaと書く。
  • 変数に関数を代入すると名前付き関数として使える。
  • 関数に関数を渡せる。
  • 関数呼び出しの引数の区切りは;、関数生成の引数の区切りは;または,
  • 関数内から関数外の変数を呼べる。
  • 宣言された関数内からその関数自身を呼べる。

part 5

次回→

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?