"Reify" và "reification" nghĩa là gì trong ngữ cảnh của lập trình (chức năng?)?


81

Tôi đã đọc thuật ngữ này rất nhiều trong các blog về haskell và lập trình chức năng (đặc biệt là trong blog của sigfpe ) nhưng tôi không có manh mối về ý nghĩa của nó. Tôi thường không biết về nó, nhưng có lẽ tôi sẽ hiểu các văn bản tốt hơn rất nhiều nếu tôi biết. Google đã không giúp tôi. Tôi bị lạc trong những thứ kỹ thuật.

Ngoài ra, ý nghĩa phi kỹ thuật của thế giới ("biến thành cụ thể trừu tượng") không giúp tôi hiểu ý nghĩa thực tế của việc sửa đổi thứ gì đó trong mã.

Tôi hơi chậm với các khái niệm khoa học máy tính, vì vậy các ví dụ thực tế với mã sẽ rất hay. : P

Câu trả lời:


40

Vì vậy, tôi đã đọc về điều này, và nó có ý nghĩa khá lớn: lấy một khái niệm trừu tượng và biến nó thành cụ thể. Hoặc, có một proxy đại diện cho khái niệm trừu tượng. Ví dụ, trong Lisp, khái niệm trừu tượng và ứng dụng thủ tục được sửa đổi khi bạn sử dụng lambdas.

Bản thân việc sửa lại là một khái niệm rộng và không chỉ áp dụng cho các ngôn ngữ lập trình chức năng.

Trong Java chẳng hạn, có những kiểu có sẵn trong thời gian chạy. Đây là những loại có thể tái sử dụng. Có nghĩa là, tồn tại một đại diện cụ thể của khái niệm trừu tượng về kiểu, trong thời gian chạy. Ngược lại, có những loại không thể tái sử dụng. Điều này đặc biệt rõ ràng trong quá trình sử dụng generic trong Java. Trong Java, các số liệu chung có thể bị xóa kiểu và vì vậy thông tin kiểu chung không có sẵn trong thời gian chạy (trừ khi kiểu được tham số hóa sử dụng các ký tự đại diện không bị ràng buộc).

Một ví dụ khác là khi bạn cố gắng mô hình hóa một khái niệm. Ví dụ, giả sử rằng bạn có một Grouplớp học và một Userlớp học. Bây giờ có một số khái niệm trừu tượng mô tả mối quan hệ giữa hai điều này. Ví dụ, khái niệm trừu tượng về một Userlà thành viên của a Group. Để làm cho mối quan hệ này cụ thể, bạn sẽ viết một phương thức được gọi là phương thức isMemberOfcho biết liệu a có phải Userlà thành viên của a hay không Group. Vì vậy, những gì bạn đã làm ở đây là bạn đã reified (làm thực / rõ ràng / bê tông) các khái niệm trừu tượng của thành viên nhóm.

Một ví dụ điển hình khác là cơ sở dữ liệu nơi bạn có các mối quan hệ cha-con giữa các đối tượng. Bạn có thể mô tả mối quan hệ này trong khái niệm trừu tượng về cây. Bây giờ, giả sử bạn có một hàm / phương thức lấy dữ liệu này từ cơ sở dữ liệu và xây dựng một đối tượng thực tế Tree . Có gì bây giờ bạn đã làm được reified khái niệm trừu tượng của cha mẹ và con cái cây giống như mối quan hệ thành một thực tế Tree đối tượng.

Quay trở lại với các ngôn ngữ chức năng nói chung, có lẽ ví dụ điển hình nhất của việc sửa đổi là việc tạo ra chính ngôn ngữ lập trình Lisp. Lisp là một cấu trúc hoàn toàn trừu tượng và lý thuyết (về cơ bản chỉ là một ký hiệu toán học cho các ngôn ngữ máy tính). Nó vẫn như vậy cho đến khi evalchức năng của Lisp được Steve Russel thực sự triển khai trên IBM 704:

Theo những gì được báo cáo bởi Paul Graham trong Hackers & Painters, p. 185, McCarthy nói: "Steve Russell nói, xem này, tại sao tôi không lập trình đánh giá này ..., và tôi nói với anh ta, ho, ho, bạn đang nhầm lẫn lý thuyết với thực hành, đánh giá này nhằm mục đích đọc, không phải cho máy tính. Nhưng anh ấy đã tiếp tục và làm được. Đó là, anh ấy đã biên dịch đánh giá trong bài báo của tôi thành mã máy IBM 704, sửa lỗi và sau đó quảng cáo đây là một trình thông dịch Lisp, chắc chắn là như vậy. Vì vậy, tại thời điểm đó Lisp đã về cơ bản là hình thức mà nó có ngày nay ... "

