2016-05-16 3 views
1

я нашел краткое введение в схему сети, и у меня немного проблемы с этой функцией:Вызов непроцедур в определении функции?

(define (title-style str) 
    (let loop ((lC#\space) (i 0) (c (string-ref str 0))) 
    ((if (char=? lC#\space) 
     (string-set! str i (char-upcase c))) 
    (if (= (- (string-length str) 1) i) 
     str 
     (loop c (+ i 1) (string-ref str (+ i 1))))))) 

(display "star wars iv: a new hope") 
(display (title-style "star wars iv: a new hope")) 

Когда я пытаюсь называть его, я получаю это:

Error: call of non-procedure: #<unspecified> 

    Call history: 

    title-style.scm:6: loop 
    ... 
    title-style.scm:1: g6   <-- 

Это ошибка происходит от Chicken Scheme, я также получаю те же результаты в Chez Scheme.

Он преобразует строку заголовка дела, а также из сообщений об ошибках, которые я получил раньше, он делает: call of non-procedure: "Star Wars Iv: A New Hope"

ответ

3

Я понимаю, что вы собираетесь делать, но это не правильно структурировать условное выражение в схеме , Кроме того, перед первым if есть скопированные открывающиеся круглые скобки (которые являются причиной сообщения об ошибке), и во всех случаях вам необходимо выполнить рекурсию. Это должно работать для непустых строк:

(define (title-style str) 
    (let loop ((lC#\space) (i 0) (c (string-ref str 0))) 
    (cond ((= (- (string-length str) 1) i) 
      str) 
      ((char=? lC#\space) 
      (string-set! str i (char-upcase c)) 
      (loop c (+ i 1) (string-ref str (+ i 1)))) 
      (else 
      (loop c (+ i 1) (string-ref str (+ i 1))))))) 

Но все-таки, это не рекомендуемый способ написать решение в схеме, вы мутируете входную строку по пути, который не поощрял, и вы мышление с точки зрения индексов. Кроме того, вы вводите дополнительное ограничение на свой вход: что строки должны быть изменчивыми, и не все диалоги Scheme поддерживают этот по умолчанию.

Функциональный хвостовой рекурсивный стиль является предпочтительным, где мы создаем новую строку в качестве вывода, оставляя исходный вход нетронутым и используем богатую библиотеку процедур списка, доступных на языке; это то, что я имею в виду:

(define (title-style str) 
    (let loop ((lC#\space) (lst (string->list str)) (acc '())) 
    (cond ((null? lst) 
      (list->string (reverse acc))) 
      ((char=? lC#\space) 
      (loop (car lst) (cdr lst) (cons (char-upcase (car lst)) acc))) 
      (else 
      (loop (car lst) (cdr lst) (cons (car lst) acc)))))) 

В любом случае, это работает, как ожидалось:

(title-style "star wars iv: a new hope") 
=> "Star Wars Iv: A New Hope" 
+1

Добавленная потенциал роста использования 'string-> list' и' list-> string' подход (по сравнению с 'string-ref') - это то, что на R7RS' string-ref' (и 'string-set!') разрешено быть O (n) (для реализаций, где строки представлены внутри как UTF-8, и поэтому каждый символ может занимать другое количество байтов). –

+0

Спасибо за помощь. Я все еще пытаюсь обернуть голову тем, как работают клетки-соты, это очень помогает. – user1610406

+0

Вероятно, никакая реализация не поддерживает это по умолчанию, когда аргумент оценивается константой строки. Курица, Ракетка, Гамбит, Икарус все отображает неопределенное поведение и часто не сигнализирует об ошибке, как рекомендует отчет. – Sylwester

Смежные вопросы