3# bao giờ là phép chia dấu phẩy động, nên 3.333

Một phần của tài liệu Lịch sử của perl (Trang 41 - 48)

Bên cạnh đó, Perl cung cấp toán tử lũy thừa kiểu FORTRAN, mà nhiều người đã từng mong mỏi cho Pascal và C. Toán tử này được biểu diễn bằng hai dấu sao, như 2**3, chính là hai luỹ thừa ba, hay tám. (Nếu kết quả không thể

khớp trong số dấu phẩy động độ chính xác gấp đôi, như một số âm mà lại luỹ

thừa theo số không nguyên, hay một số lớn lấy luỹ thừa theo số lớn, thì bạn sẽ

nhận được lỗi định mệnh.)

Perl cũng hỗ trợ cho toán tử lấy đồng dư modulus, như trong C. Giá trị của biểu thức 10 % 3 là số dư khi lấy mười chia cho ba, chính là một. Cả hai giá trị đều trước hết được đưa về giá trị nguyên, cho nên 10.5 % 3.2 được tính là 10 % 3.

Các toán tử so sánh logic là hệt như các toán tử có trong C (< <= == >= > !=), và việc so sánh hai giá trị về mặt số sẽ cho lại một giá trị đúng hay sai. Chẳng hạn, 3 . 2 cho lại đúng vì ba lớn hơn hai, trong khi 5 != 5 cho lại sai vì không đúng là năm lại không bằng năm. Các định nghĩa về đúng và sai được nói tới về sau, nhưng với hiện tại, các bạn hãy nghĩ về giá trị cho lại giống như

chúng ở trong C - một là đúng, còn không là saị (Các toán tử này sẽđwojc thăm lại trong Bảng 2-2.)

Toán tử xâu

Các giá trị xâu có thể được ghép với toán tử chấm (.). (Quả thế, đó là dấu chấm đơn.) Điều này không làm thay đổi xâu, cũng như 2+3 không làm thay đổi 2 hay 3. Xâu kết quả (dài hơn) vậy là có sẵn cho tính toán thêm hay được cất giữ

trong một biến.

“hello” . “world” # ht như “helloworld”

‘hello wordl’ . “\n” # ht như “hello world\n”

“fred” . “ “ . “barney” # ht như “fred barney”

Chú ý rằng việc ghép nối phải được gọi tường minh tới toán tử ., không giống awk mà bạn đơn thuần phải đánh dấu hai giá trị gần lẫn nhaụ

Một tập các toán tử cho xâu khác là toán tử so sánh xâụ Các toán tử này đều tựa FORTRAN, như lt thay cho bé hơn, vân vân. Các toán tử so sánh các giá trị

ASCII của các kí tự của xâu theo cách thông thường. Tập đầy đủ các toán tử so sánh (cho cả số và xâu) được nêu trong Bảng 2-2.

Bảng 2-2. Các toán tử so sánh số và xâu Phép so sánh Số Xâu Bằng == eq Không bằng != ne Bé hơn < lt Lớn hơn > gt Bé hơn hay bằng <= le Lớn hơn hay bằng >= ge

Bạn có thể tự hỏi tại sao lại có các toán tử phân tách cho số và xâu vậy, nếu số và xâu được tự động chuyển đổi lẫn cho nhaụ ta hãy xét hai giá trị 7 và 30. Nếu được so sánh như số thì 7 hiển nhiên bé hơn 30, nhưng nếu được so sánh theo xâu, thì xâu “30” sẽ đứng trước xâu “7” (vì giá trị ASCII của 3 thì bé hơn giá trị ASCII của 7), và do đó là bé hơn. Cho nên, không giống awk, Perl đòi hỏi bạn xác định đúng kiểu so sánh, liệu đó là số hay xâụ

Chú ý rằng các phép so sánh số và xâu về đại thể ngược với những điều xẩy ra cho chỉ lệnh test của UNIX, mà thường dùng kí hiệu -eq để so sánh số còn =

để so sánh xâụ

Vẫn còn một toán tử xâu khác là toán tử lặp lại xâu, bao gồm một kí tự chứ

thường đơn giản x. Toán tử này lấy toán hạng trái của nó (một xâu), và thực hiện nhiều việc ghép bản sao của xâu đó theo số lần do toán hạng bên phải chỉ ra (một số). Chẳng hạn:

“fred” x 3 # là “fredfredfred”

“barney” x (4+1) # là “barney” x 5 hay# “barneybarneybarneybarneybarney” # “barneybarneybarneybarneybarney”

(3+2) x 4 # là 5 x 4, hay thc s “5” x 4, là “5555”

