First-class citizen
Trong thiết kế ngôn ngữ lập trình nhất định, một đối tượng hạng nhất (first-class object)[a] là một thực thể hỗ trợ tất cả các thao tác thường có sẵn cho các thực thể khác. Các thao tác này thường bao gồm việc được truyền như một đối số, được trả về từ một hàm, và được gán cho một biến.[1]
Lịch sử
Khái niệm về các đối tượng hạng nhất và hạng hai được Christopher Strachey giới thiệu vào thập niên 1960.[2][3] Ông không thực sự định nghĩa thuật ngữ này một cách chặt chẽ, mà so sánh đối chiếu giữa số thực và thủ tục trong ALGOL:
Đối tượng hạng nhất và hạng hai. Trong ALGOL, một số thực có thể xuất hiện trong một biểu thức hoặc được gán cho một biến, và một trong hai có thể xuất hiện như một tham số thực sự trong một lời gọi thủ tục. Mặt khác, một thủ tục chỉ có thể xuất hiện trong một lời gọi thủ tục khác với tư cách là toán tử (trường hợp phổ biến nhất) hoặc là một trong các tham số thực sự. Không có biểu thức nào khác liên quan đến các thủ tục hoặc có kết quả là các thủ tục. Do đó, theo một nghĩa nào đó, các thủ tục trong ALGOL là những công dân hạng hai—chúng luôn phải đích thân xuất hiện và không bao giờ có thể được đại diện bởi một biến hoặc biểu thức (ngoại trừ trường hợp của một tham số hình thức)... [4]
Robin Popplestone đã đưa ra định nghĩa sau: Tất cả các mục (item) đều có những quyền cơ bản nhất định.
- Tất cả các mục đều có thể là tham số thực sự của hàm
- Tất cả các mục đều có thể được trả về làm kết quả của hàm
- Tất cả các mục đều có thể là chủ thể của các câu lệnh gán
- Tất cả các mục đều có thể được kiểm tra tính bằng nhau.[5]
Trong thập niên 1990, Raphael Finkel[6] đã đề xuất các định nghĩa về giá trị hạng hai và hạng ba, nhưng những định nghĩa này không được áp dụng rộng rãi.[7][cần nguồn tốt hơn]
Ví dụ
Các kiểu dữ liệu vô hướng đơn giản nhất, chẳng hạn như số nguyên và số thực dấu phẩy động, gần như luôn là hạng nhất.
Trong nhiều ngôn ngữ cũ hơn, mảng và chuỗi không phải là hạng nhất: chúng không thể được gán như các đối tượng hoặc được truyền dưới dạng tham số cho một chương trình con. Ví dụ, cả Fortran IV và C đều không hỗ trợ gán mảng, và khi chúng được truyền làm tham số, chỉ vị trí phần tử đầu tiên của chúng thực sự được truyền—kích thước của chúng bị mất đi. C có vẻ như hỗ trợ việc gán các con trỏ mảng, nhưng thực tế đây chỉ đơn giản là các con trỏ trỏ đến phần tử đầu tiên của mảng, và một lần nữa không mang theo kích thước của mảng.[cần dẫn nguồn]
Trong hầu hết các ngôn ngữ, kiểu dữ liệu không phải là đối tượng hạng nhất, mặc dù trong một số ngôn ngữ lập trình hướng đối tượng, lớp là các đối tượng hạng nhất và là thể hiện của các siêu lớp. Các ngôn ngữ thuộc họ lập trình hàm thường cũng có các kiểu hạng nhất, ví dụ như dưới dạng các kiểu dữ liệu đại số tổng quát, hoặc các tiện nghi siêu ngôn ngữ khác cho phép các chương trình triển khai các phần mở rộng cho chính ngôn ngữ triển khai của chúng.
Rất ít ngôn ngữ hỗ trợ sự tiếp nối (continuation) và nhãn GOTO như những đối tượng, chứ chưa nói đến việc là đối tượng hạng nhất.
| Khái niệm | Mô tả | Các ngôn ngữ |
|---|---|---|
| hàm hạng nhất | bao đóng (closure) và hàm ẩn danh | Smalltalk, Dart, Scheme, ML, Haskell, F#, Kotlin, Scala, Swift, Perl, PHP, Python, Raku, JavaScript, Delphi, Rust, Common Lisp |
| điều khiển hạng nhất | sự tiếp nối | Scheme, ML, F# |
| kiểu hạng nhất | kiểu phụ thuộc | Rocq, Idris, Agda |
| kiểu dữ liệu hạng nhất | Generic Haskell, C++11 | |
| đa hình hạng nhất | đa hình không vị từ (impredicative polymorphism) | |
| thông điệp hạng nhất | các thông điệp động (lời gọi phương thức) | Smalltalk,[8] Objective-C,[8] Common Lisp |
| lớp hạng nhất | siêu lớp và siêu đối tượng | Smalltalk, Objective-C, Ruby, Python, Delphi, Common Lisp |
| bằng chứng hạng nhất | đối tượng bằng chứng[9] | Rocq, Agda |
Hàm
Nhiều ngôn ngữ lập trình hỗ trợ việc truyền và trả về các giá trị hàm, vốn có thể được áp dụng cho các đối số. Liệu điều này đã đủ để gọi các giá trị hàm là hạng nhất hay chưa vẫn còn là vấn đề tranh cãi.
Một số tác giả yêu cầu phải có khả năng tạo ra các hàm mới trong thời gian chạy (runtime) thì mới gọi chúng là 'hạng nhất'.[cần dẫn nguồn] Theo định nghĩa này, các hàm trong C không phải là các đối tượng hạng nhất; thay vào đó, đôi khi chúng được gọi là đối tượng hạng hai, bởi vì chúng vẫn có thể được thao tác theo hầu hết các phương thức nêu trên (thông qua các con trỏ hàm).
Trong Smalltalk, các hàm (phương thức) là những đối tượng hạng nhất, giống hệt như các lớp của Smalltalk. Vì các toán tử của Smalltalk (+, -, v.v.) cũng là các phương thức, nên chúng cũng là những đối tượng hạng nhất.
Phản chiếu (Reflection)
Phần này không có nguồn tham khảo nào. |
Một số ngôn ngữ, chẳng hạn như Java và PHP, có một hệ thống con phản chiếu (reflection) rõ ràng cho phép truy cập vào các cấu trúc triển khai bên trong mặc dù chúng không thể được truy cập hoặc thao tác theo cùng một cách như các đối tượng thông thường.
Trong các ngôn ngữ khác, chẳng hạn như những ngôn ngữ thuộc họ Lisp, phản chiếu là một tính năng trung tâm của ngôn ngữ, thay vì là một hệ thống con đặc biệt. Thông thường, điều này mang hình thức của một tập hợp các tính năng sau:
- macro cú pháp hoặc fexpr - cho phép người dùng viết mã xử lý mã như dữ liệu và đánh giá nó theo quyết định riêng, cho phép, ví dụ, các chương trình viết các chương trình (hoặc tự viết lại chính mình) bên trong trình biên dịch, trình thông dịch hoặc thậm chí là trình phân tích cú pháp (các macro trình đọc);
- một trình đánh giá siêu vòng (meta-circular evaluator) - cung cấp định nghĩa về trình đánh giá của ngôn ngữ như một sự trùng ngữ (tautologisation) được biên dịch của chính nó, tạo điều kiện thuận lợi cho việc sửa đổi ngôn ngữ một cách dễ dàng mà không yêu cầu một siêu ngôn ngữ nào khác với chính nó;
- một giao thức siêu đối tượng (metaobject protocol) - một dạng đặc biệt của trình đánh giá siêu vòng cho lập trình hướng đối tượng, trong đó hệ thống đối tượng tự triển khai đệ quy thông qua một hệ thống các siêu lớp và siêu đối tượng, bản thân chúng cũng là các lớp và đối tượng.
Những điều này cho phép các dạng truy cập hạng nhất khác nhau vào việc triển khai ngôn ngữ, và nhìn chung, có thể thao tác theo cùng một cách, và hoàn toàn không thể phân biệt được với các đối tượng ngôn ngữ thông thường. Do đó, việc sử dụng chúng thường đi kèm với một số quy định và lời khuyên (mang tính văn hóa), vì việc người dùng sửa đổi hệ thống lập trình cốt lõi mà chưa được kiểm tra có thể dễ dàng làm suy yếu các tối ưu hóa hiệu suất do những người triển khai ngôn ngữ tạo ra.
Xem thêm
Ghi chú
- ^ Còn được gọi là kiểu hạng nhất (first-class type), thực thể hạng nhất (first-class entity), hoặc giá trị hạng nhất (first-class value).
Tham khảo
- ^ Scott, Michael (2006). Programming Language Pragmatics. San Francisco, CA: Morgan Kaufmann Publishers. tr. 140. ISBN 9780126339512.
- ^ Rod Burstall, "Christopher Strachey—Understanding Programming Languages", Higher-Order and Symbolic Computation 13:52 (2000)
- ^ Harold Abelson và Gerald Jay Sussman, Structure and Interpretation of Computer Programs, ấn bản lần 2, phần 1.3.4 chú thích 64 Lưu trữ ngày 9 tháng 3 năm 2015 tại Wayback Machine
- ^ Christopher Strachey, "Fundamental Concepts in Programming Languages" trong Higher-Order and Symbolic Computation 13:11 (2000); mặc dù được xuất bản năm 2000, đây là những ghi chú từ các bài giảng mà Strachey đã trình bày vào tháng 8 năm 1967
- ^ R. J. Popplestone: The Design Philosophy of POP-2. trong: D. Michie: Machine Intelligence 3, Edinburgh at the University Press, 1968
- ^ Finkel, R. Advanced Programming language Design, tr. 73
- ^ Norman Ramsey. "About first-,second- and third-class value". stackoverflow.com. Truy cập ngày 14 tháng 9 năm 2013.
- ^ a b Paritosh Shroff, Scott F. Smith. Type Inference for First-Class Messages with Match-Functions
- ^ Bove, Ana; Dybjer, Peter (2009). "Dependent Types at Work" (PDF). Language Engineering and Rigorous Software Development. Lecture Notes in Computer Science. Quyển 5520. tr. 57–99. doi:10.1007/978-3-642-03153-3_2. ISBN 978-3-642-03152-6. Lưu trữ (PDF) bản gốc ngày 2 tháng 4 năm 2014. Truy cập ngày 8 tháng 6 năm 2015. (cũng được lưu trữ)