Заменяет вхождения в списке - Ракетка - PullRequest
0 голосов
/ 26 февраля 2020

Я пишу функцию ptyper, которая принимает вложенный список, нл. Эта функция заменяет все вхождения числа с n и все вхождения символа с s. Вот что у меня сейчас:

(define (ptyper nl) (cond
((null? nl) '())
((list? nl)
 (let ((ls (car nl)))
  (list (ptyper ls))))
((number? (car nl))
 (cons "n" (cdr nl)))
((symbol? (car nl))
 (cons "s" (cdr nl)))
(else
 (cons (car nl) (cdr nl)))))

Я запустил этот тест (ptyper '(2 (ab c () "ab c"))), но получил ошибку, что их контракт нарушение. Я не совсем уверен, что я делаю не так, так что, если могли бы использовать некоторую помощь. Спасибо!

Ответы [ 2 ]

0 голосов
/ 26 февраля 2020

Вот возможное решение с одной функцией:

(define (ptyper nl)
  (cond
    ((null? nl) '())      ; if the argument is an empty list, return the empty list
    ((list? nl)           ; if the argument is a list, then
     (let* ((c (car nl))  ; get its first element
            (nc (cond ((number? c) "n") ; transform it for numbers
                      ((symbol? c) "s") ; and symbols
                      ((list? c) (ptyper c)) ; if a list recur over it
                      (else c))))       ; otherwise (e.g. a string) return as it is
       (cons nc (ptyper (cdr nl)))))    ; recursive call on the rest of the list
    (else nl)))  ; this should never happen for the specification,
                 ; return the parameter or cause an error

Обратите внимание, что ошибка в вашем случае вызвана рекурсивным вызовом. Когда функция вызывается для атома, например 2, сначала она проверяет null и list?, и эти проверки возвращают false. Затем он проверяет (number (car nl)), но nl равен 2, и поэтому car завершается неудачей.

0 голосов
/ 26 февраля 2020

Вот определение данных для S-выражения, которое моделирует ваши данные.

; An S-expr is one of: 
; – Atom
; – SL

; An SL is one of: 
; – '()
; – (cons S-expr SL)


; An Atom is one of: 
; – Number
; – String
; – Symbol

У нас есть предикаты для всех типов данных, кроме Atom, поэтому мы делаем atom?:

;; Any -> Boolean
;; is the x an atom?
(define (atom? x)
  (not (list? x)))

Мы следуем структуре данных, чтобы построить «шаблоны» для наших функций:

(define (func sexp)
  (cond
    [(atom? sexp) (func-atom sexp)]
    [else (func-sl sexp)]))


(define (func-sl sl)
  (cond
    [(empty? sl) ...]
    [else (... (func (first sl)) ... (func-sl (rest sl)) ...)]))


(define (func-atom at)
  (cond
    [(number? at) ...]
    [(string? at) ...]
    [(symbol? at) ...]))

Заполняем пробелы:

; Atom -> String
(define (subs-atom at)
    (cond
    [(number? at) "n"]
    [(string? at) at]
    [(symbol? at) "s"]))


; SL -> SL
(define (subs-sl sl)
  (cond
    [(empty? sl) sl]
    [else (cons (subs-sexp (first sl))
                (subs-sexp (rest sl)))]))

; S-exp -> S-exp
(define (subs-sexp sexp)
  (cond
    [(atom? sexp) (subs-atom sexp)]
    [else (subs-sl sexp)]))

Используя интерфейс для ptyper:

(define (ptyper nl)
  (subs-sexp nl))

(ptyper '(2 (abc () "abc")))
; => '("n" ("s" () "abc"))
...