2012-01-11 3 views
12

나는 다음으로 Clojure를하고 의아해을 배우고했습니다 의아해 : Clojure for for 루프 : while -> 예기치 않은 동작?

user=> (for [a (range 1 4) b (range 1 4)] [a b]) 
([1 1] [1 2] [1 3] [2 1] [2 2] [2 3] [3 1] [3 2] [3 3]); _no surprise here_ 

내가 조건이 거짓이면 루프를 중단해야으로 빈리스트를 볼 것으로 예상,의는 :while (not= a b)을 추가 할 수 있습니다. 이 경우 첫 번째 항목은 a = b = 1입니다. 보자 :

user=> (for [a (range 1 4) b (range 1 4) :while (not= a b) ] [a b]) 

([2 1] [3 1] [3 2]) ; _surprise!_ 

:while:when에이 (= a b)

를 필터링 변경
user=> (for [a (range 1 4) b (range 1 4) :when (not= a b) ] [a b]) 
([1 2] [1 3] [2 1] [2 3] [3 1] [3 2]); _expected_ 

아무도 설명 할 수 왜 이런 (for [ ... :while ..] ...) 동작합니다?

내가

OS X의

에 Clojure의 1.3을 사용하고 있습니다 감사합니다 및 서식의 부족을 끼쳐 드려 죄송합니다. 이것은 내 StackOverflow 처녀 게시물입니다.

답변

9

각 반복을 살펴 보겠습니다.

a = 1 
    b = 1 -> a == b, break because of while 

a = 2 
    b = 1 -> a != b, print [2 1] 
    b = 2 -> a == b, break because of while 

a = 3 
    b = 1 -> a != b, print [3 1] 
    b = 2 -> a != b, print [3 2] 
    b = 3 -> a == b, break because of while 
+0

감사합니다. Nikita. 따라서 : 내부 루프에만 적용되는 동안 외부 루프에도 적용하려면 어떻게해야합니까? 내가 가진 문제는 : ([: a : b : c : d : e : f]에서 [: a : b : c : d : e : f] : [path (find-path ab)] : while 경로) 경로); 경로가 nil 일 때 루프가 중지되어야합니다. – jbear

+0

죄송합니다. 죄송합니다. [path [find a path from to] [~ : : a : b : c : d : e : ] : while path] path) – jbear

+0

@jbear, 나도 몰라 :(당신이 경로의 게으른 seq을 생성하고 그들이 null이 아닌 동안 취하는 게 좋을지 모르겠다. 'for'가 게으르다는 것이 확실하지 않다. –

3

for:while 조건은 가장 안쪽 루프를 종료한다. 나는 for를 항상 사용한다, 그러나 :while 이렇게 드물게 나는 결코 이것을 깨닫지 않았다; 큰 질문에 감사드립니다!

슬프게도 난 당신이 할 수있는 최선의 당신이 반복하고있는 입력 시퀀스 중 하나가 아닌 정지 카운터 출력 시퀀스에 "글로벌"중지 - 카운터를 원하는 때문에, for 주위에 take-while 포장 생각 위에. 예 :

(->> (for [a (range 1 4) 
      b (range 1 4)] 
     [a b]) 
    (take-while (fn [[a b]] (not= a b)))) 

() 
+1

': while' 테스트는 그 바로 앞의 순서에 적용됩니다. 반드시 가장 안쪽의 루프가 아닌 –

+0

명확한 설명을 해주신 Alex에게 감사드립니다. 기본 구성 블록 중 하나 인 _list comprehension_이 다소 제한적일 것이라는 점에 다소 실망한 느낌이 들었습니다. 학습이 진행되면서 도움이되는 방법을 발견 할 수 있기를 바랍니다. 모두로부터. – jbear

+0

@ jbear 실제로는이 방법보다 제한이 적습니다. 다른 방법으로 uld. 이렇게하면 "글로벌"동작을 원할 경우'take-while '식에'for' 식을 쉽게 래핑 할 수 있습니다. 그러나 "글로벌"행동이'for/: while'을 위해 이루어진 것이라면 어떻게 현재의 "중간"행동을 되 찾을 수 있습니까? 당신은 완전히 for를 포기하고 map, mapcat, filter, take-while의 쥐 둥지를 만들어야합니다. – amalloy