If anyone is interested, I cleaned up the question to (hopefully) make it clearer, as well as adding the macro-calling-a-macro solution.
While some may consider it esoteric, I thought it was a good example of the power `intern` can provide, as well as a good way to avoid macros and stick to pure functions. Here is the re-worked version: http://stackoverflow.com/questions/43958471/how-to-create-clojure-defn-functions-automatically-without-macros/ Alan On Thu, May 11, 2017 at 10:15 AM, Alan Thompson <clooj...@gmail.com> wrote: > Actually someone else wrote the original CLJS question (1): > http://stackoverflow.com/questions/43897632/mapped- > calls-to-clojurescript-macro > > It was marked as a duplicate of this question (2): > http://stackoverflow.com/questions/43897632/mapped- > calls-to-clojurescript-macro This one also had an answer using > `intern` to avoid the need for a macro. > > I didn't think question (1) was an exact duplicate of (2), and I wanted to > work out the details of solving (1) using `intern` instead of macros (it > seemed like a good goal at the time...). I tried to simplify question (1) > w/o the CLJS callback stuff, and may have oversimplified. > > Since question was closed as being a "duplicate" (in error, I think), I > couldn't answer there and posed the Q&A style answer separately at (3): > http://stackoverflow.com/questions/43904628/how-to- > create-clojure-defn-functions-automatically > > The main goal I had here was simply finding a good way to avoid macros > when auto-generating functions, and to generalize/document the technique > described in (2) using `intern`. > > Alan > > P.S. Regarding (3), Joel Spolsky, creator of StackOverflow, has often > encouraged people to post both a question and its answer on the site: > https://stackoverflow.blog/2011/07/01/its-ok-to-ask-and- > answer-your-own-questions In fact, they even have a special button > for this purpose. > > > > On Thu, May 11, 2017 at 9:39 AM, Timothy Baldridge <tbaldri...@gmail.com> > wrote: > >> I assume this is a real problem you are encountering since you wrote the >> original Stack Overflow questions. As Dragan mentioned, this example >> doesn't warrant such a complex solution, maps and keywords *are* function, >> so all you really need is `foo` as a getter. Or even if they weren't >> functions you still have `(partial get foo)`. >> >> On Thu, May 11, 2017 at 10:27 AM, Alan Thompson <clooj...@gmail.com> >> wrote: >> >>> Since the original question was in CLJS, which has neither `intern` nor >>> `eval`, does that mean the macro mapping another macro approach is the only >>> solution there? >>> >>> >>> On Thu, May 11, 2017 at 9:18 AM, Alan Thompson <clooj...@gmail.com> >>> wrote: >>> >>>> I like the idea of using `eval` and `memoize`. I'll have to keep that >>>> in mind. >>>> Alan >>>> >>>> On Thu, May 11, 2017 at 7:58 AM, Timothy Baldridge < >>>> tbaldri...@gmail.com> wrote: >>>> >>>>> This is a somewhat weird answer to a overcomplicated problem. As >>>>> mentioned, the data is a map to start with, and maps are functions so >>>>> treating the maps as data is probably the best approach. And like Dragan, >>>>> I'm unsure why this example doesn't use `(data :able)`. >>>>> >>>>> When I do need to generate functions at runtime, and I can't use >>>>> macros (for the reasons mentioned), I'll either use a macro that creates a >>>>> var, or use eval perhaps in conjunction with a memoize. I used this a lot >>>>> in my work with JavaFx. Do some reflection, generate some code, eval the >>>>> code and return a function, memoize that process so we can get the >>>>> generated function via name. So the interface looks like this: >>>>> >>>>> ((get-setter button :text) "hey") >>>>> >>>>> Get-setter does a ton of reflection, but calling the returned function >>>>> remains fast due to the combination of eval and memoization. >>>>> >>>>> >>>>> >>>>> On Thu, May 11, 2017 at 2:55 AM, Dragan Djuric <draga...@gmail.com> >>>>> wrote: >>>>> >>>>>> What's wrong with (foo :able) => "Adelicious!" and (:able foo) => >>>>>> "Adelicious!"? >>>>>> >>>>>> >>>>>> On Thursday, May 11, 2017 at 9:20:19 AM UTC+2, Alan Thompson wrote: >>>>>>> >>>>>>> A recent question on StackOverflow raised the question of the best >>>>>>> way to automatically generate functions. Suppose you want to automate >>>>>>> the >>>>>>> creation of code like this: >>>>>>> >>>>>>> >>>>>>> >>>>>>> (def foo >>>>>>> {:able "Adelicious!" >>>>>>> :baker "Barbrallicious!" >>>>>>> :charlie "Charlizable"}) >>>>>>> (def bar >>>>>>> {:able "Apple" >>>>>>> :baker "Berry" >>>>>>> :charlie "Kumquat"}) >>>>>>> >>>>>>> (defn manual-my-foo [item] (get foo item)) >>>>>>> (defn manual-my-bar [item] (get bar item)) >>>>>>> >>>>>>> (manual-my-foo :able) => "Adelicious!" >>>>>>> (manual-my-bar :charlie) => "Kumquat" >>>>>>> >>>>>>> >>>>>>> You could write a macro to generate one of these at a time, but you >>>>>>> can't pass a macro to a higher-order function like `map`, so while this >>>>>>> would work: >>>>>>> >>>>>>> >>>>>>> (generate-fn :foo) ;=> creates `my-foo` w/o hand-writing it >>>>>>> >>>>>>> >>>>>>> this wouldn't work: >>>>>>> >>>>>>> >>>>>>> (map generate-fn [:foo :bar :baz]) >>>>>>> >>>>>>> While one could write a 2nd macro to replace `map`, this is a >>>>>>> symptom of the "Turtles All the Way Down" problem. One workaround is to >>>>>>> avoid macros altogether and use only functions to generate the required >>>>>>> `my-foo` and `my-bar` functions. The trick is to make use of the >>>>>>> built-in >>>>>>> Clojure function `intern` both to save the newly generated functions >>>>>>> into >>>>>>> the global environment and to retrieve the pre-existing maps `foo` and >>>>>>> `bar`. Full details are available Q&A-style at the StackOverflow >>>>>>> post >>>>>>> <http://stackoverflow.com/questions/43904628/how-to-create-clojure-defn-functions-automatically/43904717#43904717> >>>>>>> . >>>>>>> >>>>>>> Enjoy, >>>>>>> Alan >>>>>>> >>>>>>> -- >>>>>> 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. >>>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> “One of the main causes of the fall of the Roman Empire was >>>>> that–lacking zero–they had no way to indicate successful termination of >>>>> their C programs.” >>>>> (Robert Firth) >>>>> >>>>> -- >>>>> 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. >>>>> >>>> >>>> >>> -- >>> 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. >>> >> >> >> >> -- >> “One of the main causes of the fall of the Roman Empire was that–lacking >> zero–they had no way to indicate successful termination of their C >> programs.” >> (Robert Firth) >> >> -- >> 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. >> > > -- 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.