2011-04-20 7 views
7

그렇게 할 수 있습니까? 리스트의 마지막 요소를 얻고 자 할 때 변수 i = 0을 만들고 길이가 같아 질 때까지 증가시킬 것이라고 가정 해 봅시다. 어떤 생각? 예를 들어 주시면 감사하겠습니다.Scheme 함수 내에서 변수를 선언하는 방법은 무엇입니까?

감사합니다.

+1

마지막 요소를 얻으려면 어떤 알고리즘을 염두에 두셨습니까? –

+0

@larsmans : 'i'가 길이와 같을 때까지 목록을 탐색 하시겠습니까? 그것은 Scheme에서 합리적으로 들리는가? – Chan

+0

목록을 두 번 통과하기 때문에 낭비가됩니다. 처음으로 길이를 계산합니다. 알고리즘은 선형 시간 (@ sepp2k이 가정 할 때 2 차가 아닌)이지만 2 패스가 아니라 관용적입니다. –

답변

11

변수를 선언하는 데는 여러 가지 방법이 있습니다. 깨끗한 사람은 let입니다 :

(let ((x some-expr)) 
    ; code block that uses x 

그러나 당신은리스트의 마지막 요소를 얻을이 필요하지 않습니다. 그냥 재귀를 사용

(define (last xs) 
    (if (null? (cdr xs)) 
    (car xs) 
    (last (cdr xs)))) 

참고 : 당신이 원하는 경우에, 당신의 결과 cdr 캐시 변수를 사용할 수 있습니다

(define (last xs) 
    (let ((tail (cdr xs))) 
    (if (null? tail) 
     (car xs) 
     (last tail)))) 
+0

많은 감사, 아주 좋은 솔루션! 그건 그렇고, 위의 if 문에 대해서는 약간 혼란 스럽습니다. '마지막 꼬리'는 'if'에 속하는가 아니면 별도의 선언문인가? 우리는 어떻게 구별 할 수 있습니까? – Chan

+1

@Chan :'(마지막 꼬리)'는'if' 표현식의 else 부분입니다. 괄호와 들여 쓰기로 알 수 있습니다. –

3

네,이 계획에서 지역 변수를 정의하는 것이 가능, 중 사용 let 또는 함수 내에서 define. set!을 사용하면 상상할 수있는 변수를 재 할당 할 수도 있습니다.

이렇게 말하면 아마도 이런 식으로 문제를 해결하면 안됩니다. Scheme에서는 필요하지 않을 때 set!을 피하는 것이 일반적으로 좋은 습관입니다 (이 경우에는 꼭 할 필요가 없습니다). 인덱스를 사용하여 목록을 반복하는 것은 일반적으로 스키마 목록이 링크 목록이고 랜덤 액세스 O (n) (last 기능을 구현하려는 경우 O(n^2)처럼) 때문에 나쁜 생각입니다.

따라서 인덱스가없는 단순한 재귀 적 구현은 사용자가 계획하고있는 것보다 더 관용적이며 빠르다.

+1

감사합니다. 내 문제는 목록에서 마지막 요소를 제거하는 것입니다. 목록을 뒤집은 다음 첫 번째 요소를 제거 할 수는 있지만 너무 비효율적 인 것으로 보입니다. Scheming에서 생각하는 것은 C 나 C++ 같은 다른 전통적인 언어와 비교하여 완전히 이상합니다. – Chan

+0

'set! '을 사용하는 것 외에 Scheme에서 변수를 재정의하는 다른 방법이 있습니까? –

관련 문제