CHƯƠNG 1: TỔNG QUAN VỀ LẬP TRÌNH HÀM 1.1 Giới thiệu chung về ngôn ngữ lập trình hàm Lập trình hàm là một mô hình lập trình trong đó việc tính toán là sự đánh giá của các hàm toán học, không sử dụng các trạng thái, dữ liệu biến đổi và các lệnh gán biến. Lập trình hàm nhấn mạnh việc ứng dụng các hàm số, trái với phong cách lập trình mệnh lệnh, nhấn mạnh vào sự thay đổi trạng thái [2]. Các ngôn ngữ lập trình hàm, đặc biệt là các loạn thuần về lập trình hàm có ảnh hưởng lớn trong giới học thuật hơn là dùng để phát triển các phần mềm thương mại. Mục đích của việc thiết kế ngôn ngữ lập trình hàm là mô phỏng các hàm toán học một cách nhiều nhất có thể.
Trong lập trình hàm, biến là không cần thiết, như trong các bài toán học thường gặp. Trong logic toán học và khoa học máy tính, phép tính lambda là một hệ thống hình thức được sử dụng trong việc định nghĩa hàm số, ứng dụng hàm số và đệ quy. Phép tính lambda được phát triển để trở thành công cụ quan trọng trong việc nghiên cứu các vấn đề lý thuyết tính toán và lý thuyết đệ quy, và hình thành nên nền tảng cơ bản của mô hình lập trình hàm. Đôi khi người ta sử dụng các biểu thức lambda để biểu diễn cho các hàm không tên (ví dụ: λ(x) x * x thay thế cho binh_phuong(x) ≡ x*x).
Các tham số của biểu thức lambda gọi là các tham số biến kết ghép. Khi biểu thức lamda được định trị với một tham số đã cho thì biểu thức được áp dụng cho tham số đó (Ví dụ (λ(x) x * x * x) (2) = 8). Hiện nay, ngôn ngữ lập trình hàm đang dần được phổ biến với sự phát triển đáng kể của ngôn ngữ F#. Ngôn ngữ F# có thể tận dụng hầu hết các công cụ phát triển trong Visual Studio.
F# hỗ trợ lập trình hướng đối tượng. Khi lập trình với F#, các đoạn mã được viết ra cũng đơn giản hơn so với các ngôn ngữ như C# hoặc Java tuy nhiên điều khó khăn nhất đối với những lập trình viên chưa biết về lập trình hàm đó chính là cú pháp hoàn toàn mới của nó, gần như sẽ rất khác so với PHP, Java, C. Tại sao ngôn ngữ lập trình hàm lại xứng đáng để bạn bỏ thời gian để học và làm việc? Nếu là lập trình viên với nhiều đam mê thì ngôn ngữ lập trình hàm sẽ khơi gợi sự tò mò theo một cách nào đó. Trong lập trình hàm, lập trình viên sẽ làm việc thường xuyên hơn với các hàm hồi quy và quên đi các hàm như if else, while, do.
Việc lập trình nêu trên có thể khiến lập trình viên cảm thấy khó khăn hơn rất nhiều, tuy nhiên khi đã quen với nó, bạn sẽ thấy kỹ năng lập trình của mình ở một trình độ cao hơn. Ngoài ra, trong các hàm được viết ra, với các dữ liệu đầu vào thì bạn chỉ có duy nhất một đầu ra mà thôi. Các khả năng có thể xảy ra đều được trình biên dịch đánh giá và báo lỗi cho lập trình viên. LUAN VAN CHAT LUONG download : add luanvanchat@agmail.2 Các đặc điểm nổi bật của ngôn ngữ lập trình hàm Hệ thống kiểu có thể biết đến là đặc điểm nổi bật nhất trong ngôn ngữ lập trình hàm.
Trong F#, việc khai báo kiểu của biến là hoàn toàn không cần thiết. Khi định nghĩa một biến và gán giá trị cho nó, trình biên dịch sẽ tự suy luận ra biến đó sẽ sử dụng kiểu gì và gán cho biến. Tương tự như vậy, khi khai báo một hàm, lập trình viên có thể cân nhắc xem có cần khai báo kiểu dữ liệu đầu vào và kiểu dữ liệu trả về hay không vì sau khi định nghĩa các hàm tính toán, F# sẽ tự suy luận ra kiểu của các hàm đó. Việc sử dụng các kiểu dữ liệu đại số và so sánh với mẫu làm cho việc thao tác trên các cấu trúc dữ liệu phức tạp trở nên thuận tiện và rõ ràng hơn.
Sự tồn tại của việc kiểm tra kiểu mạnh mẽ trong thời gian biên dịch khiến cho các chương trình trở nên đáng tin cậy hơn, việc luận kiểu cũng giúp lập trình viên không cần khai báo thủ công các kiểu để biên dịch. Một số ngôn ngữ lập trình hàm định hướng nghiên cứu được biết đến hiện nay như Coq [3], Agda [4]. Các kiểu được sử dụng trong các ngôn ngữ trên được gọi là các kiểu phụ thuộc. Các kiểu phụ thuộc này có thể được mô tả bằng các mệnh đề tự do trong logic mệnh đề.
Các chương trình có kiểu tốt (well-typed) trong những ngôn ngữ nêu trên sẽ trở thành phương tiện cho việc viết các hàm chứng minh toán học hình thức mà từ đó trình biên dịch sẽ sinh ra các mã được chứng nhận. Ngoài ra, một đặc điểm khác có thể kể đến trong lập trình hàm đó là việc sử dụng đệ quy. Vòng lặp trong các ngôn ngữ lập trình hàm thường được thực hiện thông qua đệ quy. Hàm đệ quy sẽ tự gọi chính nó, cho phép thực hiện đi thực hiện lại một tác vụ.
Đa số các ngôn ngữ lập trình hàm đa mục đích đều cho phép đệ quy không giới hạn, tuy nhiên việc đó có thể gây ra sự thiếu căn cứ cho việc suy diễn công thức, đòi hỏi phải có các khái niệm không nhất quán trong logic do hệ thống kiểu của ngôn ngữ quy định. Các chương trình trong lập trình hàm là các định nghĩa hàm và các áp dụng hàm. Sự thực hiện là việc đánh giá các áp dụng hàm trong đó một hàm luôn cho cùng một kết quả trả về khi ta gán cho nó cùng một đối số ví dụ như f(x) + f(x) và 2*f(x) luôn cùng một kết quả. Ngoài ra, ngữ nghĩa của ngôn ngữ lập trình hàm đơn giản hơn ngữ nghĩa của ngôn ngữ lập trình mệnh lệnh.
Trong các ngôn ngữ lập trình hàm, các lời gọi chương trình con được viết thành biểu thức đơn giản. Các ngôn ngữ hàm cũng là các ngôn ngữ bậc cao và mang tính trừu tượng hơn so với các ngôn ngữ mệnh lệnh. Ngoài ra, lập trình hàm thường tránh sử dụng các biến toàn cục, trong khi đó, việc sử dụng biến toàn cục của người lập trình mệnh lệnh là cần thiết và nên dùng. Khi lập trình với ngôn ngữ hàm, người lập trình cần phải định nghĩa các hàm toán học dễ suy luận, dễ hiểu mà không cần quan tâm chúng được cài đặt LUAN VAN CHAT LUONG download : add luanvanchat@agmail.com 14 như thế nào ở trong máy.
Mặt khác, trong ngôn ngữ mệnh lệnh, việc thay đổi trạng thái toàn cục được cho rằng hoàn toàn bất lợi. Nhiều phần khác nhau của chương trình tác động không trực tiếp lên các biến và do vậy làm cho chương trình khó hiểu. Các thủ tục thường được gọi sử dụng ở các phần khác nhau của chương trình gọi nên rất khó xác định các biến bị thay đổi như thế nào sau lời gọi. Như vậy, sự xuất hiện hiệu ứng phụ làm cản trở việc chứng minh tính đúng đắn (correctness proof), cản trở tối ưu hóa (optimization), và cản trở quá trình song song tự động (automatic parallelization) của chương trình[5].
Bên cạnh những tính ưu việt, ta cũng cần xem xét những bất lợi của lập trình hàm: Thứ nhất đó là thiếu các lệnh gán và các biến toàn cục, thứ hai đó là có sự khó khăn trong việc mô tả các cấu trúc dữ liệu và khó để kiểm soát quá trình vào ra của dữ liệu. Một vấn đề khác gây khó khăn cho lập trình viên đó là rất khó để thay đổi một cấu trúc dữ liệu trong mảng. Trong ngôn ngữ mệnh lệnh, sự thay đổi một phần tử mảng rất đơn giản. Tuy nhiên trong ngôn ngữ lập trình hàm, một mảng không thể bị thay đổi.
Người ta cần sao chép mảng, loại bỏ những phần tử sẽ bị thay đổi và thay thế ngay lập tức các giá trị mới cho phần tử này. Cách tiếp cận này kém hiệu quả hơn so với phép gán cho phần tử [5]. Kết luận lại, các ngôn ngữ hàm dựa trên việc tính giá trị của các biểu thức, các biến toàn cục và phép gán kiểu bị loại bỏ, giá trị được tính bởi một hàm phụ thuộc vào các tham đối, tuy nhiên thông tin trạng thái được đưa ra tưởng minh nhờ các tham đối của hàm và kết quả [5].3 Sự phổ biến của ngôn ngữ lập trình hàm Các ngôn ngữ lập trình hàm hiện nay được biết đến khá nhiều và một trong số đó có thể kể đến là F#. Ngôn ngữ F# được cài đặt bởi tiến sĩ Don Syme tại Microsoft Research tại Cambridge.
Hiện tại được tiếp quản bởi Microsoft và vẫn đang được tiếp tục phát triển bởi nhóm chuyên gia ở cả Cambridge và Redmond. Ngôn ngữ F# mang đến cho bạn một ngôn ngữ lập trình hàm an toàn, gọn nhẹ mà hiệu quả. Theo giấy phép chia sẻ nguồn của Microsoft, các đoạn mã nguồn được cung cấp sẵn cho lập trình viên. Microsoft cho phép tải về miễn phí trình biên dịch dưới dạng phiên bản nhị phân như là một gói phần mềm độc lập hoặc là một bộ cài cho Visual Studio.
Với việc phát hành phiên bản F# 2.0 và mới nhất là F# 4.0, nhóm phát triển sẽ chuyển sang mô hình mới mà họ gọi là thả mã (Code drop) trong đó phiên bản mới của trình biên dịch và các thư viện sẽ được phát hành cùng với phiên bản mới của ngôn ngữ. Mã này hiện diện như là một phần của F# PowerPack. Hiện nay, F# phiên bản 4.0 đã được cài đặt mặc định với Visual Studio 2015 vàF# có thể chạy trên phần lớn các nền tảng như HTML5, Android, JavaScript, Windows và MacOS. LUAN VAN CHAT LUONG download : add luanvanchat@agmail.4 Giới thiệu tổng quan về ngôn ngữ lập trình hàm F# Như đã nhắc đến ở các phần trên, việc lập trình với ngôn ngữ F# khá là khác biệt so với các ngôn ngữ lập trình hiện nay như C#, Java.
Chúng ta có thể xem qua một số đoạn mã sau đây để thấy được sự khác biệt của ngôn ngữ này: module AppendList letrec append l1 l2 = match l1 with | [] -> l2 | hd::tl -> hd::append tl l2 let l1 = [1;2;3] let l2 = [9;4;5] printfn"%A" (append l1 l2) System.ReadLine() |> ignore Trên đây là một ví dụ đơn giản về việc ghép hai mảng dữ liệu lại với nhau. Trong lập trình hàm, việc khai báo kiểu cho một hàm hầu như là không cần thiết. Trình biên dịch sẽ tự suy luận kiểu cho hàm append trên và sẽ có dạng như sau: 'a list -> 'a list -> 'a listtrong đó chúng ta có thể tùy ý gán các dữ liệu cho các mảng l1 và mảng l2.