ivy
Russ Cox がなんかやってて知った
Rob Pike のスライド
demo をやって、なんとなくの使い方や性質をメモしておく
REPL
ivy で起動する
使い方は普通のREPL環境と一緒
quitで抜ける
code:example.ivy
2+2 # 入力
4 # 評価結果
# コメントは #
基本
演算子の優先順序
一項演算子はすぐ右の要素全体に作用
二項演算子はすぐ左の要素ひとつと、右の要素全体に作用する
一般的に知られる数式やよくあるプログラミング言語とは異なる
式の右からボトムアップで木ができてくイメージ?
code:precedence.ivy
# demo より引用
2*3+4 # (2*3)+4 ではなく 2*(3+4) になる
14
2**2+3 # (2**2) + 3 ではなく 2**5 になる
32
(2**2)+3 # 括弧で優先順序を明示できる
7
有理数を有理数として計算できる
code:rational.ivy
1/3
1/3
1/3 + 4/5
17/15
小数の記法で書いたときは、それに対応する有理数に変換される
表示で浮動小数が出てくるときも、内部では有理数として文字されている
code:float.ivy
1.2
6/5
大きな数でも大丈夫
64bits を超えても平気
code:big.ivy
1e100
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
3/1e10
3/10000000000
2**64
18446744073709551616
2**100
1267650600228229401496703205376
2**6400 # とかもできる。ここでは結果を省略
複素数も書ける
code:complex.ivy
1 j 3 # 1+3j をあらわす
1j3
1j1 # 虚数単位の係数は必ず必要。 1+j を表すのに 1j じゃだめ
1j1
0j-1 # -j もこう書く
0j-1
# 0と0j0は扱いが違ってそう
0j0
0j0
0
0
# 演算結果は複素数の範囲で出してくれる
sqrt -1 # sqrt は一項演算子
0j1
acos 2j1
0.507356303217j-1.46935174437
文字(列)も書ける
Unicodeのコードポイントで表現できる範囲
code:chars.ivy
# demo より引用
'x'
x
'xx' # 筆者追記:Vectorのところを参照
xx
char 0x61 # char is an operator: character with given value.
a
char 0x1f4a9
💩
code '💩' # char's inverse, the value of given character, here printed in decimal.
128169
ベクタ
スペース開けで書くとベクタにできる
code:vector.ivy
1 2 3
1 2 3
1 4/3 5/3 (2+1/3)
1 4/3 5/3 7/3
# 上の例で、括弧なしで書くと (1 4/3 5/3 2)+1/3 として評価されることに注意
1 4/3 5/3 2+1/3
4/3 5/3 2 7/3
文字列のベクタはquotesやスペース無しで表示される
code:char_vec.ivy
'h' 'e' 'l' 'l' 'o'
hello
# 複数文字のときは区別できるようにしてくれてるらしい
'h' 'e' 'll' 'o'
h e (ll) o
# でもこれは 'h' 'e' 'l' 'l' 'o' と同じ意味らしい
'hello'
hello
ベクタに対する演算も書ける
スカラと一緒にも使える
ちなみに加算とかは線形代数の行列演算っぽくはならない
Numpyその他でよくある、$ A+c=A+c⋅E と解釈されるやつ
意図的に matrix じゃなくて vector と呼んでるんだと思う
ベクタはそれ単体で一つの要素になれる点に注意
code:vector_operations.ivy
1 2 3 + 4 5 6
5 7 9
# スカラと一緒に使える
23 + 1 2 3
24 25 26
# 演算子は右から評価されるが、ベクタとしての結合のほうが強い
1 2 3 + 23
24 25 26
1 << 1 2 3 4 5
2 4 8 16 32
(1 << 1 2 3 4 5) == (2 ** 1 2 3 4 5)
1 1 1 1 1 # true が 1
演算子
比較 ==
true は 1、falseは0
code:bool.ivy
5==5
1
5==6
0
iota
1始まりの連番ベクタを生成する
code:iota.ivy
iota 10
1 2 3 4 5 6 7 8 9 10
2 ** iota 5
2 4 8 16 32
take, drop
Haskell と同じで、頭をとるか残りをとるかの処理
code:take_drop.ivy
3 take iota 10
1 2 3
3 drop iota 10
4 5 6 7 8 9 10
6 drop 'hello world'
world
負数を指定すると後ろからのインデックスになる
code:negative_take_drop.ivy
-3 take iota 10
8 9 10
-3 drop iota 10
1 2 3 4 5 6 7
Reduction
ベクタに対して、二項演算子を使って畳み込みができる
code:reduction.ivy
iota 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# sum
(+/iota 15) == (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15)
1
# factorical
1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
3628800
*/iota 10
3628800
式の分割
セミコロンで複数の式を分割できる
表示は改行が入る
max, min
max, min は二項演算子
code:max_min.ivy
3 max 7; 'is max and'; 3 min 7; 'is min'
7
is max and
3
is min
通常の二項演算子みたいに使えるし、畳み込みもできる
code:max_ivy
2 3 4 max 4 3 2
4 3 4
max/2 34 42 233 2 2 521 14 1 4 1 55 133
521
多次元ベクタ
rho 演算子で 多次元のベクタを作れる
<ベクタの形状> rho <値> と書く
code:rho_binary.ivy
5 rho 1
1 1 1 1 1
5 5 rho 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
5 5 rho 25
25 25 25 25 25
25 25 25 25 25
25 25 25 25 25
25 25 25 25 25
25 25 25 25 25
# 初期値にベクタも指定できる。一行ずつ埋まっていく
5 5 rho iota 25
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
# 長さが足りない場合はリピートされる
3 3 rho iota 4
1 2 3
4 1 2
3 4 1
一項演算子としても使える
この場合はベクタの形状を返す
code:rho_unary.ivy
x = 3 5 rho iota 15; x
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
rho x
3 5
rabel 演算子
二項だとベクタをjoinする
code:rabel_binary.ivy
1 2 3 , 4 5 6
1 2 3 4 5 6
rho 1 2 3 , 4 5 6
6
一項だとflatten
code:rabel_unary.ivy
, 3 5 rho iota 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
rho , 3 5 rho iota 15
15
ベクタの諸々
乗除算は通常の行列と同じ
code:div_vector.ivy
x = 3 5 rho iota 15;x
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
ベクタに対する階乗は、行列演算における階乗ではない
単にベクタ各値への演算適用なので、正方行列である必要はない
code:exponent.ivy
x ** 2
1 4 9 16 25
36 49 64 81 100
121 144 169 196 225
内積
<演算子1>.<演算子2>と書く
行列演算でいうところの内積を書くと+.*になる
どんな演算子も使える
code:inner_product.ivy
1 2 3 4 +.* 2 3 4 5
40
# ベクタ上で同じ位置にある要素同士を比較したとき、いくつ等しいかを計算する
(1 2 3) +.== (1 3 3)
2
# いくつ異なるか
(1 2 3) +.!= (1 3 3)
1
外積
o.<演算子> と書く
左辺の各要素を右辺に適用した結果のベクタを返す
code:outer_product.ivy
(iota 3) o.* -2
-2 # 1 * -2
-4 # 2 * -2
-6 # 3 * -2
(iota 5) o.* -1 + iota 5 # (1 2 3 4 5) o.* (0 1 2 3 4)
0 1 2 3 4 # 1 * (0 1 2 3 4)
0 2 4 6 8 # 2 * (0 1 2 3 4)
0 3 6 9 12 # 3 * (0 1 2 3 4)
0 4 8 12 16 # 4 * (0 1 2 3 4)
0 5 10 15 20 # 5 * (0 1 2 3 4)
x = iota 5; x o.== x
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
単位行列をつくる
これまでのテクニックを使うと単位行列を作れる
code:einheits_matrix.ivy
x = iota 5; x o.== x
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
5 5 rho 1 0 0 0 0 0
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
乱数
一項演算子 ?
?nと書くと、1 < x <= n なxが返る
code:random.ivy
?100
6
?100
53
?100
28
?20 rho 6 # 20 rolls of a 6-sided die.
4 1 1 1 4 1 3 4 4 4 2 5 3 5 2 5 5 3 5 4
?(20 rho 6) # 同じ意味
5 6 3 5 5 4 2 5 4 2 2 5 3 3 1 5 1 3 6 5
# こうすると初期値側が固定される
20 rho ?6
6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
20 rho (?6)
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
インデックスアクセス
code:indexing.ivy
x = ?20 rho 6
x
6 5 1 2 5 1 5 1 5 4 4 2 3 4 3 1 3 5 1 4
6
6 1 1
# 多次元ベクタへのインデックスはセミコロンで分けてアクセスする
21 22 23 24 25
16 17 18 19 20
11 12 13 14 15
6 7 8 9 10
1 2 3 4 5
sort
up, down は、ベクタを受け取って、ソートした時のインデックスを返す
code:updown.ivy
up x
3 6 8 16 19 4 12 13 15 17 10 11 14 20 2 5 7 9 18 1
1 1 1 1 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6
6 5 5 5 5 5 4 4 4 4 3 3 3 2 2 1 1 1 1 1
dehllloorw
wroolllhed
特別な変数
_
直近で評価された値を記憶している
command
)help
演算子一覧とかも出せそうだからあとでやる
)base
底を変えられる
code:base.ivy
)base # 設定の確認
ibase 10
obase 10
)base 16 # 底を16に変更
)base
ibase 16
obase 16
)obase 10 # obase だけ、ibaseだけ変えることもできる
code:base16_samples.ivy
)base 16
1<<iota 10 # 16 powers of two, base 16.
2 4 8 10 20 40 80 100 200 400 800 1000 2000 4000 8000 10000
(2**40)-1 # The largest 64-bit number base 16.
ffffffffffffffff
出力フォーマット
巨大な数を扱えるので、どこまで表示するか指定できる
code:format.ivy
)format '%.12g'
ちなみにこのフォーマットは ivy -g で使える
ほかにもたくさん
無理数
無理関数は有理数では表せないので、浮動小数点値で保持している
浮動小数点はデフォルトで256 bits
pi, e も同様
指数
non-integral な指数は無理数の結果を出力する
code:exponent.ivy
2**1/2 # Note: Non-integral exponent generates irrational result.
1.41421356237
e**1e6
3.0332153968e+434294
logarithms
code:log.ivy
log e**1e6
1000000
log e**1e8
100000000
log 1e1000000 # Yes, that is 10 to the millionth power.
2302585.09299
超越数
code:transcendentials.ivy
sin pi/2
1
cos .25*pi * -1 + iota 9
1 0.707106781187 7.70893799599e-78 -0.707106781187 -1 -0.707106781187 2.38604460223e-76 0.707106781187 1
log iota 6
0 0.69314718056 1.09861228867 1.38629436112 1.60943791243 1.79175946923
# Successive approximations to e. (We force the calculation to use float using the "float" unary operator. Why?)
(float 1+10**-iota 9) ** 10**iota 9
2.5937424601 2.70481382942 2.71692393224 2.71814592683 2.71826823717 2.71828046932 2.71828169254 2.71828181487 2.7182818271
# Default precision is 256 bits of mantissa. We can go up to 10000.
)prec 3350 # Units are bits, not digits. 2 log 10 == 3.321. Add a few more bits for floating point errors.
e
2.71828182846
ユーザ定義演算子
code:user-defined-operators.ivy
# ベクタを受け取り、平均値を返す一項演算子
op avg x = (+/x)/rho x
avg iota 100
50.5
# ベクタxから大きい順にn個の要素を返す二項演算子
op n largest x = n take xdown x 3 largest ? 100 rho 1000
999 994 982
# Population count. Use encode to turn the value into a string of bits. Use log to decide how many.
# ビット列で表現したときに1がいくつあるか?
op a base b = ((floor 1 + b log a) rho b) encode a
7 base 2
1 1 1
op popcount n = +/n base 2
popcount 7
3
popcount 1e6
7
popcount 1e100
105
# another version: op popcount n = +/'1' == '%b' text n
# 各桁の数字を足し合わせる?
# Here is one to sum the digits. The unary operator text turns its argument into text, like sprintf.
op sumdigits x = t = text x; +/(code (t in '0123456789') sel t) - code '0'
# Break it down: The sel operator selects from the right based on the non-zero elements in the left.
# The in operator generates a selector by choosing only the bytes that are ASCII digits.
sumdigits 99
18
sumdigits iota 10
46
text演算子
フォーマットを指定できる
code:text.ivy
'%x' text 1234
4d2
その他
素数列挙
code:primes.ivy
# A classic (expensive!) algorithm to count primes.
op primes N = (not T in T o.* T) sel T = 1 drop iota N
# The assignment to T gives 2..N. We use outer product to build an array of all products.
# Then we find all elements of T that appear in the product matrix, invert that, and select from the original.
primes 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
code:shuffles.ivy
# A final trick.
# The binary ? operator "deals": x?y selects at random x distinct integers from 1..y inclusive.
5?10
8 5 6 10 2
# We can use this to shuffle a deck of cards. The suits are ♠♡♣♢, the values
# A234567890JQK (using 0 for 10, for simplicity).
# Create the deck using outer product with the ravel operator:
"A234567890JQK" o., "♠♡♣♢"
(A♠) (A♡) (A♣) (A♢)
(2♠) (2♡) (2♣) (2♢)
(3♠) (3♡) (3♣) (3♢)
(4♠) (4♡) (4♣) (4♢)
(5♠) (5♡) (5♣) (5♢)
(6♠) (6♡) (6♣) (6♢)
(7♠) (7♡) (7♣) (7♢)
(8♠) (8♡) (8♣) (8♢)
(9♠) (9♡) (9♣) (9♢)
(0♠) (0♡) (0♣) (0♢)
(J♠) (J♡) (J♣) (J♢)
(Q♠) (Q♡) (Q♣) (Q♢)
(K♠) (K♡) (K♣) (K♢)
# To shuffle it, ravel into into a vector and index that by 1 through 52, shuffled.
(, "A234567890JQK" o., "♠♡♣♢")52?52 (5♡) (2♢) (A♠) (4♢) (0♣) (0♠) (0♢) (2♠) (J♡) (9♡) (2♡) (9♢) (6♣) (6♠) (Q♡) (8♢) (Q♠) (4♡) (9♣) (4♠) (3♣) (8♡) (5♣) (3♢) (J♣) (2♣) (7♡) (6♢) (7♣) (A♣) (9♠) (Q♣) (K♣) (A♡) (3♠) (6♡) (5♠) (K♢) (K♠) (J♠) (7♠) (3♡) (Q♢) (7♢) (5♢) (4♣) (0♡) (J♢) (8♠) (8♣) (A♢) (K♡)
code:loop.ivy
# There is no looping construct in ivy, but there is a conditional evaluator.
# Within a user-defined operator, one can write a condition expression
# using a binary operator, ":". If the left-hand operand is true (integer non-zero),
# the user-defined operator will return the right-hand operand as its
# result; otherwise execution continues.
op a gcd b = a == b: a; a > b: b gcd a-b; a gcd b-a
1562 gcd !11
22
疑問メモ
prelude の演算子はどんなのがある?
help でみれそう
ファイルとして実行はできる?
ファイル読み込みはできる??
角度系計算にラジアンを使うには?
arccosとかの結果はさすがに概数になる?表示用に出してるだけ?
That printed using floating-point notation for manageability but it is still an integer inside.
とあるが、さすがにacosとかの場合はわからん。acos のまま持ってんのかな
これは無理数そう
矢印キーで履歴アクセスしたいよ