2009-02-05 55 views
76

Tôi đã đọc một bài viết trên TheServerSide trên ployglot programming on the Java platform. Một số ý kiến ​​trong bài viết đề cập đến lập trình meta là khả năng tạo mã (có thể đang bay).Chính xác là gì?

Lập trình siêu lập trình khả năng tạo mã khi đang di chuyển hoặc có khả năng đưa các phương thức và thuộc tính vào đối tượng hiện tại trong thời gian chạy (như một số ngôn ngữ động như Python, Ruby và Groovy).

+5

Bạn có thể quan tâm đến câu trả lời này http://stackoverflow.com/questions/2565572/metaprogramming-self-explanatory-code-tutorials-articles-books/2566561#2566561 – ewernli

+0

@ewernli: Câu trả lời đó thực sự tốt hơn bất kỳ câu trả lời nào các câu trả lời ở đây! –

Trả lời

55

Lập trình siêu lập trình đề cập đến nhiều cách khác nhau mà chương trình có kiến ​​thức về bản thân hoặc có thể tự điều khiển.

Trong các ngôn ngữ như C#, phản ánh là một dạng lập trình meta từ khi chương trình có thể kiểm tra thông tin về chính nó. Ví dụ trả về một danh sách tất cả các thuộc tính của một đối tượng.

Trong các ngôn ngữ như ActionScript, bạn có thể đánh giá các hàm trong thời gian chạy để tạo chương trình mới như eval ("x" + i) .DoSomething() sẽ ảnh hưởng đến đối tượng x1 khi i là 1 và x2 khi tôi là 2.

Cuối cùng, một hình thức phổ biến khác của lập trình meta là khi chương trình có thể thay đổi chính nó trong thời trang không tầm thường. LISP nổi tiếng vì điều này và là điều mà Paul Graham đã giành được từ một thập kỷ trước. Tôi sẽ phải tra cứu một số bài tiểu luận cụ thể của anh ấy. Nhưng ý tưởng là chương trình sẽ thay đổi một phần khác của chương trình dựa trên trạng thái của nó. Điều này cho phép một mức độ linh hoạt để đưa ra quyết định trong thời gian chạy là rất khó khăn trong hầu hết các ngôn ngữ phổ biến hiện nay. Nó cũng đáng chú ý rằng trở lại trong những ngày tốt đẹp của lập trình trong lắp ráp thẳng, các chương trình thay đổi bản thân trong thời gian chạy là cần thiết và rất phổ biến.

Từ Paul Graham của tiểu luận "What Made Lisp Different":

Nhiều ngôn ngữ có một cái gì đó gọi là vĩ mô. Nhưng các macro Lisp là duy nhất. Và tin hay không, những gì họ làm là liên quan đến dấu ngoặc đơn. Các nhà thiết kế của Lisp đã không đặt tất cả các dấu ngoặc đơn bằng ngôn ngữ chỉ để được khác nhau. Đối với lập trình viên Blub, Mã Lisp có vẻ lạ. Nhưng những dấu ngoặc đơn có lý do. Đó là bằng chứng bên ngoài về sự khác biệt cơ bản giữa các số giữa Lisp và các ngôn ngữ khác.

Mã Lisp được tạo từ dữ liệu Lisp đối tượng. Và không phải trong ý nghĩa tầm thường rằng các tệp nguồn chứa ký tự và chuỗi là một trong các loại dữ liệu được hỗ trợ bởi ngôn ngữ . Mã Lisp, sau khi được đọc bởi trình phân tích cú pháp , được tạo thành từ cấu trúc dữ liệu mà bạn có thể duyệt qua.

Nếu bạn hiểu cách trình biên dịch hoạt động, điều thực sự xảy ra không quá nhiều mà Lisp có cú pháp lạ như vậy Lisp không có cú pháp. Bạn viết chương trình trong phân tích cú pháp cây được tạo ra trong trình biên dịch khi các ngôn ngữ khác được phân tích cú pháp. Nhưng những phân tích này có thể truy cập hoàn toàn vào các chương trình của bạn. Bạn có thể viết các chương trình thao tác chúng. Trong Lisp, các chương trình này được gọi là macro. Họ là chương trình viết chương trình.

Chương trình viết chương trình? Khi bạn có bao giờ muốn làm điều đó không? Không phải rất thường xuyên, nếu bạn nghĩ trong Cobol. Tất cả thời gian, nếu bạn nghĩ trong Lisp. Nó sẽ thuận tiện ở đây nếu tôi có thể đưa ra ví dụ về macro mạnh mẽ, và nói ở đó! làm thế nào về điều đó? Nhưng nếu Tôi đã làm, nó sẽ trông giống như sai ngữ pháp đối với một người không biết Lisp; không có chỗ ở đây để giải thích mọi thứ bạn cần biết để hiểu ý nghĩa của nó. Trong Ansi Common Lisp Tôi cố gắng để di chuyển những thứ cùng nhanh như tôi có thể, và ngay cả như vậy tôi đã không nhận được để macro cho đến khi trang 160.

