簡體   English   中英

改變 arguments 在傳遞給子 MAIN 之前的處理方式

[英]Alter how arguments are processed before they're passed to sub MAIN

鑒於文檔和對較早問題的評論,根據要求,我制作了一個最小的可重現示例,展示了這兩個語句之間的區別:

my %*SUB-MAIN-OPTS = :named-anywhere;
PROCESS::<%SUB-MAIN-OPTS><named-anywhere> = True;

給定一個只有這個的腳本文件:

#!/usr/bin/env raku
use MyApp::Tools::CLI;

以及 MyApp/Tools 中名為 CLI.pm6 的模塊文件:

#PROCESS::<%SUB-MAIN-OPTS><named-anywhere> = True;
my %*SUB-MAIN-OPTS = :named-anywhere;

proto MAIN(|) is export {*}

multi MAIN( 'add', :h( :$hostnames ) ) {
    for @$hostnames -> $host {
        say $host;
    }
}

multi MAIN( 'remove', *@hostnames ) {
    for @hostnames -> $host {
        say $host;
    }
}

從命令行進行的以下調用不會產生可識別的子例程,但會顯示用法:

mre.raku add -h=localhost -h=test1

切換my %*SUB-MAIN-OPTS =:named-anywhere; 對於PROCESS::<%SUB-MAIN-OPTS><named-anywhere> = True; 如預期的那樣,將使用提供的兩個主機名打印兩行。

但是,如果這是在一個文件中完成的,如下所示,兩者的工作方式相同:

#!/usr/bin/env raku

#PROCESS::<%SUB-MAIN-OPTS><named-anywhere> = True;
my %*SUB-MAIN-OPTS = :named-anywhere;

proto MAIN(|) is export {*}

multi MAIN( 'add', :h( :$hostnames )) {
    for @$hostnames -> $host {
        say $host;
    }
}

multi MAIN( 'remove', *@hostnames ) {
    for @hostnames -> $host {
        say $host;
    }
}

我覺得這很難理解。 重現此內容時,請注意必須如何調用每個命令。

mre.raku remove localhost test1
mre.raku add -h=localhost -h=test1

因此,當在單獨的文件中使用my %*SUB-MAIN-OPTS =:named-anywhere; . PROCESS::<%SUB-MAIN-OPTS><named-anywhere> = True; 總是有效。 對於 slurpy 數組,兩者在兩種情況下的工作方式相同。

問題是它在腳本和模塊中都不是同一個變量。

當然他們有相同的名字,但這並不意味着什么。

my \A = anon class Foo {}
my \B = anon class Foo {}

A ~~ B; # False
B ~~ A; # False
A === B; # False

這兩個類具有相同的名稱,但是是獨立的實體。


如果您查看其他內置動態變量的代碼,您會看到如下內容:

Rakudo::Internals.REGISTER-DYNAMIC: '$*EXECUTABLE-NAME', {
    PROCESS::<$EXECUTABLE-NAME> := $*EXECUTABLE.basename;
}

這可以確保變量安裝到正確的位置,以便它適用於每個編譯單元。

如果你尋找%*SUB-MAIN-OPTS ,你唯一能找到的是這一

    my %sub-main-opts   := %*SUB-MAIN-OPTS // {};

這會在主編譯單元中查找變量。 如果沒有找到它,它會創建並使用一個空的 Hash。

因此,當您嘗試在主編譯單元以外的 scope 中執行此操作時,它不在該行可以找到的位置。


要測試添加是否可以解決問題,您可以將其添加到主編譯單元的頂部。 (加載模塊的腳本。)

BEGIN Rakudo::Internals.REGISTER-DYNAMIC: '%*SUB-MAIN-OPTS', {
    PROCESS::<%SUB-MAIN-OPTS> := {}
}

然后在模塊中,這樣寫:

%*SUB-MAIN-OPTS = :named-anywhere;

或者更好的是:

%*SUB-MAIN-OPTS<named-anywhere> = True;

在嘗試了這個之后,它似乎工作得很好。


問題是, 那里曾經有過類似的東西。

考慮到它會減慢每個 Raku 程序的速度,它被刪除了。

