Kết hợp Y và tối ưu hóa cuộc gọi đuôi


20

Định nghĩa của tổ hợp Y trong F # là

let rec y f x = f (y f) x

f hy vọng sẽ có một đối số đầu tiên một số tiếp tục cho các bài toán con đệ quy. Sử dụng yf như một sự tiếp nối, chúng tôi thấy rằng f sẽ được áp dụng cho các cuộc gọi liên tiếp khi chúng tôi có thể phát triển

let y f x = f (y f) x = f (f (y f)) x = f (f (f (y f))) x etc...

Vấn đề là, một ưu tiên, lược đồ này không sử dụng bất kỳ tối ưu hóa cuộc gọi đuôi nào: thực sự, có thể có một số thao tác đang chờ xử lý trong f, trong trường hợp đó chúng ta không thể thay đổi khung ngăn xếp cục bộ được liên kết với f.

Vì thế :

  • ở một đầu, sử dụng bộ kết hợp Y yêu cầu tiếp tục khác biệt rõ ràng so với chính chức năng.
  • trên othe để áp dụng TCO, chúng tôi muốn không có hoạt động nào đang chờ xử lý trong f và chỉ gọi chính nó.

Bạn có biết bất cứ cách nào mà hai người đó có thể được hòa giải? Giống như một Y với thủ thuật tích lũy, hay một Y với thủ thuật CPS? Hoặc một lập luận chứng minh rằng không có cách nào có thể được thực hiện?


Bạn đã thêm các keywork rec để thực hiện y của bạn? Tôi nên nghĩ rằng nó cần nó từ việc đọc của tôi ..
Jimmy Hoffa

Bạn có bằng chứng nó không tối ưu hóa cuộc gọi đuôi? Tôi nên nghĩ rằng bạn có thể muốn đọc IL cho chức năng đó và xem, tôi sẽ không ngạc nhiên nếu trình biên dịch đủ thông minh để đưa ra một cái gì đó ..
Jimmy Hoffa

trong trường hợp đệ quy cởi trói thẳng thì không: tuy nhiên bạn có thể viết lại nó để cho phép điều đó đối với thực tế khung stack được sử dụng lại thông qua lệnh gọi y. vâng có thể cần phải xem IL, không có kinh nghiệm trong đó.
nicolas

5
Tôi đã tạo một tài khoản và nhận được 50 điểm chỉ để bình luận ở đây. Câu hỏi này thực sự thú vị. Tôi nghĩ rằng nó phụ thuộc hoàn toàn vào f. Chúng ta có thể thấy rằng ycó thể nối đuôi fvới một thunk (y f), nhưng như bạn nói fcó thể có một số hoạt động đang chờ xử lý. Tôi nghĩ sẽ rất thú vị nếu biết nếu có một tổ hợp riêng biệt thân thiện hơn với đuôi. Tôi tự hỏi nếu câu hỏi này sẽ được chú ý tốt hơn trên trang web CS Stackexchange?
John Cartwright

Câu trả lời:


4

Bạn có biết bất cứ cách nào mà hai người đó có thể được hòa giải?

Không, và với lý do chính đáng, IMHO.

Bộ kết hợp Y là một cấu trúc lý thuyết và chỉ cần thiết để làm cho phép tính lambda hoàn thành (hãy nhớ rằng không có vòng lặp trong phép tính lambda, cũng như lambdas có tên mà chúng ta có thể sử dụng để đệ quy).

Như vậy, tổ hợp Y thực sự hấp dẫn.

Nhưng : Không ai thực sự sử dụng bộ kết hợp Y cho đệ quy thực tế! (Ngoại trừ có thể cho vui, để cho thấy rằng nó thực sự hoạt động.)

Tối ưu hóa cuộc gọi đuôi, OTOH, đúng như tên gọi, tối ưu hóa. Nó không thêm gì vào sự xuất sắc của một ngôn ngữ, nó chỉ là do những cân nhắc thực tế như không gian ngăn xếp và hiệu suất của mã đệ quy mà chúng tôi quan tâm đến nó.

Vì vậy, câu hỏi của bạn là như: Có hỗ trợ phần cứng để giảm beta? (Giảm Beta là cách giảm các biểu thức lambda.) Nhưng không có ngôn ngữ chức năng nào (theo như tôi biết) biên dịch mã nguồn của nó thành biểu diễn các biểu thức lambda sẽ bị giảm beta khi chạy.


