質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
参照

参照は、プログラミングにおいて変数や関数といったメモリ空間上での所在を指示するデータのことを指します。その中にはデータ自体は含まれず、他の場所にある情報を間接的に指示するプログラムです。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

クロージャ

クロージャは、プログラミング言語における関数オブジェクトの一種です。 引数以外の変数を実行時の環境ではなく、 自身が定義された環境において解決することを特徴とします。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

解決済

【Rust】クロージャ(ラムダ)からメソッドを呼び出す処理は、Rubyなら簡単なのにRustではコンパイルエラーになってしまう

akira_kano1101
akira_kano1101

総合スコア16

参照

参照は、プログラミングにおいて変数や関数といったメモリ空間上での所在を指示するデータのことを指します。その中にはデータ自体は含まれず、他の場所にある情報を間接的に指示するプログラムです。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

クロージャ

クロージャは、プログラミング言語における関数オブジェクトの一種です。 引数以外の変数を実行時の環境ではなく、 自身が定義された環境において解決することを特徴とします。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

1回答

0評価

1クリップ

1047閲覧

投稿2022/03/29 11:08

編集2022/03/31 12:00

Rubyなら簡単に動かせるコードがRustでは通らない

(エラーメッセージの読み方が間違っていたので修正しました。)

こんにちは。Rustでソフトウェアの開発を行なっています。

Rubyならラムダの中でさらに同インスタンスメソッドが呼び出し# (1)および代入# (2)ができます。

ruby

# Rubyならこう書けば実現できるが… class Card def run(assignor) assignor[28] end end class App def assign(value) @value = value # (2) end def setup @value = 42 @card = Card.new end def update @card.run( ->(value) { self.assign(value) } # (1) ) puts @value # => 28と表示される end end def main app = App.new app.setup app.update end main

同様の動作をRustでも実現したい、しかし…

クロージャで同じように同オブジェクトのメソッドを呼び出そうと考えました。

しかしこれはうまくいきません。

rust

// Rustではコンパイルエラーになる #[derive(Default)] pub struct Card; impl Card { pub fn new() -> Self { Self } pub fn run<F>(&self, mut assignor: F) where F: FnMut(i32), { assignor(28); } } #[derive(Default)] struct App { value: i32, card: Card, } impl App { fn assign(&mut self, value: i32) { self.value = value; } pub fn setup(&mut self) { self.value = 42; self.card = Card::new(); } pub fn update(&mut self) { self.card.run(|value| { self.assign(value); }); println!("{}", self.value); } } fn main() { let mut app = App::default(); app.setup(); app.update(); }

エラーメッセージ抜粋

error[E0500]: closure requires unique access to `*self` but it is already borrowed --> src/main.rs:29:23 | 29 | self.card.run(|value| { | - --- ^^^^^^^ closure construction occurs here | | | | _________| first borrow later used by call | | 30 | | self.assign(value); | | ---- second borrow occurs due to use of `*self` in closure 31 | | }); | |__________- borrow occurs here

Rustでは二重に借用できないルールがあるようで、コンパイルできませんでした。

Rubyの書き方が非常に便利なため可能であればこれを何とかして実現したいです。

もし解決方法をご存じの方いらっしゃれば、恐縮ですが教えていただけないでしょうか。

よろしくお願いいたします。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

参照

参照は、プログラミングにおいて変数や関数といったメモリ空間上での所在を指示するデータのことを指します。その中にはデータ自体は含まれず、他の場所にある情報を間接的に指示するプログラムです。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

クロージャ

クロージャは、プログラミング言語における関数オブジェクトの一種です。 引数以外の変数を実行時の環境ではなく、 自身が定義された環境において解決することを特徴とします。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。