2019年11月10日 | ブログ記事

幻の一文字言語「O言語(The O Language)」の謎に迫る

tyoxu

1.はじめに

一文字言語とは、その名前が1文字である言語のことです。
有名なものだとC言語、その後継を目指すD言語、Dはdeathの頭文字でなんか縁起が悪いからE言語などがあります。

現在国内ではこの一文字言語の中でO言語のみ存在しないという通説が信じられていますが、
だがしかし、これを見てください

The O Language — The O Language 2.0 documentation
https://o.readthedocs.io

あ    っ    た

ツイッターなどを検索していると、古く不正確な情報を真に受けていまだにO言語が存在しないことを信じている人が一定数存在します。彼らには悪いのですがこの事実を世に知らしめるためこの記事ではO言語を紹介していきます。

†もくじ†
1. はじめに
2. O言語の導入と詳細 ~これで君もOerだ!!!~
3. O言語超入門編
4. いかがでしたか?
5. 付録
6. 終わりに

2.O言語の詳細と導入 ~これで君もOerだ!!!~

The O Language is an esoteric programming language used for code-golf.(https://o.readthedocs.io より)

O言語はコードゴルフ、つまりある問題を如何に短いコードで解くかの競争のために生まれてしまった言語です。
Hello Worldはこう書かれます。

"Hello!World!!!"o

"Hello!World!!!"をスタックにpushし、oでそれをpopし出力するプログラムです。

O revolves around one stack in which you can push and pop values to and from. Here are some basic rules for writing O code.

Oにはスタックの概念があり、そこに上からオブジェクトをpush(追加)し、pop(引き出し)しながらプログラムを進めていきます。
ところでO言語のインタプリタはコードがなくなった段階でスタックにあるものを全て(何と下から!)出力するため、実は出力oは必要ないです。つまり

"Hello!World!!!"

もHello!World!!!を出力します。

"Hello!World!!!

も実は同じ動きをします。
これはプログラムが終了まで読み込まれた段階で""が閉じていないならば、自動的に"を閉じてくれるためです
ここまでで何となく察しただろうがOの命令はほとんどが1文字で完結します。
変数やフロー制御もあるがその辺りは後々紹介します。
gitに乗っているサンプルコードだと

H,;]*

は入力の階乗

0J;1Kpj{K:VJ+:KpV:J;}d

はフィボナッチ数列を計算し出力します。

興味を持ってもらえたところで導入方法を紹介します。
Oのインタプリタを導入するには
https://o.readthedocs.io/en/latest/getting-started.html#getting-the-interpreter
を参照して欲しい。

git clone https://github.com/phase/o && cd o
make all
./o

をすればいい。
またはオンラインで動くIDEがある
http://o-lang.herokuapp.com

3.O言語超入門編

iは入力をstringとして読み込みpushします。
jは入力をintegerとして読み込みpushsします。
oはスタックから1つオブジェクトをpopし出力します。
pはスタックから1つオブジェクトをpopし出力し、flashをします。

0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,Fのそれぞれはそれぞれの対応するintegerをpushする。ここで注意すべきは、

1234

は1,2,3,4を順番にpushsすることです。(1234、つまりせんにひゃくさんじゅうよんを整数でスタックするのには別の方法を用います。)
q,Qは入力が数字なら数字を、そうでないならstringをpushします。便利。

""は囲まれた文字を文字列としてpushします
'は単体では次の一文字をstringとしてpushします。
""節の途中での'は、""のマクロとして働きます。

>>> "hello'madam"oo
madamhello

+ - * / %はスタックから2つ要素をpopし、計算の結果をpushします

>>> 12+o
3
>>> 75-o
2
>>> 85*o
40
>>> 42/o
2
>>> 53/
1.666667

4.いかがでしたか?

O言語はコードゴルフのための言語で四則演算とかができることがわかりましたね! これで公式サイトに載っていた内容は全てです。お疲れ様でした。 次回はKaGuiさんの記事とSilviaseさんの記事だそうです。よろしければそっちも見てね☆



この記事を書いた人
tyoxu

素人です


























































































































































5.付録

