0

This is supposed to be a definition of a function which returns t if the entered value is an even natural number and returns nil if the entered value is an odd natural number:

(defun evec (n)
    (if (zp n)
        (if (zerop n)
            t
            nil)
        (evec (- n 2))))

It correctly returns t when I enter an even number and It's supposed to return nil literally for anything else but it doesn't! Actually I guess it does not halt and I don't understand why. When I enter a number like -1 which is obviously not an even natural number, I expect from this code to go through first 'if' because (zp -1) equals t and since -1 is not equal to 0 then (zerop -1) should be nil which means that the output should be nil and the program should terminate.

In fact I know how to implement this function better in way that it actually work and all I need to know is why this code doesn't work, in order to understand this language better because I've just started learning ACL2!...

Thank you for your consideration.

Senmorta
  • 11
  • 1
  • 1
    You need to fix your indentation to make the code easier to read; `(evec (- n 2))` is called when `(zp n)` is `nil`. I take it that `zp` returns `t` for integers, and `nil` otherwise. When `n` is an integer, if it is zero, then `t` is returned, otherwise `nil` is returned. So _any even number other than zero_ should return `nil`, as should any other integer. This does not match your description, so this must not be the right code. That said, calling `(evec (- n 2))` recursively will skip over 0 for positive odd numbers, and all negative numbers will grow in a negative sense, never terminating. – ad absurdum Jun 23 '21 at 13:29
  • OK, so this function is `evenp`, but for natural numbers only. Well, what is it supposed to do when it gets something other than a natural number? Does `(evec -1)` produce an error, or does it just report false? What are the exact test cases? – Kaz Jun 23 '21 at 18:33
  • @adabsurdum I think you are wrong about zp! you can see https://www.cs.utexas.edu/users/moore/acl2/manuals/current/manual/index-seo.php/ACL2____ZP It returns true for 0 and anything other than natural numbers, which is very different from what you are considering. I've corrected the indentation. Thank you. – Senmorta Jun 24 '21 at 18:26
  • @Kaz As I said I expect it to return false. Because I think for something other than natural number it goes through first if's construction, because zp returns true, and then it should return false because that "something else" is not equal to zero. But it doesn't! It does not return anything and kinda sticks. I guess that it goes through an infinite loop and I don't know why and this is my main question. – Senmorta Jun 24 '21 at 18:30
  • @adabsurdum I think you are mistaken! (zp 2) is false! I've just recently checked it in my computer! And besides it is easy to see that 2 is a natural number and according to the document zp returns false for natural numbers and returns true for zero and anything other than natural numbers. – Senmorta Jun 24 '21 at 18:43
  • @Senmorta -- if `zp` does what is claimed, then you should be able to define `zp` as `(defun zp (n) (< n 1))`, assuming that `n` is an _integer_ value. Then your code works for all integers. Either `zp` is not behaving this way for some reason, (this `zp` gives `(zp 0)` --> `t`, `(zp -1)` --> `t`, `(zp 1)` --> `nil`), or something is different between the code run and the code posted. The structure of the code posted is correct; I can't reproduce the problem. – ad absurdum Jun 24 '21 at 19:09
  • I really appreciate your consideration but all I want to know is why my code doesn't work. I have know how to change this to get a code which works correctly. I've just started learning ACL2 and that's why I am having such a question! – Senmorta Jun 24 '21 at 21:31

1 Answers1

2

Looking at ACL2 documentation, what you want could be as simple as:

(defun evec (n)
  (and (not (zp n))
       (evenp n)

Because zp yields true for any object that is not a natural number (integer greater than zero), including objects that are not numbers at all, the following should hold:

(evec "string") -> nil
(evec -40 -> nil ;; in spite of -4 being even!
(evec 0) -> nil ;; in spite of 0 being even!
(evec 1) -> nil
(evec 2) -> t

Howeer, zp has something called a "guard" for the argument being a natural number, so the above ignore the issue of guards.

If guards are being checked then evec will somehow blow up if the input isn't a natural number, due to passing its argument to zp.

Thus only the (evec 1) and (evec 2) cases above are legitimate; the others violate the guard in zp.

(Given all that, why would we ever want to use evec rather than evenp? That is to say, if we have a number X which must be natural, why would we want that fact to be validated by the function which tests evenness? It seems like an irrelevant secondary responsibility to foist onto a function. In mathematics, there isn't a separate definition of evenness for natural numbers.)

Kaz
  • 55,781
  • 9
  • 100
  • 149
  • I've set the gaurd-checking on nil. I just want to know why my code doesn't work. Even if we put negative integers and absurd input beside (like -5 and "adwdasd" respectively!!) the code should work for natural numbers and return true for even numbers and false for odd numbers but it doesn't work as I expect for odd numbers and I don't understand why and I just want to find out. – Senmorta Jun 24 '21 at 18:22