Nền tảng toán học cho các giá trị lớp thứ nhất / thứ hai / thứ ba trong các ngôn ngữ lập trình là gì?


19

Thêm

Chỉ cần tìm thấy hai câu hỏi liên quan

/math//q/1759680/1281

/programming//a/2582804/156458


Trong các ngôn ngữ lập trình, từ Ngôn ngữ lập trình của Michael Scott

Nói chung, một giá trị trong ngôn ngữ lập trình được cho là có trạng thái lớp đầu tiên nếu nó có thể được truyền dưới dạng tham số, được trả về từ chương trình con hoặc được gán vào một biến. Các loại đơn giản như số nguyên và ký tự là giá trị hạng nhất trong hầu hết các ngôn ngữ lập trình. Ngược lại, giá trị của lớp thứ hai có thể được truyền qua như một tham số, nhưng không được trả về từ một chương trình con hoặc được gán vào một biến, và giá trị này của lớp thứ ba có thể được chuyển qua như một tham số.

Nhãn là giá trị hạng ba trong hầu hết các ngôn ngữ lập trình, nhưng giá trị hạng hai trong Algol. Chương trình con hiển thị nhiều biến thể nhất. Chúng là các giá trị hạng nhất trong tất cả các ngôn ngữ lập trình chức năng và hầu hết các ngôn ngữ script. Chúng cũng là các giá trị hạng nhất trong C # và, với một số hạn chế, trong một số ngôn ngữ bắt buộc khác, bao gồm Fortran, Modula-2 và -3, Ada 95, C và C ++. 11 Chúng là các giá trị hạng hai trong hầu hết các ngôn ngữ mệnh lệnh khác và các giá trị hạng ba trong Ada 83.

  1. Nền tảng toán học cho các giá trị lớp thứ nhất / thứ hai / thứ ba trong các ngôn ngữ lập trình là gì?

    Thuật ngữ nhắc nhở tôi về logic thứ tự / thứ hai, nhưng chúng có liên quan không?

  2. Dường như với tôi rằng sự khác biệt giữa chúng là trường hợp cụ thể mà một giá trị có thể được sử dụng

    • thông qua như một tham số,
    • trở về từ một chương trình con, hoặc
    • gán vào một biến.

    Tại sao các trường hợp cụ thể quan trọng, trong khi các trường hợp khác không được đề cập?

Cảm ơn.


23
Phân loại giá trị thành hạng nhất / hạng hai cũng không có kết quả như phân loại ngôn ngữ thành mô hình. Tất cả bạn sẽ kết thúc với những khái quát mơ hồ làm vấy bẩn bức tranh. Đây không phải là cách tiếp cận đúng để hiểu ngôn ngữ lập trình. Điều quan trọng là hiểu được cú pháp, số liệu thống kê và động lực của ngôn ngữ, nhưng điều đó quá lớn để đưa ra nhận xét
vườn

3
Ngoài ra: PL / Tôi sẽ là một ví dụ về nhãn là hạng nhất. Trong PL / I, bạn có thể khai báo các biến được nhập vào nhãn, gán cho chúng các vị trí mã và goto chúng. Bạn cũng có thể truyền chúng dưới dạng tham số và thậm chí tạo các mảng của chúng.
Theraot

@Theraot: Có lẽ tôi đang hẹn hò với chính mình, nhưng tôi có phải là người duy nhất từng phải đối phó với các GOTO được chỉ định và tính toán trong FORTRAN không? Và không, tôi đã không viết @ $%! mã, tôi đã bị mắc kẹt lại kỹ thuật đó.
jamesqf

@jamesqf Tôi biết việc gán nhãn cho FORTRAN và COBOL, không, tôi chưa sử dụng nó. Tôi không chắc về cách phân loại nhãn ở đó. Tuy nhiên, đối với những gì tôi đọc (tôi có hướng dẫn sử dụng) PL / Tôi vượt xa điều đó, và tôi tin rằng các nhãn là hạng nhất ở đó.
Theraot

Câu trả lời:


45

Không có gì cả, và nó khá độc đoán.

