跳轉到內容

Raku 程式設計/型別和上下文

來自 Wikibooks,開放世界中的開放書籍

上下文

[編輯 | 編輯原始碼]

我們已經討論了各種基本資料型別,例如標量、陣列和雜湊。每個變數的符號都會將其置於特定的上下文中。不同型別的變數在不同上下文中使用時會有不同的行為。至少有兩種基本型別的上下文,我們現在要談論其中兩種:標量上下文和列表上下文。標量是帶有 $ 符號的任何東西,而列表是像陣列和雜湊這樣的東西。

旁註:say

[編輯 | 編輯原始碼]

我們現在要談論 Raku 的一個內建函式:saysay 在程式執行時將一行文字列印到控制檯。這是我們將在後面詳細討論的更大的輸入輸出 (I/O) 系統的一部分。say 接收一個字串或一個字串列表,並將它們列印到控制檯。

say "hello world!";
say "This is ", "Raku speaking!";

旁註:範圍

[編輯 | 編輯原始碼]

範圍是具有某種數值關係的值列表。範圍使用 .. 運算子建立

my @digits = 0..9;        # (0, 1, 2, 3, 4, 5, 6, 7, 8, 9);

範圍也可以使用變數作為分隔符

my $max = 15;
my $min = 12;
my @list = $min .. $max;  # (12, 13, 14, 15);

範圍是一種與陣列完全不同的物件型別,即使範圍會建立一個類似陣列的值列表。範圍實現了一種稱為延遲求值的行為:範圍不會首先計算所有值的列表,而是僅以開始和結束點進行緊湊儲存。稍後,當實際從範圍內讀取值時,可以從範圍中計算出值。這意味著我們可以輕鬆地擁有無限範圍而不會佔用所有計算機記憶體

my @range = 1..Inf;       # Infinite range, finite memory use
my $x = @range[1000000];  # Calculated on demand

延遲求值不僅僅是範圍的行為,它實際上直接內建在 Raku 中,並且在許多地方自動使用。這意味著大型陣列不一定會佔用大量記憶體,而是可以在需要時才計算值。

上下文說明符

[編輯 | 編輯原始碼]

我們可以使用各種強制轉換技術來指定資料項的上下文。$( ) 強制將括號之間的任何內容都視為標量,即使它通常不是標量也是如此。@( )%( ) 對陣列和雜湊也是如此。由於 ~ 始終與字串相關聯,而 + 始終與數字相關聯,因此我們可以使用它們將值分別強制轉換為字串和數字

my Num $x = +"3";             # Becomes a number
my Str $y = ~3;               # The string "3"
my $z = $(2..4);              # Three elements, but still a single Range object
my @w = @("key" => "value");  # Convert hash to array

上面的示例並不是從一種型別強制轉換為另一種型別的唯一情況。強制轉換使我們能夠將變數強制轉換為特定型別。在某些情況下,複雜的變數型別或類在強制轉換方式不同時可能會表現出非常不同的行為。我們將在後面的章節中討論這些情況。

以下是一個快速列出的上下文說明符

+( )
轉換為數字
~( )
轉換為字串
$( )
轉換為標量
@( )
轉換為陣列
%( )
轉換為雜湊

我們之前討論過 Raku 是一種動態語言,因此其中的變數和資料項沒有預定義的型別。我們還提到了,幾乎是在腳註中,Raku 也有一個型別系統,如果需要,可以可選地使用它。Raku 是一種非常靈活的語言,旨在為程式設計師提供很大的自由度,以便以不同的方式進行程式設計。Raku 提供給程式設計師的一種程式設計方式是結構化的、靜態型別的程式設計。

如果為變數指定型別,Raku 將遵循該型別,並且只允許使用該型別的變數。這在某些情況下非常有用,因為某些操作類將引發編譯時錯誤而不是執行時錯誤。此外,如果編譯器知道變數型別永遠不會改變,則可以自由地執行某些型別的最佳化。這些行為是與實現相關的,當然 - 只有在你嘗試利用它們時才會有用。一般規則是,你提供給編譯器的資訊越多,編譯器為你進行的分析就越有用。

詞法變數

[編輯 | 編輯原始碼]

我們之前還提到過,變數在使用之前不需要顯式宣告。這也是對真相的稍微誇大了。變數不需要事先宣告,但 Raku 讓你可以選擇這樣做。要預先宣告變數,可以使用 my 關鍵字

my $x = 5;

my 將變數定義為區域性詞法變數。另一種方法是將其定義為 our 以使其成為全域性共享變數。Raku 中全域性變數的另一個名稱是“包變數”,因為它可供整個軟體包或檔案使用。

our $x = 5;

全域性變數很好,因為你可以在任何地方使用它們,而無需將它們傳遞來回並跟蹤它們。但是,與幼兒園不同的是,在大型程式中,共享並不總是最好的主意。

內建型別

[編輯 | 編輯原始碼]

Raku 提供了一些內建型別,Raku 編譯器事先知道這些型別。你始終可以定義自己的型別,但 Raku 從一開始就提供了一些型別。以下是一些 Raku 內建基本型別的部分列表。這不是一個完整的列表,因為 Raku 中的一些型別在目前還無法理解。

Bool
布林值,真或假。布林值是列舉型別,我們將在稍後更詳細地討論。布林值只能是 TrueFalse
Int
基本整數值
Array
值陣列,由整型下標索引
Hash
由字串索引的值雜湊
Num
浮點數
Complex
類似於浮點數,但也允許虛數和複數資料型別。
Pair
我們在討論雜湊時簡要提到了對。對是資料物件和字串的組合。
Str
字串資料物件

使用這些值,你可以像在正常的靜態型別語言中一樣編寫靜態型別程式碼

my Int $x;
$x = 5;         # Good, it's an integer
$x = "five";    # Bad, just the name of an integer

我們也可以使用型別系統來捕獲資料在變數之間移動時的錯誤

my Int $foo = 5;
my Num $bar = 3.14;

$foo = $bar;      # ERROR! $bar is not an Int!

這樣,編譯器就可以告訴你是否試圖以你沒有預想的方式使用變數。

華夏公益教科書