Rust で HashSet の要素や HashMap のキーに使う型は Eq と Hash トレイトを実装している必要がある
HashSet in std::collections - Rust
HashMap in std::collections - Rust
自前の構造体を HashSet の要素にしたり、HashMap のキーに使用するとコンパイルエラーになる。
use std::collections::HashSet; fn main() { { struct MyFoo { x: i32, } let mut hs: HashSet<MyFoo> = HashSet::new(); hs.insert(MyFoo { x: 123 }); hs.insert(MyFoo { x: 234 }); for e in hs.iter() { println!("{}", e.x); } } }
error[E0599]: the method `insert` exists for struct `HashSet<MyFoo>`, but its trait bounds were not satisfied --> examples\hm_error.rs:8:12 | 4 | struct MyFoo { | ------------ | | | doesn't satisfy `MyFoo: Eq` | doesn't satisfy `MyFoo: Hash` ... 8 | hs.insert(MyFoo { x: 123 }); | ^^^^^^ method cannot be called on `HashSet<MyFoo>` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `MyFoo: Eq` `MyFoo: Hash` help: consider annotating `MyFoo` with `#[derive(Eq, Hash)]` | 4 | #[derive(Eq, Hash)] | error[E0599]: the method `insert` exists for struct `HashSet<MyFoo>`, but its trait bounds were not satisfied --> examples\hm_error.rs:9:12 | 4 | struct MyFoo { | ------------ | | | doesn't satisfy `MyFoo: Eq` | doesn't satisfy `MyFoo: Hash` ... 9 | hs.insert(MyFoo { x: 234 }); | ^^^^^^ method cannot be called on `HashSet<MyFoo>` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `MyFoo: Eq` `MyFoo: Hash` help: consider annotating `MyFoo` with `#[derive(Eq, Hash)]` | 4 | #[derive(Eq, Hash)] | For more information about this error, try `rustc --explain E0599`.
derive で Hash と Eq をつければ良いようだ。しかしその2つだとインスタンス同士の比較ができなくて、PartialEq もつけるといいよ!、とメッセージが出るので、そのようにするとうまくいった。
#[derive(Hash, Eq, PartialEq)] struct MyFoo { x: i32, }
同様に、HashMap のキーのときも同じ対応でいけた。
#[derive(Hash, Eq, PartialEq)] struct MyFoo { x: i32, } let mut hm: HashMap<MyFoo, &str> = HashMap::new(); hm.insert(MyFoo { x: 123 }, "123"); hm.insert(MyFoo { x: 234 }, "234"); for (k, v) in hm.iter() { println!("{}, {}", k.x, v); }
WebAssembly と Rust について社内で LT した
内容をメモ
- WebAssembly とは
- WebAssembly とは
- ネイティブに近いパフォーマンスで動く
- コンパイルして作るバイナリ
- 第 4 のブラウザ用言語
- W3C 勧告として公開
- 対応ブラウザ
- 最近のブラウザはすべて対応している(IE もいなくなったので本当にすべて)
- 作成言語
- 実際に使っているひとに聞いたアンケート結果では Rust が 1 位とのこと
- 事例
- Google Earth, Google Meet, ffmpeg, CDN のエッジロケーション, Unity アプリ, WASI
- WASI (WebAssembly System Interface)
- ランタイムの三国時代 wasmer, wasmtime, wasmedge
- コンテナのようなポータブル性
- メリット
- 高速、JavaScript と共存可能
- デメリット
- なんでもかんでも改善できるわけではない
- ブラウザによって JS よりも早くなったり遅くなったりするらしい
- WebAssembly とは
- Rust とは
- Rust とは
- 6 年連続、最も愛された(=仕事で使いたい)言語 1 位
- 所感
- とにかく難しく感じる
- Rust とは
- WebAssembly + Rust
- フレームワークが存在する
- 生で書いたらこんな感じ
- デモ
Rust と WebAssembly で ボタンを getElementById したり click 属性をつけたりするサンプルメモ
Rust の WebAssembly で、ボタンを押すと、div#msgdiv にテキストを入れて、window.alert() を実行するサンプルメモ。
trunk を使用している。
index.html
<!DOCTYPE html> <html> <head></head> <body> <div id="msgdiv"></div> <input type="button" value="botan" id="foobtn"> </body> </html>
Cargo.toml
[package] name = "click-test" version = "0.1.0" edition = "2021" # [lib] # crate-type = ["cdylib", "rlib"] [dependencies] # log = "0.4.17" # wasm-logger = "0.2.0" # web-sys = "0.3.57" wasm-bindgen = "0.2.80" [dependencies.web-sys] version = "0.3.57" features = [ 'Window', 'Document', 'Element', 'HtmlElement' ]
src/main.rs
use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use web_sys::{Document, HtmlElement, Window}; #[wasm_bindgen] extern "C" { fn alert(s: &str); } fn window() -> Window { web_sys::window().unwrap() } fn document() -> Document { window().document().unwrap() } fn body() -> HtmlElement { document().body().unwrap() } pub fn main() { let cb = Closure::wrap(Box::new(move || { let el = document().get_element_by_id("msgdiv").unwrap(); // テキストを入れる el.set_text_content(Some("Hello World")); // window.alert する alert("Hello, World"); }) as Box<dyn Fn()>); let el = document().get_element_by_id("foobtn").unwrap(); let el = el.dyn_ref::<HtmlElement>().unwrap(); el.set_onclick(Some(cb.as_ref().unchecked_ref())); // これをしないと ブラウザコンソールで「Error: closure invoked recursively or destroyed already」と言って怒られる。 // forget() しておくとメモリに残り続けるらしい。 cb.forget(); }