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 日本語リファレンス 関数

Last updated at Posted at 2020-09-10

日本語チュートリアルトップ

基礎

関数は、型名FUNCTIONを持つ値である。

() -> 1は0個の引数を取り、常に1を返す関数を生成する式である。
(a) -> a * 10は1個の引数の10倍の値を返す関数を生成する式である。
(a; b) -> a * bは2個の引数の積を返す関数を生成する式である。

関数は呼び出すことができる。

f()は関数fに0個の引数を与えて呼び出す式である。
f(10)は関数fに1個の引数を与えて呼び出す式である。
f(10; 20)は関数fに2個の引数を与えて呼び出す式である。

$ fl7 'TYPE(  () -> 1  )'
FUNCTION
$ fl7 '(  () -> 1  )()'
1
$ fl7 '(  (a) -> a * 10  )(10)'
100
$ fl7 '(  (a; b) -> a * b  )(10; 20)'
200

関数の生成

ラムダ式

ラムダ式は、ラムダ演算子args -> formulaによって関数を生成する式である。
ラムダ演算子は列挙演算子a,b,cと代入系演算子var = val var : valの間の結合優先度を持つ中置演算子である。

argsには括弧( )を書き、その中で;区切りで引数列を記述する。
引数が0個の場合、空の括弧()を記述する。
formulaには関数の本文を記述する。
関数の本文では、引数を参照できる。

() -> 10
(a) -> a
(a; b; c) -> a * b * c

呼び出し時の引数チェック

ラムダ式で生成された関数は、生成時に指定された個数の引数でしか呼び出すことはできない。

引数列の区切り文字は,であってもよい

(a, b, c) -> a * b * c

引数列を囲う( )は省略してもよい

a, b, c -> a * b * c

ただし、引数が0個の場合や区切り文字が;の場合は簡単には適用できない。


Tips この記法を使うと変数への代入時に括弧が要らなくなる。

f : a, b, c -> a * b * c;

即席関数

即席関数は、即席関数演算子\formulaによって関数を生成する式である。
即席関数演算子は、そのほかの前置演算子と等しい結合優先度を持つ前置演算子である。

formulaには関数の本文を記述する。

\50
$ fl7 '(  \50  )()'
50

即席関数は何個の引数でも呼び出せる

$ fl7 '(  \50  )(1; 2; 3; 4; 5)'
50

_で第一引数を参照できる

ただし、第一引数が存在しない場合はNULLが格納されている。

$ fl7 '(  \_  )(50)'
50
$ fl7 '(  \_  )()'
NULL

Tips 前置演算子の結合優先度は後置演算子の後なので、第一引数のアクセサをコンパクトに記述できる。

次の例は、関数を与えると50に適用して返す関数fに、数値を10倍する関数を適用する例である。

$ fl7 'f : \_(50); f(a -> a * 10)'
500

__で引数列全体を参照できる

$ fl7 '(  \__  )()'
{LENGTH:[FluoriteFunction]}
$ fl7 '(  \__  )(10)'
{0:10;LENGTH:[FluoriteFunction]}

$#__で引数の個数、__.0で最初の引数が得られる。

$ fl7 '(  \$#__  )(10; 20; 30; 40; 50)'
5
$ fl7 '(  \__.0  )(10; 20; 30; 40; 50)'
10

配列

配列を関数として呼び出すと、呼び出し時の引数の個数に応じた要素の値が呼び出される。

f : [
  0 : () -> 1;
  1 : a -> a * 10;
  2 : a, b -> a * b;
];
f(), f(5), f(5; 7)
$ fl7 'f : [0 : () -> 1; 1 : a -> a * 10; 2 : a, b -> a * b]; f(), f(5), f(5; 7)'
1
50
35

オブジェクト

オブジェクトを関数として呼び出すと、CALLメソッドが呼び出される。

obj : {
  val : 3;
  CALL : _, a, b -> _.val * a * b;
};
obj(5; 7)
$ fl7 'obj : {val : 3; CALL : _, a, b -> _.val * a * b}; obj(5; 7)'
105

正規表現

正規表現を関数として呼び出すと、マッチが行われる。

$ fl7 '/-(.)-/("-g-").1'
g
$ fl7 '"abc", "123", "abc123" | */^\d+$/'
NULL
123
NULL

ストリーマ

正規表現を関数として呼び出すと、各要素の関数呼び出しのストリーマ結合になる。