Thí dụ cuối cùng đáng để xem xét chậm rãị Các dấu ngoặc trên (3+2) buộc cho phàn này của biểu thức cần phải được tính trước, cho năm. (Các dấu ngoặc

ởđây làm việc giống như trong C, hay trong toán học chuẩn.) Nhưng toán tử lặp lại xâu cần một xâu cho toán hạng bên trái, cho nên số 5 được chuyển thành xâu “5” (dùng các qui tắc sẽ được mô tả chi tiết về sau), thành xâu một kí tự. Xâu mới này rồi được sao lên bốn lần, cho xâu bốn kí tự 5555. Chú ý rằng nếu ta

đảo ngược trật tự các toán hạng, thì tssa sẽ làm năm bản sao của xâu 4, cho

44444. Điều này chỉ ra rằng việc lặp lại xâu là không giao hoán.

Số đếm bản sao (toán hạng bên phải) trước hết sẽ bị chặt cụt đi để cho giá trị

nguyên (4.8 trở thành 4) trước khi được sử dụng. Số đếm bản sao bé hơn một sẽ

Thứ tự ưu tiên và luật kết hợp của toán tử

Thứ tự ưu tiên của toán tử xác định ra cách giải quyết trường hợp không rõ ràng khi nào dùng toán tử nào trên ba toán hạng. Chẳng hạn, trong biểu thức 2+3*4, ta sẽ thực hiện phép cộng trước hay phép nhân trước? Nếu ta làm phép cộng trước thì ta sẽ được 5*4, hay 20. Nhưng nếu ta làm phép nhân trước (như

ta vẫn được dậy trong giờ toán) thì ta được 2+12, hay 14. May mắn là Perl chọn

định nghĩa toán học thông thường, thực hiện nhân trước. Bởi ffiều này, ta nói nhân có số ưu tiên cao hơn cộng.

Bạn có thể phá rào trật tự theo số ưu tiên bằng việc dùng dấu ngoặc. Bất kì cái gì trong dấu ngoặc đều được tính hết trước khi toán tử bên ngoài dấu ngoặc

được áp dụng (hệt như bạn đã học trong giờ toán). Cho nên nếu tôi thực sự

muốn cộng trước khi nhân, thì tôi có thể viết (2+3)*4, cho 20. Cũng vậy, nếu tôi muốn biểu thị rằng phép nhân được thực hiện trước phép cộng, tôi có thể trang

điểm thêm nhưng chẳng để làm gì, một cặp dấu ngoặc trong 2+(3*4).

Trong khi số ưu tiên là trực giác cho phép cộng và nhân thì ta bắt đầu lao vào vấn đề thường hay phải đương đầu với, chẳng hạn, phân biệt thế nào đối với phép ghép xâu và nâng lên luỹ thừạ Các đúng đắn để giải quyết điều này là tra cứu sơ đồ số thứ tự ưu tiên toán tử của Perl, được nêu trong Bảng 2-3. (Chú ý rằng một số các toán tử còn chưa được mô tả, và trong thực tế, thậm chí không thể xuất hiện ở bất kì đâu trong cuốn sách này, nhưng chớ có làm điều đó làm bạn hoảng sợ về việc đọc chúng.) Với những toán tử cũng có trong C, thì những toán tử đó có cùng sóo thứ tự ưu tiên như chúng có trong C (mà tôi có thể chẳng bao giờ nhớđược).

Bảng 2-3: Luật kết hợp và số ưu tiên của các toán tử (thấp nhất đến cao nhất)

Luật kết hợp

Toán tử

không Toán tử “danh sách” trái , (phẩy)

phải += và các toán tử khác (toán tử

“gán”)

phải ? : (toán tử if/then/else ba ngôi) không .. (toán tử phạm vi, cấu tử danh

sách)

trái || (hoặc logic) trái && (và logic)

trái | ^ (hoặc bit, hoặc bit loại trừ) trái & (và bit)

không == != <=> eq ne cmp (toán tử

“bằng”)

không < <= > >= lt le gt ge (toán tử

“không bằng”)

không Toán tử một ngôi có tên

không -r và (các toán tử kiểm tra tệp)* khác

trái << >> (dịch chuyển bit) trái + - . (cộng, trừ, ghép xâu) trái * / % x (nhân, chia, lấy dư, lặp

xâu) trái =~ !~ (sánh, không sánh) phải ** (luỹ thừa) phải ! ~ - (phủ định logic, phủ định bit, phủ định số) không ++ -- (tự tăng, tự giảm)

Trong sơ đồ này, bất kì toán tử đã cho nào đều có số ưu tiên lớn hơn các toán tử được liệt kê trên nó, và có số ưu tiên thấp hơn các toán tử được liệt kê dưới nó. (Điều này dựng ngược lại điều có lẽ bạn đang trông đợi, nhưng nó hệt như trong sách con lừa, và chúng tôi cũng đã dựng ngược nó xuống ở đó nữạ) Các toán tử tại cùng mức ưu tiên được giải quyết theo luật kết hợp.