Nhưng tôi nghĩ rằng tôi có thể cung cấp cho một loại lập luận rằng có thể thuyết phục. Mã nguồn của trình chỉnh sửa Viaweb là có thể là khoảng 20-25% macro. Macro khó viết hơn các hàm Lisp thông thường và được coi là kiểu xấu khi sử dụng chúng khi chúng không phải là cần thiết. Vì vậy, mọi macro trong mã đó đều ở đó vì nó phải như vậy. Điều gì điều đó có nghĩa là ít nhất 20-25% của mã trong chương trình này đang làm những điều mà bạn không thể dễ dàng thực hiện bằng bất kỳ ngôn ngữ nào khác . Tuy nhiên, người hoài nghi lập trình viên Blub có thể là về các yêu cầu của tôi cho các quyền hạn bí ẩn của Lisp, điều này nên làm cho anh ta tò mò. Chúng tôi đã không viết mã này cho số giải trí của riêng chúng tôi. Chúng tôi đã khởi động một chút, lập trình khó khăn nhất có thể trong số để đặt hàng rào kỹ thuật giữa chúng tôi và đối thủ cạnh tranh của chúng tôi.

Một người đáng ngờ có thể bắt đầu tự hỏi nếu có một số tương quan tại đây. Một đoạn mã lớn của chúng tôi là làm những việc rất khó làm bằng các ngôn ngữ khác. Kết quả phần mềm đã làm những điều mà đối thủ cạnh tranh của chúng tôi ' phần mềm không thể làm được. Có thể có một số loại kết nối. Tôi khuyến khích bạn theo dõi chuỗi đó. Có thể được nhiều hơn để người đàn ông già ủ rũ dọc theo trên nạng của mình hơn là đáp ứng mắt.

+4

Đừng quên về lập trình meta mẫu trong C++.Khả năng thực hiện các biểu thức và đưa ra các quyết định tại thời gian biên dịch, và có kết quả được biên dịch tĩnh vào tệp thực thi cuối cùng. –

+1

Tôi đã bị sốc bởi 'để đặt rào cản kỹ thuật giữa chúng tôi và đối thủ cạnh tranh của chúng tôi' và điều này là tamade chính xác. –

+1

Các chương trình tự thao tác là một tập con của tất cả các metaprogram. Metaprogramming nói chung chỉ có nghĩa là các chương trình điều khiển chương trình. –

4

Lập trình meta là viết chương trình máy tính viết hoặc điều khiển các chương trình khác (hoặc bản thân) làm dữ liệu hoặc thực hiện một phần công việc vào thời gian thực hiện khi biên dịch. Trong nhiều trường hợp, điều này cho phép các lập trình viên thực hiện nhiều việc hơn trong cùng một khoảng thời gian khi họ viết tất cả mã theo cách thủ công hoặc cho phép các chương trình linh hoạt hơn để xử lý hiệu quả các tình huống mới mà không cần biên dịch lại. (Source.)

Về cơ bản, đó là mã viết ra nhiều mã hơn, được chạy để thực hiện một số mục tiêu. Điều này thường được thực hiện hoặc trong cùng một ngôn ngữ (bằng cách sử dụng javascript để tạo ra một chuỗi javascript, sau đó eval nó) hoặc để phát ra một ngôn ngữ khác (sử dụng .NET để tạo một tập tin batch windows).

3

wikipedia có bài viết hay về chủ đề này. Người ta không phải thực hiện các sửa đổi thời gian chạy cho một thứ gì đó để hội đủ điều kiện như là lập trình meta. Ví dụ, nhiều người sử dụng các mẫu C++ để thực hiện lập trình meta tại thời gian biên dịch.

5

Lập trình meta là viết chương trình cung cấp chương trình khác. Đây là ngôn ngữ như Lisp thực sự giỏi. Nó dễ dàng hơn nhiều trong một ngôn ngữ hỗ trợ các macro thực (không phải các macro C++, mà là các macro có thể thao tác mã mà chúng xuất ra) như Ruby, Lisp, Scheme, v.v. trong một ngôn ngữ như Java.

Một triển khai là tạo một "ngôn ngữ cụ thể theo tên miền" là một cách để nâng cao một ngôn ngữ lập trình để thực hiện một tác vụ cụ thể. Nó có thể cực kỳ mạnh mẽ nếu được thực hiện đúng. Ruby on Rails là một ví dụ điển hình về loại lập trình này.

Nếu bạn quan tâm đến việc khám phá phương pháp này, hãy xem Structure and Interpretation of Computer Programs là một trong những cuốn sách nổi bật bao gồm chủ đề.

23

Vâng, lập trình meta chỉ là lập trình, nhưng về cơ bản là "viết mã viết mã".

Khả năng bạn đề cập, khi một chương trình có thể quan sát và sửa đổi cấu trúc và hành vi của chính nó được gọi là sự phản chiếu và đó là một loại siêu lập trình.

động gõ ngôn ngữ, có các tính năng phản ánh thời gian chạy mạnh mẽ, có thể do tính chất giải thích trong các ngôn ngữ ...

