DSL을 만드는 루비의“능력”보다 LISP의 매크로가 어떤 영역에서 더 낫습니까?


21

Ruby를 빛나게하는 것 중 하나는 다음과 같이 도메인 특정 언어를 더 잘 만들 수 있다는 것입니다.

매크로를 통해 LISP에서 이러한 라이브러리를 복제 할 수 있지만 Ruby의 구현이 더 우아하다고 생각합니다. 그럼에도 불구하고 LISP의 매크로가 Ruby의 매크로보다 더 좋을 수 있다고 생각하지만, 생각할 수는 없습니다.

그렇다면 어떤 영역에서 LISP의 매크로가 루비의 DSL 생성 능력보다 있다면 어떤 것이 더 좋을까요?

최신 정보

현대 프로그래밍 언어이기 때문에 나는 이것을 요청했습니다 LISP를 특이점을 접근 처럼,

  • C는 매크로 확장 프리 프로세서를 얻었 지만 매우 원시적이며 오류가 발생하기 쉽습니다.
  • C #에는 읽기 전용이지만 리플렉션을 통해 노출되는 속성이 있습니다.
  • 파이썬에는 데코레이터가 추가되어 함수의 동작 (및 v 3.0의 클래스)을 수정할 수 있지만 상당히 제한적입니다.
  • 관리가 적용되지만 루비 방식으로 우아한 DSL을 만드는 루비 TMTOWTDI.

LISP의 매크로가 특수한 경우에만 적용 가능하고 다른 프로그래밍 언어 기능이 오늘날 소프트웨어 개발의 과제를 해결할 수있는 추상화를 제기 할 수있을만큼 강력하다는 것이 궁금했습니다.


4
나는 왜 이것에 대한 찬성 투표가 있는지 확실하지 않습니다. 나는 이것이 우리가 원하는 종류의 질문이지만 ? 흥미롭고, 생각을 자극하고, 범위가 잘 정의되어 있습니다.
Tim Post

Ruby에서 다음과 같이 구현해보십시오 : meta-alternative.net/pfront.pdf
SK-logic

@Tim Post : 한 가지 문제는 Common Lisp와 Ruby를 모두 잘 알지 못한다면 대답하기 쉬운 질문이 아니라는 것입니다. 또 다른 언어는 다른 언어에 대한 상당히 무의미한 참조로, 순수 주의자를 귀찮게 할 수 있습니다. C / C ++라는 언어가 없으며 C ++의 중요한 부분은 템플릿 시스템이며 Common Lisp의 매크로 시스템은 특수한 경우에만 적용 할 수 있다는 제안입니다. 기본적으로 좋은 질문이지만 잘못 작성되어 답하기가 어렵습니다.
David Thornley

@David Thornley, 특히 C \ C ++에 대한 게시물을 업데이트하고 C에 중점을 두었습니다. Common Lisp의 경우 다른 프로그래밍 언어의 추상화가 더 높기 때문에 매크로 기능이 특별한 경우라고 생각했습니다. 다른 사람들이 CL의 매크로가 특별한 경우가 아니라는 것을 보여주기를 희망하면서 질문을 게시했지만 여전히 강력한 기능입니다.
OnesimusUnbound

@OnesimusUnbound : 적어도 이론적으로 Lisp 매크로 시스템이 할 수있는 계산이 가능하기 때문에 언어 예제 목록에 C ++ 템플릿을 포함시킬 것입니다. Lisp의 매크로가있는 한, 좋은 Common Lisp 코드 (F / OS Lisp 코드가 많이 있음)를 잡고 "defmacro"를 검색하십시오 (대소 문자를 구분하지 않는 검색을 원할 수 있습니다). 아마도 그것들을 많이 찾을 것입니다. 매크로는 작성하고 올바르게 작성하는 것이 함수보다 어렵고 일반적으로 유용해야한다는 것을 알게 될 것입니다.
David Thornley

답변:


23

Lisp를 읽고 스스로 결정하십시오.

내 요약은 Ruby가 편리한 구문을 제공하는 데 더 좋다는 것입니다. 그러나 Lisp은 새로운 추상화를 생성 한 다음 추상화를 추상화 할 수있는 능력을 갖추고 승리합니다. 그러나 실제로 Lisp를보고 그 점을 이해해야합니다. 따라서이 책은 추천합니다.


1
"람다에 맡겨라"는 비슷한 근거를 다룬다. 독서도 추천합니다.
John R. Strohm 2016 년

But Lisp wins, hands down, at the ability to create new abstractions, and then to layer abstraction on abstraction.이제 이유를 알았습니다. . .
OnesimusUnbound

Lisp 위에 어떤 종류의 구문을 제공하는 것은 큰 문제가 아닙니다. 실제로 리더 매크로 덕분에 루비보다 훨씬 쉽습니다.
SK-logic

1
@ SK-logic : 맞습니다. 그러나 Lispers는 일단 내려 가면 더 이상 Lisp처럼 느껴지지 않기 때문에 독자 매크로에서 멀어집니다. 실제로 Clojure와 같은 Lisp의 일부 변형은 언어 디자이너를 위해 독자 매크로를 예약합니다.
btilly

14

DSL 저작을위한 루비의 시설은 언어의 본질을 바꾸지 않습니다. 루비의 메타 프로그래밍 기능은 본질적으로 루비 구문과 시맨틱과 관련이 있으며, 작성한 모든 것을 루비의 객체 모델로 분류해야합니다.

매크로가 추상 프로그램 자체에서 작동하는 Lisp (및 매크로 기능이 다른 Scheme)과 대조하십시오 . Lisp 프로그램 Lisp 값이므로 매크로는 기본적으로 임의의 구문을 다른 구문에 매핑하는 함수입니다.

효과적으로 루비 DSL은 여전히 루비처럼 느껴지 지만 Lisp DSL은 Lisp처럼 느껴질 필요가 없습니다.


6
+1 : DSL의 예로 LOOP는별로 눈에 띄지 않습니다.
Frank Shearar

2

루비의 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 전체를 읽고 싶지는 않습니다 .)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.