13.2. Các Biến và các Hàm số

Bây giờ khi chúng ta đã biết rằng mỗi câu lệnh Scheme nằm trong ngoặc đơn, và rằng tên hàm số/toán tử phải được liệt kê trước, chúng ta cần biết cách tạo và sử dụng các biến, và làm thế nào để tạo và sử dụng các hàm số. Chúng ta sẽ bắt đầu với các biến.

Khai báo các Biến

Mặc dù có một vài cách khác nhau để khai báo các biến, phương pháp được ưa thích là dùng cách đặt câu (construct) let*. Nếu bạn đã quen thuộc với các ngôn ngữ lập trình khác, cách đặt câu này tương đương với việc định nghĩa một danh sách các biến cục bộ và phạm vi (scope) mà chúng hoạt động. Ví dụ, để khai báo hai biến, a và b, bắt đầu bằng 1 và 2, bạn sẽ viết:

         (let*  (
                   (a 1)
                   (b 2)
                )
                (+ a b)
         )
      

hoặc, dưới dạng một dòng:

        (let* ( (a 1) (b 2) ) (+ a b) )
      
[Note] Ghi chú

Bạn sẽ phải đặt tất cả những nội dung trên vào một dòng nếu bạn đang sử dụng cửa sổ console. Tuy nhiên, nói chung là bạn thích cách làm tương tự viết thụt vào để giúp cho các tập lệnh của bạn dễ đọc. Chúng ta sẽ nói thêm một chút về phần này khi bàn đến phần Khoảng trắng (White Space).

Câu lệnh trên khai báo hai biến, a và b, khởi tạo chúng, và sau đó in ra tổng của hai biến đó.

Biến cục bộ là gì?

Bạn sẽ nhận thấy rằng chúng ta đã biết phép tính tổng (+ a b) trong ngoặc đơn của biểu thức let* , chứ không phải sau nó.

Điều này là bởi vì câu lệnh let* định nghĩa một vùng trong tập lệnh của bạn mà trong đó các biến đã khai báo sử dụng được; nếu bạn gõ câu lệnh (+ a b) sau câu lệnh (let* ...), bạn sẽ bị sai, bởi vì các biến được khai báo chỉ đúng trong ngữ cảnh của câu lệnh let*; chúng là cái mà các nhà lập trình gọi là biến cục bộ.

Cú pháp tổng quát của let*

Dạng tổng quát của một câu lệnh let* là:

        (let* ( các biến ) các biểu thức )
      

trong đó các biến được định nghĩa trong ngoặc đơn, tức là (a 2), và các biểu thức là bất kỳ biểu thức đúng nào của Scheme. Cần nhớ rằng các biến được định nghĩa ở đây chỉ đúng trong câu lệnh let* -- chúng là các biến cục bộ.

Khoảng trắng

Trước đây chúng ta đã nói đến một việc là có thể bạn muốn sử dụng cách viết thụt vào để tổ chức và làm rõ các tập lệnh của mình. Đây là một "chính sách" hay, và không có vấn đề gì trong Scheme -- khoảng trắng bị trình diễn giải Scheme bỏ qua, và do vậy có thể tự do áp dụng nhằm giúp làm rõ và tổ chức mã trong một tập lệnh. Tuy nhiên nếu bạn làm việc trong cửa sổ console của Script-Fu, bạn sẽ phải nhập toàn bộ biểu thức trên một dòng; có nghĩa là, mọi thứ nằm giữa dấu mở và đóng ngoặc đơn của một biểu thức phải nằm trên một dòng trong cửa sổ console của Script-Fu.

Gán một giá trị mới cho một biến

Một khi bạn đã khởi tạo một biến, bạn có thể muốn thay đổi giá trị của nó sau đó trong tập lệnh. Sử dụng câu lệnh set! để thay đổi giá trị của biến:

        (let* ( (theNum 10) ) (set! theNum (+ theNum \ theNum)) )
      

Tãy đoán xem câu lệnh trên sẽ làm gì, và sau đó hãy nhập nó vào cửa sổ console của Script-Fu.

[Note] Ghi chú

Ký hiệu "\" cho biết rằng không có ngắt dòng. Cứ bỏ qua nó (đừng gõ nó vào cửa sổ console của Script-Fu và đừng nhấn phím ENTER), cứ tiếp tục với dòng thứ hai.

Các Hàm số

Bây giờ khi bạn đã hiểu các biến, chúng ta hãy làm việc với một vài hàm số. Bạn khai báo một hàm số với cú pháp sau:

        (define (tên danh_sách_tham_số) các_biểu_thức)
      

trong đó tên là tên được gán cho hàm số đó, danh_sách_tham_số là danh sách tham số các nhau bởi khoảng trắng, và các_biểu_thức là một chuỗi các biểu thức mà hàm số thực hiện khi nó được gọi. Ví dụ:

        (define (AddXY inX inY) (+ inX inY) )
      

AddXY là tên hàm số và inXinY là các biến. Hàm số này lấy hai tham số và cộng chúng với nhau.

Nếu bạn đã lập trình trong các ngôn ngữ kiểu câu lệnh (imperative language) khác (như C/C++, Java, Pascal,...), có thể bạn sẽ nhận thấy một số thứ không có trong định nghĩa hàm này khi so sánh nó với các ngôn ngữ lập trình khác.

  • Thứ nhất, lưu ý là các tham số không có "kiểu" (type) nào cả (tức là chúng ta không khai báo chúng là chuỗi hay số nguyên,...). Scheme là một ngôn ngữ không có kiểu (type-less). Điều này có ích và cho phép viết tập lệnh nhanh hơn.

  • Thứ hai, lưu ý rằng chúng ta không cần phải lo lắng làm thế nào để "trả về" kết quả hàm số của mình -- câu lệnh cuối cùng là giá trị "trả về" khi gọi hàm số này. Hãy gõ hàm số này vào console, và thử một thứ kiểu như:

                (AddXY (AddXY 5 6) 4)