Re: Function from a symbolic expression

2014-04-01 Thread Jony Hudson
Thanks all :)

@A. Webb: I knew it must be something dopey, thanks for the advice!

@Lee That is indeed exactly what I'm trying to do, and that method is much 
more elegant and straightforward. In fact, precisely what I'm trying to do 
is write some notes on symbolic regression for some students, which has 
come out looking quite a lot like an inferior version of the code you 
linked! Reminds me of the saying a week in the lab saves an hour in the 
library. Although, truthfully, I think the main benefit in writing the 
notes is to make sure _I_ understand it, not the students :-)


Jony

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Function from a symbolic expression

2014-03-31 Thread Jony Hudson
Hi all,

 I've gotten myself stuck with what is probably a simple question, and 
wonder if someone can advise. What I want to be able to do is to take a 
symbolic expression, like '(+ 1 x) say, and turn it in to a function 
programmatically, so that I can call something like:

(def ex '(+ 1 x))
(def exf (functionalise ex 'x))
(exf 3) ;; = 4

where functionalise is the thing I want to implement, and it's taking the 
symbol to treat as an argument/variable in its second place. I can come up 
with a nasty solution:

(defn functionalise [ex var] (fn [xp] (eval (postwalk-replace {var xp} 
ex

but this has the significant downside that it does the walking every time 
the resulting function is called! 

Not being much of a macro-writer, I tried the following:

(defmacro functionalise
  [ex var]
  (let [arg (gensym)
body (postwalk-replace {var arg} ex)]
`(fn [~arg] ~body)))

But it doesn't work, in the sense that evaluating it gives something like (+ 
1 G__6779) .

Like I say I've not got much macro experience, and feel like something 
hasn't clicked in my head yet. Any clues?

Thanks in advance,


Jony

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Function from a symbolic expression

2014-03-31 Thread A. Webb


On Monday, March 31, 2014 12:13:25 PM UTC-5, Jony Hudson wrote:


 (defmacro functionalise
   [ex var]
   (let [arg (gensym)
 body (postwalk-replace {var arg} ex)]
 `(fn [~arg] ~body)))


This works as written, it is just that macros do not evaluate their 
arguments, so you do not want to quote you expression. 

(def foo (functionalise (+ 2 x) x))
(foo 40) ;= 42

If you are working with quoted expressions, you'll have to eval in the 
macro and take the one-time hit there

(defmacro functionalise2
  [ex var]
  (let [arg (gensym)
body (clojure.walk/postwalk-replace {var arg} ex)]
`(fn [~arg] ~(eval body

(def foo2 (functionalise2 '(+ 2 x) x))
(foo2 40) ;= 42

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Function from a symbolic expression

2014-03-31 Thread Lee Spector

On Mar 31, 2014, at 1:27 PM, A. Webb a.webb@gmail.com wrote:
 
 If you are working with quoted expressions, you'll have to eval in the macro 
 and take the one-time hit there
 
 (defmacro functionalise2
   [ex var]
   (let [arg (gensym)
 body (clojure.walk/postwalk-replace {var arg} ex)]
 `(fn [~arg] ~(eval body
 
 (def foo2 (functionalise2 '(+ 2 x) x))
 (foo2 40) ;= 42
 

Or if the reason that you're quoting is because that's a stand-in for an 
expression that will be generated dynamically then maybe you don't want to do 
it in a macro, but instead call eval on function-defining expression that 
includes your expression and takes an argument for the variable.

Easier shown than said:

(defn functionalise
  [ex var]
  (eval (list 'fn (vector var) ex)))

(def ex '(+ 1 x))

(def exf (functionalise ex 'x))

(exf 3) ;; = 4

This calls eval only once when you call functionalise, and doesn't do any tree 
walking.

FWIW this is the trick I use in the tiny genetic programming system at: 
https://github.com/lspector/gp/blob/master/src/gp/evolvefn.clj

 -Lee 

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Function from a symbolic expression

2014-03-31 Thread François Rey

On 31/03/14 23:25, Lee Spector wrote:

(defn functionalise
   [ex var]
   (eval (list 'fn (vector var) ex)))

(def ex '(+ 1 x))

(def exf (functionalise ex 'x))

(exf 3) ;; = 4

This calls eval only once when you call functionalise, and doesn't do any tree 
walking.

FWIW this is the trick I use in the tiny genetic programming system at: 
https://github.com/lspector/gp/blob/master/src/gp/evolvefn.clj

  -Lee


That would not work with a symbol other than x:

(defexf  (functionalise  ex  '*z*))

How about this:

(defnfunctionalise  [ex  var]
  (eval`(fn[~(clojure.core/symbol  xp)]
   ~(clojure.walk/postwalk-replace  {var'xp}ex



--
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups Clojure group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Function from a symbolic expression

2014-03-31 Thread François Rey

On 31/03/14 23:51, François Rey wrote:

On 31/03/14 23:25, Lee Spector wrote:

(defn functionalise
   [ex var]
   (eval (list 'fn (vector var) ex)))

(def ex '(+ 1 x))

(def exf (functionalise ex 'x))

(exf 3) ;; = 4

This calls eval only once when you call functionalise, and doesn't do any tree 
walking.

FWIW this is the trick I use in the tiny genetic programming system 
at:https://github.com/lspector/gp/blob/master/src/gp/evolvefn.clj

  -Lee


That would not work with a symbol other than x:
(defexf  (functionalise  ex  '*z*))
How about this:

(defnfunctionalise  [ex  var]
   (eval`(fn[~(clojure.core/symbol  xp)]
~(clojure.walk/postwalk-replace  {var'xp}ex


Forget that, my code does not work with 'z too, obviously.
Too late, time to go to bed for me

--
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups Clojure group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Function from a symbolic expression

2014-03-31 Thread Lee Spector

On Mar 31, 2014, at 5:59 PM, François Rey fmj...@gmail.com wrote:
 Forget that, my code does not work with 'z too, obviously.
 Too late, time to go to bed for me

But my code *does* work with 'z as long as z is also the variable used in the 
expression, which is what I assume was intended:

(defn functionalise
  [ex var]
  (eval (list 'fn (vector var) ex)))

(def ex '(+ 1 z))

(def exf (functionalise ex 'z))

(exf 3) ;= 4

You could also generalize this for expressions with any number of variables, 
but again I'm assuming that you know what the names of the variables are.

 -Lee

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.