I've gotten a lot of the suppor methods working correctly (like
fitness) but I'm having problem convering the pseudocode on page 14
for generating random expressions to make up my initial population.
Here's what I have so far:
(defn gen-rand-expr [functions terminals max-depth arity method]
(if (or (= max-depth 0) (and (= method :grow) (< (rand) (/ (count
terminals) (+ (count terminals) (count functions))))))
(rand-element terminals)
(let [arg1 (gen-rand-expr functions terminals (- max-depth 1) arity method)
arg2 (gen-rand-expr functions terminals (- max-depth 1) arity method)
func (rand-element functions)]
(func arg1 arg2))))
First, how can I print out the definition of a function in clojure?
For example, if I do (defn add [x y] (+ x y)) how can inspect this
definition, like (show-def add) -> (defn add [x y] (+ x y)). This
would help a lot in debugging the random programs I'm trying to
generate.
Second, I believe the last line is the problem in my code. Let's
assume the function randomly selected was +, it will run (+ 1 2) and
the entire function returns 3 instead of a randomly generated syntax
tree like I need. I then tried '(func arg1 arg2) hoping it would
prevent evaluation, but then it will always just return (func arg1
arg2) which isn't what I need either. I need it to actually return a
syntax tree made up of expressions like (+ 1 2) but unevaluated.
I am guessing I need to start reading and using macros at this point?
Rob
You'll want to either eval the expression, or apply the first item in
the list to the rest:
user=> (eval (list + 1 2))
3
user=> (let [form (list + 1 2)]
(when (not (empty? form))
(apply (first form) (rest form))))
3
If it's okay, could somebody explain the difference between what's
happening here:
and here:
user> (def my-func (list + 1 2))
#'user/my-func
user> (my-func)
; Evaluation aborted.
user> (eval my-func)
user> (def my-func (list + 1 2))
#'user/my-func
3
I don't really understand how:
user>(my-func) is NOT eval on my-func in the REPL. My understanding is
the first item in the list is treated as a function, with the rest of
the list passed as arguments. Wouldn't the REPL just be calling eval
internally on everything you type in?
As, indeed, can self-evaluating forms:
user=> (eval 3)
3
user=> (eval (eval (eval (list + 1 2))))
3
user=> (eval :foo)
:foo
user=> (eval '+)
#<core$_PLUS___3949 clojure.core$_PLUS___3949@1d05c9a1>
user=> (eval 'eval)
#<core$eval__4610 clojure.core$eval__4610@4ef5c3a6>
This kind of fiddling around in a REPL is very enlightening.