$ fl7 'SIN(PI), COS(PI), TAN(PI)'
1.2246467991473532e-16
-1
-1.2246467991473532e-16
$ fl7 '(SIN, COS, TAN)(PI)'
1.2246467991473532e-16
-1
-1.2246467991473532e-16

関数の呼び出し

関数呼び出しアクセス

関数呼び出しアクセス演算子func(args)は、関数を呼び出す後置演算子である。
funcには関数を記述する。
argsには引数列を;区切りで記述する。
引数がゼロ個の場合、argsは省略される。

f0 : () -> 1;
f1 : (a) -> a * 10;
f2 : (a; b) -> a * b;
f0(), f1(), f2(10; 20)
$ fl7 'f : () -> 1; f()'
1
$ fl7 'f : (a) -> a * 10; f(10)'
100
$ fl7 'f : (a; b) -> a * b; f(10; 20)'
200

即席関数呼び出し

即席関数呼び出し演算子*funcは、引数として_を与えて関数を呼び出す前置演算子である。

_ : 50;
f : a -> a * 10;
*f
$ fl7 '_ : 50; f : a -> a * 10; *f'
500

Tips この演算子は即席関数演算子\formulaやパイプ演算子streamer | formulaなど暗黙に識別子_を定義する演算子と組み合わせて使うと強力である。

$ fl7 '1 .. 5 | *SQRT'
1
1.4142135623730951
1.7320508075688772
2
2.23606797749979

関数呼び出しパイプ

関数呼び出しパイプ演算子value => functionは、valuefunctionに適用する、パイプ系演算子と同等の結合優先度を持つ中置演算子である。

$ fl7 '1, 2, 3 => JOIN'
1,2,3

これは、以下と同等である。

$ fl7 'JOIN(1, 2, 3)'
1,2,3

中置関数呼び出し

中置関数呼び出し演算子left `function` rightは、関数functionを、leftおよびrightに対して適用する中置演算子である。

10 `DIV` 3DIV(10; 3)と同等である。

$ fl7 'DIV(10; 3)'
3
$ fl7 '10 `DIV` 3'
3

中置関数呼び出し演算子の結合優先度は、べき乗演算子よりも高い。

$ fl7 ' 10 `DIV`  3  ^ 2 '
9
$ fl7 '(10 `DIV`  3) ^ 2 '
9
$ fl7 ' 10 `DIV` (3  ^ 2)'
1

前置関数呼び出し