Sự khác biệt hữu ích duy nhất là giữa lớp đầu tiên và tất cả những người khác. Mỗi trường hợp trong khung "khác" có một bộ quy tắc riêng trong từng trường hợp và gộp tất cả chúng lại với nhau chỉ là không hữu ích. "Hạng nhất" có nghĩa là "Bạn không cần phải tra cứu các quy tắc", về cơ bản và "khác" là "Bạn phải học các quy tắc".

Ví dụ, trong các hàm riêng lẻ của C ++ là các giá trị hạng nhất, miễn là chúng không trạng thái. Bộ quá tải không phải là nhưng lambdas. Trong các hàm C # thường là các giá trị hạng nhất, nhưng có một số trường hợp khó xử phát sinh khi xử lý suy luận kiểu khiến chúng không xuất hiện trong mọi trường hợp.


10
+1, mặc dù trong bối cảnh của một cuốn sách như Lập trình ngôn ngữ lập trình so sánh một số lượng lớn các cấu trúc trong một số lượng lớn các ngôn ngữ, và phân tích các điểm tương đồng và khác biệt và hàm ý sâu sắc, tôi nghĩ loại tốc ký này có thể hữu ích. (Chỉ cần không đi xung quanh để mong người khác hiểu "đồ cũ" và "đồ thứ ba" là những thứ cụ thể.)
ruakh

(Uh, trong đó bởi "second-hand" và "second-hand" Tôi tất nhiên có nghĩa là "hạng hai" và "hạng ba". :-P)
ruakh

3
Nếu bạn muốn giao dịch với các chức năng đã qua sử dụng, bạn nên thực hiện nó bằng ngôn ngữ nơi các chức năng là công dân hạng nhất. ^^
5gon12eder

@ 5gon12eder: "chức năng đã qua sử dụng" sẽ là những chức năng bạn gọi từ thư viện của bên thứ 3 phải không?
jamesqf

11

Tôi đồng ý với DeadMG, sự khác biệt quan trọng là giữa hạng nhất và "mọi thứ khác". Tuy nhiên, có một cách quen thuộc hơn để phân loại sự khác biệt.

Giá trị hạng nhất là dữ liệu, các giá trị khác là mã. (đại khái: tôi chắc chắn có những trường hợp ngoại lệ. Nhưng đây là một xấp xỉ thực sự tốt cho các ngôn ngữ trong thế giới thực.)

Trong một số ngôn ngữ, bạn có thể coi mã là dữ liệu. Các ngôn ngữ chức năng nổi tiếng vì điều này: một số trong số chúng cho phép bạn thay đổi mã của chương trình khi nó đang chạy (nền tảng của lập trình di truyền ).

Các ngôn ngữ như C và C ++ cho phép bạn lấy địa chỉ của các hàm: trong khi bạn không thể sửa đổi chúng, bạn có thể chuyển các hàm dưới dạng tham số cho các hàm khác. C ++ cũng có đường cú pháp của functor . Ý tưởng là tạo ra một vật thể mà trên bề mặt, dường như hoạt động giống như một hàm và có thể được truyền xung quanh như thể nó là dữ liệu. Mặt khác, giá trị hạng thấp hơn có thể được coi là giá trị hạng nhất.

Về mặt toán học, tôi nghĩ cách tốt nhất là nghĩ về AST của chương trình . Thông thường, mỗi mã thông báo có một loại cụ thể có thể hoặc không thể tương thích với các loại khác. Hãy suy nghĩ l-value, r-value và toàn bộ các loại giá trị khác trong C ++ . Sau đó thêm vào các từ khóa, ký hiệu là các hàm, v.v ... Một số trong số này có thể là giá trị lớp thứ nhất, thứ hai hoặc thứ ba tùy thuộc vào ngôn ngữ.

Tôi không chắc chắn biết "lớp" giá trị là tất cả quan trọng, ngoại trừ có thể trong một môi trường học thuật. Trong thế giới thực, điều quan trọng cần biết là làm thế nào bạn có thể truyền mã xung quanh, coi nó như dữ liệu: functor, lambdas / bao đóng, con trỏ hàm, v.v.