Vì vậy, Lisp được reified từ một khái niệm trừu tượng, vào một ngôn ngữ lập trình thực tế.  


2
Có vẻ như việc cải tạo tồn tại trong một chuỗi liên tục tùy thuộc vào tình huống. Trong khi lisp trừu tượng đã được sửa đổi thành ngôn ngữ lập trình, bản thân ngôn ngữ lập trình là một dạng khái niệm khá trừu tượng để giao tiếp tính toán, phải được sửa đổi thêm thành mã máy và cuối cùng thành 1s thành 0 và cuối cùng là tín hiệu điện ... vv Như vậy sự cải tạo chỉ là sự đối lập (kép) của sự trừu tượng hóa.
CMCDragonkai

25

Cải cách

Cải cách là một hình thức khởi tạo. Khi bạn sửa đổi một khái niệm, bạn lấy một cái gì đó trừu tượng và làm cho nó trở nên cụ thể, giống như định nghĩa từ điển mà bạn đã cung cấp.

Bạn có thể chọn sửa đổi một loại như một thuật ngữ nằm trong một số cây cú pháp trừu tượng của các loại có thể.

Bạn có thể sửa đổi một mẫu thiết kế bằng cách triển khai mục đích chung cho một số ngôn ngữ. Ví dụ, một cái gì đó như

template<typename T> class Singleton {
    public:
        static T& Instance() {
            static T me;
            return me;
        }

    protected:
       virtual ~Singleton() {};
       Singleton() {};
}

sửa đổi mẫu thiết kế singleton như một mẫu trong C ++.

Bạn có thể sửa đổi ý tưởng của Hoare về quicksort thành một triển khai bằng ngôn ngữ lập trình mà bạn chọn. Theo hướng này, tôi dành rất nhiều thời gian để sửa đổi các khái niệm từ lý thuyết phạm trù thành mã Haskell.

Bạn có thể sửa đổi một ngôn ngữ làm thông dịch viên cho ngôn ngữ đó. Ý tưởng của Larry Wall về Perl , ngôn ngữ này được coi là trình thông dịch perl.

Các gói sửa đổi dữ liệuchân không sửa đổi các thuật ngữ dưới dạng biểu đồ thể hiện cách nó được cấu trúc trong bộ nhớ với tính năng chia sẻ.

Suy ngẫm

Mặt trái của việc sửa đổi là phản ánh , làm một cái gì đó cụ thể và tạo ra một sự trừu tượng, thường là do quên một số chi tiết. Có lẽ bạn muốn làm điều này vì phần trừu tượng đơn giản hơn, hoặc bằng cách nào đó nắm bắt được bản chất của những gì bạn đang nói.

Phản ánh hệ thống kiểu trong Java, C #, v.v. lấy một lớp cụ thể trong ngôn ngữ lập trình và cung cấp cho bạn cấu trúc trừu tượng của một lớp, cho phép bạn truy cập vào danh sách các thành viên mà lớp của bạn cung cấp. Ở đây chúng ta đang sử dụng khái niệm cụ thể về một kiểu và tạo ra một thuật ngữ trừu tượng từ nó để mô tả cấu trúc của nó, đồng thời loại bỏ bất kỳ giá trị cụ thể nào.

Giống như cách bạn có thể sửa đổi một ngôn ngữ lập trình thành một triển khai, đôi khi bạn có thể đi theo hướng ngược lại. Mặc dù đây thường được coi là một ý tưởng tồi, bạn có thể thực hiện và cố gắng phản ánh một đặc tả ngôn ngữ từ các thuộc tính mong muốn của hành vi của nó. TeX được triển khai đầu tiên bởi Knuth, đặc điểm kỹ thuật của sans. Bất kỳ thông số kỹ thuật nào của TeX đã được phản ánh từ quá trình triển khai của Knuth.

(Chính thức hơn nếu bạn xem sự phản chiếu như một công cụ giải trí hay quên đưa bạn từ một miền cụ thể sang một miền trừu tượng, thì lý tưởng là sự cải tạo lại gần với sự phản ánh.)

