Clojure에“기호”외에“키워드”가있는 이유는 무엇입니까?


130

나는 다른 Lisps (특히 Scheme)에 대한 지식을 가지고 있습니다. 최근에 Clojure 에 대해 읽었습니다 . "기호"와 "키워드"가 모두있는 것을 알 수 있습니다. 익숙하지만 키워드에는 익숙하지 않은 기호.

다른 Lisp에 키워드가 있습니까? 다른 표기법 (예 : 콜론)이 아닌 다른 키워드와 기호가 어떻게 다른가요?


답변:


139

키워드 및 기호에 대한 Clojure 설명서 는 다음과 같습니다 .

키워드는 스스로 평가되는 기호 식별자입니다. 그들은 매우 빠른 평등 테스트를 제공합니다 ...

기호는 일반적으로 다른 것을 나타내는 데 사용되는 식별자입니다. 그들은 함수 매개 변수를 참조하고 바인딩, 클래스 이름 및 전역 변수를 참조하도록 프로그램 형태로 사용할 수 있습니다 ...

키워드는 일반적으로 가벼운 "일정한 문자열"로 사용됩니다 (예 : 해시 맵의 키 또는 멀티 메소드의 디스패치 값). 기호는 일반적으로 변수와 함수의 이름을 지정하는 데 사용되며 매크로 등을 제외하고 직접 개체로 조작하는 것은 일반적이지 않습니다. 그러나 키워드를 사용하는 모든 곳에서 기호를 사용하는 것을 막을 수있는 것은 없습니다 (항상 인용하는 것이 마음에 들지 않는 경우).

차이를 볼 수있는 가장 쉬운 방법은 읽을 수 Keyword.javaSymbol.javaClojure의 소스에서. 몇 가지 명백한 구현 차이가 있습니다. 예를 들어 Clojure의 Symbol에는 메타 데이터가 있고 키워드에는 없습니다.

단일 콜론 구문 외에도 이중 콜론을 사용하여 네임 스페이스로 한정된 키워드를 만들 수 있습니다.

user> :foo
:foo
user> ::foo
:user/foo

일반적인 Lisp에는 Ruby 및 기타 언어와 마찬가지로 키워드가 있습니다. 물론 해당 언어에서는 약간 다릅니다. 공통 Lisp 키워드와 Clojure 키워드의 일부 차이점 :

  1. Clojure의 키워드는 기호가 아닙니다.

    user> (symbol? :foo)  
    false
  2. 구체적으로 규정하지 않은 키워드는 네임 스페이스에 속하지 않습니다.

    user> (namespace :foo)
    nil
    user> (namespace ::foo)
    "user"

( 볼만한 것들에 대한 아이디어를 주신 Rainer Joswig 에게 감사드립니다 .)


10
이것은 차이점이 무엇인지 설명 하지만 두 가지 다른 구성이 필요한 이유는 아닙니다. Clojure가 키워드와 기호의 기능을 통합하여 무언가를 만들 수 없었습니까?

25
키워드는 가볍고 편리한 구문을 가지고 있습니다. 언어는 그들 없이는 잘 작동하지만 가지고 있기는 좋으며 매우 널리 사용됩니다. 키워드는 항상 자체 평가 (예 : 변수 또는 함수 이름으로 사용할 수 없음)하고 일반적으로 기호는 항상 자체 평가할 수 없으므로 해당 기능을 통합 할 수 없습니다.
Brian Carper

