Re: testing local functions?

2010-09-10 Thread alux
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?

2010-09-10 Thread Brian Marick
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?

2010-09-10 Thread Christian Vest Hansen
>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?

2010-09-10 Thread alux
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?

2010-09-10 Thread James Reeves
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?

2010-09-10 Thread alux
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

2009-03-10 Thread David Sletten


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

2009-03-01 Thread Rich Hickey


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

2009-03-01 Thread Konrad Hinsen

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

2009-02-28 Thread Chouser

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

2009-02-28 Thread Rich Hickey

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?

2008-09-11 Thread Parth Malwankar



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?

2008-09-10 Thread Meikel Brandmeyer

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?

2008-09-10 Thread Allen Rohner



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?

2008-09-10 Thread Allen Rohner


> 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?

2008-09-10 Thread Meikel Brandmeyer

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?

2008-09-10 Thread Allen Rohner

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?

2008-09-10 Thread Allen Rohner

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
-~--~~~~--~~--~--~---