[Lưu ý: Đọc lại điều này trước khi gửi, tôi nhận ra câu hỏi này đã trở thành một chút sử thi. Cảm ơn bạn đã thưởng thức lời giải thích dài của tôi về lý do đằng sau việc theo đuổi này. Tôi cảm thấy rằng, tôi đã ở một vị trí để giúp một dự án tương tự khác, tôi sẽ có nhiều khả năng lên tàu hơn nếu tôi biết động cơ đằng sau câu hỏi.]Làm cách nào để diễn tả ngữ cảnh thiết kế ngữ cảnh miễn phí dưới dạng DSL nội bộ trong Python?
Tôi đã tham gia Structure Synth bởi Mikael Hvidtfeldt Christensen gần đây. Nó là một công cụ để tạo ra hình học 3D từ ngữ pháp tự do (chủ yếu) được gọi là Eisenscript. Cấu trúc Synth tự lấy cảm hứng từ Context Free Art. Ngữ pháp ngữ pháp miễn phí có thể tạo ra một số kết quả tuyệt vời từ các quy tắc đơn giản đáng ngạc nhiên.
Luồng công việc Synth cấu trúc hiện tại của tôi liên quan đến việc xuất tệp OBJ từ Cấu trúc Synth, nhập nó vào Máy xay sinh tố, thiết lập đèn, vật liệu, v.v., rồi kết xuất với Luxrender. Thật không may, việc nhập các tập tin OBJ này thường khiến Blender ngừng đập vì có thể có hàng ngàn đối tượng có hình học khá phức tạp. Tôi nói 'khá' bởi vì cấu trúc Synth chỉ tạo ra các hình dạng cơ bản, nhưng một hình cầu đại diện bởi hình tam giác vẫn có nhiều khuôn mặt.
Do đó, việc tạo cấu trúc trực tiếp trong Máy xay sinh tố sẽ thích hợp hơn với quy trình hiện tại (hỗ trợ sâu của Blender cho việc tạo kịch bản Python nên làm điều này có thể). Một thư viện Python thông minh có thể sử dụng khả năng instound của Blender để sử dụng một lưới để tạo ra vô số các đối tượng, do đó tiết kiệm bộ nhớ. Plus Blender là một bộ 3D đầy đủ tính năng và khả năng diễn giải CFDG sẽ cung cấp khả năng sáng tạo vượt xa những gì mà cấu trúc Synth có thể cung cấp.
Và vì vậy câu hỏi của tôi là cách tốt nhất để dịch ngữ pháp Eisenscript thành một DSL Python. Dưới đây là những gì một Eisenscript đơn giản trông giống như:
set maxdepth 2000
{ a 0.9 hue 30 } R1
rule R1 {
{ x 1 rz 3 ry 5 } R1
{ s 1 1 0.1 sat 0.9 } box
}
rule R1 {
{ x 1 rz -3 ry 5 } R1
{ s 1 1 0.1 } box
}
Để giải thích, cuộc gọi đầu tiên đến R1 (dòng 2) sẽ ngẫu nhiên gọi một trong hai định nghĩa của R1. Mỗi định nghĩa của R1 đệ quy gọi R1 (ngẫu nhiên gọi một trong hai định nghĩa) và cũng tạo ra một hộp. Dòng đầu tiên giết chết thế hệ sau khi đệ quy đã đi sâu 2000 cấp độ.
Jeremy Ashkenas (của CoffeeScript nổi tiếng) đã triển khai thành công một khối sử dụng context free DSL in Ruby. Bên trong, nó hoạt động bằng cách tạo khóa băm cho mỗi tên 'quy tắc' và lưu trữ các khối cho mỗi định nghĩa của quy tắc đó trong một mảng, được chọn ngẫu nhiên khi quy tắc được gọi.
Các định nghĩa quy tắc Eisenscript trước sẽ dịch để Ruby DSL như vậy:
rule :r1 do
r1 :x => 1, :rz => 3, :ry => 5
box :s => [1, 1, 0.1], :sat => 0.9
end
rule :r1 do
r1 :x => 1, :rz => -3, :ry => 5
box :s => [1, 1, 0.1]
end
Tôi là một người dùng mới làm quen Python và vì vậy đã và đang làm một số nghiên cứu về khả năng lập trình chức năng của Python. Có vẻ như lambda quá hạn chế để tạo ra thứ gì đó tương tự như Ruby DSL của Jeremy, và, theo như tôi có thể nói, lambda là lựa chọn duy nhất cho các chức năng ẩn danh?
Pythonista có kinh nghiệm tiếp cận thiết kế như thế nào?
Bạn có thể sử dụng 'types.MethodType' thay vì' self.instancemethod'. Ngoài ra, bạn nên sử dụng 'setattr (obj, name, thing)' thay vì sửa đổi '__dict__' trực tiếp. – JBernardo