【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
標量容器的一個默認值