Ngôn ngữ lập trình R/Biến và hàm

Từ Thư viện Khoa học VLOS
Bước tới: chuyển hướng, tìm kiếm

Biến (variables) và hàm (functions)

Chúng ta bắt đầu với bài toán cơ bản: Tính diện tích hình chữ nhật S với hai cạnh a = 10 cm và b = 20 cm. Mời bạn thử:

>a = 10
 
>b = 20
 
>S = a*b

Bạn không nên thất vọng vì chưa thấy câu trả lời mong đợi (200 cm^2). Không cần vội vàng, ta cùng phân tích xem "chúng ta vừa làm gì?".

Lênh đầu tiên ">a = 10" ta vừa tạo ra một biến với tên a, đồng thời ghi vào đó giá trị 10 bằng lênh "=". Ta bắt gặp ba khái niệm cơ bản nhất: biến (variables), giá trị (value) và lệnh gán (assigning). Để so sánh, tôi ví dụ như sau: Trong khi tính toán ta cần có bút chì và giấy nháp. Vì giấy nháp khổ rộng và ta là một người ngăn nắp nên ta chia giấy nháp thành các phần nhỏ, chẳng hạn 10 ô và đánh số theo thứ tự từ 1 đến 10. Như vậy mỗi ô có một cái tên, từ 1 đến 10 mà ta có thể ghi vào ô đó các số tùy ý, chẳng hạn 10 vào ô thứ nhất, 20 vào ô thứ hai. Trong so sánh đó, số thứ tự các ô, hay tên các ô tương ứng với tên biến (a) giá trị 10 được ghi vào ô đó tương ứng với lệnh gán "=". Như vậy lệnh "=" là lệnh ghi một giá trị vào một biến, khác với ấn tượng thường gặp là dấu so sánh hai giá trị (ta sẽ biết được viết là "==".) Nếu bạn vẫn thấy hơi khó phân biệt thì bạn có thể yên tâm sau một đôi lần cảm giác đó sẽ mất đi. Một giải pháp khác là với bạn có thể dùng dấu "<-" thay cho "=", chẳng hạn ">a <- 10", và thu được kết quả tương đương. Cá nhân tôi không thích ký hiệu đó vì nó không đẹp, hơn nữa nếu ỷ lại vào đó bạn sẽ vẫn gặp khó khăn với dấu "==" dưới đây.

Lệnh thứ hai, ">b = 20", bạn có thể tự phát biểu thành lời tương tự như trên.

Lệnh cuối cùng, ">S = a*b", ta lấy giá trị ghi trong biến a và giá trị ghi trong biến b, nhân chúng với nhau và ghi giá trị đó vào một biến mới có tên S. Chú ý là ta nhân các giá trị trong biến, chứ không nhân bản thân các biến với nhau. Nếu bạn nhớ rằng biến là tên của ô nháp mà ta chia, thì ta không thể nhân hai mảnh giấy với nhau, mà phải nhân giá trị ghi trên mảnh giấy với nhau. Bạn có thể quan sát và mường tượng thêm về ý nghĩa của dấu "=" ở đây theo phân tích ở trên.

Như vậy qua ba lệnh đơn giản, bạn cần phân biệt được biến (variables) với giá trị (values) và ý nghĩa của lệnh gán (assining).

Ta tiếp tục thử:

>ls()
 
[1] "a"         "b"         "S"

Ta thấy xuất hiện ba ký tự , chính là tên ba biến mà ta vừa tạo ra trong quá trình trên. Lệnh ls() cho câu trả lời là tên của các biến hiện đang có mặt trong không gian làm việc (workspace), hay bạn có thể nói ngược lại, không gian làm việc là tất cả các biến hiện đang có, hay các mảnh giấy nháp mà bạn đang dùng.

Một lần nữa bạn để ý sự xuất hiện của các dấu nháy đơn và nháy kép. Các dấu nháy đơn và nháy kép (được dùng như nhau) chỉ một giá trị của xâu ký tự, là một dãy các chữ cái, tương tự và ngang hàng với giá trị 10, 20 của số nguyên. Ta sẽ phân tích sâu hơn sự giống và khác của xâu ký tự và các trị số dưới đây, ở đây chúng tôi muốn nhấn mạnh phân biệt 'giá trị' và 'tên biến.' Tên biến như ta thấy không mang các dấu nháy đơn và kép như vậy. Bạn có thể nghi ngờ các dấu nháy đó trong lênh ls()? Lời giải thích là lệnh ls() cho xâu ký tự biểu diễn tên các biến, chứ không phải bản thân biến đó.

Nếu bạn đang nóng lòng muốn biết diện tích hình chữ nhật, ta gõ

>S 
 
[1]  200

Lệnh chỉ bảo gồm tên biến sẽ in giá trị của biến đó ra của sổ giao diện. Nếu bạn chưa có cơ hội gõ sai lệnh nào để chương trình báo lỗi thì giờ ta có thể thử

>s 
 
Error: object 's' not found

R báo lỗi không tìm thấy biến s (tạm thời ta gọi "object" là biến). Như vậy R phân biệt chữ thường và chữ hoa, "s" khác với "S", ta chỉ có biến "S" chứ không có biến "s". Bạn có thể thử với "Getwd()" và tự kết luận cho mình.

