Specificeren welke waarde moet worden geretourneerd in lisp

Ik ben helemaal nieuw voor het lisp-programmeren. Ik moet een programma schrijven voor een klas die woorden leest uit een xml-document. Hoe dan ook, ik heb deze functie geschreven die een array (woord) en een bestandsstream (in) nodig heeft. Ik wil dat het een lus maakt totdat het een # \ spatie in de stroom bereikt terwijl elk verzameld teken aan het woord wordt toegevoegd. Ik wil dan dat het woord wordt teruggestuurd. Ik weet zeker dat ik veel dingen verkeerd doe, maar hier is de methode die ik heb. Ik ben er vrij zeker van dat de terugkeerfunctie aan het einde volledig misplaatst is:

(defun get-string (in word)
  (loop for char = (read-char in nil)
      while (not (char= char #\space))
      do(vector-push-extend char word))
  (return word))

Nu heb ik een ander probleem. De lus blijft personages zoeken nadat het een spatie heeft gevonden en ik krijg een hoop nils. Ik moet ook stoppen met nieuwe regels, maar weet niet zeker hoe. Ik heb dit gebonden, maar het leest gewoon elk personage.

(defun get-string (in word)
 (loop for char = (read-char in nil)
      while (not (or (char= char #\space)
                (char= char #\newline)))
    do(print char))
  word)

De afdrukkar staat daar omdat ik de debugger niet zo goed begrijp en wil zien welke tekens ik aan het lezen ben.

2

2 antwoord

word is a variable and a variable evaluates to its value. In a DEFUN body, the last expression's value is returned. So the return around word is not needed, if you want to return the value of word.

4
toegevoegd

U hebt geen expliciete return -instructie nodig. Dat is alleen voor vroege returns van lexicale scopes. Dus deze versie werkt:

(defun get-string (in word)
  (loop for char = (read-char in nil)
        while (not (char= char #\space))
        do (vector-push-extend char word))
  word)

Maar ik vraag me af wat een ander ding is in je functie: is het woord parameter bedoeld om alleen lege arrays te passeren? U hoeft geen buffers door te geven om de string af te handelen, Lisp is niet C. Dankzij automatisch geheugenbeheer kunt u alleen strings maken in een functie en deze retourneren.

Daarom zou ik een functie schrijven voor het lezen van door spaties gescheiden woorden uit een dergelijke stream:

(defun read-word (&optional (stream *standard-input*))
  (with-output-to-string (word)
   (loop for char = (read-char stream nil)
         while (and char
                    (char/= char #\Space)
                    (char/= char #\Newline))
         do (write-char char word))))

Wat betreft je nieuw toegevoegde vraag: ik begrijp niet waarom je loop niet moet stoppen als je een spatie hebt gelezen. OTOH, waar u niet naar zoekt, is een NIL, de retourwaarde in het geval van een EOF. Dat is waarom ik de eerste voorwaarde (alleen char ) in de en in mijn eigen functie voor heb toegevoegd.

EDIT: mijn eigen functie vervangen door een functie die geen eigen lijnbuffering gebruikt, omdat dat fragiel, te ingewikkeld en onnodig is. Ook een antwoord toegevoegd aan de uitgebreide vraag.

1
toegevoegd
@RainerJoswig: Ik heb de code gekopieerd van een programma waarin het goed werkte. Maar je hebt waarschijnlijk gelijk dat er te veel gevallen zijn waarin het problemen zal veroorzaken, daarom zal ik het in een bewerking vervangen.
toegevoegd de auteur Rörd, de bron
@webhound: ik bedoelde niet het stream-argument. De functie die ik presenteerde, neemt ook een stroomargument. Ik bedoelde het argument woord . Wilt u de nieuwe tekens feitelijk toevoegen aan de vorige inhoud van deze array, of geeft u alleen een (zogenaamd emtpy) buffer door?
toegevoegd de auteur Rörd, de bron
@webhound: with-output-to-string kan een oude tekenreeks bevatten om aan toe te voegen als een optioneel argument. Maar omdat je een andere aanpak gaat proberen, zou ik aanbevelen om een ​​XML-bibliotheek te gebruiken, zoals CXML: cliki. net/CXML
toegevoegd de auteur Rörd, de bron
Ik weet niet helemaal of ik begrijp wat je bedoelt, maar ik geef de stroom door, omdat ik woorden uit een bestand aan het lezen ben. Voor deze functie gebruik ik een andere om tekst omver te werpen die ingepakt is in <>, dan geef ik de stroom door aan de get-word-functie die strings ophaalt tussen de xml-tags.
toegevoegd de auteur webhound, de bron
@RainerJoswig: Er was eigenlijk een personage dat al aan het woord was toegevoegd toen het werd ingeleverd. Het was een lelijk programma. Ik probeer nog steeds te wennen aan lisp. Ik heb er slechts ongeveer een week mee gewerkt. Hoe dan ook, ik schrap het originele programma en probeer een andere benadering.
toegevoegd de auteur webhound, de bron
Heb je het idee dat de sluiting een goed idee is? Hoe zit het met lezen van naar verschillende streams? Veiligheid? De LET voorkomt ook dat de DEFUN een constructie op het hoogste niveau is, wat het normaal gesproken zou moeten zijn.
toegevoegd de auteur Rainer Joswig, de bron