2
Một ví dụ về giá trị không phải mã không thuộc hạng nhất: Lua có một ..."biến" đặc biệt được sử dụng để biểu thị các tham số hàm vararg. Bạn có thể sử dụng nó trong nhiều biểu thức như thể nó là một danh sách giá trị (chẳng hạn như print(...)hoặc local args = {...}) nhưng có một số điều bạn không thể làm với nó, chẳng hạn như tham chiếu nó trong một bao đóng ( function(...) return function() return ... end end).
Đại tá Ba mươi Hai

8

Ngữ nghĩa học hàm số cung cấp một cơ sở toán học để mô tả cách các giá trị và biến hoạt động trong ngôn ngữ lập trình. Nó đã được giải thích rất tốt trong Bằng cấp Khoa học Máy tính của tôi đến nỗi tôi đã đạt điểm cao trong kỳ thi Ngữ nghĩa học, sau đó quên hầu hết và chưa bao giờ có nhu cầu sử dụng nó trong cuộc đời 20 năm làm lập trình viên.

Bạn có thể chọn sử dụng một nền tảng toán học được xác định rõ ràng, hoặc bạn có thể sử dụng thuật ngữ không chính thức như trạng thái lớp đầu tiên. Tôi đã học được nhiều hơn nếu khóa học dựa trên Ngôn ngữ lập trình của Scott, tuy nhiên toán học chính thức là cần thiết cho ai đó sẽ học PHd về thiết kế ngôn ngữ lập trình.

Nếu bạn đọc đặc tả cho hầu hết các ngôn ngữ lập trình, bạn sẽ nhận thấy sự thiếu sót về ngữ nghĩa học bất đồng chính kiến, tuy nhiên hầu hết các ngôn ngữ được thiết kế tốt đều có một người trong nhóm là một chuyên gia về thiết kế ngôn ngữ lập trình, do đó hiểu rất rõ về ngữ nghĩa học.

Vì vậy, Michearl Scott sử dụng thuật ngữ không chính thức có mối quan hệ với toán học chính thức, đồng thời trình bày đề tài theo cách mà hầu hết các lập trình viên có thể hưởng lợi. Thuật ngữ của anh ta không được người khác sử dụng, vì vậy nó không hữu ích cho việc giao tiếp, nhưng nó mang lại cho bạn một nền tảng tốt về các câu hỏi bạn nên hỏi khi lần đầu tiên nhìn thấy một ngôn ngữ lập trình mới.

Lưu ý rằng Michael L. Scott là nhà nghiên cứu hàng đầu về Computer Sci, vì vậy sẽ hiểu và rất vui khi sử dụng các phép toán chính thức, nhưng giống như các nhà nghiên cứu giỏi nhất, anh ta có kỹ năng giải thích ứng dụng nghiên cứu cho phần còn lại của chúng tôi.


Cảm ơn. Những cuốn sách đã được sử dụng trong lớp học của bạn? Những cuốn sách nào bạn đề nghị bây giờ? Tôi là người tự học
Tim

@Tim, tôi đã làm lớp học của tôi hơn 20 năm trước! Tôi hy vọng rằng cuốn sách của Michearl Scott là một trong những cuốn sách hay nhất và sẽ bao gồm nhiều hơn những gì bạn cần trừ khi bạn sẽ thực hiện nghiên cứu cấp độ PHd.
Ian

3

Không, từ "đầu tiên" trong "hạng nhất" và "thứ nhất" có nghĩa là những thứ khác nhau.

Nhưng vâng, các khái niệm "hạng nhất" và "thứ nhất" có liên quan. Cả hai đều phân loại những khái niệm mà một ngôn ngữ có thể mô tả ngôn ngữ cũng có thể trừu tượng hóa.

Một khái niệm là hạng nhất nếu các cơ chế trừu tượng thông thường của một ngôn ngữ có thể trừu tượng hóa khái niệm đó.

Ví dụ, ngôn ngữ lập trình Java có thể mô tả các số nguyên và tất cả các cơ chế thông thường để trừu tượng hóa các số nguyên (chấp nhận chúng làm tham số phương thức, trả về chúng dưới dạng kết quả hàm, lưu trữ chúng trong cấu trúc dữ liệu, ...) hoạt động cho các số nguyên.

