2016-05-16 6 views
1

fand ich eine kurze Einführung Online-Schema, und ich bin ein wenig Mühe mit dieser Funktion:Aufruf von Nicht-Prozedur in Funktionsdefinition?

(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")) 

Wenn ich es versuche Aufruf, bekomme ich diese:

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

    Call history: 

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

Dieser Fehler kommt von Chicken Scheme, ich bekomme auch die gleichen Ergebnisse in Chez Scheme.

Es einen String in Titel Fall konvertiert und aus den Fehlermeldungen ich früher bekam, es tut: call of non-procedure: "Star Wars Iv: A New Hope"

Antwort

3

Ich verstehe, was Sie tun möchten, aber das ist nicht der richtige Weg, um einen bedingten Ausdruck in Scheme zu strukturieren . Außerdem gibt es direkt vor der ersten if eine falsch platzierte öffnende Klammer (die den gemeldeten Fehler verursacht), und Sie müssen die Rekursion in allen Fällen vorantreiben. Dies sollte für nicht-leere Strings arbeiten:

(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))))))) 

Aber immer noch, es ist nicht der empfohlene Weg, eine Lösung in Schema zu schreiben, sind Sie die Eingabezeichenfolge auf dem Weg mutiert, die entmutigt ist, und du bist Denken in Bezug auf Indizes. Außerdem erlegen Sie Ihrer Eingabe eine zusätzliche Einschränkung auf: Die Zeichenfolgen müssen veränderbar sein, und nicht alle Schema-Dialekte unterstützen standardmäßig .

Es wird ein funktionaler tailrekursiver Stil bevorzugt, bei dem wir eine neue Zeichenfolge als Ausgabe erstellen, die ursprüngliche Eingabe unberührt lassen und die umfangreiche Liste der in der Sprache verfügbaren Listenprozeduren nutzen. das ist, was ich meine:

(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)))))) 

So oder so, es funktioniert wie erwartet:

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

Ein weiterer Kopf der Verwendung des 'Saiten-> list' und' Listen-> string' Ansatz (im Vergleich zu 'string-ref') ist, dass auf R7RS' string-ref' (und 'string-set!') O (n) sein darf (für Implementierungen, bei denen Strings intern als UTF-8 dargestellt werden, also jedes Zeichen kann eine andere Anzahl von Bytes belegen). –

+0

Danke für die Hilfe. Ich versuche immer noch, meinen Kopf darüber zu wickeln, wie gut Zellen funktionieren, das hilft sehr. – user1610406

+0

Wahrscheinlich unterstützt keine Implementierung dies standardmäßig, wenn das Argument eine String-Konstante ergibt. Chicken, Racket, Gambit, Ikarus zeigt alles undefinierte Verhalten und oft ohne einen Fehler zu signalisieren, wie der Bericht empfiehlt. – Sylwester

Verwandte Themen