Common lisp How can I make my variable act like the operator it is holding when it is first in the list?

So, I am very new to lisp, not an advanced programmer. Just start really.

I've been messing around trying to get a very simple genetic algorithm, from scratch, and while most of my code seems to execute at will, I'm stuck with such a simple error / misunderstanding that I'm blocked from the bottom ... Obviously, something I'm not getting it despite my watch on the internet trying to find a solution.

Basically, I know it has something to do with the fact that I am trying to call a variable as if it were an operator (which has a variable) and thus it tells me my function (which is actually just a variable, operator) is undefined.

The beginning of my code works fine.

(defvar *nb* 8)
(defvar *random-operators* '(+ - * /))
(defun get-operator ()
  "Returns an element of the list of operators chosen at random."
  (nth (random (length  *random-operators*)) *random-operators*))

      

So, (get-operator)

one of the four random operators really gets me.

I have used this even simpler code to test the structure of my code and it works as desired.

(defun ga-simple ()
  "Returns the value of genome once it matches *nb* and prints
the number of generations required."
  (do ((genome (random 10) (random 10))
       (generation-counter 1 (incf generation-counter)))
      ((eql genome *nb*)
       (format t
               "The solution is ~S, and it took ~D generations"
               genome
               generation-counter))))

      

The problem arises when I try to create a genome with three variables, one containing an operator and the other two containing integers.

(defun ga-with-operator ()
  (do ((genome 42 (opr1 int1 int2))
       (generation-counter 0 (incf generation-counter))
       (opr1 + (get-operator)
       (int1 (random 10) (random 10))
       (int2 (random 10) (random 10))
      ((eql genome *nb*)
       (format t
               "The solution is ~S, and it took ~D generations"
               genome
               generation-counter))))

      

my compiler warnings tell me where the problem is ...

;Compiler warnings for "./ga-one.lisp" :
;   In GA-WITH-OPERATOR: Unused lexical variable OPR1
;Compiler warnings for "./ga-one.lisp" :
;   In GA-WITH-OPERATOR: Undefined function OPR1/

      

And it's so clear that the function call (ga-with-operator)

says opr1 is an undefined -function-call. So from what I am gathering, when the "do" macro checks the increment condition for the genome of a variable, it reads the list, expecting opr1 to be an operator, not a variable holding the operator ... Now the operator just entered, works fine here, but i dont know how to make the lisp use the estimated value opr1 which is an operator like an operator for integers ...

To keep things simple, I created a function trying to build a single genome using my get-operator function and failed even there lol

(defun get-genome ()
 (let ((operator1 (get-operator)))
   (operator1 (random 10) (random 10))))

      

So I made a test-let function to make sure my assignment to the "let" variable is correct ...

(defun test-let ()
  (let ((rand (get-operator)))
    (print rand)))

      

What does it do ... So now I'm desperately losing and missing something clearly very simple and yet crucial to make it all stick together.

If someone can explain to me or just show me how to get a simple function (get-genome)

to work, I would really appreciate it. I know that lisp expects the operator to be the first item in the list, and my mistake is because I feed it to the variable holding the operator instead of ... How can I convince my variable is the operator it is holding?

if anyone wants to know the working code ...

(defvar *nb* 42)

(defvar *random-operators* '(+ - * /))

(defun get-operator ()
  "Return an element of the list of operators chosen at random."
  (nth (random (length  *random-operators*)) *random-operators*))

(defun get-genome ()
 (let ((operator1 (get-operator)))
   (funcall operator1 (+ 1 (random 9)) (+ 1 (random 9)))))

(defun ga-with-operator ()
  (do ((genome (get-genome) (get-genome))
       (generation-counter 0 (1+ generation-counter)))
      ((eql genome *nb*)
       (format t "The solution is ~S, and it took ~D generations"
               genome generation-counter))))

      

+1


source to share


2 answers


In Common Lisp, you need to use FUNCALL

if a function is returned by a function or a function is stored in a variable.

(defun get-genome ()
 (let ((operator1 (get-operator)))
   (funcall operator1 (random 10) (random 10))))

      

Common Lisp have different namespaces for functions and values. Thus, the name can be either a variable or a function:

(defun foo (list)
  (list list list))

      



The first list

in the last line calls the global function called list

, and the second and third are actually a local variable list

.

(defun ga-with-operator ()
  (do ((genome 42 (opr1 int1 int2))
       (generation-counter 0 (incf generation-counter))
       (opr1 + (get-operator)
       (int1 (random 10) (random 10))
       (int2 (random 10) (random 10))
      ((eql genome *nb*)
       (format t
               "The solution is ~S, and it took ~D generations"
               genome
               generation-counter))))

      

The above function has more problems.

  • Do you see the first one? Hint: try to postpone it properly. Are the parentheses correct?
  • also: is +

    not a function. This is a variable in your code. To make it a function, you will need to quote or use a quote. '+

    or #'+

    .
  • you don't need to either INCF

    generation-counter

    . Just adding 1

    is ok. The loop DO

    updates the variable. Use (1+ generation-counter)

    .
+5


source


Of course, FUNCALL

/ APPLY

is what you want, but just to finish the drawing, note that this also works:

(setf (symbol-function 'operator1) (get-operator))
(operator1 (+ 1 (random 9)) (+ 1 (random 9)))

      



The reason you don't want to do this at all is because the slot binding of the symbols function is global.

0


source







All Articles