Использование местного в Racket / Scheme - PullRequest
5 голосов
/ 30 декабря 2010

В Упражнении 18.1.12 из htdp я переписал функцию макси, используя «local».

;; maxi : non-empty-lon  ->  number
;; to determine the largest number on alon
(define (maxi alon)
  (cond
    [(empty? (rest alon)) (first alon)]
    [else (local ((define m (maxi (rest alon))))
            (cond
              [(> (first alon) m) (first alon)]
              [(> m (first (rest alon))) m]
              [else (first (rest alon))]))]))

Я не уверен, почему я сделал бы это в «реальной жизни», поскольку кажется, что версия книги короче, яснее и, вероятно, быстрее.

(define (maxi alon)
  (cond
    [(empty? (rest alon)) (first alon)]
    [else (cond
        [(> (first alon) (maxi (rest alon))) (first alon)]
        [else (maxi (rest alon))])]))

Было ли это чисто педагогическим упражнением? Может ли опытный Schemer прокомментировать приведенный выше код? Спасибо.

Ответы [ 3 ]

3 голосов
/ 25 сентября 2011

Вместо использования local можно также использовать внутренние определения Racket (особенно в более поздних версиях).

Например:

(define (maxi alon)
  (cond
    [(empty? (rest alon)) (first alon)]
    [else (define m (maxi (rest alon)))        ; here is an internal define
          (cond
            [(> (first alon) m) (first alon)]
            [(> m (first (rest alon))) m]
            [else (first (rest alon))])]))
3 голосов
/ 02 января 2011

Лично я думаю, что это плохой пример важности local, и я не верю, что вы полностью поняли важность вопроса, поэтому я пойду через концепцию, которую вы должны заметить, затемпросмотрите ваш пример и, наконец, приведите лучший пример.

КОНЦЕПЦИЯ

Во-первых, идея локального здесь (среди многих других вещей) состоит в том, чтобы уточнить означает фрагментов кода.

ВАШ ПРИМЕР

Давайте рассмотрим ваш пример, вы определили локальную константу с именем m, которая представляется правильной.Хотя, поскольку буква m не имеет значительного значения, ваше решение кажется неясным.Итак, как мы можем исправить ваше решение?

Нам нужно дать m имя, которое ясно идентифицирует то, что представляет m.Итак, мы начнем с непосредственного рассмотрения того, что представляет m, что (maxi (rest alon))

Ну (maxi (rest alon)) просто говорит, что найти максимальное число (rest alon)

Итак, давайте переименуем m вfind-max

Теперь ваш код выглядит следующим образом:

;; maxi : non-empty-lon  ->  number
;; to determine the largest number on alon
(define (maxi alon)
  (cond
    [(empty? (rest alon)) (first alon)]
    [else (local ((define find-max (maxi (rest alon))))
            (cond
              [(> (first alon) find-max) (first alon)]
              [(> find-max (first (rest alon))) find-max]
              [else (first (rest alon))]))]))

Замена m на find-max делает код намного понятнее!Оставляя нас с эмпирическим правилом , дайте вашим константам осмысленные имена.

МОЙ ПРИМЕР

Для дальнейшего пояснения давайте рассмотрим функцию, которая потребляет две точки и производит наклонотрезка, созданного соединением двух точек.Наш первый подход может быть:

;;where x1,y1 belong to point 1 and x2,y2 belong to point 2
(define (find-slope x1 y1 x2 y2)
  (sqrt (+ (sqr (- x2 x1))) (sqr (- y2 y1))))

Но мы могли бы быть более ясными, используя local:

(define (find-slope x1 y1 x2 y2)
  (local
    [(define delta-x (- x2 x1))
     (define delta-y (- y2 y1))]
    (sqrt (+ (sqr delta-x)) (sqr delta-y))))

Обратите внимание, как delta описывает, что функция делает в этой части;найти изменение в х или у.Итак, что нам нужно узнать здесь, так это то, что, хотя первое решение может использовать меньше кода, второе решение описывает , что мы делаем, и его легко прочитать.Это была полная идея вопроса, и это может показаться глупым, но это соглашение, которое они склонны подчеркивать при изучении схемы в академической среде.

Что касается эффективности первого и второго решения, то второеРешение определенно намного быстрее по понятным причинам (после того, как вы посмотрите, как Racket оценивает выражения), но это не было главной целью вопроса.

Надеюсь, это поможет

1 голос
/ 01 декабря 2015

Использование local здесь намного быстрее, потому что он оценивает (maxi (rest alon)) только один раз за рекурсию, тогда как во второй версии он оценивает (maxi (rest alon)) дважды, когда достигает последнего случая.

Local сохраняет результат, чтобы вы не делали одну и ту же работу дважды.

...