[Uwaga: Ponowne przeczytanie tego przed przesłaniem zdało mi się, że to Q stało się trochę epickie. Dziękuję za poświęcenie się moim długim wyjaśnieniom rozumowania stojącego za tym pościgiem. Czuję, że gdybym był w stanie pomóc innemu przedsiębiorstwu w podobnym projekcie, byłbym bardziej skłonny wejść na pokład, jeśli wiedziałbym, na czym polega motywacja.]Jak wyrazić gramatykę projektowania wolnego od kontekstu jako wewnętrzne DSL w Pythonie?
Dostaję się do Structure Synth przez Mikaela Hvidtfeldta Christensena ostatnio. Jest to narzędzie do generowania geometrii 3D z (głównie) bezkontekstowej gramatyki o nazwie Eisenscript. Struktura Synth jest inspirowany sztuką bez kontekstu. Gramatyki bezkontekstowe mogą tworzyć oszałamiające wyniki z zaskakująco prostych zestawów reguł.
Mój obecny przepływ pracy w ramach struktury strukturalnej obejmuje eksportowanie pliku OBJ ze struktury Synth, importowanie go do Blendera, konfigurowanie świateł, materiałów itp., A następnie renderowanie za pomocą Luxrender. Niestety, importowanie tych plików OBJ często powoduje, że Blender staje się ostry, ponieważ mogą istnieć tysiące obiektów o dość złożonej geometrii. Mówię "sprawiedliwie", ponieważ struktura Synteza generuje tylko podstawowe kształty, ale kula reprezentowana przez trójkąty nadal ma wiele twarzy.
W ten sposób generowanie struktur bezpośrednio w Blenderze byłoby lepszym rozwiązaniem niż obecny proces (powinno to umożliwić głębokie wsparcie Blendera dla skryptów w języku Python). Inteligentna biblioteka Pythona może wykorzystywać zdolności instancji Blendera do korzystania z jednej siatki do generowania niezliczonych obiektów, a tym samym do oszczędzania pamięci. Plus Blender to w pełni funkcjonalny pakiet 3D, a jego umiejętność interpretacji CFDG zapewniłaby twórcze możliwości znacznie wykraczające poza możliwości oferowane przez Structure Synth.
Moje pytanie brzmi: jak najlepiej przetłumaczyć gramatykę Eisenscript na DSL w języku Python. Oto, co proste Eisenscript wygląda następująco:
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
}
Aby wyjaśnić, pierwsze wywołanie R1 (linia 2) losowo powołać się na jedną z dwóch definicji R1. Każda definicja R1 rekursywnie wywołuje R1 (losowo wywołując jedną z dwóch definicji), a także tworzy pole. Pierwsza linia generująca zabójstwa po rekursji osiągnęła 2000 poziomów głębokości.
Jeremy Ashkenas (sławy CoffeeScript) z powodzeniem zaimplementował context free DSL in Ruby używając bloków. Wewnętrznie działa, tworząc klucz skrótu dla każdej "nazwy" reguły i przechowuje bloki dla każdej definicji tej reguły w tablicy, aby były one losowo wybierane podczas wywoływania reguły.
Dotychczasowe definicje reguł Eisenscript przełożyłoby do Ruby DSL tak:
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
Jestem użytkownikiem początkującym Python i tak robili rozeznanie w możliwościach funkcjonalnych programowania Pythona. Wygląda na to, że lambda jest zbyt ograniczona, aby stworzyć coś podobnego do Ruby DSL Jeremy'ego i, o ile mogę to stwierdzić, lambda jest jedyną opcją dla anonimowych funkcji?
Jak doświadczona Pythonista może podejść do projektu?
Możesz użyć 'types.MethodType' zamiast' self.instancemethod'. Powinieneś także użyć 'setattr (obj, name, thing)' zamiast bezpośrednio modyfikować '__dict__'. – JBernardo