문제

나는 LISP가 아마도 매크로를 사용하여 즉석에서 구문을 재정의할 수 있다는 것을 많이 읽었습니다.실제로 이것이 어디까지 진행되는지 궁금합니다.다른 언어의 컴파일러가 될 정도로 언어 구조를 재정의할 수 있습니까?예를 들어, LISP의 기능적 특성을 보다 객체 지향적인 구문 및 의미론으로 변경할 수 있습니까? 즉 Ruby와 같은 구문에 더 가까운 구문을 가질 수 있습니까?

특히, 매크로를 이용하면 괄호지옥을 없앨 수 있는 걸까요?나는 내 자신의 마이크로 기능으로 Emacs를 사용자 정의할 수 있을 정도로 (Emacs-)LISP를 충분히 배웠지만 언어를 사용자 정의하는 데 매크로가 얼마나 멀리까지 갈 수 있는지 매우 궁금합니다.

도움이 되었습니까?

해결책

정말 좋은 질문이에요.

미묘하지만 확실히 대답할 수 있다고 생각합니다.

매크로는 s-표현식에 갇히지 않습니다.키워드(기호)를 사용하여 작성된 매우 복잡한 언어에 대해서는 LOOP 매크로를 참조하세요.따라서 괄호로 루프를 시작하고 끝낼 수 있지만 내부에는 자체 구문이 있습니다.

예:

(loop for x from 0 below 100
      when (even x)
      collect x)

즉, 대부분의 간단한 매크로는 s-표현식을 사용합니다.그리고 당신은 그것들을 사용하는 데 "고착"될 것입니다.

그러나 Sergio가 대답한 것처럼 s-표현은 옳다고 느끼기 시작합니다.구문이 방해가 되지 않고 구문 트리에서 코딩을 시작합니다.

리더 매크로의 경우 다음과 같이 작성할 수 있습니다.

#R{
      ruby.code.goes.here
  }

하지만 자신만의 Ruby 구문 분석기를 작성해야 합니다.

기존 Lisp 구성으로 컴파일되는 매크로를 사용하여 블록과 같은 일부 Ruby 구성을 모방할 수도 있습니다.

#B(some lisp (code goes here))

다음과 같이 번역할 것이다

(lambda () (some lisp (code goes here)))

보다 이 페이지 그것을하는 방법에 대해.

다른 팁

예, Lisp가 컴파일러가 되도록 구문을 재정의할 수 있습니다.여러분이 생각하고 있는 일반적인 "컴파일러 매크로"와는 다른 "리더 매크로"를 사용하여 이 작업을 수행합니다.

Common Lisp에는 판독기 및 판독기 매크로가 해당 구문을 처리할 수 있도록 새로운 구문을 정의하는 기능이 내장되어 있습니다.이 처리는 읽기 시간(컴파일 또는 평가 시간 이전)에 수행됩니다.Common Lisp에서 리더 매크로를 정의하는 방법에 대해 자세히 알아보려면 Common Lisp Hyperspec을 참조하세요. Ch.2, "구문" 그리고 Ch.23, "독자".(Scheme에도 동일한 기능이 있다고 생각하지만 익숙하지는 않습니다. 구성표 소스 위해 아크 프로그래밍 언어).

간단한 예로 Lisp가 괄호 대신 중괄호를 사용하기를 원한다고 가정해 보겠습니다.이를 위해서는 다음과 같은 판독기 정의가 필요합니다.

