루비의 DSL은 전혀 DSL이 아니며, 문서가 실제로 어떻게 작동하는지에 대한 문서가 공개되어 있기 때문에 나는 그것을 사용하는 것을 싫어합니다. ActiveRecord를 예로 들어 보겠습니다. 모델 간의 연관을 "선언"할 수 있습니다.
class Foo < ActiveRecord::Base
has_one :bar
has_one :baz
end
그러나이 "DSL"의 선언 성 (Ruby class
구문 자체 의 선언 성과 같은)은 Ruby "DSLs"의 실제 작동 방식을 이해하는 사람이라면 누구나 볼 수있는 끔찍한 거짓말입니다.
class Foo < ActiveRecord::Base
[:bar,:baz,:qux,:quux].each do |table|
has_one table if i_feel_like_it?(table)
end
puts "Just for shits and giggles, and to show"
puts "just how fucked up Ruby really is, we're gonna ask you"
puts "which SQL table you want the Foo model to have an"
puts "association with.\n"
puts "Type the name of a table here: "
has_one gets.chomp.to_sym
end
( Lisp 형식 의 본문에서 그 와 비슷한 것을 시도하십시오 defclass
!)
코드베이스에 위와 같은 코드가 있으면 프로젝트의 모든 개발자 는 코드를 유지하기 전에 Ruby DSL이 실제로 작동 하는 방식을 이해해야합니다 . 사용 가능한 문서는 선언적 환상을 유지하는 관용적 사용법 만 문서화하므로 완전히 쓸모가 없습니다 .
RSpec은 디버그하기 위해 광범위한 리버스 엔지니어링이 필요한 기괴한 엣지 케이스를 가지고 있기 때문에 위의 것보다 훨씬 나쁩니다. (저는 하루 종일 테스트 케이스 중 하나를 건너 뛰는 이유를 알아 내려고 노력했습니다. RSpec은 소스에 나타나는 순서에 관계없이 테스트 케이스 이후에 컨텍스트가없는 모든 테스트 케이스를 컨텍스트없이 실행합니다. 이 context
메소드는 블록이 평소와 다른 데이터 구조로 배치 되기 때문에 )
Lisp DSL은 거의 컴파일러가 아닌 매크로로 구현됩니다. 이 방법으로 만들 수있는 DSL은 단순한 Lisp의 기존 구문을 남용하는 것이 아닙니다. 그들은 자신의 문법을 가질 수 있기 때문에 완벽하게 매끄럽게 작성 될 수있는 실제 미니 언어입니다. 예를 들어 Lisp의 LOOP
매크로는 Ruby의 each
방법 보다 훨씬 강력 합니다.
(나는 당신이 이미 답을 받아 들였다는 것을 알고 있지만, 이것을 읽는 모든 사람이 On Lisp 전체를 읽고 싶지는 않습니다 .)