Một khái niệm là thứ nhất nếu nó không thể được sử dụng để trừu tượng hóa chính nó.

Ví dụ, một lần nữa trong Java, chúng ta có thể sử dụng các phương thức để trừu tượng hóa những thứ nhất định. Nhưng chúng ta không thể sử dụng các phương thức để trừu tượng hóa các phương thức, bởi vì một tên phương thức không thể được truyền làm tham số phương thức. Điều này khác với JavaScript, nơi bạn có thể sử dụng ký hiệu ngoặc để truy cập vào một thuộc tính của một đối tượng bằng tên của nó dưới dạng một chuỗi và bạn có thể trừu tượng hóa các chuỗi.

Một khái niệm là bậc hai nếu nó có thể được sử dụng để trừu tượng hóa việc sử dụng bậc một của chính nó, nhưng không vượt quá mức sử dụng bậc hai.

Ví dụ, trong Java, bạn có thể sử dụng Generics để trừu tượng hóa các loại (như trong class Foo<T> { public List<T> content; }). Tuy nhiên, bạn không thể sử dụng thuốc generic để trừu tượng trên Generics (như trong class Bar<T> { public T<Int> content; }). Điều này khác ở Scala.

Một khái niệm là bậc ba nếu nó có thể được sử dụng để trừu tượng hóa việc sử dụng bậc một và bậc hai của chính nó, nhưng không vượt quá mức sử dụng bậc hai.

Và như vậy.

Cuối cùng, một khái niệm có thứ tự cao hơn nếu nó có thể được sử dụng để trừu tượng hóa việc sử dụng tùy ý của chính nó.

Tóm tắt: Nếu một tính năng trừu tượng là hạng nhất, thì nó cũng là thứ tự cao hơn. Và nếu một tính năng trừu tượng là thứ nhất, thì nó không thể là hạng nhất.


1
Bạn có thể làm List<List>trong Java, mặc dù. Có lẽ bạn có thể làm rõ những gì bạn có ý nghĩa với phần đó?
Polygnome

1
Điểm tốt. Ý tôi là : class Foo<A> { A<Int> ... }. Đó là, tôi có nghĩa là sử dụng một tham số loại chung như là một lớp chung. Sau đó, Foo<List>sẽ khởi tạo A<Int>đến List<Int>. Trong Java, điều đó là không thể. Tôi sẽ cố gắng chỉnh sửa điều này để trả lời sau.
Toxaris

Thật vậy, điều đó là không thể.
Polygnome

Bây giờ tôi thay thế List<List>ví dụ sai lệch . Cảm ơn đã chỉ ra vấn đề, @Polygnome.
Toxaris

@Toxaris Tôi nghĩ rằng đây chỉ là thuật ngữ bình dị mà bạn tự tạo ra. Một "khái niệm" không phải là thứ nhất hay thứ hai, một bộ lượng hóa logic là.
Miles Rout

2

Nền tảng toán học cho các giá trị lớp thứ nhất / thứ hai / thứ ba trong các ngôn ngữ lập trình là gì?

Không ai mà tôi biết.

Thuật ngữ nhắc nhở tôi về logic thứ tự / thứ hai, nhưng chúng có liên quan không?

Không hẳn vậy.

"Lớp" của một yếu tố ngôn ngữ lập trình chỉ là một cách suy nghĩ ngắn gọn về câu hỏi người dùng ngôn ngữ của tôi muốn thao tác lập trình gì? Ví dụ: C # cung cấp cho bạn một tập hợp hoạt động phong phú để thao tác các giá trị , một tập hợp các cách ít phong phú hơn để thao tác các loại và không có thao tác nào thao túng nhãn .

Tuy nhiên, trực giác của bạn rằng có một kết nối ở đây không hoàn toàn bị đặt sai chỗ. Có một sự tương tự được thực hiện từ logic bậc một đến lập trình thủ tục và từ logic bậc cao đến lập trình hàm. Logic thứ tự đầu tiên là về thao tác logic của các giá trị; lập trình thủ tục là về thao tác lập trình các giá trị. Logic bậc cao là về thao tác logic của các câu lệnh logic , lập trình hàm là về thao tác lập trình các hàm .