https://github.com/phase/o/blob/master/commands.md
を見るとなんか公式サイトに載ってない命令がめっちゃ載ってますね。
このセクションの存在に気づいてしまったそこの不幸なあなたのためにそれぞれ紹介していきましょう。
ただし上記ファイルに乗っている説明はかなりあっさりなので100%機能を網羅していない点に気をつけてください。公式リファレンスがないのが悪いんだよ

"

String parsing

説明:""で囲まれた文字列をpushする

>>> "oisu~"
output:oisu~
stack:[oisu~]

#

String to number

説明:1つpopし、それがstringなら数値型にしてpushする

>>> "100"#
output:100
stack:[100]

$

Take object from lower stack up
Arrayの宣言時に、1つ上のスタックから値をpopし、今のスタック(つまりArrayの内部である)にpushする?
説明:

>>> 12345[$$]
output:123[5,4]
stack:[[5,4],3,2,1]

%

Modulous

説明:2つpopし(2つめ)%(1つめ)を計算しpushする。

>>> 53%
output:2
stack:[2]

&

Get element from array

説明:Arrayをpopし、最下の要素を取り出し、Arrayをpushし取り出した要素をpushする

>>> [12345]&
output:[1,2,3,4]5
stack:[5,[1,2,3,4]]

'

Character literal

説明:単体で使用した場合、次の一文字をstringとしてpushする。

>>> 'a
output:a
stack:[a]

(

Decrement

説明:pushした数値から1引いた答えをpushする

>>> 5(
output:4
stack:[4]

)

Increment

説明:pushした数値から1足した答えをpushする

>>> 5)
output:6
stack:[6]

*

Multiplication

説明:2つpopした数値の積を計算する。または文字列の繰り返し?

>>> 23*
output:6
stack:[6]

>>> "oisu~"3*
output:oisu~oisu~oisu~
stack:[oisu~oisu~oisu~]

+

Addition

説明:2つpopした数値の和を計算する。または文字列の結合?
1つめにpopしたものが数値または文字列なら、2つめがArrayでも全要素に対して計算する。
1つめにpopしたものがArrayなら要素の和を計算する。(2つめをpopしない)

>>> 12+
output:3
stack:[3]

>>> "Hello!!'World!!!"+
output:Hello!!World!!!
stack:[Hello!!World!!!]

>>> [5,]+
output:15
stack[15]

,

Range

説明:popした数値から0までをまでを1刻みでpushする。

>>> "10"#,
output:109876543210
stack:[0,1,2,3,4,5,6,7,8,9,10]

-

Subtraction

説明:2つpopした数値の差(2つめ)-(1つめ)を計算する。または(2つめ)の文字列から(1つめ)の部分文字列を取り除く?
1つめにpopしたオブジェクトが数値なら、2つめがArrayでも全要素に対して計算する。
1つめがArrayなら、2つめをpopせずそれぞれの要素を偶数インデックスはそのまま、奇数インデックスは符号反転して和を計算する。

>>> 53-
output:
stack:

>>> "oisu~""is"-
output ou~
stack:[ou~]

>>> [A,]2-
output:[8,7,6,5,4,3,2,1,0,-1,-2]
stack:[[8,7,6,5,4,3,2,1,0,-1,-2]]

.

Clone the top of the stack

説明:1つpopし、同じオブジェクトを2つpushする

>>> "Hello!".
output:Hello!Hello!
stack:[Hello!,Hello!]

/

Division

説明:popした2つの数値の商(2つめ)/(1つめ)を計算しpushする。または文字列のsplit?
1つめにpopしたオブジェクトが数値、文字列なら、2つめがArrayでも全要素に対して計算する。
1つめがArrayなら、2つめをpopせず偶数インデックスの積/奇数インデックスの積を計算する。

>>> 53/
output:1.666667
stack:[1.666667]

>>> "Ha? Mango is Delicious"" "/
output:HA?MangoisDelicious
stack:[Delicious,is,Mango,"Ha?"]

>>> "Ha? Mango is Delicious"""/
output:Ha? Mango is Delicious
stack:[s,u,o,i,c,i,l,e,D, ,s,i, ,o,g,n,a,M, ,?,a,H]

