Lisp code explanation - lisp

I'm porting some code from lisp, but I got stuck at this part (apparently that's for mit-scheme)
(define (end-of-sentence? word)
(and (or (char-exist-last? word '#\.)
(char-exist-last? word '#\!)
(char-exist-last? word '#\?))
(not (initial? word))
(or (eq? (peek-char) '#\Space) ;;peek- so test for linefeed isn't affected
(eq? (peek-char) '#\n) ;;note- test for space isn't neccessary
(eq? (read-char) '#\t))))
;;counts the number of sentences in a given file and
;;stops at the given number
;;returns true once at that position, returns error if eof
(define (goto-sentence? file stop)
(define (c-g-iter num)
(cond ((= num stop)
#t)
((end-of-sentence?)
(c-g-iter (+ num 1)))
((not (char-ready?))
(error "EOF reached, number to large in goto-sentence?: " stop))
(else
(c-g-iter num))))
(begin
(open-path file)
(c-g-iter 1)))
Of course I could just skip that and implement what the comments say it does, but just wanted to be sure there's no magic happening in the background. So... how does this function even work -- where is it actually reading the characters? Is it as ugly as I think and does it consume the characters as a side-effect in the last check in end-of-sentence?? Or does the char-ready? actually read something?
But then again - what does (end-of-sentence?) (c-g-iter (+ num 1)) mean, as I don't expect c-g-iter to return a word.

I'm no scheme programmer, but it appears that characters are being consumed in read-char source
end-of-sentence? on the other hand appears to be getting called without a parameter, even though it is declared to take one. I assume that the functions it calls in turn are tolerant to whatever the system provides for unspecified parameters (nil?)
The pair (end-of-sentence?) (c-g-iter (+ num 1)) is a parameter to cond, which you can think like a switch or concise if/else; the first part is a test (end-of-sentence?), and the second is what to execute if true (c-g-iter (+ num 1))

Just adding my voice to the chorus; maybe I can provide some insight.
Some functions that are in these functions are not standard mit-sheme, such as char-exist-last? and initial?.(1) So I can't be sure what they do.
That being said, I think that end-of-sentence? takes in a string (word, so it should be a word) and returns true if its last character is a '!', '? or '.', and the next character after the word is a space, newline or tab character. Also, looking at intial, it probably can't be the first word in the sentence ('A.', for example, shouldn't return true, but 'A dog.' should.)
read-char does indeed 'consume characters' - "Returns the next character available from input-port, updating input-port to point to the following character." (Googled 'read-char mit scheme' to get MIT-Scheme input procedures.)
Per the same source char-ready? works like so: "Returns #t if a character is ready on input-port and returns #f otherwise."
Hope this is at least someone enlightening!
(1) MIT-Scheme Reference

Related

Variable as undefined function in LISP

As a project I am required to make a roman numeral converter in lisp using recursion. While working on the roman numeral to English portion I am running into a problem where the compiler is telling me that that one of my variables is is an undefined function. I am very new to lisp and could use any tips or tricks possible for this program. I would like to know the changes I would have to make to stop getting that error and if anyone has tips for my recursion that would be appreciated.
I know my code is messy but I plan on learning all the proper ways to format when I have something that works. The function is supposed to take a list of roman numerals and then convert the first and second element of the list into the corresponding integers and add them. It recursively is called until it hits NIL when it will return a 0 and add all the remaining integers and display that as an atom. Hopefully that makes sense. Thank you in advance.
(defun toNatural (numerals)
"take a list of roman numerals and process them into a natural number"
(cond ((eql numerals NIL) 0)
((< (romans (first (numerals)))
(romans (second (numerals))))
(+ (- (romans (first (numerals))))
(toNatural (cdr (numerals)))))
(t
(+ (romans (first (numerals)))
(toNatural (cdr (numerals)))))))
(defun romans (numer)
"take a numeral and translate it to its integer value and return it"
(cond((eql numer '(M)) 1000)
((eql numer '(D)) 500)
((eql numer '(C)) 100)
((eql numer '(L)) 50)
((eql numer '(X)) 10)
((eql numer '(V)) 5)
((eql numer '(I)) 1)
(t 0)))
here is the error. I use emacs and clisp for this project.
The following functions were used but not defined:
NUMERALS
0 errors, 0 warnings
In Common Lisp, the form (blah) means "call the function blah" and the form (blah foobar) means "call the function foo, with the argument foobar". Thus, you are telling the compiler to call the function numerals in multiple places, when you actually want to just use the value of the variable.
Also, unless you have a lisp environment that uses "modern mode", the symbol denoted by "toNatural" is the same as the one denoted by "tonatural" or "TONATURAL", don't use case to distinguish word breaks, use "-" (so (defun to-natural ...).

Questions on case

I tried to create an example for cond and case and came up with a simple implementation of the fizz buzz problem (see Wikipedia for details).
My initial version is:
(defun is-fizz-buzz (n)
(cond ((and (zerop (mod n 3)) (zerop (mod n 5))) 'fizz-buzz)
((zerop (mod n 3)) 'fizz)
((zerop (mod n 5)) 'buzz)
(t n)))
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
('fizz "Fizz!")
('buzz "Buzz!")
('fizz-buzz "Fizz-Buzz!")
(otherwise n))))
Now, #RainerJoswig pointed out to me that my case is wrong. I was quite surprised, as it had worked as it should, but as he's way more experienced with Lisp than I am, he's most probably right (and in fact, he is).
I tried to read and understand http://clhs.lisp.se/Body/m_case_.htm, but now I'm left with more questions than answers. As I didn't want to discuss things in 140 characters and as it may be helpful for other Lisp beginners, I thought to publish my questions here.
Basically, the syntax of case is described as
case keyform {normal-clause}* [otherwise-clause] => result*
keyform is easy: It's a form that is evaluated to get the key that is being tested. For sure
(is-fizz-buzz n)
is a form and it returns a symbol, hence everything looks fine. Additionally, as I learned from Land of Lisp, case internally works with eq, and as eq is used to compare symbols, this should be fine as well.
Now, the normal-clause: This is defined as
(keys form*)
form* again is simple, it's just a number of forms, basically with an implicit progn. For keys, it tells me that this is a designator for a list of objects. Phew. Here my questions begin…
This document tells me that a designator is:
an object that denotes another object.
Hm. As case is working with eq, I would have expected that I need to give a symbol here. And why is keys a designator for a list of objects, not for a single one? May I have multiple symbols that I can compare against in a single branch? I guess the problem here comes down to not really understanding what is meant by a designator, but maybe someone can help me and push me into the right direction. How would you explain what a designator is in Lisp?
Then, I started playing around with the code, and I noticed that if I remove the ' character, things still work. The code
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
(fizz "Fizz!")
(buzz "Buzz!")
(fizz-buzz "Fizz-Buzz!")
(otherwise n))))
produces the very same result as the code above. Why is this? I would not even have expected this to be executable at all, as (fizz "Fizz!") to me looks like a function call of fizz, which doesn't exist. Why does this work?
And then, the final question is, when I run
(case 'quote ('foo 1) ('bar 2))
it returns 1 (which does not seem to be logical, I would have expected nil). If I change this to
(case 'quote ('foo 1) ('bar 2) (otherwise 3))
it still returns 1, not 3 as I now would have expected. From the documentation I don't get why my otherwise-clause obviously does not what it should do.
Any hints why these two cases behave like they do?
CASE use EQL not EQ. EQL is in most cases the default comparison. Thus case works for identity, numbers and characters.
The keyforms are NOT evaluated. Thus it makes no sense to quote objects. Quoting means stopping evaluation. But there is no evaluation -> no quote.
The keyform is either a single item, or a list of items
(case foo
(bar 'it-is-bar)
((1 2) 'one-or-two)
(1 'one))
((apple banana orange) 'either-apple-banana-or-orange)))
It also means that one the left side are constants, no variables. bar above is the symbol bar, not the variable bar.
Problem:
(case 'quote
('foo 'foo-or-quote))
because it really is
(case 'quote
((quote foo) 'foo-or-quote))
Okay, I was able to figure out some of the problems by myself, primarily by reading this question and the according answers. This explains to me why my otherwise-clause didn't work, and it also explains why
(case 'quote ('foo 1) ('bar 2))
is being evaluated the way it is. So I guess that my fizz-buzz function at least should be:
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
(fizz "Fizz!")
(buzz "Buzz!")
(fizz-buzz "Fizz-Buzz!")
(otherwise n))))
UPDATE
Okay, now after having re-read the aforementioned question and answers multiple times, I think I finally got what is meant by a list of objects, and hence my code should be:
(defun fizz-buzz (n)
(princ (case (is-fizz-buzz n)
((fizz) "Fizz!")
((buzz) "Buzz!")
((fizz-buzz) "Fizz-Buzz!")
(otherwise n))))
For keys, it tells me that this is a designator for a list of
objects. Phew. Here my questions begin…
This document
tells me that a designator is:
an object that denotes another object.
Hm. As case is working with eq, I would have expected that I need
to give a symbol here. And why is keys a designator for a list
of objects, not for a single one? May I have multiple symbols that I
can compare against in a single branch? I guess the problem here comes
down to not really understanding what is meant by a designator, but
maybe someone can help me and push me into the right direction. How
would you explain what a designator is in Lisp?
I originally posted this as a comment, but I think this might stand as a sufficient answer, if it's the core problem in the question, so I'm adding it as an answer.
The text you need is in the HyperSpec. 1.4.1.5 Designators notes
The specific nature of the object denoted by a "<> designator"
or a "designator for a <>" can be found in the Glossary entry
for "<> designator."
The glossary entry for list designator is what you need:
list designator n. a designator for a list of objects; that is,
an object that denotes a list and that is one of: a non-nil atom
(denoting a singleton list whose element is that non-nil atom) or a proper list (denoting itself).
Thus the symbol fizz (a non-nil atom) and the list (fizz) both designate the list (fizz), the list (quote fizz) (often abbreviated as 'fizz) designates itself, etc.
Once you've learned about list designators,they're a very handy concept to use in you own code. Just document that you accept a list designator, and then convert with (if (listp x) x (list x)), and you're in business. It's very helpful, and you'll find more uses for it than you expect. E.g., I used it just the other day in an answer to How to group any consecutive numbers or items of a given series.

Let error in scheme

I have written the following code snippet in scheme,
(define (test-for-prime number divisor)
(cond (prime? number) (number)
(else (let ((next-divisor) (find-next-divisor number (+ 1 divisor)))
(test-for-prime (/ number next-divisor) (next-divisor))))))
However, I get the following error
let: bad syntax (not an identifier and expression for a binding) in: (next-divisor)
How do I rectify it?
Try this version, it fixes all the syntax errors:
(define (test-for-prime number divisor)
(cond ((prime? number)
number)
(else
(let ([next-divisor (find-next-divisor number (+ 1 divisor))])
(test-for-prime (/ number next-divisor) next-divisor)))))
You have lots of misplaced parenthesis. Some are missing, some are mistaken ... I'd suggest you take a good read at a Scheme tutorial and play around writing some basic procedures to get the hang of it, in particular here is the documentation and correct structure for a let special form:
(let ([id val-expr] ...) body ...+)
The first form evaluates the val-exprs left-to-right, creates a new location for each id, and places the values into the locations. It then evaluates the bodys, in which the ids are bound. The last body expression is in tail position with respect to the let form. The ids must be distinct according to bound-identifier=?
Also it's a good idea to use an IDE/editor which highlights this kind of problems and helps you indent the code properly. In particular, be aware that a variable must not be surrounded in parenthesis, when you write this: (x) Scheme assumes that x is a procedure and that you're calling it.
Let has the following syntax (example with two bindings):
(let ((<var> <expr>)
(<var1> <expr1>))
<body>)
If we fill in your let form, you have two bindings: next-divisor gets bound to nothing, and find-next-divisor gets bound to number, but there is a third form (+ 1 divisor) that does not fit into let's syntax.
This might be what you want:
(let ((next-divisor (find-next-divisor number (+ 1 divisor))))
;; ...
)

How to print blank character in the Lisp format function?

I hope there's someone to help me with this, because I can't find any useful answer, and I'm new with Lisp.
What I'm trying to do is to test a value of one element and to print something if its 1, otherwise to print blank character.
This works when all of the list arguments have the value 1:
(defun print-lst (list)
(format t "~%~a ~a ~a~%"
(if (= (nth 0 list) '1)
'¦)
(if (= (nth 1 list) '1)
'P)
(if (= (nth 2 list) '1)
'¦)))
so the output is ¦ P ¦. But, if the second element in list is 0, it prints NIL on that place ¦ NIL ¦ and I want it to print a space instead ¦ ¦(not just to skip that character¦¦, it is important to there is a blank character in that position in output line if the tested value is not 1).
Is there any way to return a blank character if the condition (if (= (nth 1 list) '1) 'P) is not fulfilled or is there any other way to perform this?
I hope I explained that nicely. Thank you.
If you want to make full use of the power of format, you can use a combination of format conditionals and format GOTO.
Like this:
[1]> (format nil "~#{~:[<nothing>~;~:*~A~]~^ ~}" 1 2 nil 4 nil 6)
"1 2 <nothing> 4 <nothing> 6"
In your case, this should work:
(format t "~&~#{~:[ ~;~:*~A~]~^ ~}"
...)
This works by doing the following:
~& inserts a newline unless we're already at the beginning of a line.
~#{...~} processes the arguments iteratively.
~:[...~;...~] chooses between the nil and non-nil case.
~:* unconsumes the argument that was consumed by ~:[...~].
~A outputs the item being processed.
~^ escapes from the loop on the last iteration (so as not to output an excessive space after the last item).
If takes three arguments: condition, then-form, else-form; the else-form is optional. Besides, I would use literal character syntax for literal characters.
(if (= (nth 0 list) 1)
#\P
#\Space)
Documentation:
Special form if
Character syntax
Character names
Counter question:
Do you really need output values that are identifiers ('something) or would also string literals work ("something")?
If the first is true: I suppose it is not possible to use space as an identifier.
If the second is true: use "|", "P" and " " as output values
Format is a beast waiting to devour the unwary.
That said, it looks like you may want to use some of its higher level directives here. Check out the Formatted Output section of the Lisp Hyperspec, and the format chapter of PCL (specifically, look at the section that deals with conditional formatting).

lisp code excerpt

i've been reading some lisp code and came across this section, didn't quite understand what it specifically does, though the whole function is supposed to count how many times the letters from a -z appear in an entered text.
(do ((i #.(char-code #\a) (1+ i)))
((> i #.(char-code #\z)))
can anyone explain step by step what is happening? I know that it's somehow counting the letters but not quite sure how.
This Lisp code is slightly unusual, since it uses read-time evaluation. #.expr means that the expression will be evaluated only once, during read-time.
In this case a clever compiler might have guessed that the character code of a given character is known and could have removed the computation of character codes from the DO loop. The author of that code chose to do that by evaluating the expressions before the compiler sees it.
The source looks like this:
(do ((i #.(char-code #\a) (1+ i)))
((> i #.(char-code #\z)))
...)
When Lisp reads in the s-expression, we get this new code as the result (assuming a usual encoding of characters):
(do ((i 97 (1+ i)))
((> i 122))
...)
So that's a loop which counts the variable i up from 97 to 122.
Lisp codes are written as S-Expression. In a typical S-Expression sytax, the first element of any S-expression is treated as operator and the rest as operand. Operands can either be an atom or another S-expression. Please note, an atom is a single data object. Keeping this in mind
char-code
(char-code #\a) - returns the ascii representation of a character here its 'a'.
The do syntax looks similar to the below
(do ((var1 init1 step1)
(var2 init2 step2)
...)
(end-test result)
statement1
...)
So in your example
(do ((i #.(char-code #\a) (1+ i)))
((> i #.(char-code #\z)))
)
The first s-expression operand of do is the loop initialization, the second s-expression operand is the end-test.
So this means you are simply iterating over 'a' through 'z' incrementing i by 1.
In C++ (Not sure your other language comfort level, you can write
for(i='a';i<='z';i++);
the trick with the code you show is in poor form. i know this because i do it all
the time. the code makes an assumtion that the compiler will know the current fixnum
for each character. #.(char-code #\a) eq [(or maybe eql if you are so inclided) unsigned small integer or unsigned 8 bit character with a return value of a positive fixnum].
The # is a reader macro (I'm fairly sure you know this :). Using two reader macros is
not a great idea but it is fast when the compiler knows the datatype.
I have another example. Need to search for ascii in a binary stream:
(defmacro code-char= (byte1 byte2)
(flet ((maybe-char-code (x) (if characterp x) (char-code x) x)))
`(the fixnum (= (the fixnum ,(maybe-char-code byte1)
(the fixnum ,(maybe-char-code byte2)))))
))
Declaring the return type in sbcl will probably insult the complier, but I leave it as a sanity check (4 me not u).
(code-char= #\$ #x36)
=>
t
. At least I think so. But somehow I think you might know your way around some macros ... Hmmmm... I should turn on the machine...
If you're seriously interested, there is some assembler for the 286 (8/16 bit dos assembler) that you can use a jump table. It works fast for the PC , I'd have to look it up...