Page 1 of 2

everything is wrong

Posted: Sun Sep 21, 2014 1:11 am
by hill0093
I'm new to Lisp, using lispworks 6.1 personal on windows seven.
This is a function which will eventually have calDa as its argument.
All the variables should do like 31 bit integer arithmetic like truncated divide.
Lispworks says calDa unbound.

Code: Select all

  (defun linDaOfCalDa () 
    (declare ((signed-byte 32) linDaOfCalDa calDa yr mo da i r mo14by12 calDaOfLinDa linDa) )
    (set calDa 20140920) 
    (set mo (/ calDa 100)) 
    (set yr (/ calDa 10000)) 
    (set da (- calDa (* mo 100))) 
    (mo (- mo (* yr 100))) 
    (mo14by12 (/ (- mo 14) 12)) 
    (i (+ yr 4900 mo14by12)) 
    (r (+ (* (1461 (/ i 4))) 32075) da) 
    (r (+ r (* 367 (- mo (- 2 (* mo14by12 12)))))) 
    (r (- r (/ (* 3 (/ (+ yr 4900 mo14by12) 100)) 4))) 
    (linDa (- r 1721060))
    return(linDa) 
  )

Re: everything is wrong

Posted: Sun Sep 21, 2014 2:38 pm
by Goheeca
Because set evaluates its first argument and it's an unbound symbol calDa.
Look at this:

Code: Select all

(defvar a nil)
(defvar b (find-symbol "A"))
(set b t)
a ; => t
so you are looking for devfar & setq (or setf) or let, just check them all out.

Re: everything is wrong

Posted: Sun Sep 21, 2014 5:14 pm
by hill0093
Thank you for teaching me. I modified the function.
Why is my answer now an unfinished divide?
And I am still wondering about how to ensure integer arithmetic.
CL-USER 1 > (defun linDaOfCalDa() ;calDa to be future function parameter
(declare ((signed-byte 32) linDaOfCalDa calDa yr mo da i r mo14by12 calDaOfLinDa linDa) )
(setf calDa 20140921) ;this line to be omitted later
(setf mo (/ calDa 100))
(setf yr (/ calDa 10000))
(setf da (- calDa (* mo 100)))
(setf mo (- mo (* yr 100)))
(setf mo14by12 (/ (- mo 14) 12))
(setf i (+ yr 4900 mo14by12))
(setf r (+ (/ (* 1461 i) 4) -32075 da))
(setf r (+ r (* 367 (- mo (- 2 (* mo14by12 12))))))
(setf r (- r (/ (* 3 (/ (+ yr 4900 mo14by12) 100)) 4)))
(setf linDa (- r 1721060))
(setf linDaOfCalDa linDa)
)
LINDAOFCALDA

CL-USER 2 > (linDaOfCalDa)
3063548670337/4000000

CL-USER 3 >

Re: everything is wrong

Posted: Sun Sep 21, 2014 5:38 pm
by Goheeca
For the integer division you should look into the rounding family of functions, you'll probably pick the floor function + mod & rem.

The declare is only for optimization, not for changing the meaning of a program.

Re: everything is wrong

Posted: Sun Sep 21, 2014 6:41 pm
by edgar-rft
The "unfinished divide" is a number of type RATIO:

Code: Select all

(/ 1 2)         => 1/2  ; ratio
(/ 1.0 2.0)     => 0.5  ; float
(truncate 1 2)  => 0    ; integer
More examples can be found in Practical Common Lisp, Chapter 10, Section Numbers plus the following few sections, demonstrating Common Lisp math using various types of numbers.

Re: everything is wrong

Posted: Sun Sep 21, 2014 8:24 pm
by hill0093
Thank you both for the education.
I will study more tomorrow, bedtime now.

Re: everything is wrong

Posted: Tue Sep 23, 2014 12:21 am
by hill0093
I hope yhat I got one small step ahead,
but it says that INTDIV is unbound.
(defun intDiv(num den)
(setf ans (truncate num den))
(print ans)
(return ans)
)
(print intDiv(-3 2))

Re: everything is wrong

Posted: Tue Sep 23, 2014 12:36 am
by Goheeca
You have to use the calling convention:

Code: Select all

(intDiv -3 2)

Re: everything is wrong

Posted: Tue Sep 23, 2014 4:53 am
by hill0093
I modified the call. Here is Lispworks answer.
Correct answer comes from within function, not return from function?

CL-USER 1 > (defun intDiv(num den)
(setf ans (truncate num den))
(print ans)
(return ans)
)
INTDIV

CL-USER 2 > (print (intDiv -3 2))

-1
Error: Not inside a block named NIL.

Re: everything is wrong

Posted: Tue Sep 23, 2014 5:13 am
by Goheeca
You shouldn't use return in CL. The defun has an implicit progn as a body and its value is a value of the last expression so you just write:

Code: Select all

(defun intDiv (num den)
  (truncate num den))
or

Code: Select all

(defun intDiv (num den)
  (let ((ans (truncate num den)))
    ans))