Bên cạnh đó ta học thêm một điều: mắc lỗi và gõ sai một câu lệnh là rất bình thường, không những đối với chúng tôi và bạn mà tôi tin rằng còn đối với bất cứ một lập trình viên chuyên nghiệp nào. Ta chỉ cần đọc chỉ dẫn lỗi sai đó là gì và sửa lại câu lệnh. Giả sử bạn đã gõ "Getwd()" và bây giờ muốn sửa lại câu lệnh đó, chỉ ở chữ "G", chúng ta có thể dùng phím UP (mũi tên lên), hoặc DOWN (mũi tên xuống) khi lỡ tay lên nhiều quá, khi đó bạn có thể gọi lại (echo) tất cả các câu lệnh đã gõ, và sửa cho hợp lý và enter lại. Để làm ví dụ bạn có thể sửa câu lệnh "Getwd()" vừa gõ sai.

Hình chữ nhật đã cho có hai cạnh khác nhau, giả sử bạn nảy ra ý định so sánh nó với một hình vuông cùng diện tích, ta có bài toán đơn giản như sau: Tìm cạnh của hình vuông sao cho hình vuông đó có diện tích S bằng với diện tích của hình chữ nhật trên. Nhớ lại kiến thức cấp ba một chút, ta chỉ cần một phép khai căn d={\sqrt  {S}}. Mời bạn gõ:

>d = sqrt(S)

Bạn hãy dùng lệnh gọi giá trị của d để xem kết quả. Tuy nhiên chúng tôi muốn giải thích ký hiệu bạn vừa gõ "sqrt(S)". sqrt là tên của một hàm (function). Hàm này nhận giá trị từ biến S và cho giá trị khai căn của nó. Vậy hàm nói chung là một thao tác nào đó thực hiện trên giá trị của biến và cho ra một giá trị. Hàm cũng có thể nhận một giá trị từ hai biến vào, thực ra chúng ta đã gặp hàm đó. Mời bạn kiểm tra lại các lệnh đã gõ và xem thử đó là hàm gì. Nếu bạn thành công thì chúng tôi xin chúc mừng và cho bạn biết một bí mật là nhiều sinh viên năm thứ tư học lập trình vẫn không nhận ra được điều đó, ít nhất có một bằng chứng là tôi. Dấu "*" là một hàm đặc biệt, được gọi là toán tử. Toán tử thực ra chỉ khác hàm ở cách viết mà thôi: trong khi hàm luôn luôn gồm có tên hàm, theo sau bằng dấu ngoặc đơn với các biến nhận vào trong đó, thì toán tử nhận đối số vào từ hai phía của tên toán tử "a * b".

Có rất nhiều toán tử và hàm giống như các hàm quen thuộc trong R, bạn có thể thực hiện bốn biểu thức cộng trừ nhân chia (với thứ tự nhân chia trước cộng trừ sau quen thuộc) với bốn toán tử "+", "-", "*", "/". Để làm ví dụ ta tính biểu thức sau

>f = a + b + a*b
>f

Toán tử có thể lũy thừa được viết theo hai cách "^" hoặc "**", ví dụ ta tính đường chéo của hình chữ nhật theo định lý Pythagore:

>g = sqrt(a**2+b^2)
>g

Cùng với các toán tử là một danh sách các hàm quen thuộc: sin, cos, tan, exp, log... Để làm ví dụ ta tính chơi một biểu thức vô nghĩa

>sin(a) + cos(b)

Nếu bạn quên gõ biến gán "... =" như tôi vừa gõ, giá trị thu được sẽ không ghi vào giấy nháp (biến) mà chỉ nói từ miệng thông dịch viên (xuất ra màn hình.) Một lưu ý nhỏ là hàm lượng giác luôn mặc định đơn vị đo là radial.

Một danh sách tham khảo các hàm cơ bản được tập hợp (tại đây). Tất nhiên bạn không cần phải biết hết số đó, đa số mọi người bình thường hạnh phúc với bốn phép tính cơ bản, đôi khi lũy thừa và khai căn xem ra đã hơi hiếm. Chúng ta tạm thời cũng chỉ dừng đến chừng ấy, có thể thêm phép exp và log. Điều quan trọng là chúng tôi muốn bạn ghi nhớ:

Biến là các công cụ để ghi giá trị, hàm là các thao tác thực hiện trên các giá trị (có thể là giá trị đã ghi trong biến) và cho ra một giá trị (thường được ghi vào một biến mới hoặc xuất ra màn hình.)

Trong tính toán các bảng biểu lớn, quản lý bộ nhớ là một công tác quan trọng, cũng giống như giải một bài toán dài bạn phải tổ chức giấy nháp cẩn thận, phải xóa các phần giấy ghi không còn cần thiết, để giải phóng không gian, và để tránh tự đánh đố mình giữa một đống giấy nháp. Hãy xem

>ls()

Bạn thấy không gian hiện hành đã khá lộn xộn, trước khi tiến hành thực nghiệm với các kiểu dữ liệu, ta xóa:

>rm('S')
 
>ls()

Bạn thấy biến S đã được xóa. Hàm rm() nhận vào tên biến dưới dạng ký tự (*) và xóa biến đó khỏi không gian hiện hành. Hàm này hơi đặc biệt, nó không cho giá trị ra (**). Xóa lần lượt từng biến như vậy rõ ràng mỏi tay, ta có thể xóa một số biến cùng một lúc

>rm(c('a','b'))
 
>ls()

Ta sẽ nói về ý nghĩa của hàm c() dưới đây. Xóa toàn bộ không gian hiện hành bằng lệnh:

>rm(list = ls())
 
>ls()

Lệnh ls() cho tên tất cả các biến, và trở thành đầu vào cho lệnh rm().


<< Mục lục

Liên kết đến đây