2
Bộ kết hợp Y giống như giữ lại một nút thắt mà không bị trói sau mỗi lần sử dụng. Hầu hết các hệ thống đều cắt ngắn phần này và buộc nút ở cấp độ meta sao cho không bao giờ cần phải thử lại.
Dan D.

1
Đến đoạn cuối, hãy xem xét Haskell mà tại trung tâm của nó sử dụng giảm biểu đồ để đánh giá lười biếng. Nhưng yêu thích của tôi là giảm tối ưu , luôn đi theo con đường trong mạng Church-Rosser với mức giảm ít nhất đến dạng hoàn toàn bình thường. Chẳng hạn như xuất hiện trong triển khai tối ưu các ngôn ngữ lập trình chức năng của Asperti và Guerrini . Cũng xem BOHM 1.1 .
Dan D.

@DanD. Cảm ơn các liên kết, tôi sẽ thử chúng sau trong trình duyệt nhận biết bài đăng. Chắc chắn có một cái gì đó để học cho tôi. Nhưng, bạn có chắc rằng haskell đã biên dịch không làm giảm đồ thị? Tôi nghi ngờ điều này.
Ingo

1
Trên thực tế, nó sử dụng tính năng giảm đồ thị: "GHC biên dịch sang máy G không có thẻ không quay vòng (STG). Đây là máy giảm biểu đồ đáng chú ý (nghĩa là máy ảo thực hiện giảm đồ thị như mô tả ở trên)." Từ ... Để biết thêm về máy STG, hãy xem Simon Peyton Jones Thực hiện các ngôn ngữ chức năng lười biếng trên phần cứng chứng khoán: Máy G không có thẻ Spinless .
Dan D.

@DanD. trong cùng một bài viết mà bạn đã liên kết, nó đọc thêm rằng GHC "thực hiện một số tối ưu hóa trên đại diện đó, trước khi cuối cùng biên dịch nó thành mã máy thực (có thể thông qua C sử dụng GCC)."
Ingo

0

Tôi không hoàn toàn chắc chắn về câu trả lời này, nhưng đó là điều tốt nhất tôi có thể nghĩ ra.

Tổ hợp y vốn đã lười biếng, trong các ngôn ngữ nghiêm ngặt, sự lười biếng phải được thêm bằng tay thông qua thêm lambdas.

let rec y f x = f (y f) x

Định nghĩa của bạn có vẻ như nó đòi hỏi sự lười biếng để chấm dứt, hoặc (y f)đối số sẽ không bao giờ kết thúc việc đánh giá và sẽ phải đánh giá xem có fsử dụng nó hay không . TOC trong một bối cảnh lười biếng phức tạp hơn, và hơn nữa kết quả của việc (y f)lặp lại thành phần chức năng mà không áp dụng với x. Tôi không chắc điều này cần có bộ nhớ O (n) trong đó n là độ sâu của đệ quy, nhưng tôi nghi ngờ bạn có thể đạt được loại TOC giống như có thể với một cái gì đó như (chuyển sang Haskell vì tôi thực sự không biết F #)

length acc []    = acc
length acc (a:b) = length (acc+1) b 

Nếu bạn chưa biết về nó, sự khác biệt giữa foldlfoldl'trong Haskell có thể làm sáng tỏ tình hình. foldlđược viết như sẽ được thực hiện trong một ngôn ngữ háo hức. Nhưng thay vì là TOC'd, điều đó thực sự tồi tệ hơn foldrbởi vì bộ tích lũy lưu trữ một khối lớn có khả năng không thể đánh giá được một phần. (Điều này có liên quan đến lý do tại sao cả hai foldl và foldl' không làm việc trên danh sách vô hạn.) Như vậy trong các phiên bản gần đây của Haskell, foldl'đã được bổ sung mà các lực lượng đánh giá của accumulator mỗi lần tái phát chức năng để đảm bảo không thunk khổng lồ được tạo ra. Tôi chắc chắn http://www.haskell.org/haskellwiki/Foldr_Foldl_Foldl%27 có thể giải thích điều này tốt hơn tôi.

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.