1
: 키워드가 평가하면 그들이 변경하지 않는 한 HashMaps을 등의 키와 같은 더 유용한 것 같다 (eval (eval ':a))(eval (eval ''a)). 다른 장점이 있습니까? 현명한 성능, 그들은 동일합니까?
kristianlm

5
(동일? : qwe : qwe)-> true. (동일? 'qwe'qwe)-> 거짓. 기호는 내부에 문자열을 사용하므로 비교도 빠릅니다.
dedesudes

29

공통 Lisp 에는 키워드 기호가 있습니다.

키워드도 상징입니다.

(symbolp ':foo) -> T

키워드를 특별하게 만드는 이유 :

  • : foo는 Common Lisp 판독기에서 symbol 키워드 :: foo로 구문 분석됩니다.
  • 키워드는 다음과 같이 평가됩니다. : foo-> : foo
  • 키워드 기호의 홈 ​​패키지는 키워드 패키지입니다. keyword : foo-> : foo
  • 키워드 KEYWORD에서 키워드를 내 보냅니다.
  • 키워드는 상수이며 다른 값을 할당 할 수 없습니다

그렇지 않으면 키워드는 일반적인 기호입니다. 키워드는 함수의 이름을 지정하거나 속성 목록을 가질 수 있습니다.

기억하십시오 : 공통 Lisp 기호는 패키지에 속합니다. 이것은 다음과 같이 쓸 수 있습니다 :

  • foo, 현재 패키지에서 기호에 액세스 할 수있는 경우
  • 패키지 BAR에서 FOO 기호를 내보낼 때 foo : bar
  • FOO 기호가 패키지 BAR에있을 때 foo :: bar

키워드 기호의 경우 : foo, keyword : foo 및 keyword :: foo는 모두 동일한 기호입니다. 따라서 후자의 두 표기법은 일반적으로 사용되지 않습니다.

따라서 : foo는 심볼 이름 앞에 패키지 이름을 지정하지 않으면 기본적으로 KEYWORD 패키지를 의미한다고 가정하고 패키지 KEYWORD에 포함되도록 구문 분석됩니다.


6

키워드는 자체 평가되는 기호이므로 따로 인용 할 필요가 없습니다.


5
그게 다야? 타이핑 : '보다는 오히려 큰 승리처럼 보이지 않습니다. 특히 이후 : 대부분의 키보드에서 추가 키 누르기입니다.
Laurence Gonsalves

11
글쎄, 그것은 단순히 캐릭터 그 이상입니다. 키워드는 평가 후에도 키워드를 유지하지만, 기호는 바인딩 할 때마다 평가됩니다. 그것들은 일반적으로 다른 목적으로 사용되기 때문에 의미상의 차이와 비슷합니다.
Greg Hewgill

13
키워드 Clojure의 심볼 없습니다
데이비드 Plumpton

4

: 키워드는 많은 컬렉션에서 특별히 처리되므로 실제로 편리한 구문을 사용할 수 있습니다.

(:user-id (get-users-map))

와 같다

((get-users-map) :user-id)

이렇게하면 일이 좀 더 유연 해집니다.


21
( 'a {'a 1 'b 2}) => 1 및 ({'a 1 'b 2}'b) => 2 기호의 경우에도 마찬가지입니다.
Jonas

4

키워드의 경우 키워드를 처음 구성 할 때 해시 값이 계산되고 캐시됩니다. 키워드를 해시 키로 검색하면 미리 계산 된 해시 값을 반환합니다. 문자열 및 기호의 경우 모든 조회에서 해시가 다시 계산됩니다.

동일한 이름의 키워드가 항상 동일한 이유에는 자체 해시 값이 포함됩니다. 맵과 세트의 검색은 해시 키로 만들어 지므로 검색 자체가 아닌 수많은 검색의 경우 검색 효율성이 향상됩니다.


0

키워드는 전역 이며 기호는 다릅니다 .

이 예제는 JavaScript로 작성되었지만 요점을 파악하는 데 도움이되기를 바랍니다.

const foo = Symbol.for(":foo") // this will create a keyword
const foo2 = Symbol.for(":foo") // this will return the same keyword
const foo3 = Symbol(":foo") // this will create a new symbol
foo === foo2 // true
foo2 === foo3 // false

Symbol함수를 사용하여 심볼을 구성 할 때 마다 고유 / 개인 심볼이 나타납니다. Symbol.for함수 를 통해 기호를 요청하면 매번 같은 기호가 나타납니다.

(println :foo) ; Clojure
System.out.println(RT.keyword(null, "foo")) // Java
console.log(System.for(":foo")) // JavaScript

이것들은 모두 같습니다.


함수 인수 이름은 로컬입니다. 즉 키워드가 아닙니다.

(def foo (fn [x] (println x))) ; x is a symbol
(def bar (fn [x] (println x))) ; not the same x (different symbol)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.