【Perl6】perl6 中的容器和引用

【Perl6】perl6 中的容器和引用

perl6 中沒有引用,或者說 perl6 中到處都能見到引用

常量

perl6 中聲明一個常量是通過 := 二元運算符來進行操作的,這個操作在 perl6 中又被稱作爲 bind

比如

my $b := 1;

$b = 2;
# Cannot assign to an immutable value
# in block <unit> at container.p6 line 3

perl6 會馬上拋出一個異常,來中斷程序,因爲賦值給了一個 immutable value,至於爲什麼它會是 immutable 的,這個後面再說了

Bind

my $a = 1;
my $b := $a;

$b = 2;

say $a; # 2

這段代碼實際上是 $b 這裏是一個 標量容器,然後將 $a 賦值給了 $b 的容器裏的值,賦值操作符在運算的時候,實際是直接改變了容器內部的值,引用本身就是內存的別名,這裏可以看作是 $b$a 的別名,所以 $a 也跟着一起改變了。

再回過頭來看前面的例子,爲什麼剛剛會報 immutable

my $b := 1;

$b = 2;

容器的角度來看,這裏實際上是把常量 1 賦值給了標量容器 $b 裏的值,這裏賦值的話,實際上是改變的容器內的值,但是 1 本身是個常量是不能被更改的,所以就會拋出異常了。

List

perl 中的線性容器有 Array, List, Seq

Array 是可變的,List 是不可變的,Seq 一般是指 的序列,通過惰性列表出來的數據結構就是 Seq

先來看一個 List 的例子

my $list = (1, 2, 3);

$list[1] = 1;
# Cannot modify an immutable List ((1 2 3))

List 中的每個元素都是 Immutable 的,但是並不影響整體的賦值。

my $list = (1, 2, 3);

$list = ();

但是如果你用 Bind 將它和現有的 List 字面量進行綁定的話,它就不能被賦值給其他的值了。

這是因爲 List 字面量被裝入了 $list 容器,後面更改值的時候,被認定爲正在修改一個 List 字面量,因此會報錯。

但是我們怎麼讓 $list 的元素變成可變的呢?用一個標量容器去封裝它。如何聲明一個標量容器,Scalar 並沒有提供一個 new 方法來爲我們創建 Scalar 的實例,但是我們可以通過匿名的 $ 來創建,像下面這樣。

my $list = (my $, my $, my $);

這裏實際上 list 中的每個元素都是一個標量元素,用賦值來修改元素的值的時候,實際上是修改的元素容器內部的值。

$list[0] = 1;
$list[1] = 2;
$list[2] = 3;

也可以在聲明的時候就初始化它,然後再進行改變

my $list = (my $ = 1, my $ = 2, my $ = 3);

$list[0] = 4;
.say for $list.List;
# 4
# 2
# 3

爲了防止一些意外的情況發生,可以用 Positional 進行修飾

my Positional $list = (my $ = 1, my $ = 2, my $ = 3);

Array

如果每次要聲明一個可變的 list,這樣做確實很麻煩,有一個 sigil 可以從一開始就幫你做好這一切,它就是 @,對,就是數組

my @names = ['Jon', 'Henry', 'Jerry'];

say @names.WHAT; # Array

數組會在創建的時候就把每個元素進行標量容器的裝箱,從而使得它是可變的。但是卻不會影響元素的本身的類型

@names[2] = 'hah';

say @names[0].WHAT # Str

奇怪的 List

來看一個奇怪的例子

my $list = (1, 2, 3);

.say for $list; # (1, 2, 3)
say $list.WHAT; # List

這裏只打印出了一個元素,是 (1, 2, 3),但是我們 WHAT 它的類型,確實是一個 List,這是爲什麼呢?

因爲 $ sigil 就代表一個標量,而標量的意思就是一個值,因此,會出現這樣的情況,但是它確實是個 List,可以通過 List 來讓它迭代起來!

my $list = (1, 2, 3);

.say for $list.List;
# 1
# 2
# 3

如果你認爲這樣是正常的,那麼看看下面的例子

my $list := (1, 2, 3);

.say for $list;
# 1
# 2
# 3

這裏沒有使用 List 還是能正常的迭代,這是爲什麼呢?

:= 用於將元素的值裝入標量的容器內,所以是可以迭代的

容器的默認值

容器的值是可以有默認值的

my $name is default('qqqq') = 'Henry';

$name = Nil;

say $name; # qqq

包括數組容器也可以有默認值的

my @arr is default<-1> = [1, 2];

say @arr[2]; # -1

容器的值的默認值也是可以有默認值的,Perl 在開始執行之前就已經分配了默認值了,比如

my $hello;

say $hello # Any

Any 就是這個 $hello 標量容器的一個默認值

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章