0

Push 0

説明:0をpushします

>>> 0
output:0
stack:[0]

1

Push 1

説明:1をpushします

>>> 1
output:1
stack:[1]

2

Push 2

説明:2をpushします

>>> 2
output:2
stack:[2]

3

Push 3

説明:3をpushします

>>> 3
output:3
stack:[3]

4

Push 4

説明:4をpushします

>>> 4
output:4
stack:[4]

5

Push 5

説明:5をpushします

>>> 5
output:5
stack:[5]

6

Push 6

説明:6をpushします

>>> 6
output:6
stack:[6]

7

Push 7

説明:7をpushします

>>> 7
output:7
stack:[7]

8

Push 8

説明:8をpushします

>>> 8
output:8
stack:[8]

9

Push 9

説明:9をpushします

>>> 9
output:9
stack:[9]

:

Assign to variable

説明:1つpopし、次の一文字をそのマクロとします。その後、popしたものをpushします

>>> :V;"oisu~"V*
output:oisu~oisu~oisu~oisu~oisu~
stack:[oisu~oisu~oisu~oisu~oisu~]

;

Pop top value of stack

説明:スタックの最上の要素をpopします。

>>> 12345;
output:1234
stack:[4,3,2,1]

<

Less than

説明:popした数値2つを比較し、(2つめ)<(1つめ)なら1を、そうでないなら0をpushします。
または1つめの文字列が2つめの文字列を部分文字列としてもつかどうか?
1つめにpopしたものが数値または文字列なら、2つめがArrayでも全要素に対して計算する?

>>> 12<
output:1
stack:[1]

>>> "Mango""ngo"<
output:1
stack[1]

>>> "Mango""nngo"<
output:0
stack[0]

=

Equal to

説明:popした2つの数値、文字列、コードブロックを比較し、等しいなら1を、そうでないなら0をpushする

>>> 11=
output:1
stack:[1]

>>> '11=
output:0
stack[0]

>

Greater than

説明:popした数値2つを比較し、(2つめ)<(1つめ)なら1を、そうでないなら0をpushします。
または2つめの文字列が1つめの文字列を部分文字列としてもつかどうか?
1つめにpopしたものが数値または文字列なら、2つめがArrayでも全要素に対して計算する?

>>> 13<
output:1
stack:[0]

?

If????

説明:3つpopし、(3つめ)が0なら1つめのコードブロックを。そうでないなら2つめのコードブロックを実行します

>>> 01>{"true"}{"false"}?
output:false
stack:false

@

Rotate top three items on stack

説明:スタックの先頭3要素を回転させます。(例を参照)

>>> 1234@
output:1342
stack:[2,4,3,1]

A

Push 10

説明:10をpushします

>>> A
output:10
stack:[10]

B

Push 11

説明:11をpushします

>>> B
output:11
stack:[11]

C

Push 12

説明:12をpushします

>>> C
output:12
stack:[12]

D

Push 13

説明:13をpushします

>>> 
output:13
stack:[13]

E

Push 14

説明:14をpushします

>>> 14
output:14
stack:[14]

F

Push 15

説明:15をpushします

>>> F
output:15
stack:[15]

G

Push alphabet

説明:"abcdefghijklmnopqrstuvwxyz"をpushします。これいる?

>>> G
output:abcdefghijklmnopqrstuvwxyz
stack:[abcdefghijklmnopqrstuvwxyz]

H

