Chức năng dàn dựng (khái niệm) là gì?


24

Trong một bài viết CACM gần đây [1], các tác giả trình bày một triển khai cho các chức năng theo giai đoạn . Họ sử dụng thuật ngữ này như thể nó đã được biết đến và không có tài liệu tham khảo nào trông giống như một lời giới thiệu rõ ràng.

Họ đưa ra một lời giải thích ngắn (sự nhấn mạnh của tôi và số tham chiếu đã thay đổi; đó là 22 trong bản gốc)

Trong bối cảnh tạo chương trình, lập trình đa tầng (viết tắt là MSP, được đặt bởi Taha và Sheard [2] cho phép các lập trình viên trì hoãn việc đánh giá một biểu thức chương trình đến giai đoạn sau một cách rõ ràng (do đó, dàn dựng một biểu thức). Giai đoạn hiện tại hoạt động hiệu quả như một trình tạo mã bao gồm (và có thể thực thi) chương trình của giai đoạn tiếp theo.

Tuy nhiên, Taha và Sheard viết (nhấn mạnh của tôi):

Một chương trình nhiều giai đoạn là một chương trình liên quan đến việc tạo, biên dịch và thực thi mã, tất cả nằm trong cùng một quy trình. Ngôn ngữ nhiều giai đoạn thể hiện các chương trình nhiều giai đoạn. Dàn dựng, và do đó lập trình nhiều giai đoạn, giải quyết nhu cầu về các giải pháp cho mục đích chung mà không phải trả chi phí diễn giải theo thời gian.

Họ hơn là đi đến một số tài liệu tham khảo cho các tác phẩm cũ được cho là cho thấy dàn dựng có hiệu quả, điều này cho thấy khái niệm này thậm chí còn cũ hơn. Họ không đưa ra một tài liệu tham khảo cho chính thuật ngữ này.

Những tuyên bố này dường như là trực giao, nếu không mâu thuẫn; có lẽ những gì mà Boomf và Oderky viết là một ứng dụng của những gì Taha và Sheard đề xuất, nhưng có lẽ đó là một quan điểm khác về cùng một điều. Họ dường như đồng ý rằng một điểm quan trọng là các chương trình (viết lại) các phần của chính họ khi chạy, nhưng tôi không biết liệu đó có phải là một khả năng cần thiết và / hoặc đủ hay không.

Vì vậy, những gì được dàn dựng tương ứng là những diễn giải về dàn dựng trong bối cảnh này? Thuật ngữ này đến từ đâu?


  1. Phân đoạn mô-đun nhẹ: Cách tiếp cận thực dụng để tạo mã thời gian chạy và DSL được biên dịch bởi T. Rompf và M. Oderky (2012)
  2. MetaML và lập trình đa giai đoạn với các chú thích rõ ràng của W. Taha và T. Sheard (2000)

Mâu thuẫn nào bạn thấy giữa hai tuyên bố? Đối với tôi, họ trông giống như họ đang nói về cùng một điều, với sự nhấn mạnh khác nhau.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles Tôi không cần tạo / biên dịch mã thời gian chạy để trì hoãn việc đánh giá một cái gì đó (xem phần tiếp theo). Rất có thể đó chỉ là một điểm nhấn khác (tôi thừa nhận tùy chọn đó trong câu hỏi), nhưng tôi thực sự không thể nói được.
Raphael

Bạn có thể kiểm tra tài liệu triển khai ngôn ngữ lập trình Julia và tài liệu siêu lập trình trên @generated functions: julia.readthedocs.org/en/latest/manual/metaprogramming/ Lỗi
SalchiPapa

Câu trả lời:


21

Theo hiểu biết tốt nhất của tôi, thuật ngữ tính toán theo giai đoạn được Bill Scherlis sử dụng lần đầu tiên trong bài báo này . Trước đó, thuật ngữ " đánh giá một phần " được sử dụng cho cùng một khái niệm, nhưng ý tưởng về tính toán theo giai đoạn là khác nhau một cách tinh tế. Cả hai ý tưởng đều liên quan đến định lý Smn của Kleene .

Nếu bạn có một hàm của hai đối số, nhưng bạn biết một đối số, nói m , sau đó bạn có thể thực hiện một số tính toán của hàm ngay lập tức bằng cách sử dụng kiến thức của các đối số đầu tiên. Những gì bạn còn lại sau đó là một hàm ϕ m ( n ) có tính toán chỉ phụ thuộc vào đối số thứ hai, chưa biết ,.φ(m,n)mφm(n)

Ý tưởng của việc đánh giá một phần là để tính toán các chức năng chuyên ngành tự động . Đưa ra mã cho hàm ban đầu , đánh giá một phần thực hiện phân tích tĩnh để xác định bit nào của mã phụ thuộc vào và bit nào phụ thuộc vào và biến đổi nó thành hàmφm(n) φmn , cho m , xây dựng ϕ m . Đối số thứ hai n sau đó có thể được đưa vào hàm chuyên biệt này.φ'mφmn

Ý tưởng của tính toán dàn dựng là suy nghĩ về hàm trước tiên. Nó được gọi là chức năng "dàn dựng" vì nó hoạt động trong nhiều giai đoạn. Khi chúng ta đưa ra đối số m đầu tiên , nó sẽ xây dựng mã cho hàm chuyên biệt ϕ m . Đây là "giai đoạn đầu tiên." Trong giai đoạn thứ hai, đối số thứ hai được cung cấp cho ϕ m , phần còn lại của công việc.φ'mφmφm

Vì vậy, công việc đánh giá một phần là để chuyển đổi mã cho một chức năng bình thường đến một chức năng dàn dựng φ ' . Scherlis dự tính rằng việc chuyển đổi này có thể được thực hiện bằng các cơ chế tổng quát hơn so với các phương pháp đánh giá từng phần trước đó. Chủ đề của "tính toán theo giai đoạn" hiện nay liên quan đến các vấn đề như:φφ'

  • Làm thế nào để xác định chức năng dàn dựng?
  • Những ngôn ngữ lập trình và hệ thống loại nào nên được sử dụng để xác định các chức năng theo giai đoạn?
  • Các ngữ nghĩa của các ngôn ngữ như vậy là gì?
  • Làm thế nào để chúng tôi đảm bảo sự gắn kết và chính xác của các chức năng theo giai đoạn?
  • Những kỹ thuật nào hữu ích cho việc xây dựng các chức năng theo giai đoạn tự động hoặc bán tự động?
  • Làm thế nào để chúng tôi chứng minh tính đúng đắn của các kỹ thuật như vậy?

Tính toán dàn dựng có thể rất quan trọng trong thực tế. Trong thực tế, mọi trình biên dịch có hiệu lực tính toán theo giai đoạn. Đưa ra một chương trình nguồn, nó xây dựng một chương trình mục tiêu được dịch và tối ưu hóa, sau đó có thể lấy đầu vào thực tế và tính kết quả. Thật khó để viết các chương trình tính toán theo giai đoạn trong thực tế bởi vì chúng ta phải tung hứng nhiều giai đoạn và đảm bảo rằng những điều đúng đắn được thực hiện đúng lúc. Mọi người đã viết một trình biên dịch đã đấu tranh với các vấn đề như vậy. Thật khó để viết các chương trình viết các chương trình khác, chúng có thể là chương trình ngôn ngữ máy (trình biên dịch), truy vấn SQL (thao tác cơ sở dữ liệu) hoặc HTML / Máy chủ trang / mã Javascript (ứng dụng web) và vô số các ứng dụng khác.


φ'φ'

Vì vậy, điều bạn muốn nói là đánh giá một phần là sự trừu tượng đối với lập trình đa giai đoạn, có nghĩa là eval một phần không bao hàm lập trình nhiều giai đoạn mà lập trình đa giai đoạn bao hàm một phần eval. Trong đó eval một phần có thể được thực hiện trong một hoặc nhiều giai đoạn vì việc curry trong các ngôn ngữ chức năng không nhất thiết phải liên quan đến nhiều giai đoạn và tạo mã khi chạy, phải không?
denis631

1
Không chính xác. Một người đánh giá một phần biên dịch một chương trình bình thường thành chương trình 2 giai đoạn và sau đó chạy giai đoạn đầu tiên. Trong lập trình dàn dựng, bạn tự viết chương trình nhiều giai đoạn.
Uday Reddy

9

Mặc dù các câu trả lời khác là đúng về mặt kỹ thuật, tôi không nghĩ rằng họ đưa ra một sự hiểu biết chính xác về lý do tại sao các nhà khoa học máy tính quan tâm đến các chức năng được dàn dựng.

Bằng cách tạo các chức năng theo giai đoạn, bạn xác định các chương trình tạo chương trình. Một trong những mục tiêu lớn của lý thuyết ngôn ngữ thực tế hiện đại là tối đa hóa khả năng tái sử dụng. Chúng tôi muốn làm cho nó có thể viết các thư viện không chỉ là các hàm và đối tượng hữu ích, mà còn giúp các lập trình viên bằng cách cung cấp các công trình kiến ​​trúc bậc cao hơn.

Sẽ thật tuyệt nếu chúng ta có thể thoát khỏi tất cả các mã soạn sẵn. Chúng ta có thể giảm thiểu ngôn ngữ đặc tả. Ví dụ, nếu chúng ta muốn một bộ điều khiển hướng sự kiện, giao tiếp với các bộ điều phối khác với một thiết kế luồng đã cho, chúng ta sẽ có thể chỉ định một cách gọn gàng, và tất cả các trình nghe IO và các kết nối đối tượng và hàng đợi có thể được xây dựng từ đặc tả đó.

Ngôn ngữ miền có xu hướng là những đại diện nhỏ gọn mà chúng tôi đang tìm kiếm. Khi mọi người làm việc trong một miền trong một thời gian, ngôn ngữ họ sử dụng có xu hướng giảm hầu hết sự trùng lặp thông tin và trở thành một đặc tả kỹ thuật tinh gọn. Vì vậy, lý thuyết dàn dựng này có xu hướng trở thành một hệ thống dịch thuật từ ngôn ngữ miền sang ngôn ngữ thực thi.

Trình biên dịch là kỹ thuật xếp hạng, nhưng nó bỏ lỡ mục tiêu. Mục tiêu của dàn dựng hiện đại là cho phép xây dựng các chương trình xây dựng chương trình để tối đa hóa việc tái sử dụng và tự động hóa việc xây dựng chương trình bất cứ khi nào có thể. Sẽ thật tuyệt nếu một ngày yêu cầu chức năng của một chương trình là chương trình.

Xem "Lập trình tạo" của Czarnecki và Eisenecker (ISBN-13: 978-0201309775).


@Raphael: Đây là chương ba với những điều cơ bản về tên miền và tái sử dụng. Nhìn vào thậm chí tối ưu hóa bạn đề cập. FFT không được thực hiện bằng cách dàn dựng để làm cho nó chạy nhanh hơn. Nó được thực hiện để lập trình viên không phải tính toán bảng giá trị mỗi lần bằng tay, sao chép chúng vào chương trình và xây dựng một danh sách lớn. Đó là để giảm thiểu công việc được thực hiện và sử dụng lại các bước cơ bản hơn. Tương tự với vòng lặp unrolling. Làm điều đó bằng tay lặp lại thông tin và không thể được sử dụng lại.
ex0du5

Quan điểm DSL này dường như giới hạn phân tầng ở một cấp độ (một trình biên dịch DSL bên trong chương trình), phải không?
Raphael

1
@Raphael: Nó thực sự phụ thuộc vào quan điểm của bạn. Rõ ràng, khái niệm này không có sức mạnh tính toán khi được xem đơn giản là nguồn -> bản dịch thực thi. Chúng ta chỉ cần xây dựng một trình biên dịch cho ngôn ngữ DS và được thực hiện. Sức mạnh của nó đến từ đâu trong vòng lặp. Khi xây dựng các thư viện sẽ được sử dụng và mở rộng bởi các dự án trong tương lai, các giai đoạn tự nhiên sẽ xuất hiện bên trong ranh giới thư viện. Bạn có thể có một thư viện biến đổi các đặc tả đối tượng thành nguồn để tuần tự hóa đầy đủ, và sau đó một thư viện khác xây dựng lớp vận chuyển được xây dựng trên một số thông số công văn ...
ex0du5

1
@Raphael: Việc dàn dựng có thể được thực hiện tự nhiên hơn với nhiều giai đoạn. Nếu một đoạn mã đã có các yêu cầu của nó thay đổi rất nhiều theo thời gian, trong khi các mã khác ổn định hơn nhiều, thì có thể phù hợp do "các lớp cắt" để tách giai đoạn thành các lớp có giao diện ổn định hơn. Sau đó, bạn có thể ảnh hưởng ít hơn đến hệ thống với các thay đổi và tôn vinh hình thức dàn dựng của nguyên tắc đóng mở. Đó là những mối quan tâm thực tế không có sự cần thiết về toán học, nhưng tất cả đều dựa trên thực tiễn. Chúng tôi không muốn một ngôn ngữ biên dịch duy nhất, chúng tôi muốn cho phép tiến hóa.
ex0du5

5

Câu trả lời được đưa ra trong phần phối cảnh kỹ thuật cho bài viết trong câu hỏi [1]. Vấn đề đang được xem xét là khu vực căng thẳng giữa mã chung và mã cụ thể:

Các chương trình có thể được viết là mục đích chung hoặc mục đích đặc biệt. Mã mục đích chung có lợi thế là có thể sử dụng được trong nhiều tình huống, trong khi mã mục đích đặc biệt có thể được viết theo cách tận dụng các đặc điểm độc đáo của môi trường thực thi và do đó đạt được hiệu quả với chi phí tái sử dụng.

Tất nhiên chúng tôi muốn giải quyết căng thẳng này, đó là đạt được mã chung thực hiện cụ thể:

Chúng ta có thể đặt câu hỏi: Có thể viết mã sao cho mục đích chung nhưng sau đó nó có tự động chuyên môn hóa cho tình huống trong tay trong khi thực hiện không?

Điều này đã nảy sinh ý tưởng về việc các chương trình (chung) tự viết lại trong thời gian chạy để thực hiện cho một tình huống cụ thể:

Kết quả là, một hướng nghiên cứu quan trọng đã tham gia vào việc tìm kiếm công nghệ trình biên dịch và ngôn ngữ có thể cho phép các lập trình viên viết mã mục đích chung sau đó được chuyển thành mã chuyên dụng hiệu suất cao một cách chính xác và hiệu quả trong thời gian chạy.

Tôi đoán JIT của Java là một ví dụ tốt. Một ý tưởng đặc biệt là lập trình nhiều giai đoạn, mà Lee giải thích như sau:

Trong dòng nghiên cứu này, một trong những ý tưởng cốt lõi là khái niệm dàn dựng. Chúng tôi tưởng tượng việc thực hiện một chương trình tiến hành trong một loạt các giai đoạn, mỗi giai đoạn tính toán các giá trị được sử dụng bởi các giai đoạn sau. Sau đó, những gì chúng tôi tìm kiếm là viết mã chương trình để bằng cách nào đó các giai đoạn này được làm rõ ràng. Nếu điều này được thực hiện, thì chúng ta có thể sắp xếp để mã giai đoạn sau được biên dịch thành các trình tạo mã tối ưu hóa so với kết quả của các tính toán ở giai đoạn trước.

Đó là, "dàn dựng" là một cách xem xét các hàm / mã phù hợp để xác định các giai đoạn trong tính toán / thực thi có thể được đơn giản hóa khi biết kết quả của các giai đoạn trước. Tính toán "Trì hoãn" như trong trích dẫn đầu tiên trong câu hỏi có thể là một tác dụng phụ cần thiết để tách các giai đoạn một cách hợp lý, nhưng nó không phải là vấn đề.

Rompf và Oderky đề cập đến biến đổi Fourier nhanh như một ví dụ có thể mang tính hướng dẫn.


  1. Con cáo và con nhím: quan điểm kỹ thuật của Peter Lee (2012)
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.