簡體   English   中英

如何創建 map 的字符串以在 Rust 中運行?

[英]How can I create a map of strings to functions in Rust?

我正在制作一個 Lisp來學習 Rust。

作為評估步驟的一部分,我需要創建一個關聯結構,將字符串(或其他)映射到函數。 在我更熟悉的語言中(Ruby,Clojure)我會簡單地在 hashmap 中定義匿名函數,例如

{ :+ (fn [a b] (+ a b))
  :- (fn [a b] (- a b)) } ; etc

在 Rust 中,這是不可能的,因為類型錯誤expected closure, found a different closure

let repl_env = HashMap::new();

repl_env.insert("+", |a, b| a + b);
repl_env.insert("-", |a, b| a - b); // expected closure, found a different closure

我想這里發生的事情是

  • 編譯器將HashMap中的類型推斷為<String, WhateverTypeTheFirstClosureIs>
  • 第二個閉包沒有相同的時間,因為編譯器錯誤繼續說, no two closures, even if identical, have the same type

我可以向 arguments 添加類型,從而使返回類型可推斷,但這無濟於事——我假設我需要以某種方式注釋閉包本身的類型? 我在文檔中找不到執行此操作的方法。 該錯誤提示裝箱,但將閉包包裝在Box::new中無濟於事。 (我以前從未Box過)。

我還想知道 HashMap 中的HashMap閉包在這里使用是否正確。 我應該使用某種enum嗎? (稍后當我將用戶定義的函數添加到我的 lisp 時,我想動態地添加一些東西,所以我假設不會)。

您實際上不需要在這里關閉,因為您沒有關閉任何東西,您只是在使用匿名 static 函數。

這意味着您可以將匿名函數轉換為 function 指針,它會正常工作,例如

let mut repl_env: HashMap<_, fn(i32, i32) -> i32> = HashMap::new();

repl_env.insert("+", |a, b| a + b);
repl_env.insert("-", |a, b| a - b);

如果你確實需要閉包,那么你必須使用某種動態調度(因為每個閉包都是完全不同的類型),通常類似於 `Box eg

let mut repl_env: HashMap<_, Box<dyn Fn(i32, i32) -> i32>> = HashMap::new();

repl_env.insert("+", Box::new(|a, b| a + b));
repl_env.insert("-", Box::new(|a, b| a - b));

后一個版本就是錯誤消息所談論的內容:裝箱閉包[和](在這種情況下)使其成為特征 object。

我應該使用某種枚舉嗎?

使用枚舉可能是個好主意,因為最終您將擁有具有不同簽名的函數:這里您僅限於(i32, i32) -> i32的簽名。 盡管您也可以將通用簽名更新為例如(Values) -> Value並在內部執行分派/類型檢查/...

稍后當我向我的 lisp 添加用戶定義的函數時,我想動態地添加一些東西,所以我假設不會。

如果你想保持“本地”和“用戶”功能之間的區別,你總是可以有一個變體,它在你的枚舉中存儲評估用戶 function 的結果。 無論如何,您都需要一種方法來區分它們,因為最終評估者不會以相同的方式稱呼它們。

雖然我認為通常的方法是使所有可見函數統一為“用戶空間”,並根據內置函數實現這些函數(可以在語法上區分,或者特殊的 forms,甚至由編譯器進行模式匹配,可能會也可能不會用戶區可以訪問)。

我不知道 Lisps 通常是如何從根本上做到這一點的,但是例如你可以讓解釋器評估條款

(+ a b)

並檢查+是已知/標准 function 並且ab是已知的兼容類型,然后在內部執行操作而不實際調用任何東西。

有趣的是,您可以提供一個正確定義的+ function 作為

(define (+ a b)
  (+ a b))

乍一看這看起來很荒謬,因為它應該遞歸自身,但內部節點可以由解釋器進行模式匹配,因此它可以作為高階函數的鈎子。

例如,這就是有多少 Smalltalks 處理了這個問題。 非文字發送將進入 trampoline 方法,然后該方法將無形地反彈到操作的內置方法中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM