수색…
S- 표현
Scheme의 표현식이 실행될 것입니다. 그것이 보통이라고 같이 S-표현은 시작 ( 과로 끝 ) . 표현식의 첫 번째 구성원은 실행될 것입니다. 표현식의 다음 구성원은 표현식을 평가하는 동안 표현식에 전송 될 매개 변수입니다.
예를 들어 숫자 추가 :
(+ 1 2 3)
이 경우 + 는 여러 매개 변수를 사용하는 add 함수의 심볼입니다. 1 , 2 및 3 은 + 기능으로 전송됩니다.
S-Expression은 다음 예와 같이 S-Expressions을 매개 변수로 포함 할 수 있습니다.
(if (< x y)
x
y)
어느처럼 읽을 수 x 보다 작은 y 반환 x 그렇지 않은 경우의 y . 이 예제에서는 해결 된 값에 따라 조건식을 평가합니다. x 또는 y가 반환됩니다. 이것으로 평가 될 수있다.
(if #t x y)
x
(if #f x y)
y
초보자를위한 덜 분명한 예는 S- 표현식을 S- 표현식의 첫 번째 구성원의 일부로 갖는 것입니다. 이 방법을 사용하면 동일한 매개 변수를 사용하여 분기를 만들지 않고도 호출 할 함수를 변경하여 메서드의 동작을 변경할 수 있습니다. 다음은 x가 y보다 작 으면 숫자를 더하거나 빼는 식의 간단한 예입니다.
((if (< x y) + -)
1 2 3)
x 가 y 보다 작 으면 표현식은 다음과 같이 평가됩니다.
(+ 1 2 3)
6
그렇지 않으면
(- 1 2 3)
-4
보시다시피 Scheme은 프로그래머가 복잡한 코드를 작성하는 동시에 프로그래머에게 코드 복제를 방지하는 도구를 제공합니다. 다른 언어들에서도 다음과 같이 쓰여진 동일한 예제를 볼 수 있습니다 :
(if (<xy) (+ 1 2 3) (- 1 2 3))
이 메소드의 문제점은 변경되는 유일한 메소드가 호출되는 동안 많은 코드를 복제한다는 것입니다. 이 예제는 매우 간단하지만 더 많은 조건을 사용하면 비슷한 유사한 행이 중복되는 것을 볼 수 있습니다.
단순한 매크로
scheme의 let 표현식은 실제로 매크로입니다. 그들은 람다 (lambdas)로 표현 될 수 있습니다. 간단한 let은 다음과 같이 보일 것입니다 :
(let ((x 1) (y 2))
(+ x y))
let 본체의 마지막 표현식 값이 리턴 될 때 3을 리턴합니다. 보시다시피, let-expression은 실제로 뭔가를 실행하고 있습니다. 이 코드 부분을 lambdas로 변환하면 다음과 같은 결과를 얻을 수 있습니다.
((lambda (x y) (+ x y)) 1 2)
여기서 우리는 익명의 lambda를 1과 2로 직접 호출하는 것을 볼 수 있습니다. 따라서이 경우 결과는 3입니다.
이를 염두에두고, 우리는 let 표현식이 두 부분으로 구성된다는 것을 이해합니다. 그것은 람다와 같은 매개 변수와 몸체를 가지고 있지만 차이점은 let 표현식이 평가 직후에 호출된다는 것입니다.
let 표현식이 추상보기에서 구체적보기로 어떻게 작동하는지 설명하려면, 다음과 같이 보일 것입니다.
(let params body ...)
(let (param1 param2 ...) body ...)
(let ((p1 val1) (p2 val2) ...) body ...)
매개 변수는 let 의 본문에 사용될 쌍 (name value) 목록입니다.
표현식을 사용하는 이유는 무엇입니까?
표현식은 언어와 같은 변수의 초기화와 마찬가지로 메소드에 변수를 저장하는 데 특히 유용합니다. 그것은의 사용에 유리한 define 때문에하자 표현에서, 변수는 실제로 현재 실행 환경에 변수를 추가하고 정의 사용 ... 사라 졌어요. 전역 환경에 추가 된 변수는 제거 할 수 없습니다. 표정을 어디서나 사용하는 것이 안전하다고하자. 또한 부모 범위를 건드리지 않고 고스트 변수에 사용될 수 있습니다.
예 :
(let ((x 1))
(let ((x 2) (y x))
(display x)
(display y))
(display x))
그것은 인쇄 할 것이다 :
2
1
1
이 경우 x 는 1로 정의되고 두 번째 let 의 x 값은 2 로 고시됩니다. 변수 y 는 상위 범위의 값 x 로 시작됩니다. 내부 let 표현식이 실행 된 후, x 의 초기 값이 1로 표시됩니다. 내부 let 표현식은 상위 범위의 값을 변경하지 않습니다.
변수를 초기화해야 할 때마다 let 식을 다음과 같이 사용해야합니다.
(let (
(user (get-current-user session))
(db (get-current-db session))
(ids (get-active-ids session))
)
(mark-task-completed db user ids)
(change-last-logged db user)
(db-commit db))
여기이 예제에서 변수는 초기화되고 코드 블록에서 여러 번 사용됩니다. let식이 끝나면 변수는 더 이상 필요 없으므로 자동으로 해제됩니다.
쌍의 점으로 구분 된 구문
cons 생성자를 사용하는 것보다 좀 더 컴팩트 한 방법으로 cons cell을 작성하는 특별한 구문이 있습니다.
쌍은 다음과 같이 작성할 수 있습니다.
'(1 . 2) == (cons 1 2)
큰 차이점은 따옴표를 사용하여 pairs 을 만들 수 있다는 것입니다. 그렇지 않으면 Scheme이 적절한 목록을 만듭니다 (1 . (2 . '())) .
도트 구문을 사용하면 표현식에 2 명의 구성원 만 포함됩니다. 각 구성원은 쌍을 포함하여 모든 유형이 될 수 있습니다.
'(1 . (2 . (3 . 4)))
> (1 2 3 . 4)
목록의 마지막 쌍의 cdr 이 빈 목록 '() 이 아니라는 것을 보여주기 위해 끝에 부적절한 목록이 점으로 표시되어야합니다.
리스트를 보여주는 이런 방식은 때때로 다음 표현이 기대할 수없는 것처럼 표현되기 때문에 언젠가는 혼란 스럽습니다.
'((1 . 2) . ( 3 . 4))
> ((1 . 2) 3 . 4)
이후 목록은 일반적으로 건너 뜁니다 . , 목록의 첫 번째 인수는 (1 . 2) , 두 번째 인수는 3 되지만 목록이 부적절하므로 마지막 인수가 . 목록의 마지막 요소가 '() 이 아님을 보여줍니다. 데이터가 다른 방식으로 표시 되더라도 내부 데이터는 생성 된 그대로입니다.