Giống như với số ưu tiên, luật kết hợp giải quyết trật tự của các phép toán khi hai toán tử có cùng mức ưu tiên cùng tác động trên ba toán hạng:

2 ** 3 ** 4 # 2 ** (3 ** 4), hay 2 ** 81, hay xp x 2.41e24

72 / 12 / 3 # (72 / 12) / 3, hay 6 / 3, hay 2

30 / 6 * 3 # (30/6)*3, hay 15

Trong trường hợp thứ nhất, toán tử ** có luật kết hợp phải, cho nên các dấu ngoặc được áp dụng từ bên phảị So sánh với nó, các toán tử * và / có luật kết hợp trái, cho tập các dấu ngoặc bên tráị

Chuyển đổi giữa số và xâu

Nếu một giá trị xâu được dùng như một toán hạng cho một toán tử số (chẳng hạn, +), thì Perl sẽ tự động chuyển xâu thành giá trị số tương đương, dường như

nó đã được đưa vào như một giá trị dấu phẩy động* . Những chất liệu phi số

* Perl 5.0 tổ hợp các toán tử kiểm tra tệp và toán tử một ngôi có tên vào cùng mức sốưu tiên

* Các giá trị hệ tám và hệ mười sáu không được hỗ trợ trong chuyển đổi tựđộng nàỵ Bạn hãy dùng hex() và oct() để diễn giải các giá trị hệ mười sáu và tám.

đằng đuôi và khoảng trắng đằng đầu đều bị bỏ qua một cách yên lặng và lễ phép, cho nên “ 123.45fred” (với dấu cách đứng trước) chuyển thành 123.45 với lời cảnh báo* . Tại một cực điểm của điều này, một cái gì đó không phải là số tẹo nào chuyển thành không mà không có báo trước (như xâu fred được dùng như

số).

Giống vậy, nếu một giá trị số được cho khi đang cần tới một giá trị xâu (cho phép ghép xâu chẳng hạn), thì giá trị số sẽđược mở rộng thành bất kì xâu nào sẽ được in ra cho số đó. Chẳng hạn, nếu bạn muốn ghép nối X và theo sau là kết quả của 4 nhân với 5 thì bạn có thể làm đơn giản là:

“X”.(4*5) # ht như “X”.20, hay “X20”

(Nhớ rằng các dấu ngoặc này buộc 4*5 phải được tính trước khi xem xét toán tử ghép nối xâụ)

Nói cách khác, bạn không thực sự phải lo lắng gì về liệu bạn có một số hay một xâu (phần lớn thời gian). Perl thực hiện mọi chuyển đổi cho bạn.

Biến vô hướng

Một biến là một tên gọi cho một chỗ chứa giữ được một hay nhiều giá trị. Tên của biến là không đổi trong toàn bộ chương trình, nhưng giá trị hay các giá trị được chứa trong biến đó về cơ bản thì lại thay đổi đi thay đổi lại trong suốt sự

thực hiện chương trình.

Một biến vô hướng thì giữ một giá trị vô hướng riêng (biểu thị cho một số, hay một xâu, hay cả hai). Các tên biến vô hướng bắt đầu với dấu đô la và tiếp theo sau là một chữ, rồi thì có thể là nhiều chữ, số hay dấu gạch thấp. Chữ hoa và chữ thường là phân biệt: biến $A là khác biến $a. Và tất cả các chữ, số và gạch thấp đều có nghĩa, cho nên:

$a_very_long_variable_that_ends_in_1

là khác với

$a_very_long_variable_that_ends_in_2

Bạn nói chung nên chọn tên biến mang một nghĩa nào đó có liên quan tới giá trị của biến đó. Chẳng hạn, $xyz123 có lẽ không mang tính mô tả nhiều lắm nhưng $line_length thì lại có nghĩạ

Các toán tử trên biến vô hướng

Phép toán thông dụng nhất trên biến vô hướng là phép gán, chính là cách đặt một giá trị cho một biến. Toán tử gán của Perl là dấu bằng (giống như C hay FORTRAN), để tên biến bên vế trái và cho giá trị của biểu thức bên vế phải, kiểu như:

$a = 17; # cho $a giá tr 17

$b = $a + 3; # cho $b giá tr hin ti ca $a cng vi 3 (20)

* Trừ phi bạn bật tuỳ chọn -w trên dòng lệnh

$b = $b * 2; # cho $b giá tr ca $b được nhân vi 2 (40)