Macro for [Q

説明:[Qのマクロ。

>>> H]
input:po
output:[po]
stack:[[po]]

I

Macro for [i

説明:[iのマクロ。

>>> I]
input:po
output:[po]
stack:[[po]]

J

Magic var

説明:初めて読んだときは:Jのマクロとして働き、2度目以降は単にJの値をpushする

>>> AJ2J
output:10210
stack:[10,2,10]

K

Magic var

説明:初めて読んだときは:Kのマクロとして働き、2度目以降は単にKの値をpushする

>>> AK2K
output:10210
stack:[10,2,10]

L

Lambda (Push next character as a standalone CodeBlock: Lo -> {o})

説明:次の1文字を単体でコードブロックにしてpushする

>>> "Mango"Lo
output:Mango{o}
stack:[{o},Hello]

M

Macro for [i~

説明:[i~のマクロ

>>> M]
input:12+
output:[3]
stack:[[3]]

N

Push blank CodeBlock

説明:{}(空のコードブロック)をpushする

>>> N
output:{}
stack:[{}]

Q

Input var

説明:入力を受け付ける。数値なら数値型、そうでないなら文字列型としてpushする

>>> QQ+
input:1
2
output:2
stack:[2]

S

Blank String

説明:""のマクロ。

>>> "Ha? Mango is Delicious"S/
output:Ha? Mango is Delicious
stack:[s,u,o,i,c,i,l,e,D, ,s,i, ,o,g,n,a,M, ,?,a,H]

T

String with space " "

説明:" "のマクロ。

>>> "Ha? Mango is Delicious"T/
output:Ha?MangoisDelicious
stack:[Delicious,is,Mango,Ha?]

U

Newline string "\n"

説明:"\n"のマクロ。改行文字。

>>> "Ha? Mango "U+"is Delicious"+
output:Ha? Mango 
is Delicious
stack:[Ha? Mango \nis Delicious]

V

Commonly used for variables

説明:O言語でもっとも一般的な変数名

>>> A:VVVV
output:10101010
stack:[10,10,10,10]

W

Push 32

説明:32をpushする

>>> W
output:32
stack:[32]

X

Push 33

説明:33をpushする。

>>> W
output:33
stack:[33]

Y

Push 34

説明:34をpushする

>>> Y
output:34
stack:[34]

Z

Push 35

説明:35をpushする

>>> Z
output:35
stack:[35]

[

Start array

説明:[]で囲まれたところはArrayになる。[]内のコードを別のスタック上で実行し、結果のスタックをArrayとしてpushする?

>>> AK[K,;;]
output:10[10,9,8,7,6,5,4,3,2]
stack:[[10,9,8,7,6,5,4,3,2],10]

\

Swap two objects on stack

説明:スタックの先頭2要素を入れ替える。

>>> A,\
output:109876543201
stack:[1,0,2,3,4,5,6,7,8,9,10]

]

End array

説明:Arrayの宣言の終了。ここまで読んだらスタックの内容をArrayにしてpushする。

>>> AK[K,;;]
output:10[10,9,8,7,6,5,4,3,2]
stack:[[10,9,8,7,6,5,4,3,2],10]

^

Power?

説明:2つ数値をpopして、(2つめ)^(1つめ)を計算してpushする
1つめにpopしたものが数値なら、2つめがArrayでも全要素に対して計算する。
1つめにpopしたものがArrayなら最下要素の(下から2つめ^(下から3つめ^(.......)))計算する?

>>> 33^
output:27
stack:[27]

>>> [334]3^
output:[27,27,64]
stack:[[27,27,64]]

[234]^
output:2417851639229258349412352
stack:[2417851639229258349412352]
note:2^(3^4)

_

Negate

説明:popした数値の符号を逆転したものをpushする

>>> 5_
output:-5
stack:[-5]

`

Reverse String

説明:popしたstringを逆転させたものをpush

>>> "Ha? Mango is Delicious"`
output:suoicileD si ognaM ?aH
stack:[suoicileD si ognaM ?aH]

c

Compress int to string

説明:数値をstringに圧縮する?詳細不明

d

For loop

説明:2つpopする。(1つめ)のコードブロックを(2つめ)の回数だけ繰り返す。
または2つめがArrayやstringならforeachとして働く?

>>> 9{"Hello"oUo}d
output:Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
stack:[]

>>> "oisu~"{np}d
[334]{np}d
output:o
i
s
u
~
3
3
4

stack:[]

e

Is even? / String length

説明:1つpopする。popしたものがstring、Arrayの場合、string、Arrayをpushし、長さをpushする。
数値をpopした場合、0なら1、それ以外なら0をpushする。

>>> "Hello"e
output:Hello5
stack:[5,Hello]

>>> 0e
output:1
stack:[1]

i

String input

説明:文字列を標準入力から受け取り、stringとしてpushする。

>>> i
input:oisu~
output:oisu~
stack:[oisu~]

j

Number input

説明:文字列を読み取り、数値としてpushする。できない場合はエラーを出力し停止。

>>> j
input:10
output:10
stack:[10]

l

Push length of stack

説明:今のスタックの長さをpushする

>>> 12345[12345]{12345}l
output:12345[1,2,3,4,5]{12345}7
stack:[7,{12345},[1,2,3,4,5],5,4,3,2,1]

m

Math functions

説明:次の一文字と合わせて数学関数を実行するらしい。謎

>>> 1ms
output:0.841471
stack:[0.841471]
note:sin(1)~=0.841471

>>> 1ma
output:0.540302
stack:[0.540302]
note:cos(1)~=0.540302

>>> 1mt
output:1.557408
stack:[1.557408]
note:tan(1)~=1.557408

>>> mp
output:3.141593
stack:[3.141593]
>>>

>>> ml
output:299792458
stack:[299792458]
note:光速のことか?

他にも色々あったにはあった
ソースコードを見る限りでは、

q sqrt
[ floor
] ceil
s sin
S asin
c cos
C acos
t tan
T atan

d mdst:sqrt(x^2+y^2)
r mrng:range x:y

p pi
e e
l light speed

n

Used in for loops

説明:d中に呼ぶと、ループ回数をpushする。

>>> 9{noUo}d
output:0
1
2
3
4
5
6
7
8
stack:[]

o

Print object

説明:1つpopして標準出力する。

>>> 9{noUo}d
output:0
1
2
3
4
5
6
7
8
stack:[]

p

Print object with new line

説明:1つオブジェクトをpopし、標準出力に出力後flashする。

>>> 9{np}d
output:0
1
2
3
4
5
6
7
8
stack:[]

q

Push input as string/number

説明:stringまたは数値型として入力をpushする

>>> q
input:10
output:10
stack:[10]

s

Split string into char array

説明:stringをpopし、charのArrayとしてpopする

>>> "Hello"s
output:[H,e,l,l,o]
stack:[[H,e,l,l,o]]

w

While Loop

説明:2つpopする。(1つめ)のコードブロックを(2つめ)が0でない限り繰り返す?2つめをpushする?謎

>>> 3_Kp{K):K}{Kp}w
output:-3
-2
-1
{K):K}
stack:[{K):K}]

