이 챕터는 두 동사를 합쳐 새로운 합성 동사를 만드는 것을 목표로 한다.
3 장에서 나왔던 합성 접속사인 @:
(at colon, "At"이라고 한다.)를 상기하자. sum
과 square
라는 동사를 이용해서 새로운 합성 동사인 제곱의 합을 만들수 있다.
sum =: +/
square =: *:
sumsq =: sum @: square | sumsq 3 4 |
sum@:square | 25 |
일반적인 구조는 다음과 같다. 모나드 동사 f
, g
가 있다면
(f @: g) y 는 f (g y) 이다.
특이한 것은 f
는 g y
의 결과 전체에 적용된다는 것이다. 예를 들어 g
가 어떤 테이블의 각 행에 따로 적용된다고 해보자.
g =: sum " 1
f =: <
y =: 2 2 $ 1 2 3 4 | g y | f g y | (f @: g) y |
1 2 3 4 |
3 7 | +---+ |3 7| +---+ |
+---+ |3 7| +---+ |
가장 간단한 형태의 합성을 보았다. 이제 좀 더 다양한 변형을 보자.
만약 f
가 모나드이고 g
가 다이아드이면 f @: g
는 아래와 같은 의미를 가지는 다이아딕 동사가 된다.
x (f @: g) y 는 f (x g y) 이다.
예제를 보자. 두 벡터 x
와 y
의 곱의 합은 "스칼라 곱"이라고 한다.
sp =: +/ @: *
x =: 1 2 | y =: 2 3 | x * y | +/(x * y) | x sp y |
1 2 | 2 3 | 2 6 | 8 | 8 |
표현식 x (f @: g) y
에서 동사 f
가 x g y
의 결과 전체에 한 번 적용 되었음을 마지막 예제에서 알 수 있다.
접속사 &:
(mpersand colon, "Appose"라고 읽는다.)는 다이아드인 f
와 모나드인 g
를 합성한다. 구조는 다음과 같다.
x (f &: g) y 는 (g x) f (g y) 이다
예를 들어 두 리스트가 같은 길이인지 알아보고자 할 땐 = &: #
를 쓴다.
eqlen =: = &: #
x | y | #x | #y | (#x) = (#y) | x eqlen y |
1 2 | 2 3 | 2 | 2 | 1 | 1 |
f
가 g x
와 g y
에 적용 되었음을 알 수 있다.
복습을 잠깐 하자. 우리는 세 가지 합성 방법을 배웠다.
(f @: g) y = f (g y)
x (f @: g) y = f (x g y)
x (f &: g) y = (g x) f (g y)
으리고 이번엔 네 번째 합성 방법이다.
(f &: g) y = f (g y)
이 방법은 분명 첫 번째 방법과 똑같다. 이런 명백한 중복은 모나딕과 다이아딕 케이스 두 경우를 다 정의하는 이중적인 정의를 할 때에 유용하게 쓰인다.
우선 첫 번째와 두 번째 방법에서 만약 g
가 이중적이라면 그의 합성인 f @: g
또한 이중적이다. 예를 들어 g
가 불안정한 내장 동사인 |.
라고 해보자. |. y
는 y
의 순서를 반대로 바꾸는 것이고 x |. y
는 y
를 x
의 순서로 바꾸는 것이다.
y =: 'abcdef' | (< @: |.) y | 1 (< @: |.) y |
abcdef | +------+ |fedcba| +------+ |
+------+ |bcdefa| +------+ |
위의 세 번째와 네 번째 합성 방법은 만약 f
가 이중적이면 f &: g
또한 이중적이다. 예를 들어서 f
가 %
(역원 또는 나누기)이고 g
가 *:
(제곱)라고 해보자.
% *: 2 | (% &: *:) 2 | (*: 3) % (*: 2) | 3 (% &: *:) 2 |
0.25 | 0.25 | 2.25 | 2.25 |
"Atop"이라고 부르는 접속사 @
가 있다. 이 녀석은 접속사 @:
의 변형중 하나이다. 아래는 f @: g
와 f @ g
의 차이에 대해 설명하는 예제이다.
y =: 2 2 $ 0 1 2 3
y | f | g | (f @: g) y | (f @ g) y |
0 1 2 3 |
< | sum"1 | +---+ |1 5| +---+ |
+-+-+ |1|5| +-+-+ |
f @: g
에서 f
는 딱 한 번만 적용된다. 하지만 f @ g
에서는 g
가 적용되는 것마다 그에 상응하는 것에 f
가 적용된다. 이것을 f
의 적용이 g
의 적용을 따라간다 라고 말한다.
일반적으로 동사는 세 가지 랭크(모나딕, 왼쪽, 오른쪽)아 있고 동사 f
의 랭크들을 알아보기 위해서는 표현식 f b. 0
을 쓰면 된다고 7장에서 말했었다. 간단히 예제를 보자.
g | g b. 0 |
sum"1 | 1 1 1 |
동사 g
의 모나딕 랭크가 G
라고 해보자.
G =: 0 { (g b. 0)
그럼 f @ g
은 f @: g
가 각각의 G
-셀에 적용된다. 즉 f @: g"G
이다.
(f @ g) y | (f @: g)"G y |
+-+-+ |1|5| +-+-+ |
+-+-+ |1|5| +-+-+ |
그리고 일반적인 구조는 다음과 같다.
(f @ g) y 는 (f @: g) " G y 이다
다음으로 g
가 다이아드인 f @ g
합성을 볼 것이다. f
와 g
가 다음과 같다고 해보자.
f =: <
g =: |. " 0 1 NB. 다이아딕
그럼 x g y
는 y
의 벡터를 그와 연관된 x
의 스칼라에 따라 회전시킨다는 의미가 된다. 예제를 보자.
x=: 1 2 | y=: 2 3 $ 'abcdef' | x g y |
1 2 | abc def |
bca fde |
여기서 이제 f @: g
와 f @ g
의 차이가 드러난다.
f (x g y) | x (f @: g) y | x (f @ g) y |
+---+ |bca| |fde| +---+ |
+---+ |bca| |fde| +---+ |
+---+---+ |bca|fde| +---+---+ |
f @: g
에서는 동사 f
가 한 번만 적용됨을 알 수 있다. 하지만 f @ g
에서는 각각의 g
적용에 f
가 다시 각각 적용된다.
g
의 왼쪽과 오른쪽의 랭크를 각각 L
과 R
이라고 해보자 그러면 f @ g
는 x
의 L
-셀과 그와 관계된 y
의 R
-셀에 따로 f @: g
이 적용되는 것과 같다. 득 f @ g
는 (f @: g)"G
이다. 여기서 G = L,R
이다.
G =: 1 2 { (g b. 0) | x (f @:g)" G y | x (f @ g) y |
0 1 | +---+---+ |bca|fde| +---+---+ |
+---+---+ |bca|fde| +---+---+ |
이에 대한 구조는 아래와 같다.
x (f@g) y = x (f@:g) " G y
접속사 &
가 연산자들을 붙인다고 챕터 3에서 배웠다. 명사 하나와 다이아딕 동사를 하나를 인자로 받아 모나드를 만든다. 예를 들어서 +&6
은 인자에 6
을 더하는 모나드이다.
만약 &
의 양쪽 인자가 모두 동사이면 &
는 다르게 작동한다. 이 경우에는 연산자들을 합성한다. (그리고 이 경우 "Compose"라고 읽는다.) 이제 f
가 다이아딕인 f & g
합성에 대해서 보자
g
가 "Square" 함수이고 f
가 두개의 리스트를 잇는 "comma" 함수라고 하자.
f =: ,
g =: *:
x =: 1 2 | y =: 3 4 | g x | g y |
1 2 | 3 4 | 1 4 | 9 16 |
아래의 예제에서 f &: g
와 f & g
의 차이를 볼 수 있다.
(g x) f (g y) | x (f &: g) y | x (f & g) y |
1 4 9 16 | 1 4 9 16 | 1 9 4 16 |
f &: g
에서 동사 f
는 한 번만 적용되어 1 4 , 9 16
를 수행함을 알 수 있다. 반면 f & g
에서는 f
가 각각 두번 적용 되었다. 처음에 한번 적용되어 1,9
가 나오고 그 다음에 적용되어 4,16
이 나왔다.
구조는 다음과 같다.
x (f & g) y 는 (g x) (f " G,G) (g y) 이다.
G
가 g
의 모나딕 랭크라면 f
는 x
의 G
-셀들과 그에 연관된 y
의 G
-셀들에 따로 적용된다. 아래에 예제가 있다.
G =: 0 { (g b. 0) | (g x)(f " (G,G))(g y) | x (f & g) y |
0 | 1 9 4 16 |
1 9 4 16 |
f & g
합성은 이중적이다. 다이아딕 x f&g y
의 경우는 위에서 다뤘다. 모나딕 f&g y
은 f@g y
와 같다.
f =: <
g =: *:
f&g 1 2 3 | f@g 1 2 3 |
+-+-+-+ |1|4|9| +-+-+-+ |
+-+-+-+ |1|4|9| +-+-+-+ |
아래에 위에서 봐왔던 8개의 경우를 요약해놨다.
@: (f @: g) y = f (g y)
@: x (f @: g) y = f (x g y)
&: (f &: g) y = f (g y)
&: x (f &: g) y = (g x) f (g y)
@ (f @ g) y = (f @: g) " G y
@ x (f @ g) y = x (f @: g) " LR y
& (f & g) y = (f @: g) " G y
& x (f & g) y = (g x) (f " (G,G)) (g y)
G
는 g
의 모나딕 랭크이고 LR
은 g
의 오른쪽, 왼쪽 랭크의 벡터이다.
"Square"(제곱) 동사인 *:
는 "Square-root"(제곱근) 동사인 %:
의 역이라고 할 수 있다. 역수를 만드는 동사는 자신이 자신의 역이다.
*: 2 | %: 4 | % 4 | % 0.25 |
4 | 2 | 0.25 | 4 |
J의 많은 동사들은 역을 가지고 있다. 내장 접속사 ^:
(caret colon, "Power"라고 한다.)는 표현식 f ^: _1
을 이용해서 동사 f
의 역을 구한다. (이건 관례적으로 역함수를 f-1으로 쓰는 것과 비슷하다)
예를 들어서 제곱의 역함수는 제곱근이다.
sqrt =: *: ^: _1 | sqrt 16 |
*:^:_1 | 4 |
^:
는 내장 동사뿐만이 아니라 사용자 정의 동사들 까지도 자동으로 역을 찾는다. 예를 들어 "제곱근 곱하기 2"의 역은 "절반의 제곱"이 된다.
foo =: (2&*) @: %:
fooINV =: foo ^: _1
foo 16 | fooINV 8 | foo fooINV 36 |
8 | 16 | 36 |
이제 접속사 &.
(ampersand dot. "Under"라고 한다.)로 합성하는 방법에 대해 알아보자. 합성 "f
Under g
"는 g
를 적용하고 그 다음에 f
를 적용하고 g
의 역을 적용한다라는 의미이다.
예제를 보자. 어떤 숫자의 제곱근은 로그를 구하고 그것을 반으로 나눈 다음 진수(antilog)를 구하면 된다. 즉 "halving under logarithm"이다. 절반으로 나누는 동사는 -:
이고 로그는 ^.
이다.
SQRT =: -: &. ^. | SQRT 16 |
-:&.^. | 4 |
일반적인 구조는 다음과 같다.
(f &. g) y 는 (g ^: _1) f g y 이다.
8장이 끝났다.