문제
내가 다음 구조의 해석 컴퓨터 프로그램 고 시도하는 동안을 해결하 Ex1.3 에 도착했을 다음과 같은 코드를 처음으로 시도:
(define (sumsq a b c)(
(define highest (if (> (if (> a b) a b) (if (> a c) a c)) (if (> a b) a b) (if (> a c) a c)))
(define second_h (if (> (if (> a b) b a) (if (> a c) c a)) (if (> a b) b a) (if (> a c) c a)))
(+ (* highest highest) (* second_h second_h)))
그것은 작동하지 않고 그리고 해결책을 발견에서 그들을 SICP Wiki
;; ex 1.3
;; implemented using only techniques covered to this point
(define (square x) (* x x))
(define (sum-of-squares x y)
(+ (square x) (square y)))
(define (largest-two-of-three x y z)
(if (>= x y)
(sum-of-squares x (if (>= y z) y z))
(sum-of-squares y (if (>= x z) x z))))
차이었을 사용하여 여러 문에서 변수를 정의한 다음 합계,사각형하는 동안 올바른 방법으로 정의하는 각 라인으로 기능한다.
는 기능을 계획 중이너?또는 놓치지 않았다 모든 것은?
해결책
당신이 쓴 것 (추가 Paren)은 다음과 같습니다.
(define (sumsq a b c)
(define highest
(if (> (if (> a b) a b)
(if (> a c) a c))
(if (> a b) a b)
(if (> a c) a c)))
(define second_h
(if (> (if (> a b) b a)
(if (> a c) c a))
(if (> a b) b a)
(if (> a c) c a)))
(+ (* highest highest) (* second_h second_h)))
그들의 솔루션은 별도의 제곱과 제곱의 합계를 별도의 기능으로 수행하지만, 그것이 중요한 것이라고 생각하지 않습니다. 글을 쓰지 않습니다 (+ (* a a) (* b b))
~ 할 것이다 당신이 계산하는 두 값의 이름을 지정하지 못하도록 멈추면 마지막에 하나의 큰 표현으로 함수를 쓸 수 있지만 지금은 더 큰 것들이 있습니다.
나는 당신이 가지고있는 문제는 당신의 (만약 ...) 표현이 너무 크다는 것입니다. 여러 번 나타나는 두 가지 패턴이 있습니다. (if (> a b) a b)
그리고 (if (> a b) b a)
. 이것들은 최대 및 최소 함수이므로 다음과 같이 정의하는 것이 유용합니다.
(define (min a b) (if (< a b) a b))
(define (max a b) (if (< a b) b a))
이렇게하면 솔루션을 다음과 같이 다시 작성할 수 있습니다.
(define (sumsq a b c)
(define highest
(if (> (max a b) (max a c))
(max a b)
(max a c)))
(define second_h
(if (> (min a b) (min a c))
(min a b)
(min a c)))
(+ (* highest highest) (* second_h second_h)))
다시 단순화하면 다음과 같습니다.
(define (sumsq a b c)
(define highest
(max (max a b) (max a c)))
(define second_h
(max (min a b) (min a c)))
(+ (* highest highest) (* second_h second_h)))
이 글쓰기가 훨씬 더 쉬운 방법에 주목하십시오. (max (max a b) (max a c))
분명히 최대 값입니다 a
b
그리고 c
, 실제로 다시 작성할 수 있습니다 (max (max a b) c)
. 보고 있습니다 second_h
, 그러나 그것이 옳다는 것은 분명하지 않습니다. 언제 일어날 것인가 a
세 값 중 가장 작습니까?
그들이 솔루션에서 사용하는 트릭은 먼저 비교하는 것입니다. x
그리고 y
. 만약에 x < y
, 당신은 그것을 알고 있습니다 y
세 가지 중 가장 작지 않으므로 가장 높거나 두 번째로 최고입니다. 사용하려는 다른 숫자는 더 높습니다. x
그리고 z
,이 두 가지 중 낮은 사람은 당신이 무시하고자하는 세 가지 중 가장 작은 것입니다. 비슷한 논리가있을 때 적용됩니다 y < x
.
다른 팁
당신이 사용해야 하는 적절한 들여쓰기하고 줄 바꿈을 개요를 얻을 통해 귀하의 프로그램으로 흐릅니다.귀하의 첫 번째 제안을 읽은 다음과 같다:
(define (sumsq a b c) ((define highest (if (> (if (> a b) a b) (if (> a c) a c)) (if (> a b) a b) (if (> a c) a c))) (define second-h (if (> (if (> a b) b a) (if (> a c) c a)) (if (> a b) b a) (if (> a c) c a))) (+ (* highest highest) (* second-h second-h)))
첫번째 것을 사항:괄호가 일치하지 않;거기에 하나 더 많은 열었다 닫힙니다.신중 검사는 하나 괄호에서 두 번째 라인은 잘못된 것입니다.이것은,부수적으로,하나만 매달려의 끝에서 당신의 첫 번째 줄 수 있습니다.나는 것을 짐작할 때는 시도를 평가하이,아무 일도로 독자 기다렸다가 끝날의 문입니다.
적절한 압은 매우 중요합니다.내가 생각하는 SICP 지 않는 명시적으로 그것을 설명하지만,예를은 일반적으로 수행하는 이 방법입니다.내가 찾는 스타일 가이드 기.
두 번째 관찰당신은 자신을 반복을 많이합니다.에서 모든 사람들 중첩 if
문까지 여부를 당신이 정말로 가지고 오른쪽의 값이다.보 해결책을 발견하시는 방법이 매우 단순화될 수 있습니다.
당신도를 깨고 복잡성을 제공하여 subresults 이름입니다.깨는 복잡성은 좋지만,그것은 일반적으로 더 나은 이름은 결과가 아니지만,그 개념이 있습니다.생각이 무엇을 하는지 이름을 지정한 다음 이러한 활동입니다.사람들은 함수,그리고 그들의 언어는 당신이 마지막으로 거는 이제껏 당신의 문제를 해결합니다.
계획의 아이디어 중 하나는입니다 bottom-up programming
각 개념 작업에 대한 함수를 만듭니다. 이것이 많은 기능 프로그래밍 언어에서 권장되는 접근법입니다.
이 접근법을 통해 인수에 대해 하나의 논리적 작업을 구현하는 많은 작은 기능으로 끝납니다. 그렇게하면 코드가 훨씬 더 모듈화되고 깨끗합니다.
솔루션은이 양식을 가졌습니다. (정의 (func param) (정의 ...) (정의 ...))
그러나이 형태가 필요하다 : (정의 (func param) 본체)
본문은 기능의 구현입니다 ... 그것이하는 일, 반환하는 것입니다. 당신의 몸은 단지 더 많은 정의였습니다. 따라서 Scheme 통역사가 솔루션이 허용되지 않은 이유를 설명합니다.
"체계 기능은 1 라이너입니까?" 다음과 같이 보이는 "시작"양식을 조사해야합니다. (시작 (+ 1 1) (+ 2 2)) => 4
위의 예에서 (+ 1 1)의 결과는 방금 던져 지므로 시작이 부작용이있을 때만 시작되는 것을 볼 수 있습니다.
당신은 계획의 일부 (특히 Let and Lambda)가 그들의 몸 주위에 암시 적 시작을 가지고 있음을 알고 있어야합니다. 그래서 이것은 유효합니다.
(let ((x 1))
(+ 1 1)
(+ 2 2))
시작 없이도. 이로 인해 코드를 더 간단하게 작성합니다.
마지막으로, 학습 계획을 계속할 때 항상 시작과 부작용없이 무언가를 할 수있는 방법을 찾으십시오. 특히 대부분의 계획서의 처음 몇 장에서 "나는 그 변수를 설정하고 싶다면 이것을하고 싶다." 그것은 계획 방식입니다. 부작용에는 전혀 잘못된 것이 없지만, 그 중에 많이 사용하면 실제로 가장 잘 작동하는 방식으로 프로그래밍 체계가 아니라는 것을 의미합니다.
연습 1.3은 세 개의 숫자를 인수로 취하는 절차를 정의하고 두 개의 더 큰 숫자의 제곱 합을 반환하도록 요청합니다. 내장 체계 절차를 사용하는 것과 같은 절차를 쉽게 정의 할 수 있습니다. square
, max
, 그리고 min
, 그러나 우리는이 시점 에서이 절차를 아직 접하지 않았으므로 아직도 정의 할 것입니다.
(define (square x)
(* x x))
(define (max x y)
(if (> x y) x y))
(define (min x y)
(if (< x y) x y))
(define (sum-of-highest-squares x y z)
(+ (square (max x y))
(square (max (min x y) z))))
그만큼 sum-of-highest-squares
절차는 최대 x와 y의 제곱을 추가하여 작동합니다 (이 두 가지의 최대는 3 개 중 가장 낮은 것부터 제거)와 나머지 2 개 (최소 x 및 y)의 제곱이 제거됩니다. 첫 번째 단계에서 남은 값은 무엇보다) 및 z.
참고 : 이것은 내 블로그 게시물에서 나온 것입니다 SICP 운동 1.1-1.5. 다른 많은 SICP 솔루션으로 이동할 링크도 있습니다.