평가 모델을 더 잘 이해하기 위해 정의를 가지고 놀고 목록의 길이에 대해 두 개를 썼습니다.왜 엄격한 길이 함수가 현저하게 빠르게 수행됩니까?
순진 정의 :
len :: [a] -> Int
len [] = 0
len (_:xs) = 1 + len xs
엄격한 (꼬리 재귀) 정의 :
slen :: [a] -> Int -> Int
slen [] n = n
slen (_:xs) !n = slen xs (n+1)
len [1..10000000]
수행 5-6 초 정도 걸립니다.
slen [1..10000000] 0
은 수행하는 데 약 3-4 초가 걸립니다.
이유가 궁금합니다. 공연을 확인하기 전에 나는 len
에 최대로 평가할 수있는 썽크가 하나 밖에 없기 때문에 같은 것을 수행 할 것이라고 확신했습니다.
len [a,b,c,d]
= 1 + len [b,c,d]
= 1 + 1 + len [c,d]
= 1 + 1 + 1 + len [d]
= 1 + 1 + 1 + 1 + len []
= 1 + 1 + 1 + 1 + 0
= 4
그리고 눈에 띄게 빨라 slen
하게 무엇
slen [a,b,c,d] 0
= slen [b,c,d] 1
= slen [c,d] 2
= slen [d] 3
= slen [] 4
= 4
: 데모 목적을 위해?
P. 또한 tail-recursive lazy 함수 (그냥 slen
와 같은)를 닫으려는 시도를했습니다. 어쩌면 tail-recursive 때문일 수도 있지만, 순진한 정의와 거의 동일하게 수행되었습니다.
마지막 단계 인 len은 O (1)가 아닙니다. n 개의 숫자를 더하는 것은 O (n)입니다. 'slen'은 또한 O (n) 메모리를 사용하고, len은 O (1) 메모리를 사용합니다. –
@DavidYoung 오 ~ 알았어! 답으로 쓰실 것을 환영합니다. 당신은 또한 메모리 소비를 설명 할 수 있습니까? (또는 내가 그것을 더 이해할 수있는 곳으로의 참조). 고마워요! – MasterMastic
죄송합니다, 나는 그것을 뒤로 가지고 있습니다. 'len'은 O (n) 메모리를 사용하고'slen'은 O (1) 메모리를 사용합니다. –