Re: Function from a symbolic expression
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
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
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
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
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
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
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.