2008-08-21 27 views
6

Tôi đã cố gắng hiểu cách khối Ruby hoạt động, và để làm điều đó tôi đã cố gắng thực hiện chúng trong C.Các khối Ruby/đóng cửa Java trong C

Một cách dễ dàng để thực hiện đóng cửa là vượt qua a void* với ngăn xếp kèm theo để đóng/chức năng nhưng các khối Ruby cũng có vẻ xử lý các trả về và các câu lệnh ngắt từ phạm vi sử dụng khối.

loop do 
    break i if (i >= 4000) 
    i *= 2 
end 

Tôi nghĩ rằng một trong các đề xuất đóng cho Java cũng hoạt động như thế này.

Vì vậy, làm cách nào bạn triển khai Ruby-block/Java-closures trong C?

+0

"Vì vậy, làm thế nào bạn sẽ thực hiện Ruby-block/Java-đóng cửa trong C?" Ít nhất cho đến khi Java 7 được phát hành, không có thứ gì như đóng Java. –

+0

Yea, đó là lý do tại sao tôi nói "đóng cửa các đề xuất cho Java" ngay trước đó. –

Trả lời

10

Khái niệm về bao đóng đòi hỏi khái niệm về ngữ cảnh. Ngữ cảnh của C dựa trên ngăn xếp và thanh ghi của CPU, do đó, để tạo khối/đóng, bạn cần có khả năng thao tác con trỏ ngăn xếp theo cách chính xác (và reentrant) và lưu trữ/khôi phục sổ đăng ký nếu cần.

Cách này được thực hiện bởi thông dịch viên hoặc máy ảo là phải có cấu trúc context hoặc một cái gì đó tương tự và không sử dụng ngăn xếp và đăng ký trực tiếp. Cấu trúc này theo dõi một ngăn xếp và tùy chọn một số thanh ghi, nếu bạn đang thiết kế một máy ảo dựa trên đăng ký. Ít nhất, đó là cách đơn giản nhất để làm điều đó (mặc dù hơi kém hiệu quả hơn là thực sự lập bản đồ những thứ chính xác).

2

Có một tập tốt của các slide trên Ruby Blocks như một phần của "Rails với Passion" khóa học:

Ruby_Blocks.pdf

này bao gồm đại diện cho một khối, làm thế nào họ có được thông qua tranh luận và thực hiện, và hơn nữa vào những thứ như đối tượng Proc. Nó được giải thích rất rõ ràng.

Sau đó, có thể bạn sẽ quan tâm xem cách các nhân viên JRuby xử lý những điều này trong phân tích cú pháp của họ sang Java. Hãy xem nguồn tại số codehaus.

3

Tôi chưa thực sự triển khai bất kỳ thứ gì trong số này, vì vậy hãy mang theo một bao muối.

Có hai phần để đóng: môi trường dữ liệu và môi trường mã. Như bạn đã nói, bạn có thể vượt qua một khoảng trống * để xử lý các tham chiếu đến dữ liệu. Có lẽ bạn có thể sử dụng setjmp và longjmp để thực hiện luồng điều khiển phi tuyến tính mà Ruby yêu cầu.

Nếu bạn muốn đóng cửa, có thể bạn nên lập trình bằng ngôn ngữ thực sự hỗ trợ chúng. :-)

CẬP NHẬT: Những điều thú vị đang diễn ra ở Clang. Họ đã tạo mẫu cho một đóng cửa cho C. http://lists.cs.uiuc.edu/pipermail/cfe-dev/2008-August/002670.html có thể chứng minh được đọc thú vị.