tĩnh gõ ngôn ngữ cũng có các kỹ thuật lập trình meta mạnh mẽ, ví dụ như C++ template metaprogramming ...

7

Đây chỉ là ý kiến ​​cá nhân của tôi, mà có lẽ là định nghĩa tự do nhất về lập trình meta.

Tôi nghĩ rằng nó bao gồm:

  1. sinh mã Compile hoặc hệ Runtime mã (hoặc cả hai)
  2. Aspect-Oriented tư duy hoặc Aspect Oriented Programming
  3. DRY Nghĩ

Tôi nghĩ bạn có thể đến đó bằng cách sử dụng bất kỳ cách nào trong số này và kết hợp:

  1. Reflection
  2. DSL (Domain Ngôn ngữ cụ thể)
  3. Attributes (NET) hoặc chú thích (Java)
  4. Generics (.NET/Java)
  5. Templates (C++)
  6. method_missing (Ruby)
  7. đóng cửa/chức năng hạng nhất/đại biểu
  8. AOP - Aspect Oriented Programming
19

Câu hỏi hay. Tôi rất tiếc khi thấy rằng không có câu trả lời nào thực sự trả lời câu hỏi của bạn một cách chính xác. Có lẽ tôi có thể giúp ...

Định nghĩa về lập trình meta thực sự khá đơn giản: nó có nghĩa là các chương trình điều khiển chương trình.

Câu trả lời được chấp nhận của bạn cho biết các chương trình tự thao túng. Đó thực sự là metaprogram nhưng chúng là một tập con của tất cả các metaprogram.

All:

  • parsers
  • ngôn ngữ cụ thể
  • miền (DSL)
  • miền Embedded ngôn ngữ cụ thể (EDSLs)
  • Trình biên dịch
  • phiên dịch
  • rewriters Term
  • provers lý

là metaprograms. Vì vậy, GCC compiler là một metaprogram, các CPython interpreter là một metaprogram, các Mathematica computer algebra system là một metaprogram, các Coq theorem prover là một metaprogram và như vậy.

Câu trả lời khác đã khẳng định rằng metaprogram là chương trình tạo ra các chương trình khác. Đó thực sự là metaprograms nhưng, một lần nữa, chúng là một tập con của tất cả các metaprogram. Thư viện Fastest Fourier Transform in the West (FFTW) là một ví dụ về một metaprogram như vậy. Mã nguồn được viết chủ yếu trong OCaml và nó tạo ra các bit của mã C (được gọi là codelets) được kết hợp để tạo ra các thói quen hiệu suất cao Fast Fourier Transform được tối ưu hóa cho các máy cụ thể. Thư viện đó thực sự được sử dụng để cung cấp các thói quen FFT trong Matlab. Mọi người đã viết các chương trình để tạo ra các phương pháp số trong nhiều thập kỷ, kể từ những ngày đầu của FORTRAN.

Ngôn ngữ lập trình đầu tiên hỗ trợ tích hợp cho lập trình meta là LISt Processor (LISP) vào cuối những năm 1950. LISP 1.5 bao gồm một số tính năng làm cho lập trình meta dễ dàng hơn. Thứ nhất, loại dữ liệu cốt lõi của LISP là các danh sách lồng nhau, tức là các cây như (a (b c) d), có nghĩa là bất kỳ mã LISP nào cũng có thể được thể hiện như một cấu trúc dữ liệu. Điều này được gọi là homoiconicity. Thứ hai, mã LISP có thể được chuyển đổi thành dữ liệu dễ dàng bằng QUOTE. Ví dụ: (+ 1 2 3) thêm 1 + 2 + 3 và (QUOTE (+ 1 2 3)) tạo biểu thức thêm 1 + 2 + 3 khi được đánh giá. Thứ ba, LISP cung cấp một bộ đánh giá siêu vòng tròn cho phép bạn sử dụng trình thông dịch hoặc trình biên dịch máy chủ để đánh giá mã LISP tại thời gian chạy, bao gồm cả mã LISP chạy theo thời gian chạy. Con cháu của LISP bao gồm SchemeClojure. Trong tất cả các ngôn ngữ lập trình meta này thường thấy nhất ở dạng chương trình tự sửa đổi, thường sử dụng macro.

Trong những năm 1970, Robin Milner đã phát triển một MetaLanguage (ML) mà phát triển thành các gia đình ML của ngôn ngữ lập trình bao gồm Standard MLOCaml và mạnh mẽ ảnh hưởng HaskellF#. Các ngôn ngữ này giúp dễ dàng diễn tả các ngôn ngữ khác. Trong những ngôn ngữ này, metaprogram thường được thấy dưới dạng lexers, parsers, interpreters và compilers.

Năm 1994, Erwin Unruh discovered that the C++ template system was Turing complete and could be used to execute arbitrary programs at compile time. Lập trình meta mẫu C++ mang metaprogramming tới khối lượng chưa rửa (ab) đã sử dụng nó cho nhiều thứ khác nhau, bao gồm tạo ra các phương thức số trong Blitz++ library.