정적으로 형식화 된 전체 Lisp 변형이 가능합니까? 이와 같은 것이 존재하는 것이 의미가 있습니까? Lisp 언어의 장점 중 하나는 정의의 단순성이라고 생각합니다. 정적 입력이이 핵심 원칙을 손상시킬까요?
답변
예, 가능합니다. 표준 HM 스타일 유형 시스템은 일반적으로 대부분의 관용적 Lisp / Scheme 코드에 대해 잘못된 선택입니다. 정적 타이핑을 사용하는 “Full Lisp”(실제로 Scheme과 더 비슷 함) 인 최신 언어에 대해서는 Typed Racket 을 참조하십시오 .
답변
Lisp 처럼 보이는 정적으로 형식화 된 언어 만 원하는 경우 해당 언어 를 나타내는 추상 구문 트리를 정의한 다음 해당 AST를 S- 표현식으로 매핑하여 쉽게 수행 할 수 있습니다. 그러나 나는 결과를 Lisp라고 부르지 않을 것이라고 생각합니다.
구문 외에 실제로 Lisp-y 특성이있는 것을 원한다면 정적으로 형식화 된 언어로이를 수행 할 수 있습니다. 그러나 Lisp에는 많은 유용한 정적 타이핑을 얻기 어려운 많은 특성이 있습니다. 설명을 위해 Lisp의 기본 구성 요소를 형성하는 cons 라는 목록 구조 자체를 살펴 보겠습니다 .
단점을 목록이라고 부르는 것은 (1 2 3)
마치 하나처럼 보이지만 약간 잘못된 이름입니다. 예를 들어, C ++ std::list
또는 Haskell의 목록 과 같이 정적으로 형식화 된 목록과 전혀 비교할 수 없습니다 . 이들은 모든 셀이 동일한 유형 인 1 차원 연결 목록입니다. Lisp는 기꺼이 (1 "abc" #\d 'foo)
. 또한 정적 유형 목록을 목록 목록을 포함하도록 확장하더라도 이러한 개체 유형은 목록의 모든 요소가 하위 목록이어야합니다. 당신은 ((1 2) 3 4)
그들에게 어떻게 표현 하겠습니까?
Lisp conses는 잎 (원자)과 가지 (conses)가있는 이진 트리를 형성합니다. 또한, 그러한 나무의 잎은 어떤 원자 (비 죄수) Lisp 유형을 포함 할 수 있습니다! 이 구조의 유연성으로 인해 Lisp는 기호 계산, AST를 처리하고 Lisp 코드 자체를 변환하는 데 매우 능숙합니다!
그렇다면 정적으로 형식화 된 언어로 그러한 구조를 어떻게 모델링할까요? 매우 강력하고 정확한 정적 유형 시스템을 가진 Haskell에서 시도해 보겠습니다.
type Symbol = String
data Atom = ASymbol Symbol | AInt Int | AString String | Nil
data Cons = CCons Cons Cons
| CAtom Atom
첫 번째 문제는 Atom 유형의 범위입니다. 분명히, 우리는 우리가 빙빙 돌고 싶은 모든 유형의 물체를 포괄 할 수있는 충분한 유연성의 Atom 유형을 선택하지 않았습니다. 위에 나열된 Atom 데이터 구조를 확장하려고하는 대신 (분명히 깨지기 쉬운 Atomic
것을 알 수 있음) 원자로 만들고자하는 모든 유형을 구별 하는 마법 유형 클래스가 있다고 가정 해 보겠습니다 . 그런 다음 시도해 볼 수 있습니다.
class Atomic a where ?????
data Atomic a => Cons a = CCons Cons Cons
| CAtom a
그러나 이것은 트리의 모든 원자가 동일한 유형 이어야하기 때문에 작동하지 않습니다 . 우리는 그들이 잎마다 다를 수 있기를 바랍니다. 더 나은 접근 방식은 Haskell의 실존 적 수량 자를 사용해야합니다 .
class Atomic a where ?????
data Cons = CCons Cons Cons
| forall a. Atomic a => CAtom a
그러나 이제 당신은 문제의 핵심에 도달했습니다. 이런 종류의 구조에서 원자로 무엇을 할 수 있습니까? 모델링 할 수있는 공통 구조는 무엇입니까 Atomic a
? 이러한 유형으로 어떤 수준의 유형 안전성이 보장됩니까? 우리가 타입 클래스에 어떤 함수도 추가하지 않았 음을 주목하세요. 그리고 좋은 이유가 있습니다 : 원자들은 Lisp에서 공통점을 공유하지 않습니다. Lisp에서 그들의 슈퍼 타입은 단순히 t
(즉, top) 이라고 불립니다 .
그것들을 사용하기 위해서는 원자의 가치를 실제로 사용할 수있는 것으로 동적으로 강요 하는 메커니즘을 생각해 내야 합니다. 그리고 그 시점에서 기본적으로 정적으로 입력 된 언어 내에서 동적으로 입력 된 하위 시스템을 구현했습니다! ( Greenspun의 10 번째 프로그래밍 규칙에 대한 가능한 결과에 주목할 수밖에 없습니다 .)
하스켈은 바로 그러한에 대한 지원을 제공하는 참고 동적 서브 시스템 와 Obj
A를 함께 사용 유형, Dynamic
유형과 Typeable 클래스 우리의 교체 Atomic
임의의 값이 해당 유형으로 보존 할 수 있도록 클래스를, 이러한 유형의 명시적인 강제 백을. 이것이 Lisp cons 구조를 전체적으로 일반화하기 위해 사용해야하는 종류의 시스템입니다.
또한 할 수있는 작업은 다른 방식으로 이동하여 기본적으로 동적으로 형식화 된 언어 내에 정적으로 형식화 된 하위 시스템을 포함하는 것입니다. 이를 통해보다 엄격한 유형 요구 사항을 활용할 수있는 프로그램 부분에 대한 정적 유형 검사의 이점을 얻을 수 있습니다. 예를 들어 이것은 CMUCL의 제한된 형식의 정확한 유형 검사 에서 취한 접근 방식 인 것 같습니다 .
마지막으로 계약 스타일 프로그래밍을 사용하여 둘 사이의 전환을 탐색하는 데 도움이되는 동적 및 정적으로 형식화 된 두 개의 개별 하위 시스템을 가질 가능성이 있습니다. 이런 식으로 언어는 정적 유형 검사가 도움말보다 더 방해가되는 Lisp의 사용과 정적 유형 검사가 유리한 사용을 수용 할 수 있습니다. 이것은 다음 주석에서 볼 수 있듯이 Typed Racket이 취하는 접근 방식 입니다.
답변
내 대답은 높은 수준의 자신감이 없으면 아마도 . 예를 들어 SML과 같은 언어를보고 Lisp와 비교하면 각 기능의 핵심은 거의 동일합니다. 결과적으로 Lisp의 핵심 (함수 응용 프로그램 및 기본 값)에 어떤 종류의 정적 유형을 적용하는 데 큰 문제가없는 것 같습니다.
귀하의 질문은 완전 하다고 말하고 있으며 문제가 발생하는 부분은 코드로서의 데이터 접근 방식입니다. 유형은 표현식보다 더 추상적 인 수준에 존재합니다. Lisp에는 이러한 구분이 없습니다. 모든 것이 구조적으로 “평평”합니다. 어떤 식 E : T (여기서 T는 그 유형의 일부 표현)를 고려 하고이 식을 일반 ol ‘데이터로 간주하면 여기서 T의 유형은 정확히 무엇입니까? 글쎄, 그것은 종류입니다! 종류는 더 높은 순서 유형이므로 계속 진행하여 코드에서 이에 대해 말하겠습니다.
E : T :: K
당신은 내가 이것으로 어디로 가고 있는지 볼 수 있습니다. 코드에서 유형 정보를 분리함으로써 이러한 유형의 자기 참조를 피하는 것이 가능할 것이라고 확신합니다. 이 문제를 해결하는 방법에는 여러 가지가있을 수 있지만 어떤 방법이 가장 좋은지는 분명하지 않습니다.
편집 : 아, 그래서 약간의 인터넷 검색을 통해 Qi를 찾았 습니다. 정적으로 입력된다는 점을 제외하고 Lisp와 매우 유사합니다. 아마도 정적 타이핑을 얻기 위해 어디에서 변경했는지 확인하기 시작하는 것이 좋습니다.