Các phản ánh gói tôi duy trì cung cấp một phương pháp cụ thể hóa mà phải mất một hạn và mang lại một loại đại diện cho nó, sau đó một phương pháp cho phép bạn tạo ra một thuật ngữ mới phản ánh. Ở đây miền 'cụ thể' là hệ thống kiểu và miền trừu tượng là các thuật ngữ.


21

Từ Haskell Wiki :

Để "sửa đổi" một cái gì đó là lấy một cái gì đó trừu tượng và coi nó như vật chất. Một ví dụ cổ điển là cách mà người xưa lấy các khái niệm trừu tượng (ví dụ: "chiến thắng") và biến chúng thành các vị thần (ví dụ: Nike, nữ thần chiến thắng của Hy Lạp).

Loại được sửa lại là một giá trị đại diện cho một loại. Sử dụng các loại đã sửa đổi thay vì các loại thực có nghĩa là bạn có thể thực hiện bất kỳ thao tác nào với chúng mà bạn có thể làm với các giá trị.


15

Một công dụng mà tôi có thể nghĩ đến (tôi chắc rằng có những cách khác!) Là biến một lớp học thành một từ điển. Hãy Eqhọc cả lớp (tạm thời quên mất /=toán tử):

class Eq a where
    (==) :: a -> a -> Bool

Nếu chúng tôi sửa đổi lớp này, nó sẽ trở thành:

data EqDict a = EqDict (a -> a -> Bool)

mà có thể được xây dựng, kiểm tra, v.v. Cũng cần lưu ý là bạn chỉ có thể có một Eqtrường hợp cho mỗi kiểu, nhưng có nhiều EqDictgiá trị. Nhưng việc xây dựng tự động các thể hiện (ví dụ: nhận được bình đẳng cho danh sách khi bạn có nó cho các phần tử) không hoạt động; bạn sẽ phải tự xây dựng EqDict [a]giá trị.

Quá trình sửa đổi đơn giản như sau (đối với trường hợp này):

reify :: Eq a => EqDict a
reify = EqDict (==)

Một hàm sử dụng Eqlớp có thể biến đổi một cái gì đó như thế này:

-- silly example, doesn't really do anything
findMatches :: Eq a => a -> [a] -> [a]
findMatches x ys = [ y | y <- ys, x == y ]

-- version using EqDict
findMatchesDict :: EqDict a -> a -> [a] -> [a]
findMatchesDict (EqDict f) x ys = [ y | y <- ys, f x y ]

Nếu bạn mở gói EqDict và chỉ cần vượt qua một a -> a -> Bool, bạn sẽ nhận được các ..Bychức năng, like Data.List.nubByvà bạn bè - một thủ thuật tương tự đối với các Ordkhách hàng tiềm năng Data.List.sortBy.


9

Ngay cả trong ngữ cảnh của Haskell, thuật ngữ này được sử dụng rất rộng rãi. Gói sửa đổi của Andy Gill cho phép bạn lấy cấu trúc đệ quy và biến chúng thành đồ thị rõ ràng. Bài đăng của Sigpfe về tính liên tục mô tả việc sửa đổi khái niệm "phần còn lại của tính toán" thành một giá trị mà bạn có thể chuyển qua. Mẫu Haskell có chức năng sửa đổi (được thực thi, cùng với mã TH nói chung, tại thời điểm biên dịch) mà khi được cung cấp tên của giá trị Haskell sẽ trả về thông tin có sẵn trên đó (nơi khai báo, loại, v.v.).

Tất cả những trường hợp này có điểm gì chung? Họ đang nói về việc lấy một thứ gì đó mà chúng ta có thể suy luận và biết, nhưng chúng ta không thể trực tiếp thao tác theo chương trình và biến nó thành một giá trị lớp đầu tiên thực tế mà chúng ta có thể đặt tên và chuyển xung quanh giống như bất kỳ thứ gì khác. Và đó thường là ý định mà mọi người muốn truyền đạt khi họ sử dụng từ này.


2

Tôi biết có khái niệm cải cách trong RDF. Như đã nói bởi Tim Bernes-Lee :

Sự sửa đổi trong ngữ cảnh này có nghĩa là sự diễn đạt một điều gì đó bằng ngôn ngữ bằng cách sử dụng ngôn ngữ để ngôn ngữ đó có thể xử lý được.

Tôi cho rằng nó giống như sự phản chiếu hoặc xem xét nội tâm. Tôi hy vọng bạn nhận được một số câu trả lời tốt ở đâ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.