;; { and } become list delimiters, along with ( and ).
(set-syntax-from-char #\{ #\( )
(defun lcurly-brace-reader (stream inchar) ; this was way too easy to do.
  (declare (ignore inchar))
  (read-delimited-list #\} stream t))
(set-macro-character #\{ #'lcurly-brace-reader)

(set-macro-character #\} (get-macro-character #\) ))
(set-syntax-from-char #\} #\) )

;; un-lisp -- make parens meaningless
(set-syntax-from-char #\) #\] ) ; ( and ) become normal braces
(set-syntax-from-char #\( #\[ )

당신은 Lisp에게 {가 (와 같고 }가 a와 같다고 말하고 있는 것입니다.그런 다음 함수(lcurly-brace-reader) 리더가 {를 볼 때마다 호출하고 사용자는 이를 사용합니다. set-macro-character 해당 기능을 {에 할당합니다.그런 다음 Lisp에게 ( 및 )가 [ 및 ]와 같다고 말합니다(즉, 의미 있는 구문이 아닙니다).

예를 들어, 수행할 수 있는 다른 작업은 다음과 같습니다. 새로운 문자열 구문 생성 또는 [ 및 ]를 사용하여 고정 표기법을 포함하고 이를 S-표현식으로 처리합니다.

또한 이보다 훨씬 더 나아가서 리더에서 작업을 실행하는 자체 매크로 문자를 사용하여 전체 구문을 재정의할 수 있으므로 실제로는 한계가 없습니다.이것은 단지 이유 중 하나일 뿐입니다. 폴 그레이엄 그리고 다른 사람 Lisp가 컴파일러를 작성하기에 좋은 언어라고 계속 말하세요.

나는 Lisp 전문가도 아니고 심지어 Lisp 프로그래머도 아니지만, 언어를 약간 실험한 후 잠시 후 괄호가 '보이지 않게' 되기 시작하고 코드가 다음과 같이 보이기 시작한다는 결론에 도달했습니다. 당신은 그것이되기를 원합니다.s-exprs 및 매크로를 통해 생성한 구문 구조에 더 많은 관심을 기울이고 목록 및 괄호 텍스트의 어휘 형식에는 덜 주의를 기울이기 시작합니다.

들여쓰기 및 구문 색상 지정에 도움이 되는 좋은 편집기를 활용하는 경우 특히 그렇습니다(괄호를 배경과 매우 유사한 색상으로 설정해 보세요).

언어를 완전히 대체하고 'Ruby' 구문을 얻을 수는 없지만 필요하지는 않습니다.언어 유연성 덕분에 원하는 경우 '루비 프로그래밍 스타일'을 따르는 것처럼 느껴지는 방언을 사용하지 않아도 됩니다.

나는 이것이 단지 경험적 관찰이라는 것을 알고 있지만, 이것을 깨달았을 때 Lisp 깨달음의 순간이 있었던 것 같습니다.

계속해서 Lisp에 새로 온 사람들은 "모든 괄호를 제거하기를 원합니다." 몇 주 동안 지속됩니다.프로그래머는 현재 "괄호"로 인식하는 것을 선호하기 때문에 일반적인 S-Expression Parser 위에 심각한 범용 프로그래밍 구문을 구축하는 프로젝트는 없습니다. 익숙해지는 데 약간의 시간이 걸리지 만 많지는 않습니다!일단 익숙해지면 기본 구문의 가소성을 실제로 이해할 수 있으며, 특정 프로그래밍 구조를 표현하는 방법이 단 한 가지인 언어로 돌아가는 것은 정말 짜증나는 일입니다.

즉, Lisp는 도메인별 언어를 구축하기 위한 탁월한 기반입니다.XML보다 낫지는 않더라도 그만큼 좋습니다.

행운을 빌어요!

내가 본 Lisp 매크로에 대한 가장 좋은 설명은 다음과 같습니다.

https://www.youtube.com/watch?v=4NO83wZVT0A

55분쯤부터 시작합니다.최고의 Lisp 교과서인 "Practical Common Lisp"의 저자인 Peter Seibel의 강연 영상입니다.

Lisp 매크로에 대한 동기는 일반적으로 설명하기 어렵습니다. 왜냐하면 간단한 튜토리얼에서 제시하기에는 너무 긴 상황에서 실제로 그 자체로 나타나기 때문입니다.Peter는 훌륭한 예를 제시합니다.당신은 그것을 완전히 이해할 수 있고 Lisp 매크로를 적절하고 적절하게 사용할 수 있습니다.

귀하는 다음과 같이 질문했습니다."LISP의 기능적 특성을 보다 객체 지향적인 구문 및 의미론으로 변경할 수 있습니까?"대답은 '예'입니다.사실 Lisp에는 원래 객체 지향 프로그래밍이 전혀 없었습니다. Lisp가 객체 지향 프로그래밍 이전부터 존재했기 때문에 놀라운 일은 아닙니다!그러나 1978년에 우리가 OOP에 대해 처음 배웠을 때 우리는 무엇보다도 매크로를 사용하여 OOP를 Lisp에 쉽게 추가할 수 있었습니다.결국 Lisp에 우아하게 들어맞는 매우 강력한 객체 지향 프로그래밍 시스템인 CLOS(Common Lisp Object System)가 개발되었습니다.모든 것이 확장으로 로드될 수 있습니다. 아무것도 내장되어 있지 않습니다!매크로로 다 해결됐네요.

Lisp에는 언어의 표면 구문을 확장하는 데 사용할 수 있는 "리더 매크로"라는 완전히 다른 기능이 있습니다.리더 매크로를 사용하면 C와 유사한 구문이나 Ruby와 유사한 구문을 갖는 하위 언어를 만들 수 있습니다.그들은 내부적으로 텍스트를 Lisp로 변환합니다.이는 대부분의 실제 Lisp 프로그래머가 널리 사용하지 않는데, 주로 새로운 구문을 이해하기 위해 대화형 개발 환경을 확장하기가 어렵기 때문입니다.예를 들어, Emacs 들여쓰기 명령은 새로운 구문으로 인해 혼동될 수 있습니다.하지만 열정적이라면 Emacs도 확장 가능하므로 새로운 어휘 구문에 대해 가르칠 수 있습니다.

일반 매크로는 개체 목록에서 작동합니다.가장 일반적으로 이러한 개체는 다른 목록(따라서 트리를 형성함) 및 기호이지만 문자열, 해시 테이블, 사용자 정의 개체 등과 같은 다른 개체일 수도 있습니다.이러한 구조를 s-exp.

따라서 소스 파일을 로드하면 Lisp 컴파일러가 텍스트를 구문 분석하고 s-exp를 생성합니다.매크로는 이에 대해 작동합니다.이것은 훌륭하게 작동하며 s-exps의 정신 내에서 언어를 확장하는 놀라운 방법입니다.

또한 앞서 언급한 구문 분석 프로세스는 컴파일러가 텍스트를 s-exp로 변환하는 방식을 사용자 정의할 수 있는 "리더 매크로"를 통해 확장될 수 있습니다.그러나 나는 Lisp의 구문을 다른 것으로 바꾸는 대신 수용할 것을 제안합니다.

Lisp의 "기능적 특성"과 Ruby의 "객체 지향 구문"을 언급하면 ​​약간 혼란스러워 보입니다."객체 지향 구문"이 무엇인지 잘 모르겠지만 Lisp는 다중 패러다임 언어이며 객체 지향 프로그래밍을 지원합니다. 극도로 잘.

그나저나, 내가 Lisp라고 하면 내 말은 커먼 리스프.

편견을 버리시길 권합니다 Lisp에게 솔직하게 말해주세요.

괄호 지옥?다음 항목에는 더 이상 괄호가 없습니다.

(function toto)

다음보다:

function(toto);

그리고

(if tata (toto)
  (titi)
  (tutu))

이하:

if (tata)
  toto();
else
{
  titi();
  tutu();
}

나는 괄호가 적고 ';' 그렇지만.

당신이 묻는 것은 당신이 좋아하는 초콜릿 케이크에서 지옥 같은 갈색 재료를 모두 제거할 수 있도록 전문 초콜릿 제조자가 되는 방법을 묻는 것과 다소 비슷합니다.

예, 근본적으로 구문을 변경할 수 있으며 "괄호 지옥"을 피할 수도 있습니다.이를 위해서는 새로운 판독기 구문을 정의해야 합니다.리더 매크로를 살펴보세요.

그러나 나는 그러한 매크로를 프로그래밍하기 위한 Lisp 전문 지식 수준에 도달하려면 더 이상 괄호를 "지옥"이라고 생각하지 않을 정도로 언어에 몰입해야 한다고 생각합니다.즉.당신이 그것을 피하는 방법을 알게 되면, 당신은 그것을 좋은 것으로 받아들이게 될 것입니다.

Lisp를 Ruby처럼 보이게 하려면 Ruby를 사용하세요.

Ruby(및 Python)를 매우 lisp와 같은 방식으로 사용하는 것이 가능하며 이는 Ruby가 그렇게 빨리 수용된 주요 이유 중 하나입니다.

리더 매크로가 XML 템플릿과 같은 복잡한 작업으로 Lisp 리더를 확장할 수 있는 방법에 대한 다음 예를 참조하세요.

http://common-lisp.net/project/cl-quasi-quote/present-class.html

이것 사용자 라이브러리 XML의 정적 부분을 컴파일 타임에 네트워크 스트림에 쓰기 순서대로 사용할 준비가 된 UTF-8로 인코딩된 리터럴 바이트 배열로 컴파일합니다.그리고 그들은 일반적인 lisp 매크로에서 사용할 수 있으며 직교합니다...쉼표 문자의 배치는 어떤 부분이 상수이고 어떤 부분이 런타임에 평가되어야 하는지에 영향을 줍니다.

자세한 내용은 다음에서 확인할 수 있습니다. http://common-lisp.net/project/cl-quasi-quote/

Common Lisp 구문 확장을 위한 또 다른 프로젝트: http://common-lisp.net/project/cl-syntax-sugar/

@스파크스

때때로 LISP는 Emacs 확장이라는 명확한 언어 선택입니다.원한다면 Ruby를 사용하여 Emacs를 확장할 수도 있겠지만, Emacs는 LISP로 확장되도록 설계되었기 때문에 그런 상황에서는 사용하는 것이 타당할 것 같습니다.

까다로운 질문입니다.lisp는 이미 구조적으로 구문 분석 트리에 너무 가깝기 때문에 많은 수의 매크로와 구문 분석기 생성기에서 자신만의 미니 언어를 구현하는 것 사이의 차이가 그다지 명확하지 않습니다.그러나 열고 닫는 괄호를 제외하면 lisp와 전혀 닮지 않은 결과를 쉽게 얻을 수 있습니다.

내 마음을 사로잡은 매크로의 용도 중 하나는 DB에 대한 SQL 요청의 컴파일 타임 확인이었습니다.

컴파일 타임에 전체 언어를 사용할 수 있다는 사실을 알게 되면 흥미롭고 새로운 관점이 열립니다.이는 또한 흥미롭고 새로운 방식으로 자신의 발을 쏠 수 있음을 의미합니다(예: 재현할 수 없는 렌더링 컴파일은 매우 쉽게 디버깅의 악몽으로 바뀔 수 있음).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top