Tại sao các trường hợp cụ thể quan trọng, trong khi các trường hợp khác không được đề cập?

Bạn sẽ phải hỏi tác giả cho câu trả lời dứt khoát.

Tôi sẽ không quá bận tâm về khái niệm "đẳng cấp" này. Đây không phải là một điều chính thức xác định. Đó là một tốc ký mà các nhà thiết kế ngôn ngữ sử dụng để nói về những thứ có thể được điều khiển theo chương trình.


2

Giá trị hạng nhất của Viking, trong bối cảnh này, là thuật ngữ tiêu chuẩn trong lý thuyết ngôn ngữ lập trình. Giá trị hạng nhất là thứ có thể được thao tác như giá trị bình thường trong ngôn ngữ, thứ có thể được tính khi chạy. Tất nhiên, đó là một định nghĩa tautological cho đến khi bạn xác định một ngữ nghĩa cho ngôn ngữ, và sau đó một giá trị là bất cứ điều gì ngữ nghĩa định nghĩa là một giá trị. Quan điểm của khái niệm là xác định những gì có thể được thao tác trực tiếp, trái ngược với chỉ được truy cập gián tiếp.

Ví dụ: trong hầu hết mọi ngôn ngữ lập trình, các số nguyên máy có kích thước giới hạn (ví dụ: số nguyên 8 bit hoặc số nguyên 32 bit hoặc số nguyên 64 bit, v.v.) là các giá trị hạng nhất. Bạn có thể lưu trữ chúng trong các biến, chuyển chúng và trả chúng về các hàm, v.v. Trong hầu hết các ngôn ngữ nhưng không phải là ngôn ngữ cấp thấp như assembly và C, chuỗi là giá trị hạng nhất - nhưng trong C, chúng không chỉ là bạn nhận được con trỏ đến chuỗi. Trong C, chuỗi và mảng không phải là giá trị hạng nhất: ví dụ: bạn không thể truyền một mảng cho hàm, bạn không thể gán một mảng cho một biến mảng, v.v. Trong C, các hàm không phải là giá trị hạng nhất một trong hai: bạn không thể lưu trữ một hàm trong một biến, chỉ một con trỏ tới một hàm. Ngược lại, chuỗi và hàm là các giá trị hạng nhất trong hầu hết các ngôn ngữ lập trình cấp cao: bạn có thể lưu trữ chúng trong một chuỗi, v.v.

Một ví dụ về một khái niệm không phải là hạng nhất trong nhiều ngôn ngữ lập trình được thiết kế để biên dịch là các kiểu. Trong một ngôn ngữ như C hoặc Java, các kiểu sống trong thời gian biên dịch, bạn không thể thao tác chúng bằng các cấu trúc ngôn ngữ. (Java cũng có một hệ thống kiểu động dựa trên các lớp; các lớp là các giá trị hạng nhất thông qua sự phản chiếu.) Ngược lại, một ngôn ngữ như Python có một typehàm trả về một giá trị đại diện cho kiểu đối số của nó.

Sự phủ định của giá trị hạng nhất của người dùng trong thuật ngữ tiêu chuẩn là không phải là một giá trị hạng nhất. Thuật ngữ giá trị hạng hai của LÊNH không được sử dụng phổ biến, và giá trị của lớp thứ ba còn ít hơn. Đừng mong đợi để nhìn thấy chúng bên ngoài cuốn sách này. Hoàn toàn không có cơ sở để xác định thứ hai, vì điều này có thể được chuyển qua như một tham số, và thứ ba, vì không thể truyền thông số như một tham số, không có quy mô nào có thể được đánh số một cách có ý nghĩa. Rất ít ngôn ngữ tạo ra sự khác biệt giữa các giá trị có thể được truyền dưới dạng tham số cho các hàm và giá trị có thể được gán cho các biến, vì vậy không hữu ích khi xác định tên cho khái niệm này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.