盡管我認為它導致的任何減速仍然是一個問題,因為仍然存在的行必須查看是否存在該名稱的動態變量。
(給出的理由更多,坦率地說,我不同意所有這些理由。)

願一杯茶給未來思考事物意義的SO讀者帶來啟迪。 [1]

麗茲的相關回答

我認為Liz 對 SO 問一個類似問題的回答可能是一個很好的讀物,可以很好地解釋為什么模塊主線中的my (就像一個較小our )不起作用,或者至少確認核心開發人員知道它。

她后來對另一個 SO 的回答解釋了如何通過將my放在RUN-MAIN使用它。

為什么 slurpy 數組默認工作但沒有在任何地方命名?

關於事情為何如此的一個豐富資源是聲明 S06 的 MAIN 子程序部分(子程序概要) [2]

關鍵摘錄:

像往常一樣,開關被假定為第一個,並且第一個非開關之后的所有內容,或 - 之后的任何開關都被視為位置或 go 進入 slurpy 陣列(即使它們看起來像開關)。

所以看起來這是默認行為的來源,其中命名不能go 來自任何地方; 似乎@Larry [3]聲稱“通常的” shell 約定如所描述,並暗示這應該表明默認行為是原樣的。

自從 Raku 正式發布以來, RFC: Allow subcommands in MAIN讓我們走上了通往今天的:named-anywhere選項的道路。 RFC 提出了一個非常強大的 1-2 拳——一個無可挑剔的兩行黑客散文/數據論點,很快就導致了粗略的共識,並帶有一個帶有此提交消息的工作代碼 PR:

允許 --named-switches 在命令行中的任何位置。

Raku 類似於 GNU,因為它具有“--double-dashes”,並且在遇到“--”時停止解釋命名參數,但與類似 GNU 的解析不同,它在遇到任何位置參數時也停止解釋命名參數。 此補丁通過允許在位置后命名為 arguments 以准備允許子命令,使其更像 GNU。

> 改變 arguments 在傳遞給子 MAIN 之前的處理方式

在 S06 的上述鏈接部分中, @Larry還寫道:

通常,頂級 Raku“腳本”只是評估其匿名主線代碼並退出。 在主線代碼中,程序的 arguments 以原始形式從@*ARGS數組中獲得。

這里的重點是您可以在將@*ARGS傳遞給MAIN之前對其進行預處理。

繼續:

然而,在主線代碼的末尾,將使用@*ARGS中保留的任何命令行 arguments 調用MAIN子例程。

請注意,正如 Liz 所解釋的,Raku 現在有一個在調用MAIN之前調用的RUN-MAIN例程。

然后是標准參數處理(可通過使用標准選項進行更改,其中目前只有:named-anywhere一個,或諸如SuperMAIN類的用戶區模塊,它添加了各種其他功能)。

最后@Larry指出:

通過顯式調用MAIN可以輕松引入其他 [命令行解析] 策略。 例如,您可以使用語法解析您的 arguments 並將生成的Match object 作為Capture傳遞給MAIN

文檔修復?

昨天您寫了一條評論,建議進行文檔修復

我現在看到我們(集體)知道編碼問題。 那么為什么文檔是這樣的呢? 我認為您的 SO 和以前的 SO 的組合提供了足夠的軼事來支持至少考慮提出相反的文檔問題 再一次,Liz 在其中一個 SO 中暗示可能會出現修復,至少對於our的 s。 SO 本身可以說是 doc。 所以也許等待更好? 我會踢球,讓你決定。 如果您決定提交文檔問題,至少您現在有幾個 SO 要引用。

腳注

[1]我想明確一點,如果有人認為發布此 SO 有任何錯誤,那么他們是對的,錯誤完全是我的。 我向@acw 提到我已經進行了搜索,因此他們可以相當合理地得出結論,他們也沒有必要進行搜索。 所以,mea culpa,包括糟糕的咖啡啟發雙關語。 (糟糕的雙關語,不錯的咖啡。)

[2]當您了解 Raku 時,Imo 這些古老的歷史推測性設計文檔值得一讀再讀,盡管它們在某些方面已經過時。

[3] @Larry出現在 Raku 文化中,作為 Larry Wall 等人(由 Larry 領導的 Raku 語言團隊)的一種有趣且方便的簡寫。

暫無
暫無

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

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