X



Rust part8
■ このスレッドは過去ログ倉庫に格納されています
0323デフォルトの名無しさん
垢版 |
2020/03/30(月) 04:40:37.32ID:Oymj8mf6
>>322
ところで、
let &x = y;
ってどういう意味ですか?

let y:i32 = 5;
let x:&i32 = y;
とは違うんでしょうか?
0325デフォルトの名無しさん
垢版 |
2020/03/30(月) 11:38:27.40ID:/1SwYHDd
>>323
左辺に代入する時にパターンマッチ使ってDestructuringしてる
例えばyが&i32ならxはi32になる

let i = 1;
let &i = i;
これがコンパイル取らないのは
右辺がintegerで左辺がreferenceを要求しててマッチしないから

let i:i32 = 1;
let i = &i;
let &i = i;
let i:() = i;
↑こうやって試せば3行目の&iへの代入でiが&i32じゃなくi32になってるのが分かる
https://play.rust-lang.org/?version=stable&;mode=debug&edition=2018&gist=1d23370e99b388e2205c43e863885315
0327デフォルトの名無しさん
垢版 |
2020/03/30(月) 14:34:27.40ID:yinACqvq
>>326
C で言う void みたいなもんだよ。
あり得ない型を指定してエラーメッセージを出させたら
メッセージに右辺の側の型も表示されるという
型確認のテクニック
0328デフォルトの名無しさん
垢版 |
2020/03/30(月) 15:23:14.22ID:/1SwYHDd
1.38からはstd::any::type_nameがstabilizeされてるので
エラーメッセージやnightly使わずに変数の型をprintして確認できるみたい
(consumeしないようにreferenceで渡すから少し分かりにくいかもだけど)

fn type_of<T>(_: &T) -> &str {
std::any::type_name::<T>()
}

fn main() {
let i = 1;
let i = &i;
let &i = i;
println!("{}", type_of(&i));
}

type_name_of_valってのも追加されてるけど
こっちはまだstabilizeされてない
0329デフォルトの名無しさん
垢版 |
2020/03/30(月) 16:45:46.87ID:Oymj8mf6
>>327
なるほど。貴重なテクニック有難うございます。

>>328
それを使えば構造体(?)や参照型などの lifetime も表示できますでしょうか?

何か lifetimeを確認する方法をご存知の型がいらっしゃればご教授頂ければ幸いです。
0331デフォルトの名無しさん
垢版 |
2020/03/30(月) 18:43:59.32ID:QPHAwv8T
/1SwYHDd氏やるなぁ
こういう細かいことまで知ってる人のRust歴気になる
0332デフォルトの名無しさん
垢版 |
2020/03/31(火) 00:49:28.04ID:bdtzxXSI
さっきオナラしようとしたらウンチが少し出てしまったんだけど
ばれてないからいいよね ごめんね
0335デフォルトの名無しさん
垢版 |
2020/04/01(水) 05:04:17.87ID:2vQ3PjhV
やりたいこと
Optionからの安全な値の取り出しを構文レベルで保証、およびNone時に数行の処理と戻り値を伴う正常の早期returnをしたい

if Some(v) = foo.get() {
安全に取り出せるがネストが嫌すぎる
} else {
位置が遠すぎる
}

let v = if Some(v) = foo.get() {
v        安全取り出しだが冗長すぎて嫌
} else {
}

let v = match foo.get() {
Some(v) => v    安全取り出しだが冗長すぎて嫌
None => { }
}

if foo.is_none() {
構文で保証されずプログラマの注意力次第で嫌すぎる
}
let v = foo.get().unwrap();

let v = foo.get().ok_or_else(||{
は?正常終了つってんだろが?エラー値で返すんじゃねえよバカか?
})?;
0338デフォルトの名無しさん
垢版 |
2020/04/01(水) 09:19:54.63ID:yrAQuZWY
構文を調整したいならマクロじゃない?
let v = safe_get!(v, {
失敗した
return Ok (());
});
みたいな。ベタ書き以外でearly returnしたいならマクロか?演算子みたいにコンパイラサポートがいると思う。
0339デフォルトの名無しさん
垢版 |
2020/04/01(水) 10:13:55.16ID:0Fs3VJge
なんでboolって1byteあるの?
0340デフォルトの名無しさん
垢版 |
2020/04/01(水) 11:20:10.79ID:5VJq6KKK
C は bit field あるのにな
0341デフォルトの名無しさん
垢版 |
2020/04/01(水) 11:25:37.12ID:qjrNWUcZ
>>335
map_or_elseでSomeの時とNoneの時に適用するクロージャを渡せる
でもどうしても1行で書きたいとかchainしたい場合じゃなければ普通にmatchかif-else使うな

fn foo(){
get().map_or_else(|| bar(), |x| baz(x))
}

fn foo(){
match get() {
None => bar(),
Some(x) => baz(x)
}
}

https://play.rust-lang.org/?version=stable&;mode=debug&edition=2018&gist=dd9040426e54f1dfc6e39d07bbd219fb
0344デフォルトの名無しさん
垢版 |
2020/04/01(水) 13:43:58.79ID:npfcBiID
>>343
それはearly returnって言わなくない?
そりゃ結果は同じだけど、元の人は構文的なことを言ってるわけで。
0345デフォルトの名無しさん
垢版 |
2020/04/01(水) 14:12:02.37ID:Wuhu+msT
ネストが嫌なんだから無理でしょ
ネストしないコードを書く人なんだろうけど
0346デフォルトの名無しさん
垢版 |
2020/04/01(水) 17:06:40.66ID:qjrNWUcZ
>>344
なるほど理解した

どうしてもearly returnがしたくてunwrapも嫌なら
if letを2回やるか、is_none+if let Someでもいい気がする
マクロ書いてもidiomaticな形に比べて読みやすくなるかっていうと微妙なので

fn foo(x: &str) -> Result<()>{
let v = safe_get!(get(x), { …; return Ok(()) });
let v = baz(v)?;
qux(v)?
}

fn foo(x: &str) -> Result<()>{
if let Some(v) = get(x) {
let v = baz(v)?;
qux(v)?;
}
Ok(())
}
0347デフォルトの名無しさん
垢版 |
2020/04/01(水) 19:39:22.27ID:2vQ3PjhV
"処理と戻り値"を伴う""正常""の早期returnをしたいといってるだろがErrでラップして返すとかバカか?

こういうSomeから取り出すだけの部分が冗長だから消えてなくなれつってんだよ
is_none()でやるのは構文保証ではなく"プログラマーの注意力"による保証だからクソだつってんだよ

let v = match foo.get() { Some(v) => v, None => {
bar.modify();
baz.modify();
return Ok(bar, baz);
}};

let v = if let Some(v) = foo.get() { v } else {
bar.modify();
baz.modify();
return Ok(bar, baz);
}};
0348デフォルトの名無しさん
垢版 |
2020/04/01(水) 20:41:14.76ID:SX13wyIA
>>347
だからその冗長な部分はマクロで潰せと言ってるんだが。
マクロが嫌なら無理としか言いようがないが。
0352デフォルトの名無しさん
垢版 |
2020/04/01(水) 21:36:47.02ID:qjrNWUcZ
>>347
>"処理と戻り値"を伴う""正常""の早期returnをしたいといってるだろがErrでラップして返すとかバカか?

えっ、 Errでラップして返してる?

まぁそれはいいとしてearly returnだけじゃなく
戻り値の型と取り出した値をどうするかをセットで考えてないから
そうなっちゃうんだと思うよ
0353デフォルトの名無しさん
垢版 |
2020/04/01(水) 22:01:23.20ID:SX13wyIA
RFCざっと見てきたけど、あっちでも
「map_errでいいんじゃ?」「return;できねーよ」ってやってるな。
そんなに難解なリクエストでもないと思うんだが。
0354デフォルトの名無しさん
垢版 |
2020/04/01(水) 22:20:38.50ID:0Fs3VJge
fn check<T>(mut f: impl FnMut(T) -> bool)

