0
votes

I have been working on this problems, " make a function that given two months, say if the first month appears before the second in the calendar printing true " . I can only use , cons, append, list, equal, defun, car, cdr, cond , T , NIL

I though the best way to do this is , assing a value to each of the months , and make separated functions , one funtions for the months and another one that verify the month.

Here my code: I wont paste all of it just cause im still testing: I did it this way , not sure if I assigned the correct value to the month , cause im not sure how to assing a value to a string.

 (defun months(month)
             (cond ((null month)0)
                   ((= month (format t "january") 1))
                    ((= month (format t "february") 2))
                             nil ))

    the other function:

    (defun check-month(month1 month2)
        (if (< (months month1) (months month2))
            T
            NIL
        )   
    )

and when I called the function check-month it says:

 (check-month "january" "february")

*** - IF: variable months has no value


The actual result should be like this: 
  (check-month “january” ”february”)
      T
2
Nowhere in the problem statement is there a reference to strings, are you sure you aren't making this more difficult than necessary?coredump
your code makes a bunch of basic errors. This book might help to learn the basics of Lisp: cs.cmu.edu/~dst/LispBook You can download a PDF from there.Rainer Joswig

2 Answers

3
votes

This isn't an answer in the form of code, since I don't want to do your homework for you.

First of all: the error you mention clearly comes from some code other than the code in your question: it is always a good idea to actually check the code you think you are checking.

Secondly, what purpose does an expression like (if (f ...) t nil) serve? The only useful purpose is if you want to canonicalize the return value of (f ...) to t or nil. But what does (equal a b) return?

Secondly: if you are really only allowed to use cons, append, list, equal, defun, car, cdr, cond t and nil then you are not allowed to use <, or =, or a number of other functions and other operators that you have used. So you have an interesting problem to solve.

An approach to solving it is to write a function called first-in-list: this takes three arguments, and here's its specification:

(first-in-list a b l) returns whichever of a or b is first in l, comparing with equal, or nil if neither of them is (and it's up to you what it returns if a and b are the same).

You can write this function with cond, car, cdr, equal, nil, t and an auxiliary function called first-in-list which you will have to write.

Now you can write a function month-before-p which takes two arguments ma and mb and:

  • checks if ma is equal to mb and returns nil if so (this avoids the ambiguity in first-in-list's specification;
  • checks if (first-in-list ma mb (list "january" ....)) is equal to ma or mb;
  • for added value could check if the result of the call to first-in-list was nil, which is an error.

This function can also be written with cond, equal, t, and nil, as well as the auxilliary function first-in-list you have already written.

3
votes

Format outputs things. It does not make sense there. Besides, it is not in the list of operators you are allowed to use.

= compares numbers. Strings are not numbers. Besides, it is not in the list of operators you are allowed to use. From that list, use equal to determine equality.

This should answer your original question (but “assing” is not an english word).

However, < is not in the list of operators you are allowed to use, so converting a string to a number is not useful for you.

Instead, I'd propose the following: given a list ("january" "february" "march" …), write a function that takes a month name and returns the rest of the list starting with that month. Then call it with the first month name and check that the second is contained in the return value.

Hint: in standard, unconstrained Lisp, it could look like this: (member month-b (member month-a months :test #'equal) :test #'equal)).