Chú ý rằng dòng cuối dùng biến $b hai lần: khi lấy được giá trị của nó (ở vế

phải dấu =), và khi xác định xem phải đặt biểu thức tính được vào đâu (ở vế trái của dấu =). Điều này là hợp lệ, an toàn và trong thực tế, khá thông dụng. Trong thực tế, nó thông dụng đến mức chúng ta sẽ thấy trong vài phút đây là ta có thể

viết điều này bằng việc dùng cách viết tắt qui ước.

Bạn có thể đã chú ý rằng các biến vô hướng bao giờ cũng được tham khảo bằng dấu $ đứng trước. Trong lớp vỏ, bạn dùng $ để lấy một giá trị, nhưng để $

đứng một mình để gán một giá trị mớị Trong awk hay C, bạn để cho $ riêng hoàn toàn. Nếu bạn cứ phải viết đi viết lại các biến rất nhiều thì bạn sẽ thấy mình ngẫu nhiên bị gõ saị Thường hay bị vậỵ (Giải pháp của tôi là chấm dứt việc viết chương trình vỏ, awk và C, nhưng điều đó lại có thể không có tác dụng cho bạn.)

Việc gán vô hướng có thể được dùng như một giá trị cũng như một phép toán, như trong C. Nói cách khác, $a = 3 có một giá trị, cũng như $a+3 có một giá trị. Giá trị chính là số được gán, cho nên giá trị của $a = 3 là 3. Mặc dầu

điều này dường như có vẻ kì lạ lúc thoáng nhìn, việc dùng một phép gán như

một giá trị lại có ích nếu bạn muốn gán một giá trị trung gian trong một biểu thức cho một biến, hay nếu bạn muốn đơn giản sao cùng một giá trị cho một hay nhiều biến. Chẳng hạn:

$b = 4 + ($a = 3); # gán 3 cho $a, ri cng kết qu đó vi 4 đặt vào $b, được 7 $b, được 7

$d = ($c = 5); # sao 5 vào $c, và ri sao vào $d

$d = $c = 5; # cũng điu y nhưng không có du ngoc

Thí dụ cuối làm việc tốt vì phép gán có tính kết hợp bên phảị

Toán tử gán hai ngôi

Các biểu thức như $a = $a + 5 (trong đó cùng một biến lại xuất hiện ở cả

hai vế của phép gán) thường xuất hiện đến mức Perl (giống như C) có cách viết tắt cho phép toán làm thay đổi biến - toán tử gán hai ngôi. Gần như tất cả các toán tử hai ngôi tính một giá trị đều có dạng phép gán hai ngôi tương ứng với dấu bằng có bổ sung thêm phần tử. Chẳng hạn, hai dòng sau đây là tương

đương:

$a = $a + 5 ; # không có toán t gán hai ngôi

$a += 5 ; # có toán t gán hai ngôi

Và tương tự như thế:

$b = $b * 3; $b *= 3;

Trong từng trường hợp, toán tử này làm cho giá trị hiện tại của biến được thay đổi theo một cách nào đó, thay vì đơn giản ghi đè lên giá trị này bằng kết quả của một biểu thức mới nào đó.

Toán tử gán thông dụng khác là toán tử ghép nối xâu:

$str = $str . “ ”; # thêm ducách vào $str

$str .= “ ”; # cũng điu y vi toán t gán

Gần như tất cả các toán tử hai ngôi đều hợp lệ theo cách nàỵ Chẳng hạn, toán tử nâng lên luỹ thừa của sẽ được viết là **=. Cho nên, $a **= 3 có nghĩa là “nâng một số trong $a lên luỹ thừa ba, rồi đặt kết quả trở lại $a”.

Giống như toán tử gán đơn, các toán tử này cũng có một giá trị : giá trị mới của biến. Chẳng hạn:

$a = 3;

$b = ($a += 4); # $a và $b c hai bây giđều là 7

Nhưng không may là trật tự tính toán của các toán hạng của toán tử hai ngôi lại không được xác định, cho nên một số biểu thức không thể nào được xác định hoàn toàn:

$a = 3;

$b = ($a += 2) * ($a -= 2); # Chương trình ti: $b có th là 15 hay 3

Nếu toán hạng bên phải của phép nhân được tính đầu tiên thì kết quả sẽ là 3 lần 1, hay 3. Tuy nhiên, nếu toán hạng bên trái được tính trước toán hạng bên phải, thì nó là 5 lần 3, hay 15. Bạn chớ có làm điều này, chừng nào bạn còn chưa vào Cuộc tranh luận Perl rối rắm.

Tự tăng và tự giảm

Dừng cũng đã đủ dễ dàng để thêm một vào $a bằng việc nói $a += 1. Perl còn đi xa hơn và thậm chí lại còn làm ngắn hơn cho điều này nữạ Toán tử ++

Một phần của tài liệu Lịch sử của perl (Trang 41 - 48)

Tải bản đầy đủ (PDF)

(143 trang)