fn check<T, F>(mut f: F)
where F: FnMut(T) -> bool
って同意義ですか?
0355デフォルトの名無しさん
垢版 |
2020/04/02(木) 03:46:30.54ID:0zdT1xZ7
>>354
恐らくだけど、前者は必ずその関数を定義する。
後者は、Fがその型の場合にのみその関数を定義する。
0356デフォルトの名無しさん
垢版 |
2020/04/02(木) 03:48:18.19ID:0zdT1xZ7
なお、このような場合の whereは、日本人感覚からすれば、ifと読み替えてもいい。
0357デフォルトの名無しさん
垢版 |
2020/04/02(木) 05:35:03.07ID:zwgg3bUK
前者の場合 check::<T, F>() でコールできるが後者はできない
0358デフォルトの名無しさん
垢版 |
2020/04/02(木) 17:07:56.47ID:SaXsz2/b
前者と後者が逆?
0360デフォルトの名無しさん
垢版 |
2020/04/02(木) 21:53:44.49ID:zwgg3bUK
>>358
逆にだったすまん
0361デフォルトの名無しさん
垢版 |
2020/04/02(木) 23:30:20.89ID:SaXsz2/b
そもそもcheck::<T, F>()じゃ引数渡してないから呼び出せなくない? 試してないけど
0362デフォルトの名無しさん
垢版 |
2020/04/03(金) 00:13:24.70ID:RIPEgpHK
構文で解決すべきところを皆が俺俺マクロで解決して統一感ない状態を生むのが良いと考えるやついるのか?
0363デフォルトの名無しさん
垢版 |
2020/04/03(金) 00:44:31.97ID:11HfTHW1
if foo.is_none() {
シンプルにこれでいいと思うんだが...
これぐらいの細かい挙動で構文拡張しろとかマクロ書けとかなったらC++みたいになっていくのが目に見えるしから嫌だわ
しかもこんな嫌だ嫌だ言ってて質問する立場なのにこんな逆ギレもしてて救いようがない
0364デフォルトの名無しさん
垢版 |
2020/04/03(金) 00:44:38.25ID:8O7qKRUc
現状は335が冗長と言う状態で統一されてるんだからいいんじゃないの。
その冗長さをどうしても許容できない人は(少数派である以上)マクロで解決するしかないし、もし大多数が賛同できる新構文を思い付いたならRFC出せばいい。
0365デフォルトの名無しさん
垢版 |
2020/04/03(金) 14:52:15.88ID:11HfTHW1
test bench_test ... bench: 111,111 ns/iter (+/- 11,111)
ベンチマークの +/- ってどういう意味?
0366デフォルトの名無しさん
垢版 |
2020/04/03(金) 15:47:04.36ID:uTu5qR57
>>363
is_none()は==NULLや==nilと同じ書き忘れのリスクを伴う"プログラマの注意力"を消耗するだけのゴミだろ
0368デフォルトの名無しさん
垢版 |
2020/04/03(金) 19:54:55.15ID:CGYa3yhA
if letやmatchにしないとSomeだったときの処理書けないしょ
0370デフォルトの名無しさん
垢版 |
2020/04/04(土) 00:07:28.35ID:cnL2FB3T
rust実用化に成功したプロジェクトって何があるの?お前らの会社では成功してるの?
0374デフォルトの名無しさん
垢版 |
2020/04/04(土) 08:43:05.69ID:ziV4A0+Z
Utcはフィールドを持たないstructだから
イメージ的にはUtc{}.ymdとしているかんじ
0377デフォルトの名無しさん
垢版 |
2020/04/04(土) 17:26:12.04ID:9lNQDQEm
pub が付いてないものをそんなに簡単に使えたらモジュールの意味がないやろ……。
0378デフォルトの名無しさん
垢版 |
2020/04/04(土) 17:26:43.72ID:9lNQDQEm
そのモジュールをコピペして新しいモジュールを作れば自由に出来るんとちゃう?
0380デフォルトの名無しさん
垢版 |
2020/04/04(土) 20:42:49.37ID:oHbtMe0Y
iteratorを受け取ってSelfを返す。
iteratorは各要素がImageResult<Frame>のもの

Box<dyn …>してるのはコンパイル時にTrait ObjecのSizeが決まるようにするため
(Generics使えば不要)

‘aはiteratorのlifetimeをSelfのlifetimeにするため
0382デフォルトの名無しさん
垢版 |
2020/04/05(日) 10:19:35.11ID:LNp8foc9
>>381
dyn は C++ で言う抽象クラスみたいなもんだよ。
トレイトオブジェクトというのは実際にはそのトレイトを実装している様々な型の可能性があって、
それら全てを格納可能な大きさはわからない。
Box は C/C++ でいうポインタみたいな用途で使われる。
大きさがわからなくてもオブジェクトの場所を指すことは出来る。

「そのトレイトを実装している型ならなんでも」と「そのトレイトを実装している型のいずれか」というのは違う意味で、
ジェネリクスは後者。
言い換えると、実行時にディスパッチされる多相とコンパイル時にディスパッチされる多相ってこと。
コンパイル時に型がわかるのなら大きさもコンパイル時にわかる。
大きさがわかるなら Box を経由しなくていい。

ライフタイムの 'a は Frames の型引数の 'a と同じだから、
new の返り値 (Self) の寿命は iterator の寿命と同じになる。
0383デフォルトの名無しさん
垢版 |
2020/04/05(日) 11:42:45.53ID:/6aVgV0B
Boxと&dynの違いって参照元がヒープかスタックかの違い?
0385デフォルトの名無しさん
垢版 |
2020/04/05(日) 14:35:00.95ID:8bGOOvBY
>>381
大前提として変数や関数の引数や戻り値はコンパイル時にサイズが決まってないといけない

Iterator Traitを実装してる型を引数として受け取りたいからといって
`pub fn new(iterator: Iterator<…>) -> Self` と書くと
Iterator Traitのサイズがコンパイル時にはわからないのでコンパイルエラーになる
`let foo: str;`でエラーになるのと同じ

Box<dyn Trait>か&dyn Traitの形にすれば
Iterator Traitへの参照(=Trait Objectというfatポインタ)になって
受け渡しするサイズが固定されるのでエラーにならない

ジェネリクスを使って
`pub fn new<T: Iterator<…>>(iterator: T) -> Self` と書いた場合は
実際の呼び出しに使われているTの型ごとにコンパイラがバイナリを生成するので
コンパイル時にTのサイズが決まってる (impl Trait使った場合も同じ)

>>382も書いてるように前者は動的ディスパッチ、後者は静的ディスパッチなので
異なる型が混在するコレクションを使いたい時やバイナリサイズを小さくしたい時以外は
ジェネリクスを選ぶほうが一般的
0386デフォルトの名無しさん
垢版 |
2020/04/05(日) 17:53:06.31ID:fOt2g8TG
あーなんとなくわかってっきた
ジェネリクスと同じことがトレイトオブジェクトでも実現できて、その書き方がBox<dyn...>ということか
0388デフォルトの名無しさん
垢版 |
2020/04/05(日) 21:52:05.83ID:/6aVgV0B
そもそもRustはかなり型のサイズに厳しいけどなんで?
コンパイラの最適化のため?
0389デフォルトの名無しさん
垢版 |
2020/04/05(日) 22:38:29.83ID:8bGOOvBY
>>388
他言語なら暗黙的に参照として扱われるようなものも
明示的に&を付けたりBox化することを求めるから厳しく感じるんだと思う

明示的に求めるのはowned/shared/mutableの3つを
一貫性を持って区別して書くようにっていう設計選択じゃないかな

>大前提として変数や関数の引数や戻り値はコンパイル時にサイズが決まってないといけない
↑これ他言語でも常識かもしれないけど自分はRustやるまで意識したことなかったよ
0390デフォルトの名無しさん
垢版 |
2020/04/05(日) 23:09:09.40ID:/qXmUwFk
> pub fn new(iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>) -> Self
入力にimpl Traitってまだ無理なんだっけ?

>>386
同じではない。
ジェネリックスはパラメトリック多相の事だから静的ディスパッチになるけどtrait objectは動的ディスパッチそのもの。

>>388
そう。
リージョンでメモリ管理するときリージョンのサイズが事前に決まるなら
リージョンはヒープじゃなくてスタックに確保できるからrustは型システムが
サイズが事前に決まる事を強制してる。
rustでは
0391デフォルトの名無しさん
垢版 |
2020/04/05(日) 23:12:44.10ID:/qXmUwFk
途中で送ってしもた。

rustでは当たり前に見えるけどこんな事してるのrustくらいでヒープが必要ならクロージャさえも自分でbox化する必要がある。
0392デフォルトの名無しさん
垢版 |
2020/04/05(日) 23:13:46.13ID:dvIeqTXE
スタック上に長さ不定のデータが作れるとバグの温床になる。
他の言語だと大体の値がヒープに乗せること前提で動いているんで気にしたことが無いのだと思われる。
C/C++でも非推奨なんだけど、初心者向け釣りサイトでは平気でやってることがあるし、できちゃうから面倒
0393デフォルトの名無しさん
垢版 |
2020/04/06(月) 00:16:34.72ID:WU94L+3C
配列サイズが決められてないかつ、関数内で配列生成するけど返り値はサイズ固定のスライス記法の書き方するようにする方法ってない?
つまりはVecのアロケートが嫌な場合
fn name(v: Vec<A>) -> Vec<A> {
v.iter().map(***).collect
}

これだとスタック確保できるけど無駄なデータ入ってるし、動的なサイズの配列を返せない
fn name(v: Vec<A>) -> [i32; 10] {
let mut arr = [0; 10];
for (i, x) in v { arr[i] = x}
arr
}

こういうスライスのスタック版みたいな感じのことがしたい
fn name(v: Vec<A>) -> [A] {
let mut arr = [0; v.len()];
for (i, x) in v { arr[i] = x}
arr
}
0394デフォルトの名無しさん
垢版 |
2020/04/06(月) 00:54:32.32ID:jrbG9hxT
>>390
impl Traitは引数にも使えるよ

>>393
[A]だとサイズがコンパイル時に決まらないから&[A]か&mut [A]を返すのはできる
ただ入力がVecで長さが不定なので
出力の参照元にその長さの配列を使うのは無理じゃないかな
0395デフォルトの名無しさん
垢版 |
2020/04/06(月) 00:59:52.27ID:jrbG9hxT
あと関数内部で配列生成したら
そのlifetimeが関数内に閉じるので参照も返せないね
0396デフォルトの名無しさん
垢版 |
2020/04/06(月) 01:07:26.57ID:jrbG9hxT
やるとしたら
外側のスコープで固定サイズの配列をバッファとして作っておいて
関数ではバッファを満たして返すイメージ
0397デフォルトの名無しさん
垢版 |
2020/04/06(月) 01:16:22.32ID:FD55gb+K
C言語でいうところの if ( (c=foo()) == bar) { ...(cを使う処理)
みたいなことやりたいんですがどうすればいいですか?
fooが結構重くて2回呼び出したくないのですが、
let c = foo();
if c == bar {...
とやるしかない?
0398デフォルトの名無しさん
垢版 |
2020/04/06(月) 01:49:32.44ID:JJIxYQHA
matchとifガード使えば似たようなことは出来る
0399デフォルトの名無しさん
垢版 |
2020/04/06(月) 02:48:45.03ID:WU94L+3C
>>396
何かしらのライブラリでなんかないかな?
static使うぐらいなら素直にVec使うわ...
0401デフォルトの名無しさん
垢版 |
2020/04/06(月) 04:04:37.66ID:FD55gb+K
>>398
match foo() {
c if c == bar => { .. },
_ => (),
}
こういう感じでしょうか。この場合だと記載量としてはかなり微妙ですが何かに使えそうなので覚えときます。
ありがとうございます。

>>399
今回の場合はfoo()がboolじゃないのと、barが変数なのでシャドーイングされてうまくいかないようです・・・。
if let foo @ bar = foo() { ...
みたいなことやろうとしましたがダメでした。
https://play.rust-lang.org/?version=nightly&;mode=debug&edition=2018&gist=d580f91c98f26cf52a23791489914ec3
0403デフォルトの名無しさん
垢版 |
2020/04/06(月) 22:57:49.62ID:2RUK7fME
Vecとかのコンテナ系の使い方は大分変わるよ
例えばイベント駆動の何かを作るときには考えた方が良いかと思う
struct XEventSource {
listeners : Vec<Box<dyn Handler>>,
...
}
trait Handler { fn handle(ev: &XEvent) -> () }

impl XEventSource {
fn addLisnter(&mut self, listener : Box<dyn Handler>) -> () {
 self.listeners.push(listener);
}
fn emit(&self) -> () {
 XEvent ev = ...;
 for listener in listeners.iter() {
  listener.handle(&ev);
 }
}
}
みたいに作ると、利用者が好きに作った構造体でもHandlerをimplすればlistenersに足せる
ジェネリクスだとイベントリスナの実際の型1つしかaddできないので不便
0404デフォルトの名無しさん
垢版 |
2020/04/06(月) 23:45:59.83ID:TaQVQ6iW
>>402
実行時に型を振り分けるとなると仮想関数テーブルを辿る必要があるんで実行時コストが少し増えるよ。
(Rust では仮想関数って言わないのかな? 正確な用語がわからん。)

トレイトを実装している型を実際には一種類しか使わないのだったら、
実行時間を除けば見かけ上の動作で違いはないかもしれんな。
でも基本的にはやりたいことを出来る範囲で制約は厳しい方がいい。
間違いの検出される可能性が高まるから。

制約をどのように表現するかというのはプログラミング言語の設計においては重要なトピックで、
構造化プログラミングが提唱されたのも goto だと制御をどこへ移動するのか制約を付けられないってのがある。
さらにそれを発展させた形として型で制約を付けようってのが色々と考えられてきたし、
Rust では更にオブジェクトの寿命に制約を付けようという考えが実現された。

その関数では何ができるのか、そして「何をしてはいけないのか」ってのを考えると
Rust らしいプログラムが出来ると思う。
0405デフォルトの名無しさん
垢版 |
2020/04/07(火) 08:14:23.99ID:FPXvnSDp
APIサーバーでJSON受け取るときに値の型が違ったりオーバーフローするときってどうしてる?
serde_json::from_str で構造体の属性でエラーメッセージとかつけれたらいいのにな
0406デフォルトの名無しさん
垢版 |
2020/04/07(火) 15:06:01.62ID:+YUDNjw9
from_strの結果そのまま使ってるけどダメなの
シンタックスエラーとか含めると大変じゃない
0407デフォルトの名無しさん
垢版 |
2020/04/07(火) 15:54:15.51ID:FPXvnSDp
海外向けサーバーだったらいいけど日本向けサーバーの場合は?
serde_jsonのエラーメッセージcustomizableじゃないから辛い
0408デフォルトの名無しさん
垢版 |
2020/04/07(火) 16:02:31.28ID:+YUDNjw9
serde_json::Error を見ると行と列と大雑把な原因はとれるみたい
細かくやるなら置換するしかなさそうだね
0409デフォルトの名無しさん
垢版 |
2020/04/08(水) 10:01:13.64ID:qyTF9Er6
reached the configured maximum number of stack frames
でスタックフレームの制限にかかるんだけどオプションとかで変えれる?
0410デフォルトの名無しさん
垢版 |
2020/04/11(土) 23:13:20.24ID:EhWtF4tX
impl<'_, T> Drop for std::collections::vec_deque::Drain<'_, T>
こういう風にちゃんとパス書かれたのもあれば、デフォルトインポートされてないのに省略されてる型あるけどどうなってるの?
https://doc.rust-lang.org/std/ops/trait.Drop.html
0411デフォルトの名無しさん
垢版 |
2020/04/11(土) 23:59:49.19ID:Ni1vKiQd
フルパス書かなくてもいいように
mod.rsに指定されてるものとされてないもの
0413デフォルトの名無しさん
垢版 |
2020/04/13(月) 09:02:25.60ID:45YCco/F
それが必要な理由は?ここはお前の便利帳じゃねーんだから
有益な使い方が有れば紹介してから聞け
0415デフォルトの名無しさん
垢版 |
2020/04/13(月) 11:59:07.30ID:WFzH9Pd8
>>413
データ入ったVecと各種定数とメモ化用のmutなHashMap使ったDFSするときとか、引数がむっちゃ長くなるんです

>>414
全然わからんのであきらめます・・・
0416デフォルトの名無しさん
垢版 |
2020/04/14(火) 07:17:51.31ID:WrIQImmd
Copyでの関数呼び出しとポインタ作成ってコスト的にはプリミティブのどの型からが処理重い?
ここらへんCSの知識ないからわかんない
0417デフォルトの名無しさん
垢版 |
2020/04/15(水) 02:35:11.54ID:rawye3jg
Rust仕事で使ってる人〜
ウチはコロナの影響でプロジェクト吹き飛んだよん( ;∀;)
0419デフォルトの名無しさん
垢版 |
2020/04/15(水) 05:30:29.65ID:SZSUFLJC
組み込みで試験的に導入したけどムズイ
まあ慣れの問題もあるのだろうけど
0421デフォルトの名無しさん
垢版 |
2020/04/15(水) 21:11:58.85ID:60TKpqE+
Nimは?
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況