Undesired output in Racket - racket

I'm working on a homework assignment and am a little bit confused as to what produced this output. Here is the code:
#lang racket
(define (my_calc calcType radius); define the function and set up the parameters
(define PI 3.1416); define PI
(cond ((and (= calcType 1) (positive? radius))); check to see whether the calc function is one and the radius is positive
((* 2 PI radius radius)); return the area of a circle
((and (= calcType 2) (positive? radius))); check to see whether the calc function is 2 and the radius is positive
((* (/ 4 3) PI radius radius radius)); return the volume of a sphere
(else #f); if calc function is not 1 or 2 or the radius is not positive, return false
)
)
(my_calc 1 10)
(my_calc 2 10)
(my_calc 0 1)
(my_calc 1 0)
and here is the output:
#t
628.32
6.2832
0
I have no idea why the first one would return true, it should return the area of a circle. There isn't even a return statement that would allow that. The second one seems to work just fine. The third one should produce false, but it produces the second answer divided by a hundred for some reason. And the 0 at the bottom is beyond me. Can anyone help me? Thank you.

Your first procedure in a cond case has to be the test expression followed by the result. See the documentation, https://docs.racket-lang.org/reference/if.html.
For example:
(cond
[; test expression
(and (= calcType 2) (positive? radius))
; following result
((* (/ 4 3) PI radius radius radius))]
[else whatever]
)
I would recommend using square brackets for each cond case for legibility.
In your case,
[(and (= calcType 1) (positive? radius))]
The test expression is (and (= calcType 1) (positive? radius)) but there is no following procedure.
You have the same problem for all of your cond cases. Good luck.

Related

Getting the measurements for stretching

I am creating an algorithm to help me expand boxes to the correct size, as such:
I made a code that asks two points that should be the new depth and measures them. Then subtracts to the original depth of the block (0.51) and then asks the side to stretch.
(defun mystretchh ( dis / pt1 pt2 sel )
(while
(and
(setq pt1 (getpoint "\nFirst point of selection window: "))
(setq pt2 (getcorner pt1 "\nSecond point of selection window: "))
(not (setq sel (ssget "_C" pt1 pt2)))
)
(princ "\nNo objects where found in the selection window.")
)
(if sel
(progn
(command "_.stretch" sel "" "_non" '(0 0) "_non" (list dis 0))
t
)
)
)
(defun c:test (/ a x c p)
;ungroup
(command "pickstyle" 0)
;variables
(initget (+ 1 2 4))
(setq p (getpoint "\nSelect first point: "))
(setq c (getpoint "\nSelect second point: "))
(command "_.dist" p c)
(setq x (rtos (getvar 'distance) 2 3))
;calculate distance to stretch
(setq a (- x 0.51))
;stretch
(mystretchh a)
;regroup
(command "pickstyle" 1)
(print "Module modified.")
(princ)
)
I have two problems:
The stretch is working backwards, I tried using negative values to no avail.
It reports a syntax error, but I cannot find it.
I haven't touched AutoLISP for half a year - maybe some of you can find the problems in a blink of an eye.
You can calculate the distance between two points using the standard distance function, rather than calling the DIST command and then retrieving the value of the DISTANCE system variable.
Hence, this:
(command "_.dist" p c)
(setq x (rtos (getvar 'distance) 2 3))
Can become:
(setq x (rtos (distance p c) 2 3))
However, you are receiving a syntax error because you have converted the distance to a string using rtos, and then you are attempting to perform arithmetic on the string here:
(setq a (- x 0.51))
There is no need to convert the distance to a string, and so these expressions can become:
(setq a (- (distance p c) 0.51))
You may also want to check whether (distance p c) is greater than 0.51 before performing this subtraction to avoid unexpected results.
To determine the appropriate direction, since your current code can only stretch along the x-axis, you'll need to check whether or not the x-coordinate of point p is greater than that of point c.

Unused Lexical Variable

Just started learning lisp. I have no idea why I am getting these errors or even what they mean. I am simply trying to code an approximation of pi using the Gregory-Leibniz series, here is the code.
(defun gl (n)
(defparameter x 0) ;init variable to hold our runnning sum
(loop for y from 0 to n ;number of iterations, starting from 0 to desired n
(if (= y 0) ;if n is 0 then we just want 4
(defparameter w 4))
(if (> y 0) ;else, 4*(-1^y)/((2 * y)+1)
(defparameter w (* 4 (/ (exp -1 y) (+ (* 2 y) 1)))))
(+ x w)) ;add to our running sum
(write x)) ;once loop is over, print x.
I have tried using setq, defvar, let etc. instead of defparameter but I still get "Undeclared free variable X".
I also get the error "Unused lexical variable N" even though I am using it for my loop, which is weird also.
How can I fix this and why is it happening? Thanks!
Here is the code after Emacs auto-indented it:
(defun gl (n)
(defparameter x 0)
(loop for y from 0 to n
(if (= y 0)
(defparameter w 4))
(if (> y 0)
(defparameter w (* 4 (/ (exp -1 y) (+ (* 2 y) 1)))))
(+ x w))
(write x))
Compiling the following code with SBCL gives one error and two warnings.
One warning says that x is undefined.
You should not call defparameter from inside your function, since defvar and defparameter are used to declare dynamic variables and to set their value in the global scope. Prefer to have let bindings, or, since you already are using a loop, a with clause. When you want to modify a binding, use setf.
The errors comes from the macroexpansion of LOOP, which is malformed. For SBCL, that means that the code is treated as dead-code for the rest of the function compilation; that explains why n appears not to be used, which is what the second warning is about.
There are various fixes remaining to be done:
Use function EXPT, not EXP.
Calling (+ x w) only computes a value but does not modify x, the result is useless.
Prefer using if as expression, like a ternary operator in other languages, in your case the code can be simplified
Adding one can be done with function 1+ (that's the name of the function, not a special syntax for adding constants)
The write operation is rarely needed, especially if you are computing a mathematical formula; just return the value, and the REPL will print it automatically.
Small corrections that make your code works:
(defun gl (n)
(let ((x 0))
(loop
for y from 0 to n
for w = (if (= y 0)
4
(* 4 (/ (expt -1 y) (+ (* 2 y) 1))))
do (setf x (+ x w)))
(write x)))
I would personally get rid of x and w, and use a SUM loop clause.
(defun gl (n)
(loop
for y from 0 to n
sum (if (zerop y)
4
(* 4 (/ (expt -1 y)
(1+ (* 2 y)))))))

What is the difference between the two summation functions in Common Lisp, thanks

Both code examples are the for the summation formula:
Code example 1
(defund sigma (func n)
(cond ((= n 1)(funcall func 1)
(t (+ (sigma func(1- n))
(funcal func n))))))
Code example 2
(defund sigma(n)
(cond ((= n 1)1)
(t (+ n(sigma func(1- n))))
Both code examples are the for the summation formula
No they do not. While the second sums the numbers, the first calls a function with the number as argument and sums the result.
It would have f(i) instead of just i after the sigma in the mathematical notation. In higher order function lingo it is a term function. Here are some examples using 10:
(sigma (lambda (v) 1) 10) ; ==> 10 in CL I'd use (sigma (constantly 1) 10)
(sigma #'1+ 10) ; ==> 65
(sigma #'identity 10) ; ==> 55
The second would only produce the third example:
(sigma 10) ; ==> 55
PS: Your functions have syntax errors and typos I have just ignored. You'lll need to fix these before it works. The hardest one is perhaps the missing ending parenthesis in the first cond term making the cond only have one term and the second function also passing func, which doesn't make sense since its version only takes one argument.

Racket - comparing/analyzing two structures

So I have an assignment with the following criteria:
The definition of a function named euclidean-distance is given. This function computes the distance between two points in the xy-plane. The points are given as four separate numbers: x1, y1, x2, and y2.
Rewrite the function so that it takes two arguments, both of which are of type Posn, and run the same computation.
> (define the-origin (make-posn 0 0))
> (define some-point (make-posn 3 7))
> (euclidean-distance the-origin some-point)
#i7.615773105863909
> (euclidean-distance (make-posn 1 1) (make-posn 4 5))
5
My trouble here is that I'm not sure how to extract the information I need in order to compare square the differences and such. What I have so far:
(define (euclidean-distance posn1 posn2)
(sqrt (+ (sqr (- posn1-x posn2-x))
(sqr (- posn1-y posn2-y)))))
Not sure how to go about what I need to do.
Just use the accessor procedures of each position, like this:
(define (euclidean-distance posn1 posn2)
(sqrt (+ (sqr (- (posn-x posn1) (posn-x posn2)))
(sqr (- (posn-y posn1) (posn-y posn2))))))

Lisp macro that does loop "unrolling"

My first steps with Lisp macros...
(defconstant width 7)
(defconstant height 6)
...
; board is a 2D array of width x height
; and this is my first ever macro:
(defmacro at (y x)
`(aref board ,y ,x))
; "board" must be available wherever the macro is used.
(defun foo (board ...)
...
(loop for y from 0 to (1- height) do
; thanks to the "at" macro, this is cleaner:
(let ((score (+ (at y 0) (at y 1) (at y 2))))
(loop for x from 3 to (1- width) do
(incf score (at y x))
; ...do something with score
(decf score (at y (- x 3)))))))
The code uses my first ever macro, the "at" one. It emits "access instructions" to read from board[y][x], so it can only be used in places where "board" exists, like the function "foo" above.
This worked - and then I realized that... I can go further.
The two nested loops are "statically" constrained: from 0 to height-1 for y, from 3 to (width-1) for x... so in theory, I can create a macro that emits (unrolls!) the exact incf and decf instructions done in the loops' code!
I tried this:
(defmacro unroll ()
(loop for y from 0 to (1- height) do
`(setf score (+ (at ,y 0) (at ,y 1) (at ,y 2)))
(loop for x from 3 to (1- width) do
`(incf score (at ,y ,x))
`(decf score (at ,y (- ,x 3))))))
...but failed - "(macroexpand-1 '(unroll))" shows me NIL.
What am I doing wrong?
In case it is not clear, I want to use two nested loops and emit "code" at the beginning of the outer loop, and for each iteration of the inner loop.
Any help most appreciated (I am a LISP newbie).
UPDATE: After #larsmans' kind advice, I succeeded in applying this change to my code - and to my immense satisfaction, I watched the Lisp version of my Score4 algorithm become the 2nd fastest implementation, behind only C and C++ (and faster than OCaml!).
You should collect the statements you generate inside the macro's loop, not pretend to execute them with do:
(defmacro unroll ()
(loop for y from 0 to (1- height)
collect
`(begin (setf score (+ (at ,y 0) (at ,y 1) (at ,y 2)))
,#(loop for x from 3 to (1- width)
collect `(begin (incf score (at ,y ,x))
(decf score (at ,y (- ,x 3))))))))