Re: testing local functions?
Brian, thats way cool! (I still have to think this through, thats high magic!) Thank you for sharing this, and kind regards, alux On 10 Sep., 21:04, Brian Marick wrote: > I've worked out a way to test local functions. When I tried it out by hand, > it felt good. See here:http://bit.ly/b1AoG7 > > Implementing it is on my wishlist for Midje, my test > framework.http://github.com/marick/Midje > > On Sep 10, 2010, at 6:24 AM, alux wrote: > > > Hello, > > > I always thought it to be good style to make helper functions only as > > visible as needed, e.g. by using letfn. > > > But when I want to test my code, I just dont see a way to access these > > local functions for tests. > > - > Brian Marick, independent consultant > Mostly on agile methods with a testing slant > Author of /Programming Cocoa with > Ruby/www.exampler.com,www.exampler.com/blog,www.twitter.com/marick -- 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
Re: testing local functions?
I've worked out a way to test local functions. When I tried it out by hand, it felt good. See here: http://bit.ly/b1AoG7 Implementing it is on my wishlist for Midje, my test framework. http://github.com/marick/Midje On Sep 10, 2010, at 6:24 AM, alux wrote: > Hello, > > I always thought it to be good style to make helper functions only as > visible as needed, e.g. by using letfn. > > But when I want to test my code, I just dont see a way to access these > local functions for tests. - Brian Marick, independent consultant Mostly on agile methods with a testing slant Author of /Programming Cocoa with Ruby/ www.exampler.com, www.exampler.com/blog, www.twitter.com/marick -- 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
Re: testing local functions?
>From someone who's window to your code is your public API, a refactoring should make no observable change. So if you only test on the public API, but you test it thoroughly, then your tests will ensure that this property holds. Tests that delve into implementation details and private things, are more brittle because they are affected by changes in implementation details. On Fri, Sep 10, 2010 at 14:16, alux wrote: > Hi James, > > thanks for your answer. > >> your tests should be testing your public interface > > Hhmmm. > Well, I tend to disagree here. I sometimes like to have tests in place > for things I want to refactor. To not inadvertently do something > foolish. > > But I agree that this is not easily accomplishable. > > Greetings, alux > > On 10 Sep., 13:39, James Reeves wrote: >> On 10 September 2010 12:24, alux wrote: >> >> > I always thought it to be good style to make helper functions only as >> > visible as needed, e.g. by using letfn. >> >> > But when I want to test my code, I just dont see a way to access these >> > local functions for tests. >> >> I don't believe you can. You could make them private functions, and >> then test them by referring directly to their vars, e.g. >> >> (#'your.namespace/private-function ...) >> >> But in general, your tests should be testing your public interface, >> not a specific implementation. Your tests shouldn't care what your >> code does behind the scenes, so long as the publicly accessible >> functions return the correct result. >> >> - James > > -- > 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 -- Venlig hilsen / Kind regards, Christian Vest Hansen. -- 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
Re: testing local functions?
Hi James, thanks for your answer. > your tests should be testing your public interface Hhmmm. Well, I tend to disagree here. I sometimes like to have tests in place for things I want to refactor. To not inadvertently do something foolish. But I agree that this is not easily accomplishable. Greetings, alux On 10 Sep., 13:39, James Reeves wrote: > On 10 September 2010 12:24, alux wrote: > > > I always thought it to be good style to make helper functions only as > > visible as needed, e.g. by using letfn. > > > But when I want to test my code, I just dont see a way to access these > > local functions for tests. > > I don't believe you can. You could make them private functions, and > then test them by referring directly to their vars, e.g. > > (#'your.namespace/private-function ...) > > But in general, your tests should be testing your public interface, > not a specific implementation. Your tests shouldn't care what your > code does behind the scenes, so long as the publicly accessible > functions return the correct result. > > - James -- 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
Re: testing local functions?
On 10 September 2010 12:24, alux wrote: > I always thought it to be good style to make helper functions only as > visible as needed, e.g. by using letfn. > > But when I want to test my code, I just dont see a way to access these > local functions for tests. I don't believe you can. You could make them private functions, and then test them by referring directly to their vars, e.g. (#'your.namespace/private-function ...) But in general, your tests should be testing your public interface, not a specific implementation. Your tests shouldn't care what your code does behind the scenes, so long as the publicly accessible functions return the correct result. - James -- 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
testing local functions?
Hello, I always thought it to be good style to make helper functions only as visible as needed, e.g. by using letfn. But when I want to test my code, I just dont see a way to access these local functions for tests. (I've seen fogus playing with the test of functions that are namespace private http://blog.fogus.me/2010/09/03/monkeying-with-clojures-deftest/ , but at least as far as I can see, this can't be generalised to my problem.) Do you know any way to test them? Thank you, alux -- 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
Re: letfn - mutually recursive local functions
On Feb 28, 2009, at 2:38 PM, Rich Hickey wrote: > > I've added letfn, which lets you define mutually recursive local > functions a la CL's labels. > > (defn ring [n] > (letfn [(a [n] (if (zero? n) n (b (dec n > (b [n] (if (zero? n) n (c (dec n > (c [n] (if (zero? n) n (a (dec n] > (c n))) > > (ring 1000) > > Note this is still subject to stack limits, i.e. no TCO, so please > don't report your StackOverflowErrors. Useful for bounded data only. > Do you advocate usage of 'letfn' and 'let' similar to the distinction between LABELS and FLET in CL? In other words, FLET implies non- recursive local function definition whereas LABELS suggests (mutually) recursive function(s). So, (letfn [(f [x] (+ x 2))] (f 8)) ; LABELS should ideally be: (let [f (fn [x] (+ x 2))] (f 8)) ; FLET Aloha, David Sletten --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Re: letfn - mutually recursive local functions
On Mar 1, 2009, at 4:18 PM, Konrad Hinsen wrote: > > On 01.03.2009, at 01:38, Rich Hickey wrote: > >> I've added letfn, which lets you define mutually recursive local >> functions a la CL's labels. >> >> (defn ring [n] >> (letfn [(a [n] (if (zero? n) n (b (dec n >> (b [n] (if (zero? n) n (c (dec n >> (c [n] (if (zero? n) n (a (dec n] >> (c n))) > > I noticed that letfn does not permit destructuring in its argument > lists: > > (letfn [(a [[f & r]] f)] > (a [1 2 3])) > > java.lang.IllegalArgumentException: fn params must be Symbols > (NO_SOURCE_FILE:2) > > Is this intentional? > Fixed in svn 1317 - thanks for the report. Rich --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Re: letfn - mutually recursive local functions
On 01.03.2009, at 01:38, Rich Hickey wrote: > I've added letfn, which lets you define mutually recursive local > functions a la CL's labels. > > (defn ring [n] > (letfn [(a [n] (if (zero? n) n (b (dec n > (b [n] (if (zero? n) n (c (dec n > (c [n] (if (zero? n) n (a (dec n] > (c n))) I noticed that letfn does not permit destructuring in its argument lists: (letfn [(a [[f & r]] f)] (a [1 2 3])) java.lang.IllegalArgumentException: fn params must be Symbols (NO_SOURCE_FILE:2) Is this intentional? Konrad. --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Re: letfn - mutually recursive local functions
On Sat, Feb 28, 2009 at 7:38 PM, Rich Hickey wrote: > > I've added letfn, which lets you define mutually recursive local > functions a la CL's labels. > > (defn ring [n] > (letfn [(a [n] (if (zero? n) n (b (dec n > (b [n] (if (zero? n) n (c (dec n > (c [n] (if (zero? n) n (a (dec n] > (c n))) > > (ring 1000) > > Note this is still subject to stack limits, i.e. no TCO, so please > don't report your StackOverflowErrors. Useful for bounded data only. This does work quite nicely with trampoline, though: (letfn [(a [n] #(if (zero? n) n (b (dec n (b [n] #(if (zero? n) n (c (dec n (c [n] #(if (zero? n) n (a (dec n] (trampoline c 10)) --Chouser --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
letfn - mutually recursive local functions
I've added letfn, which lets you define mutually recursive local functions a la CL's labels. (defn ring [n] (letfn [(a [n] (if (zero? n) n (b (dec n (b [n] (if (zero? n) n (c (dec n (c [n] (if (zero? n) n (a (dec n] (c n))) (ring 1000) Note this is still subject to stack limits, i.e. no TCO, so please don't report your StackOverflowErrors. Useful for bounded data only. Rich --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Re: local functions?
On Sep 11, 3:01 am, Allen Rohner <[EMAIL PROTECTED]> wrote: > > For very short functions one can use the cut notation: #(...). In case > > there are several functions or functions going over several lines, this > > is a sign that they should go into an own defn(-) with appropriate > > docstring. > > Maybe the solution is to use defn-. Scheme made me used to the local > function approach for encapsulation. I don't have a problem with doing > > (defn foo [x] > (defn bar [y] > ) > (defn baz [z]) > (do_stuff (bar[x])) > > except that the interior defns are public. I like the idea. defn- would also work like this but that won't prevent bar and baz from being used inside the package itself. (let [foo (fn [x] ...)] (foo 42)) Does tend to get a little ugly if fn grows more than a line or two. Not sure how it can be done though. Parth --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: local functions?
Hi, Am 11.09.2008 um 00:07 schrieb Allen Rohner: Maybe the solution is to use defn-. Scheme made me used to the local function approach for encapsulation. I don't have a problem with doing (defn foo [x] (defn bar [y] "doc string") (defn baz [z] "doc string2") (do_stuff (bar[x])) except that the interior defns are public. To me, the local functions are a stronger indication that bar and baz are *only* used inside foo. That indication isn't as apparent with (defn bar [y] ...) (defn baz [z] ...) (defn foo [x] (do_stuff (bar x))) The question is: is it necessary to have this indication? For me the grouping is given by the namespace (or the file). I found the following pattern quite often lately: (defn- first-step "Do something." ...) (defn- second-step "Do another thing." ...) (defn the-global-glue [x] (-> x first-step second-step ... nth-step)) For me this is more readable than a cramped: (defn the-global-glue (let [first-step ... ... second-step ... ...] (-> ))) As I said: This is mostly personal style. Your mileage may vary. As an aside, how is (defn- ) supposed to work? private symbols cannot be referred to outside of the namespace? The macroexpand looks identical: user=> (macroexpand '(defn- foo [x] x)) (def foo (clojure/fn ([x] x))) user=> (macroexpand '(defn foo [x] x)) (def foo (clojure/fn ([x] x))) Yes. private definitions are not accessible from outside the namespace. (defn- foo [x] x) is equivalent to (def #^{:private true} foo (fn [x] x)) The meta-stuff is handled in the reader, IIUIC. So it doesn't show up in the reader output and hence in the macro expansion. Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: local functions?
On Sep 10, 5:01 pm, Allen Rohner <[EMAIL PROTECTED]> wrote: > > For very short functions one can use the cut notation: #(...). In case > > there are several functions or functions going over several lines, this > > is a sign that they should go into an own defn(-) with appropriate > > docstring. > Sorry, emacs again. I'm having the stupids today. Maybe the solution is to use defn-. Scheme made me used to the local function approach for encapsulation. I don't have a problem with doing (defn foo [x] (defn bar [y] "doc string") (defn baz [z] "doc string2") (do_stuff (bar[x])) except that the interior defns are public. To me, the local functions are a stronger indication that bar and baz are *only* used inside foo. That indication isn't as apparent with (defn bar [y] ...) (defn baz [z] ...) (defn foo [x] (do_stuff (bar x))) As an aside, how is (defn- ) supposed to work? private symbols cannot be referred to outside of the namespace? The macroexpand looks identical: user=> (macroexpand '(defn- foo [x] x)) (def foo (clojure/fn ([x] x))) user=> (macroexpand '(defn foo [x] x)) (def foo (clojure/fn ([x] x))) Allen --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: local functions?
> For very short functions one can use the cut notation: #(...). In case > there are several functions or functions going over several lines, this > is a sign that they should go into an own defn(-) with appropriate > docstring. Maybe the solution is to use defn-. Scheme made me used to the local function approach for encapsulation. I don't have a problem with doing (defn foo [x] (defn bar [y] ) (defn baz [z]) (do_stuff (bar[x])) except that the interior defns are public. --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: local functions?
Hi, Am 10.09.2008 um 21:43 schrieb Allen Rohner: Is there a cleaner way to create local functions than (let [foo (fn [x] ...)] (foo 42)) ? In which way would another notation be cleaner? I think this is mainly an issue of personal taste. So here is mine: For very short functions one can use the cut notation: #(...). In case there are several functions or functions going over several lines, this is a sign that they should go into an own defn(-) with appropriate docstring. As always: YMMV. Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: local functions?
I apologize for the double post. An emacs shortcut didn't work very well in my firefox edit window. :-). Now to actually finish what I was trying to type. I was considering putting this in Rich's Clojure poll, but I wasn't sure it was broken yet. Is there a cleaner way to create local functions than (let [foo (fn [x] ...)] (foo 42)) ? I find that syntax to be slightly annoying, because you could end up with multiple lines and a good amount indentation even in small local functions. I find myself writing lots of small defns right before a "real" defn that I intended to write. It would be nice if there were a nice way t define these inside the "real" defn. I would like to write a macro to improve this, but I don't see how you could ever end up with the following, unless there is a way to mess with the enclosing function's bindings (def bar [x] (localfn foo [y] ...) (localfn baz [z] ...) (foo (baz x))) Allen --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
local functions?
I was considering putting this in Rich's Clojure poll, but I wasn't sure it was broken yet. Is there a cleaner way to create local functions than (let [foo (fn [x] ...)] (foo 42)) ? I find that syntax to be slightly annoying, because you could end up with multiple lines and a good amount indentation even in small local functions. I would like to write a macro to improve this, but I don't see how you could ever end up with (def bar [x] --~--~-~--~~~---~--~~ 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 To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---