I am working on a Lisp program that contains code to read in the dimensions of boxes and then sort them from shortest to longest lengths (and set each of these new lengths as new variables).
When I attempt to load my file into the interpreter, I get the following error:
- SYSTEM::%EXPAND-FORM: invalid form (40)
Assuming this error is stemming from line 40 of my code, here are lines 34-45:
(defun get-box ()
(let ((d1) (d2) (d3))
(setf d1 (read))
(setf d2 (read))
(setf d3 (read))
(list d1 d2 d3))
(if (= -1 d1)
(exit)
(setf new-d1 (first (sort (d1 d2 d3)) #'<))
(setf new-d2 (second (sort (d1 d2 d3)) #'<))
(setf new-d3 (third (sort (d1 d2 d3)) #'<))
(next-part-of-program (new-d1, new-d2, new-d3)))
Is there anything inherently wrong syntactically or semantically with my if statement in this code snippet? What does the EXPAND-FORM error come from/mean in Lisp?
Any help is greatly appreciated. Thanks!
When you see a message mentioning symbols in the "SYS" package (also known as "SI" and "SYSTEM" in different implementations), especially when the symbols are internal (prefixed with two colons), and, moreover, their names contain non-alphanumeric characters (e.g., % or $), chances are this message is implementation-specific, and you will help us help you by mentioning which implementation you are using.
That said, I think you are using CLISP, in which case this 40 does not name a line in your file.
You either have a literal 40 in an inappropriate place in your file, or you have a variable with the value of 40 which you evaluate during macroexpansion with a misplaced comma.
An if can have only a single expression for the consequent, and a single for the alternative (the "else" part). If you need to write more than one expression, pack them inside progn. I believe this is what you intended:
(if (= d1 -1) ; condition. It's bad style to write Yoda conditions!
(exit) ; consequent
(progn ; alternative
…))
Also, be aware that there seems to be a misplaced parentheses at the end of this line:
(list d1 d2 d3))
… And anyway, the above line is doing nothing, you can simply delete it. Also this part is wrong:
(sort (d1 d2 d3)) #'<)
It should be:
(sort (list d1 d2 d3) #'<)
And in here, the commas are wrong:
(new-d1, new-d2, new-d3)
Also, in this line the variables should have an initial value, and you should also declare new-d1, new-d2 and new-d3
(let ((d1) (d2) (d3))
With all the fixes in place, this is how the code should look:
(defun get-box ()
(let ((d1 0) (d2 0) (d3 0) (new-d1 0) (new-d2 0) (new-d3 0))
(setf d1 (read))
(setf d2 (read))
(setf d3 (read))
(if (= d1 -1)
(exit)
(progn
(setf new-d1 (first (sort (list d1 d2 d3) #'<)))
(setf new-d2 (second (sort (list d1 d2 d3) #'<)))
(setf new-d3 (third (sort (list d1 d2 d3) #'<)))
(next-part-of-program new-d1 new-d2 new-d3)))))
Related
Why am I getting the error: cond: expected a clause with a question and an answer, but found a clause with only one part? What am I doing wrong?
Basically, I have to find out if the discriminant is a positive / negative number.
(define (has-real-roots? a b c)
(cond
[(positive? (- (square b) (* 4 a c)))]
[else false]))
As per the documentation, each clause in a cond expression requires two parts: the "question" (a condition), and an "answer" (the value to return). Your code is missing the "answer" part for the first clause, in this case returning true would be appropriate:
(define (has-real-roots? a b c)
(cond [(positive? (- (square b) (* 4 a c))) true]
[else false]))
But you don't really need to use a cond here, this is simpler and does the same thing:
(define (has-real-roots? a b c)
(positive? (- (* b b) (* 4 a c))))
Racket Documentation
It just you have many one arm if than else what to check or we call it case so we use cond. You should match language syntax.
#lang racket
(cond
[#false 'you-wont-entry-this-part-because-test-express-is-false]
[#false 'you-wont-entry-this-part-because-test-express-is-false]
[#true 'entry-this]
[else 'last-condiction])
#|
(cond
[test-express-1 if-test-express-1-is-true-do-this]
[test-express-2 if-test-express-2-is-true-do-this]
...
[else if-test-express-1-to-n-all-false-do-this])
|#
To preface this, I'm very new to Clojure. I was wondering why I'm getting a ClassCastExpection on this piece of code. I've looked at it and syntactically and logically it looks correct?
Clojure Code:
; (load-file "cje842asg1.clj")
(def lstnum '(76 85 71))
; 2a
(defn sum [list] (
(if (empty? list)
0
(+ (first list (sum (rest list))))
)
)
)
; if empty return zero, else add the first num in list and pass in the
; rest.
(sum lstnum)
Any help is appreciated.
The code has 2 separate errors.
The first is calling (first list (sum (rest list))) which is calling first with 2 arguments when you meant to make the second part the second argument to +.
The other one leading to the actual exception is the extra () around the function body. Note the ((if ...)) which means you are trying to call whatever the if returns as a function. In this case it is returning a number, leading to the class java.lang.Long cannot be cast to class clojure.lang.IFn error.
The corrected version would be
(defn sum [list]
(if (empty? list)
0
(+ (first list)
(sum (rest list)))))
Moving the arguments to + into separate lines makes it easier to read in this case (IMHO).
I am still in the process of understanding macros and though I think I understand the basics of "backquote" "unquote" and "unquote splicing", I had thought they were only used/useful in macros.
however I came across this Common Lisp code from Rosetta code (the calender task),
(defun month-strings (year month)
"Collect all of the strings that make up a calendar for a given
MONTH and YEAR."
`(,(date-calc:center (month-to-word month) (length *day-row*))
,*day-row*
;; We can assume that a month calendar will always fit into a 7 by 6 block
;; of values. This makes it easy to format the resulting strings.
,# (let ((days (make-array (* 7 6) :initial-element nil)))
(loop :for i :from (date-calc:day-of-week year month 1)
:for day :from 1 :to (date-calc:days-in-month year month)
:do (setf (aref days i) day))
(loop :for i :from 0 :to 5
:collect
(format nil "~{~:[ ~;~2,d~]~^ ~}"
(loop :for day :across (subseq days (* i 7) (+ 7 (* i 7)))
:append (if day (list day day) (list day))))))))
here back-quote, unquote, and unquote splicing are used in a normal function, and it works to create a list of strings.
and while I do not use Scheme, the Racket solution had something similar,
(define days
(let ([? (if (= mn 12) (λ(x y) y) (λ(x y) x))])
(round (/ (- (find-seconds 0 0 12 1 (? (+ 1 mn) 1) (? yr (+ 1 yr))) s)
60 60 24))))
(list* (~a mname #:width 20 #:align 'center) "Su Mo Tu We Th Fr Sa"
(map string-join
(nsplit 7 `(,#(make-list pfx " ")
,#(for/list ([d days])
(~a (+ d 1) #:width 2 #:align 'right))
,#(make-list (- 42 pfx days) " ")))))))
which I did not test.
my questions are,
Why would this be necessary in a function, what is the use case?
and how is it different from a macro ?
quasiquote, unquote and unquote-splicing are just syntax sugar for a combination of quoted datum, list, and cons. Imagine this:
`(,a b c) ; == (cons a '(b c))
`(a b ,c) ; == (list 'a 'b c)
`(a b ,#c d) ; == (cons 'a (cons 'b (append c '(d))))
These are small trivial examples, so you can imagine the right hand side might become crazy complex, but it is nice to know that the quasiquote magic makes new cons when needed and keep literals as is in the tails. Thus using nconc of quasiquoted expression would not work in the first case, but in the second and third because the last cons is needed to be fresh in those cases.
If you have a function that creates a list structure, quasiquote will make the code more clear and consice since the form will look more like the result. It is no different than a macro since both create list structure. A macro differs in what happens with the result. In a function the value is returned and in a macro code gets replaced.
You can check what happens after using the macro with macroexpand:
(macroexpand '`(,a ,b ,#c))
; ==> (cons a (cons b c))
; ==> t
Backquote
See the CLHS on Backquote.
The example
The example is similar to this code:
CL-USER 14 > (let ((a 1)
(b 2)
(c '(3 4 5)))
`(,a ; a gets evaluated and put in
,b ; b gets evaluated and put in
,#c)) ; c gets evaluated and spliced in
(1 2 3 4 5)
The effect of above code is similar to using the function list*.
CL-USER 15 > (let ((a 1)
(b 2)
(c '(3 4 5)))
(list* a b c))
(1 2 3 4 5)
Which version you use is mostly a matter of taste.
list* creates a list of the first values and puts them in front of the last value, which usefully should be a list.
List creation
There are many ways and styles to create a list. The two here:
use nested functions like cons, list, list*, append, ... This is especially useful when there are many elements to be computed.
use templates of lists with the backquote operator and ,, ,#, ,. for evaluating. This is especially useful when there are nested lists with fixed objects and a few objects to compute.
Thus the backquoted way is useful when you think of list templates to fill out. Whenever you want to create (nested) lists, which are based on templates with a lost of constant structure (meaning objects and nesting), then this is a way to do it. This is not limited to macros - it is a general mechanism to build lists.
You can also think of templates being an inversion:
functions evaluate by default and constant elements need to be quoted
backquote templates don't evaluate by default and variable elements need to be unquoted.
Warning
Backquoted expressions themselves don't need to be pure lists. The internal representation of backquoted expressions is undefined and implementations actually differ.
Vectors, too
Note that this works for vectors, too:
CL-USER 20 > (let ((a 1)
(b 2)
(c '(3 4 5)))
`#(,a
,b
,#c))
#(1 2 3 4 5)
Quasi-Quote (QQ) is a list constructor in Scheme.
It’s more flexible than quote ('), list or cons because it allows for mixing symbols with expression evaluations.
The QQ has two helper mechanisms:
unquote - denoted (,)
unquote-splicing - denoted (,#)
When QQ is used, a quote context is initiated. Unquote allows us to momentarily escape the quote context and evaluate the expression right after the unquote. Unquote-splicing both escapes an entire list from the quote context as well as “unwraps” the list.
Consider:
(define b 5)
(define s (list 1 2))
Note the differences in the values of the following expressions: Quote, Quasi-Quote.
Input:
'(a b c)
`(a b c)
Output
> (a b c)
> (a b c)
Input
'(a ,b c)
`(a ,b c)
Output
> (a ,b c)
> (a 5 c)
Input
'(a ,s c)
`(a ,s c)
Output
> (a ,s c)
> (a (1 2) c)
Input
'(a ,#s c)
`(a ,#s c)
Output
> (a ,#s c)
> (a 1 2 c)
Source: Compilation course I took , The Common Lisp Cookbook - Macros and Backquote
This question might be so easy, but I spent some time on it and I could not figure out what the problem is. I am new to Scheme ;)
Okay, this is my code:
(define foo
(lambda (x)
((if(equal? (car x) 4) "A" "B")
(if(equal? (car (cdr x)) 3) "A" "B")
(if(equal? (car(cdr (cdr x))) 5) "A" "B")
)
))
(foo '(4 3 5))
I get the following error, when I run the code:
> application: not a procedure; expected a procedure that can be
> applied to arguments given: "A" arguments...: "A" "A"
To fix the error, simply do this:
(define foo
(lambda (x)
(if (equal? (car x) 4) "A" "B")
(if (equal? (car (cdr x)) 3) "A" "B")
(if (equal? (car (cdr (cdr x))) 5) "A" "B")))
The problem? that in your code there's an extra and erroneous pair of () surrounding the if expression, so Scheme thinks that if is returning a function (which is not). Remember, in Scheme this: (f) means: execute f as a function with no arguments.
Now that we found the syntax error, let's see what else is wrong with the code. For starters, if you write a sequence of expressions inside a procedure only the value of the last one is returned, so the first two ifs are being completely ignored! After reading the comments I understand that you want to return "AAA" for the input '(4 3 5), or "ABA" for input '(4 6 5). The trick here is that we must use string-append to stick together all the strings:
(define foo
(lambda (x)
(string-append
(if (equal? (car x) 4) "A" "B")
(if (equal? (cadr x) 3) "A" "B")
(if (equal? (caddr x) 5) "A" "B"))))
Now it works as expected:
(foo '(4 3 5))
=> "AAA"
(foo '(4 6 5))
=> "ABA"
Let me start off by saying, "Welcome to Scheme!" Don't get frustrated and whatever you do, keep on
trying to understand the functional-programming way of doing things.
Your perseverance will pay off, and you will become a better programmer
for the effort, even when you go back to using Java.
Scheme is a good place to start learning functional programming.
I hope the following will help you to see how you might start to
change your thinking, so here goes:
Here is a bit about why you got the weird error you saw. If you
have:
(define foo
(lambda (x)
((if(equal? (car x) 4) "A" "B")
(if(equal? (car (cdr x)) 3) "A" "B")
(if(equal? (car(cdr (cdr x))) 5) "A" "B")
)
))
Then:
(foo '(4 3 5))
is equal to:
((if (equal? (car '(4 3 5)) 4) "A" "B"))
(if (equal? (car (cdr '(4 3 5))) 3) "A" "B")
(if (equal? (car (cdr (cdr '(4 3 5)))) 5) "A" "B"))
Because that is what you get when you replace every occurrence
of x with (4 3 5) in the body of the lambda-expression you wrote.
This next bit of reasoning is a bit of a shortcut, but notice that:
(car '(4 3 5)) = 4
AND
(car (cdr '(4 3 5))) = (car '(3 5)) = 3
AND
(car (cdr (cdr '(4 3 5)))) = (car (cdr '(3 5))) = (car '(5)) = 5
So, when we substitute equals for equals in the above expression,
we get:
((if (equal? 4 4) "A" "B")
(if (equal? 3 3) "A" "B")
(if (equal? 5 5) "A" "B"))
and this is the same as:
("A" "A" "A")
This is a peculiar Scheme expression, and the reason Scheme complains is
because you're trying to invoke a function called "A" and apply it to
two arguments, "A" and "A".
From the discussion above, it's pretty clear that you're trying to
derive a new structure, based on the input. So, what you need is
a function which derives the new structure, based on an examination
of the existing structure, and assembles a new one. This is what
is returned by the function.
Scheme is a functional language, which means that it is very
expression-oriented. In Scheme, the computer is turned into a kind of
mechanical expression-evaluator. This is very different from
what we became used to in object-oriented languages (e.g., Java,
C#) because those languages are all about carefully controlling
changeable state. In functional languages, it's all about
calculating the value of an expression. (By the way, In a deep
and beautiful way, it just so happens that everything you can
do in the world of "mutable state programming" can be done in
the world of "mechanical evaluation of expressions." There's a
deep and fundamental equivalence between the two, believe it or not.)
If you are trying to create a new list, based on tests of the individual
elements in list (4 3 5), then you need to write expressions which do
two separate things: construct lists from smaller things, and examine
the various elements of the list (in this case, 4, 3, and 5.)
(define foo
(lambda (x)
(cons (if (equal? (car x) 4) "A" "B")
(cons (if (equal? (car (cdr x)) 3) "A" "B")
(cons (if (equal? (car (cdr (cdr x))) 5) "A" "B") '() )))))
So, (foo '(4 3 5)) results in ("A" "A" "A"), which is a list of strings.
You eventually want to append them all together into a single string,
right? So, there's already a function called fold-right which provides
a way to do this. The fold-right function can use the string-append
function to accomplish this:
(fold-right string-append "" (foo '(4 3 5)))
which should provide an answer of "AAA".
(fold-right string-append "" (foo '(4 4 4)))
gives an answer of "ABB"
Using functions like fold, fold-right, etc, is a more of a functional
programming way to do these kinds of things.
Depending on the circumstances, you may want to use those folding functions
instead of writing the foo function in terms of the string-append function, as
Oscar Lopez did above.
Like I said earlier, you have to think about things very differently
when using a functional programming language, and get away from thinking
of programs as sequences of operations which change the internal state
of the computer's memory. You have to start thinking in terms of the
computer as a powerful expression evaluation machine instead.
I hope this helps, and is an encouragement to you to keep working at learning Scheme.
Because the body of your lambda is wrapped in parentheses, the first if is being treated as a procedure, and when it tries to apply the results of the other if's to it, you get the error you got.
If you are trying to return a list of the values of those 3 if's, then you should use the list function.
I am trying to define my own function to make my hw2 easier but it is not working. Could you take a look at it and tell me what I am missing?
(DEFUN testAL(x)
COND ( ( ATOMP(x) ) 'this-is-an-atom )
( ( LISTP(x) ) 'this-is-a-list )
( T 'this-is-neither ) )
I want this conditional function to take an input X and output if it is an atom, list, or neither. Problem is that when I input NIL, I get an error: Attempt to take the value of the unbound variable `COND'.
Homework 2 consists of the following question:
Which of the following are atoms, which lists, which both and witch neither?
a. nil
b. (expt 10 3)
c. (a b)
d. 64
e. T
f. (No place like home)
g. ‘(+ 3 5 6)
Your parenthesis are not in the correct places. A parenthesis, unless quoted, are the start of a function application.
It begins with a variable cond that is not bound. It's not the special form (cond (predicate consequent) (predicate2 consequent2)) since it doesn't start with an open parenthesis.
From indentation alone I guess you meant to write:
(DEFUN testAL (x)
(COND ((ATOM x) 'this-is-an-atom)
((LISTP x) 'this-is-a-list)
(T 'this-is-neither)))
(testal 'test) ; ==> THIS-IS-AN-ATOM
(testal '(a b c)) ; ==> THIS-IS-A-LIST
I have removed the extra parenthesis around x since (x) means apply the function x while x means the variable x. With x in a different position like (+ x 3) then + is the function to be applied and x is one of its operands.
I changed atomp to atom. Since atom is one of the very first primitives defined with the very first LISP in the 50's, it does not have a postfix p like most other predicates.
Edit: Multiple match
You could just have several cond (or if since you only have one test in each) and do side effects like (print "THIS-IS-AN-ATOM") since your base case will never trigger (nothing is neither list nor atom in CL). This is perhaps the easies solution.
(DEFUN testAL (x)
(if (ATOM x) (print 'this-is-an-atom))
(if (LISTP x) (print 'this-is-a-list)))
(testal '()) ; ==> THIS-IS-A-LIST (but prints both)
For a more functional approach I would have done it with higher order functions keeping the code testable and supply a print-function that does the side effects. Be aware that this might not be as easy to read for a beginner:
;; a list of pairs of predicate and their desription
(defparameter *type-predicates-and-description*
'((douglasp . this-is-the-answer-to-everything)
(floatp . this-is-a-floating-pont-number)
(integerp . this-is-an-integer)
(numberp . this-is-a-number)
(null . this-is-null)
(listp . this-is-a-list)
(characterp . this-is-a-character)
(stringp . this-is-a-string)))
;; custom made predicate
(defun douglasp (x)
(and (numberp x) (= x 42)))
;; returns all the types of a particular value
(defun get-type-info (x)
"return a list if types thet describes argument"
(flet ((check-type (acc type-pair)
"Accumulate description when predicate match"
(if (funcall (car type-pair) x)
(cons (cdr type-pair) acc)
acc)))
;; test x for each type predicate-description
(let ((res (reduce #'check-type
*type-predicates-and-description*
:initial-value '())))
;; check of empty list (no types matched)
(if (null res)
(list 'this-is-neither)
res))))
;; test it
(get-type-info '()) ; ==> (THIS-IS-A-LIST THIS-IS-NULL)
(get-type-info 42) ; ==> (THIS-IS-A-NUMBER
; THIS-IS-AN-INTEGER
; THIS-IS-THE-ANSWER-TO-EVERYTHING)
(get-type-info #()) ; ==> (THIS-IS-NEITHER)
;; Make a function to do side effects
(defun print-type-info (x)
(format t "~{~a~^, ~}." (get-type-info x)))
(print-type-info '()) ; ==> NIL
; and prints "THIS-IS-A-LIST, THIS-IS-NULL."