Полностью смущен ракетным синтаксисом - пожалуйста, помогите - PullRequest
0 голосов
/ 02 ноября 2019

Меня просят выучить ракетку для университета, и в конце концов мне придется делать довольно сложные вещи с древовидной структурой и наборами данных. Я только начал, и я не могу понять, как этот код работает, даже с документами Racket, Google и SO.

Я пытаюсь написать функцию, которая принимает три числовых аргумента и возвращает наибольшее, вот что у меня есть:

(define (mymax x1 x2 x3)
    (cond
        ((and (x1 > x2) (x1 > x3)) x1)
        (else (and (x2 > x1) (x2 > x3)) x2)
        (else (and (x3 > x1) (x3 > x2)) x3)
))
(print (mymax 10 5 1))

Итак ...

  • Не знаю, правильно ли я использую и сравнение
  • Я получаю ошибку "cond: плохой синтаксис (условие `else 'должно быть последним) в: (else (and (x2> x1) (x2> x3)) x2)"
  • У меня нет ни малейшего представления, как вернутьзначение из функции

Извините, что был настолько невежественным, но это просто не имеет смысла, любая помощь, проливающая свет на эти точки пули, будет огромной помощью

Ответы [ 2 ]

5 голосов
/ 02 ноября 2019

Вот синтаксис для условного выражения :

(cond
  [ConditionExpression1 ResultExpression1]
  [ConditionExpression2 ResultExpression2]
  ... 
  [ConditionExpressionN ResultExpressionN])


(cond
  [ConditionExpression1 ResultExpression1]
  [ConditionExpression2 ResultExpression2]
  ...
  [else DefaultResultExpression])

Оценка условного выражения следует 2 правилам

1) правилу cond_false

(cond                    == (cond
  [#false ...]               ; first line removed
  [condition2 answer2]       [condition2 answer2]
  ...)                       ...)

2) правило cond_true

(cond                    == answer-1
  [#true answer-1]
  [condition2 answer2]
  ...)

Это второе правило также применяется, когда условие другое (но учтите, что еще может произойти только впоследнее предложение).


Пример :

(cond
  [(= 2 0) #false]
  [(> 2 1) (string=? "a" "a")]
  [else (= (/  1 2) 9)])

== {при оценке от (= 2 0) до #false}

(cond
  [#false #false]
  [(> 2 1) (string=? "a" "a")]
  [else (= (/  1 2) 9)])

== {по правилу cond_false }

(cond
  [(> 2 1) (string=? "a" "a")]
  [else (= (/  1 2) 9)])

== {при оценке от (> 2 1) до #true}

(cond
  [#true (string=? "a" "a")]
  [else (= (/  1 2) 9)])

=={по правилу cond_true }

(string=? "a" "a")

== {по оценке (string=? "a" "a") до true}

#true

(define (mymax x1 x2 x3)
    (cond
        ((and (x1 > x2) (x1 > x3)) x1)
        (else (and (x2 > x1) (x2 > x3)) x2)
        (else (and (x3 > x1) (x3 > x2)) x3)
))
(print (mymax 10 5 1))
  • выражение типа (2 > 1) не будет работать. Это должно быть (> 2 1). Синтаксис для приложения функции является синтаксисом префикса, то есть за открывающей скобкой должно следовать имя функции, за которым должны следовать аргументы.

  • ошибка, которую вы получаете из-за неправильного синтаксиса для второго предложения. (else (and (x2 > x1) (x2 > x3)) x2) Этот пункт состоит из 3 частей: else, (and (x2 > x1) (x2 > x3)) и x2. Однако в соответствии с синтаксисом cond предложение должно содержать только 2 элемента.

После избавления от else s и создания префикса >:

(define (mymax x1 x2 x3)
  (cond
    ((and (>  x1 x2) (> x1 x3)) x1)
    ((and (> x2 x1) (> x2 x3)) x2)
    ((and (>  x3 x1) (> x3 x2)) x3)))

(print (mymax 10 5 1))

Программа печатает 10. Но обратите внимание, что это не сработает для (mymax 5 5 5), поэтому мы превращаем все > с в >= с:

(define (mymax x1 x2 x3)
  (cond
    [(and (>= x1 x2) (>= x1 x3)) x1]
    [(and (>= x2 x1) (>= x2 x3)) x2]
    [(and (>=  x3 x1) (>= x3 x2)) x3]))

(mymax 10 5 1)
; => 10
(mymax 5 5 5)
; => 5

Наконец, функции не «возвращают» значения. Лучшей мысленной моделью было бы думать, что их тело уменьшает до значения.

(define (f x-1 ... x-n)
  f-body)

(f v-1 ... v-n) 
; == f-body
; with all occurrences of x-1 ... x-n 
; replaced with v-1 ... v-n, respectively

См .: Руководство по ракеткам , Справочник по ракеткам , HtDP .

1 голос
/ 02 ноября 2019

важна абстракция

хорошо: n -> n-1 -> ... -> 3 -> 2 -> сделано

плохо: 1 = 1, 2 = 2,3 = 3 !, ..., n = n!

; common version is ok but we use >= 6 times if x3 is biggest
; most important part is it's mine be wrong if you don't careful
; if you try 4 number using this way you need 4! condition than it's easy make mistake
(define (mymax-common x1 x2 x3)
  (cond
    [(and (>= x1 x2) (>= x1 x3)) x1]
    [(and (>= x2 x1) (>= x2 x3)) x2]
    [(and (>= x3 x1) (>= x3 x2)) x3]))


; make abstract
(define (mymax-3 x1 x2 x3)
  (local ((define (which-bigger a b) (if (>= a b) a b)))
    (cond
      [(>= x1 x2)
       (which-bigger x1 x3)]
      [else
       (which-bigger x2 x3)])))

(mymax-3 1 2 3)
(mymax-3 3 2 1)
(mymax-3 3 3 3)

; make abstract
(define (mymax-5 x1 x2 x3 x4 x5)
  (local ((define (which-bigger a b) (if (>= a b) a b)))
    (which-bigger (which-bigger (which-bigger (which-bigger x1 x2) x3) x4) x5)))

(mymax-5 1 2 3 4 5)
(mymax-5 5 4 3 2 1)
(mymax-5 5 5 5 5 5)

; make abstract
(define (mymax-n n1 . lst)
  (local ((define (which-bigger a b) (if (>= a b) a b)))
    (foldr which-bigger n1 lst)))

(mymax-n 1 2 3 4 5 6 7 8 9 10)
(mymax-n 10 9 8 7 6 5 4 3 2 1)
(mymax-n 10 10 10 10 10 10 10 10 10)

(define (mymax-n-sort n1 . lst)
  (first (sort (cons n1 lst) >)))

(mymax-n-sort 1 2 3 4 5 6 7 8 9 10)
(mymax-n-sort 10 9 8 7 6 5 4 3 2 1)
(mymax-n-sort 10 10 10 10 10 10 10 10 10)
...