前置関数呼び出し演算子``` function arg ``は、関数`function`を、`arg`に対して適用する前置演算子である。

`SQRT` 4SQRT(4)と同等である。

$ fl7 'SQRT(4)'
2
$ fl7 '`SQRT` 4'
2

前置関数呼び出し演算子の結合優先度はそのほかの前置演算子と共通である。

$ fl7 '-`SQRT`--4'
-2

コンポジット

コンポジット123idenは、数値部123と識別子部idenを単位のように繋げて記述することで関数UNIT_idenの呼び出しができる文法である。
123は、1文字以上の半角数字列([0-9]+)もしくは中腹に1個の小数点.を含む2文字以上の半角数字列([0-9]+\.[0-9]+)である
idenは、識別子に利用可能な文字集合のうち、半角数字である10個を除いたもの([a-zA-Z_\u0080-\uFFFF])である。

UNIT_km : _ -> _ * 1000;
UNIT_ : _ -> _ * 1;

4km + 34
$ fl7 'UNIT_km : _ -> _ * 1000; UNIT_㍍ : _ -> _ * 1; 4km + 34㍍'
4034

二項コンポジット

数値部と識別子部の後に更に数値部があってもよい。
ただし、ideneもしくはEである場合、指数リテラルが優先される。

UNIT_div : a, b -> a / b;
UNIT_e : a, b -> a / b;

100div50, 100e50
$ fl7 'UNIT_div : a, b -> a / b; UNIT_e : a, b -> a / b; 100div50, 100e50'
2
1e+52

多重コンポジット

数値部で始まり数値部と識別子部が交互に来ていれば、コンポジットはいくらでもつなげることができる。

その場合、コンポジットは右優先結合で入れ子状に呼び出される。

UNIT_a : [
  1 : a    -> "[$a]";
  2 : a, b -> "[$a, $b]";
];

1a2a3a4, 1a2a3a4a
$ fl7 'UNIT_a : [ 1 : a -> "[$a]"; 2 : a, b -> "[$a, $b]"; ]; 1a2a3a4, 1a2a3a4a'
[1, [2, [3, 4]]]
[1, [2, [3, [4]]]]

Tips キロやミリのついた単位関数を作成する際は、第2引数を戻り値に統合すると呼び出しが便利である。

UNIT_km : [
  1 : a    -> a * 1000;
  2 : a, b -> a * 1000 + b;
];
UNIT_m : [
  1 : a    -> a * 1;
  2 : a, b -> a * 1 + b;
];
UNIT_mm : [
  1 : a    -> a * 0.001;
  2 : a, b -> a * 0.001 + b;
];

54km13m265mm
$ fl7 'UNIT_km : [ 1 : a    -> a * 1000; 2 : a, b -> a * 1000 + b; ]; UNIT_m : [ 1 : a    -> a * 1; 2 : a, b -> a * 1 + b; ]; UNIT_mm : [ 1 : a    -> a * 0.001; 2 : a, b -> a * 0.001 + b; ]; 54km13m265mm'
54013.265

関数名にはUNIT_がなくてもよい

UNIT_付きの関数とそうでない関数が両方存在する場合、前者が優先される。

UNIT_f : _ -> _ * 100;
f : _ -> _ * 10;
g : _ -> _ * 10;

7f, 7g
$ fl7 'UNIT_f : _ -> _ * 100; f : _ -> _ * 10; g : _ -> _ * 10; 7f, 7g'
700
70

関数は動的名前解決される

ただし、動的名前解決ではUNIT_を省略することはできない。

@{UNIT_f : _ -> _ * 100};

7f

静的名前解決される関数が優先される。

$ fl7 '@{UNIT_f : _ -> _ * 100}; 7f'
700

$ fl7 '@{UNIT_f : _ -> _ * 100}; f : _ -> _ * 10; 7f'
70

部分適用

左部分適用・右部分適用

左部分適用演算子func << argsは、funcの引数列に先頭からargsを部分適用する中置演算子である。
右部分適用演算子func >> argsは、funcの引数列に末尾からargsを部分適用する中置演算子である。

argsは、部分適用する引数列を括弧( )内に;区切りで指定する。

f : a, b, c, d -> [a, b, c, d];
(  f << (10; 20)  )(30; 40),
(  f >> (10; 20)  )(30; 40),
$ fl7 'f : a, b, c, d -> [a, b, c, d]; (  f << (10; 20)  )(30; 40), (  f >> (10; 20)  )(30; 40),'
10,20,30,40
30,40,10,20

( )は省略してもよい

$ fl7 'JOIN(1, 2, 3; "|")'
1|2|3
$ fl7 '(JOIN >> "|")(1, 2, 3)'
1|2|3

メソッドアクセス

メソッドアクセス演算子object::methodは、objectのメンバmethodに対して、objectを左部分適用する後置演算子である。

{
  m = obj, i -> i * obj.v;
  v = 20;
}::m(5)
$ fl7 '{m = obj, i -> i * obj.v; v = 20}::m(5)'
100

働きとしては、object::methodobject.method << objectと等価である。

obj : {
  m = _, i -> i * _.v;
  v = 20;
};
obj::m(5),
(obj.m << obj)(5),
obj.m(obj; 5),
$ fl7 'obj : {m = _, i -> i * _.v; v = 20}; obj::m(5), (obj.m << obj)(5), obj.m(obj; 5)'
100
100
100

Tips メソッドアクセスは関数呼び出しアクセスとともに後置演算子扱いなので、前置演算子である即席関数\formulaよりも優先する。

以下のコードの関数fは与えられたオブジェクトのメソッドmを呼び出して返す関数である。

f : \_::m();
obj : {
  m : \_.a;
  a : 50;
};
f(obj)
$ fl7 'f : \_::m(); obj : {m : \_.a; a : 50}; f(obj)'
50

メソッド風左バインド

メソッドアクセス演算子object::methodmethod節が丸括弧だった場合、メソッド風左バインド演算子value::(function)となる。
これは左バインド演算子を用いた式function << valueと同等である。

repeat : string, number -> string * number;
"a"::(repeat)(5),
(repeat << "a")(5),
repeat("a"; 5),
$ fl7 'repeat : string, number -> string * number; "a"::(repeat)(5), (repeat << "a")(5), repeat("a"; 5)'
aaaaa
aaaaa
aaaaa
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?