{

Start CodeBlock

説明:コードブロックの開始

>>> {"Hello"}
output:{"Hello"}
stack:[{"Hello"}]

>>> {"Hello"}{o"World"o}+
output:{"Hello"o"World"o}

Stack:[{"Hello"o"World"o}]

}

End CodeBlock

説明:コードブロックを閉じる

>>> {"Goodbye"}
output:{"Goodbye"}
stack:[{"Goodbye"}]

>>> {"Oisu~"}3*
output:{"Oisu~""Oisu~""Oisu~"}
stack:[{"Oisu~""Oisu~""Oisu~"}]

note:扱いは文字列に近いか?

~

Eval

説明:コードブロックまたはstringの式を実行

>>> "334"~{"334"}~
output:334334
stack:[334,4,3,3]

6. 終わりに

なんか色々実行してたらよくわからない機能を発見して追記が3回ぐらいあったんですがそれ以降はもう疲れたので書いていません。
自分で試してレッツエンジョイO言語ライフ!
じゃあ私C#書くので✋

この記事を書いた人
tyoxu

素人です

この記事をシェア

このエントリーをはてなブックマークに追加

関連する記事

2019年11月21日
DEATH STRANDING【AdC2019 22日目】
Amanogawa
2019年11月20日
AAっぽい動画を作る【Advent Calendar 2019 21日目】
hosshii
2019年11月20日
キラッとプリ☆チャンつくってみた!
d_etteiu8383
2019年11月19日
Advent Calendar 2019 20日目
Adwaver_4157
2019年11月18日
C++スタイルのキャスト演算子を使おう!【アドベントカレンダー2019 19日目】
kegra
2019年11月17日
据え置きの音をお外に持ち出そう
liquid1224

活動の紹介

カテゴリ

タグ