Scheme에서 eq ?, eqv ?, equal ?, =의 차이점은 무엇입니까?
그 작업의 차이점이 무엇인지 궁금합니다. Stack Overflow에서 비슷한 질문을 보았지만 Lisp에 관한 질문이며 세 연산자 사이에 비교가 없습니다. 그러니 이미 질문이 있으시면 알려주세요.
Scheme에서 다양한 유형의 명령을 작성하고 있는데 다음과 같은 출력이 나타납니다.
(eq? 5 5) -->#t
(eq? 2.5 2.5) -->#f
(equal? 2.5 2.5) --> #t
(= 2.5 2.5) --> #t
누군가 이것이 왜 그런지 설명 할 수 있습니까?
이 질문에 점진적으로 대답하겠습니다. =
동등성 술어 부터 시작하겠습니다 . =
조건은 두 개의 번호가 동일한 지 여부를 확인하는 데 사용됩니다. 숫자가 아닌 다른 값을 제공하면 오류가 발생합니다.
(= 2 3) => #f
(= 2.5 2.5) => #t
(= '() '()) => error
eq?
술어는 두 개의 파라미터 메모리에 동일한 객체를 respresent 여부를 확인하는데 사용된다. 예를 들면 :
(define x '(2 3))
(define y '(2 3))
(eq? x y) => #f
(define y x)
(eq? x y) => #t
그러나 '()
메모리에는 빈 목록이 하나뿐입니다 (실제로 빈 목록은 메모리에 존재하지 않지만 메모리 위치에 대한 포인터 0
는 빈 목록으로 간주됩니다). 따라서 빈 목록 eq?
을 비교할 때 항상 반환됩니다 #t
(메모리에서 동일한 객체를 나타 내기 때문에).
(define x '())
(define y '())
(eq? x y) => #t
이제 구현에 따라 숫자, 문자열 등과 같은 기본 값에 대해 eq?
반환하거나 반환하지 않을 수 있습니다 #t
. 예를 들면 다음과 같습니다.
(eq? 2 2) => depends upon the implementation
(eq? "a" "a") => depends upon the implementation
이것이 eqv?
술어가 등장하는 곳 입니다. 은 eqv?
정확히 동일하다 eq?
항상 반환하는 것을 제외하고, 조건 #t
같은 원시 값. 예를 들면 :
(eqv? 2 2) => #t
(eqv? "a" "a") => depends upon the implementation
따라서 eqv?
의 상위 집합입니다 eq?
당신이 사용해야하는 대부분의 경우 eqv?
대신은 eq?
.
마지막으로 equal?
술어에 도달합니다 . equal?
술어는 정확히 동일하다 eqv?
또한 두 그룹, 벡터 등이 만족 요소 대응 여부를 테스트하는데 사용될 수 있다는 것을 제외하고는, 술어 eqv?
술어. 예를 들면 :
(define x '(2 3))
(define y '(2 3))
(equal? x y) => #t
(eqv? x y) => #f
일반적으로 :
=
두 숫자가 같은지 테스트 하려면 술어를 사용하십시오 .eqv?
두 개의 비 숫자 값이 동일한 지 여부를 테스트 하려면 술어를 사용하십시오 .equal?
두 목록, 벡터 등이 동일한 지 테스트 하려면 술어를 사용하십시오 .eq?
수행중인 작업을 정확히 알지 못하는 경우 술어를 사용하지 마십시오 .
.NET과 관련된 RNRS 사양에는 전체 두 페이지가 eq?, eqv?, equal? and =
있습니다. 다음은 R7RS 사양 초안 입니다. 확인 해봐!
설명:
=
숫자를 비교하면 2.5와 2.5는 수치 적으로 동일합니다.equal?
숫자가으로 감소하면=
2.5와 2.5는 수치 적으로 동일합니다.eq?
'포인터'를 비교합니다. Scheme 구현에서 숫자 5는 '즉시'(가능성)로 구현되므로 5와 5는 동일합니다. 숫자 2.5는 Scheme 구현에서 '부동 소수점 레코드'할당이 필요할 수 있지만 두 포인터는 동일하지 않습니다.
eq?
인 #t
은 동일한 어드레스 / 오브젝트 인 경우. 일반적으로 동일한 기호, 부울 및 객체에 대해 #t를 기대하고 값이 다르거 나 동일한 구조가 아닌 다른 유형의 값에 대해 #f를 기대할 수 있습니다. Scheme / Lisp 구현은 포인터에 유형을 포함하고 포함하는 전통을 가지고 있습니다. 충분한 공간이면 같은 공간에 값을 입력합니다. 따라서 일부 포인터는 실제로 주소가 아니라 char R
또는 Fixnum 과 같은 값 10
입니다. 다음은 될 것 eq?
"주소는"임베디드 형 + 값이 때문이다. 일부 구현은 불변 상수도 재사용합니다. (eq? '(1 2 3)'(1 2 3))은 해석 될 때 #f 일 수 있지만 동일한 주소를 얻을 수 있으므로 컴파일 할 때 #t 일 수 있습니다. (자바의 상수 문자열 풀처럼). 이 때문에eq?
지정되지 않으므로 #t 또는 #f로 평가되는지 여부는 구현에 따라 다릅니다.
eqv?
#t는 eq?
. 데이터가 너무 커서 포인터에 맞지 않는 경우에도 숫자 또는 문자이고 값이 동일하면 #t 입니다. 따라서 eqv?
해당 유형이 지원되는 유형 중 하나인지, 둘 다 동일한 유형이고 대상 객체의 데이터 값이 동일한 지 확인하는 추가 작업을 수행합니다.
equal?
eqv?
쌍, 벡터, 문자열 및 바이트 벡터와 같은 복합 유형 인 equal?
경우 부분에 대해 재귀 적으로 수행 하는 것과 동일한 일에 대해 #t입니다 . 실제로 두 개체가 동일하게 보이면 #t를 반환합니다 . R6RS 이전에는 equal?
원형 구조 에 사용 하는 것이 안전하지 않습니다.
=
is like eqv?
but it only works for numeric types. It might be more efficient.
string=?
is like equal?
, but it only works for strings. It might be more efficient.
equal?
recursively compares two objects (of any type) for equality.
Note this could be expensive for a large data structure since potentially the entire list, string, vector, etc must be traversed.
If the object just contains a single element (EG: number, character, etc), this is the same as
eqv?
.
eqv?
tests two objects to determine if both are "normally regarded as the same object".
eqv?
andeq?
are very similar operations, and the differences between them are going to be somewhat implementation specific.
eq?
동일 eqv?
하지만 더 미세한 구별을 식별 할 수 있으며 더 효율적으로 구현 될 수 있습니다.
- 사양에 따르면 이는 .NET의보다 복잡한 작업과 달리 빠르고 효율적인 포인터 비교로 구현 될 수 있습니다
eqv?
.
=
숫자가 같은지 숫자를 비교합니다.
- 두 개 이상의 숫자를 제공 할 수 있습니다. 예 :
(= 1 1.0 1/1 2/2)
스키마 구현에 대해서는 언급하지 않았지만 Racket에서는 eq?
인수가 동일한 객체를 참조하는 경우에만 true를 반환합니다. 두 번째 예는 시스템이 각 인수에 대해 새로운 부동 소수점 숫자를 생성하기 때문에 #f를 산출하는 것입니다. 그들은 같은 대상이 아닙니다.
equal?
및 =
가치 등가 확인되지만, =
숫자에만 적용됩니다.
If you're using Racket, check here for more information. Otherwise, check the documentation of your scheme implementation.
Think of eq?
as pointer equality. The authors of the Report want it to be as general as possible so they don't say this outright because it's implementation-dependent, and to say it, would favor the pointer-based implementations. But they do say
It will usually be possible to implement eq? much more efficiently than eqv?, for example, as a simple pointer comparison
Here's what I mean. (eqv? 2 2)
is guaranteed to return #t
but (eq? 2 2)
is unspecified. Now imagine a pointer-based implementation. In it eq?
is just pointer comparison. Since (eq? 2 2)
is unspecified, it means that this implementation is free to just create new memory object representation of each new number it reads from the source code. eqv?
must actually inspect its arguments.
OTOH (eq 'a 'a)
is #t
. This means that such implementation must recognize symbols with duplicate names and use the same one representation object in memory for all of them.
Suppose an implementation is not pointer-based. As long as it adheres to the Report, it doesn't matter. The authors just don't want to be seen as dictating the specifics of implementations to the implementors, so they choose their wording carefully.
This is my guess anyway.
So very coarsely, eq?
is pointer equality, eqv?
is (atomic-)values-aware, equal?
is also structure-aware (checks into its arguments recursively, so that finally (equal? '(a) '(a))
is required to be #t
), =
is for numbers, string=?
is for strings, and the details are in the Report.
'Program Club' 카테고리의 다른 글
실제 MySQL 쿼리 시간 측정 (0) | 2020.10.28 |
---|---|
AngularJS의 필터 내에서 매개 변수를 사용하는 방법은 무엇입니까? (0) | 2020.10.28 |
jQuery Chosen 드롭 다운 목록 지우기 및 새로 고침 (0) | 2020.10.28 |
HTTP 오류 429 (너무 많은 요청)를 피하는 방법 (0) | 2020.10.28 |
jQuery에서 React.js로 이동하는 방법은 무엇입니까? (0) | 2020.10.28 |