Re: Question about building modular code in Clojure

2009-05-25 Thread Konrad Hinsen

On 23.05.2009, at 02:13, Mark Engelberg wrote:

> OK, after looking at deftemplate with macroexpand, it's starting to
> make more sense.  I suppose one downside to this versus load is that
> it's probably much more difficult to debug (just because all your code
> is wrapped in a macro), but basically I like the idea.

Right, debugging is always a bit more difficult with macros. Ideally,  
you'd have debugged most of the functions before wrapping them into a  
template.

I have added deftemplate to clojure.contrib.macro-utils. I found that  
it is quite useful for lightweight macro programming: for very simple  
macros, it is easier to use than the standard templating mechanism  
with syntax-quote. I plan to add gensym support when I find the time.

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: Question about building modular code in Clojure

2009-05-22 Thread Mark Engelberg

OK, after looking at deftemplate with macroexpand, it's starting to
make more sense.  I suppose one downside to this versus load is that
it's probably much more difficult to debug (just because all your code
is wrapped in a macro), but basically I like the idea.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-22 Thread Konrad Hinsen

On 22.05.2009, at 11:01, Mark Engelberg wrote:

> I was thinking that if you have:
> (def a 2)
> (def b 3)
> (defn f [] a)
>
> and you set it up with your deftemplate macro where f is the thing
> that is parameterized, then if you try to pass in a new value for f,
> like:
> (fn [] b), it macro expands to
> (let [f (fn [] b)]
>   (def a 2)
>   (def b 3))
> which clearly doesn't work.

Templates do nothing but symbol remplacement, so if you specify f as  
a template parameter and pass in (fn [] b) as its value, you get

(defn (fn [] b) [] a)

If you want to be able to pass in a function object, you'd have to  
write your template as

(deftemplate my-template [function]
(def a 2)
(def b 3)
(def f function))

If you want to redefine the function f given in the template, you'd  
just write the new definition after the template expansion.

> I find it ironic that after years of eschewing objects, I'm
> discovering that at the module level, I desperately want something
> object-like.

You have very much the same problems using objects. You can add and  
override methods and attributes, but you still have to refer to  
existing attributes and methods by the names defined in the original  
class. You also have to be careful not to use these names again for a  
different purpose. With templates, you have to know the symbols used  
in specific places in order to be able to refer to them and to avoid  
overwriting them. The restrictions and conditions are thus very similar.

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: Question about building modular code in Clojure

2009-05-22 Thread Mark Engelberg

On Fri, May 22, 2009 at 1:37 AM, Konrad Hinsen
 wrote:
> As long as it uses the same variables as the template, it would still
> work, but (like the load-and-redefine method) it would fail as soon
> as the template author decides to change the names of his variables.
> I suppose that to some extent such a risk is inevitable with any
> method based on textual replacement. C macros are famous for that
> kind of problem, and my templates work at pretty much the same level
> as C macros.
>

I was thinking that if you have:
(def a 2)
(def b 3)
(defn f [] a)

and you set it up with your deftemplate macro where f is the thing
that is parameterized, then if you try to pass in a new value for f,
like:
(fn [] b), it macro expands to
(let [f (fn [] b)]
  (def a 2)
  (def b 3))
which clearly doesn't work.

So you need to pre-declare b, or get b into the namespace with some
means other than the template first.  And if you did that, it would
point at the "old b", which works fine in this case, but might fail
for more complex kinds of recursions where eventually the value of b
depends on a call to the parameterized function.

I see now that my suggestion to include all the defines before the let
would also fail badly.

I find it ironic that after years of eschewing objects, I'm
discovering that at the module level, I desperately want something
object-like.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-22 Thread Konrad Hinsen

On 22.05.2009, at 10:03, Mark Engelberg wrote:

> However, there seems to be one way that this solution falls short of
> the load-and-redefine technique.

I don't think it can ever fall short of the load-and-redefine  
technique because you can emulate it completely (unless I overlooked  
something): you set up a template without any parameters. In that  
case, it will be introduced verbatim into the namespace where the  
template is used, and then you can redefine whatever you want. You  
still gain something compared to load-and-redefine: the template is  
an ordinary Clojure object residing in a namespace, so it works  
without any namespace trickeries and a template can even be used if  
its defining namespace has been aot-compiled and the original source  
code is not available.

Of course, I'd like to do even better than that and make  
parametrization of the template as clean as possible, so your  
counterexample is still relevant.

> Imagine if, in the example above, the function that you want to set  
> up for extension is
> print-grav-stats.  I don't think that will work with your method
> because print-grav-stats refers to variables that would not be in
> scope when the macro expands.

As long as it uses the same variables as the template, it would still  
work, but (like the load-and-redefine method) it would fail as soon  
as the template author decides to change the names of his variables.  
I suppose that to some extent such a risk is inevitable with any  
method based on textual replacement. C macros are famous for that  
kind of problem, and my templates work at pretty much the same level  
as C macros.

A well-defined template should define anything meant to be changed as  
template parameters, clearly state the symbols that the template  
itself inserts into the namespace, and use gensyms for anything else.  
My current version doesn't permit to define gensyms, but I think that  
could be added easily.  Of course, writing such a well-behaved  
template represents more effort than wrapping a piece of code in a  
(deftemplate ...) form.

> If there were a way to declare all the
> variables in the body of the macro BEFORE the let, and then the
> definitions, I think that might fix it, but I'm not totally sure how
> to do that.

What do you call "variables" here? All the symbols that are used  
inside the template expansion?

> If you don't have side effects in forms, you can simply execute the
> forms before the let, thus ensuring all vars are in scope.  I think
> just changing expansion to:
> (list (list 'quote (cons 'do forms))
>(list 'list (list 'quote `symbol-macrolet) param-map
>(list 'quote (cons 'do forms
> would do the trick.

I'd expect that executing before the let would lead to lots of  
"undefined symbol" errors.

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: Question about building modular code in Clojure

2009-05-22 Thread Mark Engelberg

On Wed, May 20, 2009 at 8:14 AM, Konrad Hinsen
 wrote:
> Here is another solution that I consider preferable to the use of
> load.

Konrad, this is an interesting approach, and it does feel like a
better way to organize similar modules than using load.

However, there seems to be one way that this solution falls short of
the load-and-redefine technique.  Imagine if, in the example above,
the function that you want to set up for extension is
print-grav-stats.  I don't think that will work with your method
because print-grav-stats refers to variables that would not be in
scope when the macro expands.  If there were a way to declare all the
variables in the body of the macro BEFORE the let, and then the
definitions, I think that might fix it, but I'm not totally sure how
to do that.

If you don't have side effects in forms, you can simply execute the
forms before the let, thus ensuring all vars are in scope.  I think
just changing expansion to:
(list (list 'quote (cons 'do forms))
   (list 'list (list 'quote `symbol-macrolet) param-map
   (list 'quote (cons 'do forms
would do the trick.

Not sure what to do to handle forms with side effects.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-20 Thread Konrad Hinsen

On 20.05.2009, at 17:14, Konrad Hinsen wrote:

> Here is another solution that I consider preferable to the use of
> load. It requires you to specify explicitly which vars you want to be
> replaceable (which I consider an advantage)

That's actually not true: it doesn't require a specification of the  
replaceable parameters, it merely permits it.

> ; Note: it is important to give namespace-qualified symbols here,   
> otherwise the symbol macro
> ; expansion gets into an infinite loop.

That isn't true either, as macro expansion stops when the expression  
does not change any more. I should read my own code before making  
stupid assertions about it ;-)

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: Question about building modular code in Clojure

2009-05-20 Thread Konrad Hinsen

On 17.05.2009, at 21:24, Mark Engelberg wrote:

> I don't want to post my actual code here, so let's run with this
> *gravity* example based off of what Adrian posted as a simple
> illustration.

Here is another solution that I consider preferable to the use of  
load. It requires you to specify explicitly which vars you want to be  
replaceable (which I consider an advantage), but otherwise it is very  
simple to transform a piece of code into a reusable template. If you  
(and/or others) consider this useful, I'd be happy to add it to  
clojure-contrib.

Konrad.

; This would be in clojure-contrib
(ns deftemplate)

(use 'clojure.contrib.macro-utils)

(defmacro deftemplate [name params & forms]
   (let [param-map (for [p params] (list (list 'quote p) (gensym)))
template-params (vec (map second param-map))
param-map (vec (apply concat param-map))
expansion (list 'list (list 'quote `symbol-macrolet) param-map
(list 'quote (cons 'do forms)))]
 `(defmacro ~name ~template-params ~expansion)))

; This would be the slightly modified version of the original namespace
(ns gravity)

(deftemplate/deftemplate grav-template [*gravity* say-grav]

   (defn halve-grav []
 (/ *gravity* 2.0))

   (defn mult-grav [x]
 (* *gravity* x))

   (defn print-grav-stats []
 (say-grav *gravity*)
 (say-grav (halve-grav))
 (say-grav (mult-grav 2

(def *gravity* 1.0)

(defn say-grav [grav]
   (prn "Gravity is:" grav))

; Note: it is important to give namespace-qualified symbols here,  
otherwise the symbol macro
; expansion gets into an infinite loop.
(grav-template gravity/*gravity* gravity/say-grav)


; This would be the cloned-then-modified namspace
(ns gravity-variation1)

(def *gravity* 0.38)

(defn say-grav [grav]
   (prn "Gravity on Mars is:" grav))

(gravity/grav-template gravity-variation1/*gravity* gravity- 
variation1/say-grav)

; This would be the namespace using the two previous ones
(ns consumer)

(gravity/print-grav-stats)
(gravity-variation1/print-grav-stats)


--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-20 Thread Laurent PETIT

2009/5/18 Mark Engelberg :
>
> On Mon, May 18, 2009 at 4:23 AM, Laurent PETIT  
> wrote:
>> The most modular I can think of right now is just about creating a
>> gravity type and using multimethods for all your functions.
>>
>> This way you would have dynamic resolution of methods that do not work
>> with precompiled fns.
>
> Can you elaborate on this?  I've tried to think of a multimethod
> solution, perhaps even a multimethod that dispatches on what the
> current namespace is, but haven't made much progress.

It is the solution provided by Meikel ( "structure with multimethods")
I was thinking of.

The problem being, as you mentioned, that it is not a cheap
refactoring to go incrementally from pure fns with globals to
structure with multimethods.

>
> >
>

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-19 Thread Mark Engelberg

On Tue, May 19, 2009 at 9:08 PM, George Jahad
 wrote:
]> It seems like what you are really trying to do is simulate
> inheritance/overriding in clojure.  What's wrong with using
> gen-class and proxy for that?

I guess it's still an open question as to whether gen-class and proxy
are mainly for Java interop, or whether it will be necessary to use
them for day-to-day "Clojure-proper" programming to create
encapsulated ADTs, extensible modules, or other areas where Clojure
currently seems weak.  I certainly hope that Clojure will continue to
grow in ways that make gen-class and proxy unnecessary except for Java
interop, because I find gen-class to be a bear to use (I spent hours
trying to set up the classpath so that I could write and read the
compiled files, and when you don't actually need the code
pre-compiled, it can actually be less convenient), and I find
accessing objects via dot syntax through Clojure to be comparatively
ugly.  I don't know, maybe Rich intends that certain things will
always be handled on the Java side, but I certainly hope that isn't
the case.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-19 Thread George Jahad


On May 18, 9:56 am, Mark Engelberg  wrote:
>
> So how to do this?  As far as I can tell, these various modules are
> all "hard-linked" to point at one another, and I don't see how to make
> this linkage more dynamic.  To change one file, I'd have to create new
> versions of ALL the files.  It would be great if each file could store
> a variable for what namespace it needs to use to get at the other
> functions.  For example, the generator has a variable that points at
> the solver namespace, and accesses the solver functions through that
> variable.  Then, you could have one master file that loads the
> particular versions of the modules you want, and links them to one
> another.  But I really don't see how such glue could be written.  Any
> suggestions?
>


It seems like what you are really trying to do is simulate
inheritance/overriding in clojure.  What's wrong with using
gen-class and proxy for that?

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-19 Thread Konrad Hinsen

On 19.05.2009, at 23:44, maxsu wrote:

> There, it's well defined and mathematical, and pretty neat; for
> example, we can have a equality module where all we have to do is give
> it a  '<' function that knows how to compare a certain kind of data,
> and and we get back shiny and correct >, <=, >=, and = functions.

That's possible in Clojure as well, see  
clojure.contrib.generic.comparison. The implementation is based on  
multimethods.

> 2) The function just defines functions to the namespace it lives in,
> which could probably be fixed by defining it differently.

You could replace it by a macro creating the definitions in the  
current namespace.

> I've been wondering about a similar problem, working with a little
> gravity simulator for a system of particles, where I'd like to be able
> to have the option of building a simulation where the particles have a
> different representation, or where the gravity constant is different,
> or a different integration scheme is substituted for the default. To
> that end, I had been thinking of using a map to store the resulting
> structure along with all its functions, but by the time I'd get to
> writing all the functions to interface with that, I'd have created a
> kind of light object system, and I don't know if that's the right
> thing to do :).

It's one option. If it turns out to work fine, you could abstract out  
the object system and make it available in the form of a library.  
There is nothing wrong about creating light-weight object systems.

> I just thought of the idea of instantiating derived functions from
> modular structures now, and I'm not actually sure that this will work
> at run-time if it's done through a macro, so I'd like some feedback.

What exactly do you have in mind?

> And what do you guys think of storings fns in a map to achieve
> structure modularity?

That's perfectly fine with me.

> Finally, is it possible to write functions that duplicate and modify a
> namespace, returning a anonymous namespace which can be then imported
> to the current scope, or passed elsewhere?

Probably yes, minus the anonymous part (how would you access an  
anonymous namespace?). However, namespaces contain compiled functions  
in which all symbols have already been resolved, which is the problem  
that started this whole discussion. Copying a function from one  
namespace to another one won't make it use different global vars.

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: Question about building modular code in Clojure

2009-05-19 Thread maxsu

Don't call it monkey patching! We'll start to feel like we're in ruby,
writing code that relies on modifications to Object :).

In certain languages you can create modular units which are
incomplete, and require that the user supply custom functions and
constants in order to create an 'instance' of the module structure.
There, it's well defined and mathematical, and pretty neat; for
example, we can have a equality module where all we have to do is give
it a  '<' function that knows how to compare a certain kind of data,
and and we get back shiny and correct >, <=, >=, and = functions.

Here's a way of doing it that might work in clojure, but looks kinda
ugly:

(defn equalifier "pollutes the namespace with relational operators
derived from a custom less-than function."
  [  [a b] (= [a b] (not ( true ; under our relation, 2*x '=' x^2
(my> (+ 2 %) (fac %)  => true ; x + 2 is 'greater than' the factorial
function over x

Thus, we'll get well behaved comparison functions that do a specific
sort of comparison, if we give it a less-than function that is itself
well behaved.

This approach is neat, except for 2 problems I've run across:
1) The function will just spew the names into the namespace, without
any way for you to prevent collisions, or associate the functions with
just one structure, so it's difficult to use to create multiple
instances .
2) The function just defines functions to the namespace it lives in,
which could probably be fixed by defining it differently.

A macro, called like (module-inst myname-modulename & args) could let
you do:

(module-inst mystring-equalifier (fn [a b] (< (count a) (count b)))

(mystring< "apples" "oranges") => true
(mystring= "cat" "dog") = true

Here, the macro has taken care of reading the module definition into
the right namespace, and has renamed the module functions according
the user's directive. Hehe, I haven't learned to write that macro yet.
And anyways, this approach still feels a little unnatural, as though
it's breaking the language's natural means of modularization. Could
our modules be instantiated into their own empty namespaces, to better
prevent collisions, or to be able to "pass" the module instance around
the program by passing the namespace reference?

Anyways, back to the gravity example. It feels kind of icky to give
the user the option to change the function of a code library by
changing constants, possibly while the library is being used.. that
just blows the referential transparency of the library, without giving
you multiple customized instances. However, the threaded approach
seems a little different and more natural to clojure, and should work
in the cases where you don't need to have two versions of the same
library side by side, but that's another area of the language I
haven't explored yet.

I've been wondering about a similar problem, working with a little
gravity simulator for a system of particles, where I'd like to be able
to have the option of building a simulation where the particles have a
different representation, or where the gravity constant is different,
or a different integration scheme is substituted for the default. To
that end, I had been thinking of using a map to store the resulting
structure along with all its functions, but by the time I'd get to
writing all the functions to interface with that, I'd have created a
kind of light object system, and I don't know if that's the right
thing to do :).

I just thought of the idea of instantiating derived functions from
modular structures now, and I'm not actually sure that this will work
at run-time if it's done through a macro, so I'd like some feedback.

And what do you guys think of storings fns in a map to achieve
structure modularity?

Finally, is it possible to write functions that duplicate and modify a
namespace, returning a anonymous namespace which can be then imported
to the current scope, or passed elsewhere?

The last one sounds like a bit of what an MLer might mean when she
says "Modules are first class in ML", minus nasty algebraic type
notation :D

- max suica
--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-19 Thread MikeM


>
> So how to do this?  As far as I can tell, these various modules are
> all "hard-linked" to point at one another, and I don't see how to make
> this linkage more dynamic.  To change one file, I'd have to create new
> versions of ALL the files.  It would be great if each file could store
> a variable for what namespace it needs to use to get at the other
> functions.  For example, the generator has a variable that points at
> the solver namespace, and accesses the solver functions through that
> variable.  Then, you could have one master file that loads the
> particular versions of the modules you want, and links them to one
> another.  But I really don't see how such glue could be written.  Any
> suggestions?
>

I don't know if this is any better than approaches suggested by
others, but consider the following:

(ns solver)

(defn solve
[x] x)

(ns generator
 (:use [solver])

(def *gravity* 1.0)

(defn gen-fn
[]
(let [grav *gravity*
  sol-fn solver/solve]
  (fn [x] (sol-fn (* x grav)

___
At the REPL-

(def f0 (binding [*gravity* 2.0]
  (gen-fn)))

Then when you want to test a change to a function in the solver
namespace:

(def f1 (binding [*gravity*2.0
  solver/solve (fn[x] (/ x 5))]
  (gen-fn)))

Others have suggested using binding - the difference here is that you
create closures around specific values of the vars you expect you will
want to change. This avoids the problem with binding and laziness and
multiple threads - once you create the closure you capture and persist
the value of the dynamic var for all threads to see at any time in the
future.




--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-19 Thread Mark Engelberg

On Tue, May 19, 2009 at 6:18 AM, Meikel Brandmeyer  wrote:
> I think the idea of decoupling is called "inversion of control"
> or "dependency injection". I'm sure it works for you, but it
> sure did in this (admittedly) simple example. There are
> various ways at passing around parameter:
> - global with binding
> - multi-arity functions
> - keyword functions

Thanks for writing up this example.  You use a number of interesting
techniques.  The technique you used to implement keyword functions is
something  I haven't seen before, so that was especially interesting
to me.  Your multimethod approach was also clever.

Essentially, your solution is to pass all the functions from other
modules as extra parameters, and then thread those extra parameters
through all the calls between functions.  I think that can probably
work (I think it might break down if there are recursive dependencies,
such as the solver depends on the analyzer, and the analyzer also
depends on the solver, but I need to think that through more to be
sure).  The obvious downside is that one must make a fairly radical
restructuring when you're ready to make the transition from your
initial "don't think about swapping out these functions" pass to a
fully modular plug-and-play version.  And it seems that the complexity
grows with the number of functions and/or modules you want to leave
open for extension.

That's why I was mainly looking for solutions that involve globals and
rebinding, because I thought it would "scale better".  But
unfortunately, as pointed out earlier in the thread, those techniques
don't really work for this kind of problem.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-19 Thread Meikel Brandmeyer

Hi,

Am 18.05.2009 um 18:56 schrieb Mark Engelberg:


OK, so let's talk more about what this glue code should look like.
I've been lumping this problem together with the other, because in my
mind they are related, but perhaps there is a clean way to glue
together modules without the incremental extension technique.

Let's say I've got a namespace for my generate functions, a namespace
for my solve functions, a namespace for my analysis functions, and a
namespace for my filter functions.

Now, the generator uses the solve functions, e.g.,
generator/generate-puzzle will somewhere call solve/solve-puzzle
So presumably, at the top of generator.clj, I have
(ns generator (:require solve))

Similarly, generator also has dependencies on functions in analysis
and filter namespaces.  Furthermore, some of the filter functions have
dependencies on the analysis functions, and so on.  In other words,
assume that most of the modules have dependencies on each other.

However, let's say my solve-puzzle function isn't working as
effectively as I'd like.  It solves the puzzle in a brute force way,
and I realize I'd like to try another version that solves the puzzle
more like the way a human would solve it.  So, I want to swap it out
with a new solve module, i.e., a new namespace, and have all the other
namespaces point to it.  Maybe even make it easy to swap back and
forth at runtime so I can compare the two approaches.

So how to do this?  As far as I can tell, these various modules are
all "hard-linked" to point at one another, and I don't see how to make
this linkage more dynamic.  To change one file, I'd have to create new
versions of ALL the files.  It would be great if each file could store
a variable for what namespace it needs to use to get at the other
functions.  For example, the generator has a variable that points at
the solver namespace, and accesses the solver functions through that
variable.  Then, you could have one master file that loads the
particular versions of the modules you want, and links them to one
another.  But I really don't see how such glue could be written.  Any
suggestions?

On the other hand, it's pretty straightforward to achieve this when
you use "objects" for your modules.  To be clear, I'm *not* a fan of
using OO to create bundled data structures with elaborate chains of
inheritance, but what I'm starting to realize is that in OO, you get a
pretty decent "module" system for free, using the same concepts that
OO programmers are already familiar with.  In the absence of OO, the
details of the module system become much more important because
modularity becomes an orthogonal issue that is not really covered by
the other aspects of the language (thus all the research papers on the
topic of modules in functional programming languages).


I'm still not sure I understand all your problems, but please find below
some thought on how to decouple the modules.

(ns puzzle.generator
  (:use
 [clojure.contrib.def :only (defvar)]))

; Various parameters
(defvar *gravity*
  1.0
  "The default gravity of Earth: 1.0")

(defn puzzle-seq
  ([]
   (puzzle-seq *gravity*))
  ([gravity]
   (repeatedly #(generate-puzzle gravity

(ns puzzle.analyzer)

(defn make-standard-analyzer
  []
  (fn [x y z]
(judge-difficulty-on-parameter x y z)))

(defn make-other-analyzer
  []
  (fn [x y z]
(do-other-difficulty-judgement x y z)))

(ns puzzle.solver
  (:use
 [puzzle.analyzer :only (make-standard-analyzer)]))

(defn brute-force-strategy
  [puzzle analyzer]
  ...)

(defn smart-human-strategy
  [puzzle analyzer]
  ...)

(defn solve
  [puzzle & options]
  (let [{:keys [analyzer strategy]
 :or   {analyzer (make-standard-analyzer)
strategy brute-force-strategy}}
(apply hash-map options)]
(let [difficulty (strategy puzzle analyzer)]
  [difficulty puzzle])))

(ns puzzle.glue
  (:require
 (puzzle [generator :as generator]
 [solver :as solver])))

(defn create-puzzles
  [difficulties]
  (for [[d p] (map solver/solve (generator/puzzle-seq))
:when (some difficulties d)]
p))

(ns puzzle.glue.variationX
  (:require
 (puzzle [generator :as generator]
 [analyzer :as analyzer]
 [solver :as solver])))

; Try different strategy with other analysis method.
(defn experimental-strategy
  [puzzle analyzer]
  ...)

(defn create-puzzles
  [difficulties]
  (for [[d p] (map (fn [puzzle]
 (solver/solve puzzle :strategy experimental- 
strategy
   :analyzer (analyzer/make-other- 
analyzer)))

   (generator/create-puzzles 0.75))
:when (some difficulties d)]
p))

I think the idea of decoupling is called "inversion of control"
or "dependency injection". I'm sure it works for you, but it
sure did in this (admittedly) simple example. There are
various ways at passing around parameter:
- global with binding
- multi-arity functions
- keyword functions

Using some str

Re: Question about building modular code in Clojure

2009-05-18 Thread Feng



On May 17, 3:24 pm, Mark Engelberg  wrote:
> Thanks for your questions.  I'll try to explain better.
>
> First, I'll explain that my line of work is to build tools to generate
> puzzles.  I often have a module which generates the puzzles through
> various random processes, using certain probabilities and parameters.
> Then, I have another module that solves the puzzles.  Another module
> analyzes the solving process to measure its difficulty.  A final
> module filters and sorts the puzzles based on the analysis.
>
> For an initial rapid prototyping programming session, it often
> suffices to just express each "module" as a separate file/namespace,
> with the key parameters as globals at the top of the file.  These
> modules expressly refer to each other, with no indirection.
>
> But then, as I want to explore variations, it gets more complicated.
> What if I want to try a different set of parameters in the generator?
> What if I want to swap out the printing function in the analyzer?
> What if I want to swap out the whole analysis module with something
> different?
>
> For many years, my primary language for doing these sorts of programs
> has been Python.  In my first pass, I just have a bunch of functions
> in a file with global variables at the top.  For exploring simple
> changes, I can just import a file and then mutate the global
> parameters.  When things get too complex for that, I reorganize into
> objects, and express the variation through inheritance and overriding
> the things I want to change.
>
> Right now, I'm working on my first sizeable project in Clojure.
> Again, I began by expressing each "module" as a file with some global
> parameters at the top.  But now, I'm beginning to get to the point
> where I need to explore variations, and it's not clear to me how to
> reorganize.
>
> I don't want to post my actual code here, so let's run with this
> *gravity* example based off of what Adrian posted as a simple
> illustration.
>
> gravity.clj:
> (ns gravity)
> (def *gravity* 1.0)
> (defn say-grav [grav]
>  (prn "Gravity is:" grav))
>
> (defn halve-grav []
>  (/ *gravity* 2.0))
>
> (defn mult-grav [x]
>  (* *gravity* x))
>
> (defn print-grav-stats []
>   (say-grav *gravity*)
>   (say-grav (halve-grav))
>   (say-grav (mult-grav 2)))
>
> Now, let's say I want to explore the following:
>
> gravity_variation1.clj:
> (ns gravity-variation1)
> -- Copy of everything in gravity.clj except with the following changes --
> (def *gravity* 0.38)
> (defn say-grav [grav]
>   (prn "Gravity on Mars is:" grav))
>
> And now I want to compare the two variations in one consumer file:
> consumer.clj:
> (ns consumer)
> (gravity/print-grav-stats)
> (gravity-variation1/print-grav-stats)
>
> So, how to do this in a clean way?  And then, if I have other consumer
> files that use the gravity module, how do I set it up so that it is a
> parameter as to which gravity module they use?
>
> I've explored some of the dynamic rebinding techniques that Adrian
> suggested, but haven't been satisfied with the results.  It's hard to
> constantly rebind things at the point of function call, and difficult
> to analyze what's going to happen as the code gets more complex, and
> you're using a mixture of functions from both "variations".  I can
> start passing more and more things around as parameters, but that gets
> to be a rather complicated refactoring, and then these modules get
> much harder to use.
>
> So how to do this in other languages?:
>
> In Python, I might refactor as follows:
> class Gravity:
>   gravity = 1.0
>   def halveGravity(self):
>      return self.gravity/2.0
>   etc.
>
> One nuisance of refactoring a module written as globals-plus-functions
> into classes in Python is you have to explicitly insert self
> everywhere, but at least it's a very straightforward translation.  In
> a language where the self reference is implied, it would be even
> easier (although most OO languages force you to use objects from the
> get-go, so there wouldn't really be any refactoring to do anyway).
>
> Then, you can express the variation through inheritance and
> overriding.  The consumer code might look like:
> gravity = Gravity()
> gravityVariation1 = GravityVariation1()
>
> gravity.printGravStats()
> gravityVariation1.printGravStats()
>
> There are some tricks you can do to make these behave more like static
> methods, so they can be called without an instance, but that's not
> idiomatic Python.
>
> I haven't done a whole lot of Java, but I imagine that you could
> accomplish the same thing by using a class with static methods to
> represent a "module" of code.  I've recently been reading the Scala
> book, and it seems like they've taken the idea of singleton objects as
> modules one step further, along with traits to handle mixins of
> partial implementations, in order to address a lot of these issues
> even better than vanilla Java.
>
> And what about functional languages?  Well, I'm pretty sure that PLT
> Scheme has a sophist

Re: Question about building modular code in Clojure

2009-05-18 Thread Mark Engelberg

On Mon, May 18, 2009 at 2:16 AM, Meikel Brandmeyer  wrote:
> If that is true, you should maybe consider some glue.
>
>     /- Analysis
> Glue -- Solve
>     \- Create
>
> The Glue part combines/uses the different modules. There you
> could change parameters easily with binding, swap in another
> analysis module, whatever...

OK, so let's talk more about what this glue code should look like.
I've been lumping this problem together with the other, because in my
mind they are related, but perhaps there is a clean way to glue
together modules without the incremental extension technique.

Let's say I've got a namespace for my generate functions, a namespace
for my solve functions, a namespace for my analysis functions, and a
namespace for my filter functions.

Now, the generator uses the solve functions, e.g.,
generator/generate-puzzle will somewhere call solve/solve-puzzle
So presumably, at the top of generator.clj, I have
(ns generator (:require solve))

Similarly, generator also has dependencies on functions in analysis
and filter namespaces.  Furthermore, some of the filter functions have
dependencies on the analysis functions, and so on.  In other words,
assume that most of the modules have dependencies on each other.

However, let's say my solve-puzzle function isn't working as
effectively as I'd like.  It solves the puzzle in a brute force way,
and I realize I'd like to try another version that solves the puzzle
more like the way a human would solve it.  So, I want to swap it out
with a new solve module, i.e., a new namespace, and have all the other
namespaces point to it.  Maybe even make it easy to swap back and
forth at runtime so I can compare the two approaches.

So how to do this?  As far as I can tell, these various modules are
all "hard-linked" to point at one another, and I don't see how to make
this linkage more dynamic.  To change one file, I'd have to create new
versions of ALL the files.  It would be great if each file could store
a variable for what namespace it needs to use to get at the other
functions.  For example, the generator has a variable that points at
the solver namespace, and accesses the solver functions through that
variable.  Then, you could have one master file that loads the
particular versions of the modules you want, and links them to one
another.  But I really don't see how such glue could be written.  Any
suggestions?

On the other hand, it's pretty straightforward to achieve this when
you use "objects" for your modules.  To be clear, I'm *not* a fan of
using OO to create bundled data structures with elaborate chains of
inheritance, but what I'm starting to realize is that in OO, you get a
pretty decent "module" system for free, using the same concepts that
OO programmers are already familiar with.  In the absence of OO, the
details of the module system become much more important because
modularity becomes an orthogonal issue that is not really covered by
the other aspects of the language (thus all the research papers on the
topic of modules in functional programming languages).

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-18 Thread Mark Engelberg

On Mon, May 18, 2009 at 4:23 AM, Laurent PETIT  wrote:
> The most modular I can think of right now is just about creating a
> gravity type and using multimethods for all your functions.
>
> This way you would have dynamic resolution of methods that do not work
> with precompiled fns.

Can you elaborate on this?  I've tried to think of a multimethod
solution, perhaps even a multimethod that dispatches on what the
current namespace is, but haven't made much progress.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-18 Thread Laurent PETIT

Hi,

The most modular I can think of right now is just about creating a
gravity type and using multimethods for all your functions.

This way you would have dynamic resolution of methods that do not work
with precompiled fns.

2009/5/17 Mark Engelberg :
>
> Thanks for your questions.  I'll try to explain better.
>
> First, I'll explain that my line of work is to build tools to generate
> puzzles.  I often have a module which generates the puzzles through
> various random processes, using certain probabilities and parameters.
> Then, I have another module that solves the puzzles.  Another module
> analyzes the solving process to measure its difficulty.  A final
> module filters and sorts the puzzles based on the analysis.
>
> For an initial rapid prototyping programming session, it often
> suffices to just express each "module" as a separate file/namespace,
> with the key parameters as globals at the top of the file.  These
> modules expressly refer to each other, with no indirection.
>
> But then, as I want to explore variations, it gets more complicated.
> What if I want to try a different set of parameters in the generator?
> What if I want to swap out the printing function in the analyzer?
> What if I want to swap out the whole analysis module with something
> different?
>
> For many years, my primary language for doing these sorts of programs
> has been Python.  In my first pass, I just have a bunch of functions
> in a file with global variables at the top.  For exploring simple
> changes, I can just import a file and then mutate the global
> parameters.  When things get too complex for that, I reorganize into
> objects, and express the variation through inheritance and overriding
> the things I want to change.
>
> Right now, I'm working on my first sizeable project in Clojure.
> Again, I began by expressing each "module" as a file with some global
> parameters at the top.  But now, I'm beginning to get to the point
> where I need to explore variations, and it's not clear to me how to
> reorganize.
>
> I don't want to post my actual code here, so let's run with this
> *gravity* example based off of what Adrian posted as a simple
> illustration.
>
> gravity.clj:
> (ns gravity)
> (def *gravity* 1.0)
> (defn say-grav [grav]
>  (prn "Gravity is:" grav))
>
> (defn halve-grav []
>  (/ *gravity* 2.0))
>
> (defn mult-grav [x]
>  (* *gravity* x))
>
> (defn print-grav-stats []
>  (say-grav *gravity*)
>  (say-grav (halve-grav))
>  (say-grav (mult-grav 2)))
>
>
> Now, let's say I want to explore the following:
>
> gravity_variation1.clj:
> (ns gravity-variation1)
> -- Copy of everything in gravity.clj except with the following changes --
> (def *gravity* 0.38)
> (defn say-grav [grav]
>  (prn "Gravity on Mars is:" grav))
>
> And now I want to compare the two variations in one consumer file:
> consumer.clj:
> (ns consumer)
> (gravity/print-grav-stats)
> (gravity-variation1/print-grav-stats)
>
> So, how to do this in a clean way?  And then, if I have other consumer
> files that use the gravity module, how do I set it up so that it is a
> parameter as to which gravity module they use?
>
> I've explored some of the dynamic rebinding techniques that Adrian
> suggested, but haven't been satisfied with the results.  It's hard to
> constantly rebind things at the point of function call, and difficult
> to analyze what's going to happen as the code gets more complex, and
> you're using a mixture of functions from both "variations".  I can
> start passing more and more things around as parameters, but that gets
> to be a rather complicated refactoring, and then these modules get
> much harder to use.
>
> So how to do this in other languages?:
>
> In Python, I might refactor as follows:
> class Gravity:
>  gravity = 1.0
>  def halveGravity(self):
>     return self.gravity/2.0
>  etc.
>
> One nuisance of refactoring a module written as globals-plus-functions
> into classes in Python is you have to explicitly insert self
> everywhere, but at least it's a very straightforward translation.  In
> a language where the self reference is implied, it would be even
> easier (although most OO languages force you to use objects from the
> get-go, so there wouldn't really be any refactoring to do anyway).
>
> Then, you can express the variation through inheritance and
> overriding.  The consumer code might look like:
> gravity = Gravity()
> gravityVariation1 = GravityVariation1()
>
> gravity.printGravStats()
> gravityVariation1.printGravStats()
>
> There are some tricks you can do to make these behave more like static
> methods, so they can be called without an instance, but that's not
> idiomatic Python.
>
> I haven't done a whole lot of Java, but I imagine that you could
> accomplish the same thing by using a class with static methods to
> represent a "module" of code.  I've recently been reading the Scala
> book, and it seems like they've taken the idea of singleton objects as
> modules one step further, along with traits to handle mi

Re: Question about building modular code in Clojure

2009-05-18 Thread Meikel Brandmeyer

Hi,

Am 18.05.2009 um 12:42 schrieb Konrad Hinsen:


Such a use of binding will lead to bad surprises as soon as you use
it with lazy sequences:

(map #(lcm % 6) (range 6))
-> (0 6 6 6 12 30)

(binding [clojure.contrib.math/gcd (fn [a b] 1)]
  (map #(lcm % 6) (range 6)))
-> (0 6 6 6 12 30)

You have to use doall to get the result you expect:


As with any other resource be like a Closable
in a with-open block or the resulset-seq of a database.
The doall is always necessary when you pass a lazy
seq outside your region of authority, .. in case it uses
a resource. This is not limited to binding.

Sincerely
Meikel



smime.p7s
Description: S/MIME cryptographic signature


Re: Question about building modular code in Clojure

2009-05-18 Thread Laurent PETIT

2009/5/18 Konrad Hinsen :
>
> On May 18, 2009, at 11:58, Adrian Cuthbertson wrote:
>
>> I know I keep plugging this - sorry - but it just keeps surfacing
>> as a solution;
>>
>> (lcm 4 6)
>> 12
>> (binding [clojure.contrib.math/gcd (fn [a b] 1)] (lcm 4 6))
>> 24
>
> Such a use of binding will lead to bad surprises as soon as you use
> it with lazy sequences:

And there's also the problem that bindings do not "traverse" threads,
even if one thread is just used as a "technical thread" (e.g. a thread
from a pool of threads).

So if e.g. some code works without parallelism, it may well not work
anymore if one piece on the call chain is delivered with a new version
that uses parallel computing (e.g. starts using pmap instead of map).



>
> (map #(lcm % 6) (range 6))
> -> (0 6 6 6 12 30)
>
> (binding [clojure.contrib.math/gcd (fn [a b] 1)]
>   (map #(lcm % 6) (range 6)))
> -> (0 6 6 6 12 30)
>
> You have to use doall to get the result you expect:
>
> (binding [clojure.contrib.math/gcd (fn [a b] 1)]
>   (doall (map #(lcm % 6) (range 6
> -> (0 6 12 18 24 30)
>
> The reason is that the temporary binding remains active only while
> map creates the lazy sequence that it returns, but it is no longer
> active when the actual elements of the lazy sequence are evaluated.
>
> More details and examples in my blog post:
>   http://onclojure.com/2009/05/06/simulating-dynamic-scoping/
>
> 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: Question about building modular code in Clojure

2009-05-18 Thread Adrian Cuthbertson

Aha! Thank you for clarifying that. Reinforces your point on
monkey-patching :). I will read your blog post with careful attention.

Adrian.

On Mon, May 18, 2009 at 12:42 PM, Konrad Hinsen
 wrote:
>
> On May 18, 2009, at 11:58, Adrian Cuthbertson wrote:
>
>> I know I keep plugging this - sorry - but it just keeps surfacing
>> as a solution;
>>
>> (lcm 4 6)
>> 12
>> (binding [clojure.contrib.math/gcd (fn [a b] 1)] (lcm 4 6))
>> 24
>
> Such a use of binding will lead to bad surprises as soon as you use
> it with lazy sequences:
>
> (map #(lcm % 6) (range 6))
> -> (0 6 6 6 12 30)
>
> (binding [clojure.contrib.math/gcd (fn [a b] 1)]
>   (map #(lcm % 6) (range 6)))
> -> (0 6 6 6 12 30)
>
> You have to use doall to get the result you expect:
>
> (binding [clojure.contrib.math/gcd (fn [a b] 1)]
>   (doall (map #(lcm % 6) (range 6
> -> (0 6 12 18 24 30)
>
> The reason is that the temporary binding remains active only while
> map creates the lazy sequence that it returns, but it is no longer
> active when the actual elements of the lazy sequence are evaluated.
>
> More details and examples in my blog post:
>   http://onclojure.com/2009/05/06/simulating-dynamic-scoping/
>
> 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: Question about building modular code in Clojure

2009-05-18 Thread Konrad Hinsen

On May 18, 2009, at 11:58, Adrian Cuthbertson wrote:

> I know I keep plugging this - sorry - but it just keeps surfacing  
> as a solution;
>
> (lcm 4 6)
> 12
> (binding [clojure.contrib.math/gcd (fn [a b] 1)] (lcm 4 6))
> 24

Such a use of binding will lead to bad surprises as soon as you use  
it with lazy sequences:

(map #(lcm % 6) (range 6))
-> (0 6 6 6 12 30)

(binding [clojure.contrib.math/gcd (fn [a b] 1)]
   (map #(lcm % 6) (range 6)))
-> (0 6 6 6 12 30)

You have to use doall to get the result you expect:

(binding [clojure.contrib.math/gcd (fn [a b] 1)]
   (doall (map #(lcm % 6) (range 6
-> (0 6 12 18 24 30)

The reason is that the temporary binding remains active only while  
map creates the lazy sequence that it returns, but it is no longer  
active when the actual elements of the lazy sequence are evaluated.

More details and examples in my blog post:
   http://onclojure.com/2009/05/06/simulating-dynamic-scoping/

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: Question about building modular code in Clojure

2009-05-18 Thread Adrian Cuthbertson

On Mon, May 18, 2009 at 11:29 AM, Mark Reid  wrote:
> ...
> test=> (lcm 4 6)
> 24
> 
>
> Maybe a variant of ns could be written that allows the overriding of
> specific functions? e.g.,
>

I know I keep plugging this - sorry - but it just keeps surfacing as a solution;

(lcm 4 6)
12
(binding [clojure.contrib.math/gcd (fn [a b] 1)] (lcm 4 6))
24

Adrian.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-18 Thread Mark Reid

> What's wrong with this:
>
> user=> (ns test (:use [clojure.contrib.math :exclude (lcm)]))
> nil
> test=> (sqrt 2)
> 1.4142135623730951
> test=> (lcm 3 6)
> java.lang.Exception: Unable to resolve symbol: lcm in this context
> (NO_SOURCE_FILE:3)
> test=> (defn lcm [a b] 1)
> #'test/lcm
> test=> (lcm 3 6)
> 1
> test=>

I think a better example for Mark's concern about existing functions
using a faster version of an algorithm would be redefining gcd as this
is called by lcm. I tried the following:


user=> (ns test (:use [clojure.contrib.math :exclude (gcd)]))
nil
test=> (gcd 4 6)
java.lang.Exception: Unable to resolve symbol: gcd in this context
(NO_SOURCE_FILE:3)
test=> (lcm 4 6)
12


So it seems lcm is still compiled against the original gcd. Let's try
to fix that:


test=> (defn clojure.contrib.math/gcd [a b] 1)
java.lang.Exception: Can't create defs outside of current ns
(NO_SOURCE_FILE:8)
test=> (ns clojure.contrib.math)
nil
clojure.contrib.math=> (defn gcd [a b] 1)
#'clojure.contrib.math/gcd
clojure.contrib.math=> (ns test)
nil
test=> (lcm 4 6)
24


Maybe a variant of ns could be written that allows the overriding of
specific functions? e.g.,


(ns2 test (:use [clojure.contrib.math :redef (gcd [a b] 1) (lcm [a b]
2)))


Regards,

Mark
--
http://mark.reid.name
--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-18 Thread Michael Wood

On Mon, May 18, 2009 at 11:07 AM, Michael Wood  wrote:
> On Mon, May 18, 2009 at 9:47 AM, Mark Engelberg
>  wrote:
>>
>> On Sun, May 17, 2009 at 11:48 PM, Konrad Hinsen
>>  wrote:
>>>  It's the approach of "cloning and
>>> mutating" something that smells of "quick and dirty", although I
>>> agree it is quite convenient in the prototyping phase.
>>
>> I disagree that incremental extension of a module is a "quick and
>> dirty" prototyping technique, and would argue that this is a
>> fundamentally desirable feature.
>>
>> As an example, I authored clojure.contrib.math.  Someone came up with
>> a slightly faster algorithm for one of the functions (which is used in
>> turn by other functions in the library),
^^^

Ah, ignore my answer then.  Sorry for the noise :)

-- 
Michael Wood 

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-18 Thread Meikel Brandmeyer

Hi,

Am 18.05.2009 um 09:47 schrieb Mark Engelberg:


As an example, I authored clojure.contrib.math.  Someone came up with
a slightly faster algorithm for one of the functions (which is used in
turn by other functions in the library), but I can't include it unless
he signs a contributor agreement.  If he wants to create his own
version of the module for his own personal use, in which he swaps out
my function for his faster one, there appears to be no good way to do
this, short of copying my entire file, commenting out my function, and
replacing it with his.  Clearly this is not an acceptable solution,
because then he won't benefit from any future updates I make to the
module.  He can't use the "load" trick, all because of the (ns
clojure.contrib.math) declaration at the top of the file.

Based on this discussion, it sounds like I (and all library authors)
should have provided all of my math functions in one file (say,
math_functions.clj), and then had a separate file (math.clj)
containing:
(ns clojure.contrib.math
 (:load "math_functions"))

just to make it possible for users to get at my code in its
uncompiled, unlinked-to-clojure.contrib.math-namespace form for the
purposes of incremental extension.

If all library authors want to start doing this, I guess that's one
solution.  I'm just hoping there is a better way.


I think the right way of this scenario is called quilt, hg patch queue
or StGIT. If you don't want to use this, there is the in-ns trick to
modify the desired functions.

In any case, modifying the inner workings of another library is only
a ugly hack. Making such things easy wouldn't be my main priority
if I were a language designer.

But this is of course not very helpful to your original problem. I have
some gut feeling, that you try to transport some notion, which just
doesn't work in Clojure that way. I got the impression that the
dependencies of your modules look like this:
Analysis -> Solve -> Create

If that is true, you should maybe consider some glue.

 /- Analysis
Glue -- Solve
 \- Create

The Glue part combines/uses the different modules. There you
could change parameters easily with binding, swap in another
analysis module, whatever...

But the impression I got, might also be wrong.

Sincerely
Meikel



smime.p7s
Description: S/MIME cryptographic signature


Re: Question about building modular code in Clojure

2009-05-18 Thread Michael Wood

On Mon, May 18, 2009 at 9:47 AM, Mark Engelberg
 wrote:
>
> On Sun, May 17, 2009 at 11:48 PM, Konrad Hinsen
>  wrote:
>>  It's the approach of "cloning and
>> mutating" something that smells of "quick and dirty", although I
>> agree it is quite convenient in the prototyping phase.
>
> I disagree that incremental extension of a module is a "quick and
> dirty" prototyping technique, and would argue that this is a
> fundamentally desirable feature.
>
> As an example, I authored clojure.contrib.math.  Someone came up with
> a slightly faster algorithm for one of the functions (which is used in
> turn by other functions in the library), but I can't include it unless
> he signs a contributor agreement.  If he wants to create his own
> version of the module for his own personal use, in which he swaps out
> my function for his faster one, there appears to be no good way to do
> this, short of copying my entire file, commenting out my function, and
> replacing it with his.  Clearly this is not an acceptable solution,
> because then he won't benefit from any future updates I make to the
> module.  He can't use the "load" trick, all because of the (ns
> clojure.contrib.math) declaration at the top of the file.
>
> Based on this discussion, it sounds like I (and all library authors)
> should have provided all of my math functions in one file (say,
> math_functions.clj), and then had a separate file (math.clj)
> containing:
> (ns clojure.contrib.math
>  (:load "math_functions"))
>
> just to make it possible for users to get at my code in its
> uncompiled, unlinked-to-clojure.contrib.math-namespace form for the
> purposes of incremental extension.

What's wrong with this:

user=> (ns test (:use [clojure.contrib.math :exclude (lcm)]))
nil
test=> (sqrt 2)
1.4142135623730951
test=> (lcm 3 6)
java.lang.Exception: Unable to resolve symbol: lcm in this context
(NO_SOURCE_FILE:3)
test=> (defn lcm [a b] 1)
#'test/lcm
test=> (lcm 3 6)
1
test=>

It doesn't solve your problem with global vars, of course.

-- 
Michael Wood 

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-18 Thread Konrad Hinsen

On May 18, 2009, at 9:47, Mark Engelberg wrote:

> On Sun, May 17, 2009 at 11:48 PM, Konrad Hinsen
>  wrote:
>>  It's the approach of "cloning and
>> mutating" something that smells of "quick and dirty", although I
>> agree it is quite convenient in the prototyping phase.
>
> I disagree that incremental extension of a module is a "quick and
> dirty" prototyping technique, and would argue that this is a
> fundamentally desirable feature.

It's pretty much what is called "monkey patching", with the  
difference that you monkey-patch a clone instead of the original  
object. I don't think there is universal agreement about its  
desirability. I have done it as well (in Python), and while it had  
mostly worked fine, I have regretted it in a few situations, after  
long hours of debugging. It is definitely a risky technique, as it  
requires a good understanding of the original code, plus regular  
verification that updated versions of that code still behave as they  
did before.

> Clearly this is not an acceptable solution, because then he won't  
> benefit from any future updates I make to themodule.  He can't use  
> the "load" trick, all because of the (ns clojure.contrib.math)  
> declaration at the top of the file.

He can still write a variant of load that redefines to ns macro in  
clojure.core, loads the file, and restores clojure.core/ns to its  
original value. In fact, nothing prevents you (or anyone else) to  
provide such a variant of load as a library function to make this  
easier. The only condition is to have access to the source code; if  
all you have is precompiled class files, the source code is gone and  
load won't work any more.

> Based on this discussion, it sounds like I (and all library authors)
> should have provided all of my math functions in one file (say,
> math_functions.clj), and then had a separate file (math.clj)
> containing:

I wouldn't really want to encourage people to monkey-patch my  
libraries (and then complain to me if it doesn't work). However,  
there is the more interesting question of how to write a library that  
is meant to be extended/modified in a well-defined way. In OO, one  
would encourage subclassing for overriding some methods. As far as I  
know, there is no single equally universal technique for functional  
programming.

> If all library authors want to start doing this, I guess that's one
> solution.  I'm just hoping there is a better way.

I don't think there is any other way at the namespace level. Once a  
namespace is evaluated, all functions are compiled and all references  
are resolved.

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: Question about building modular code in Clojure

2009-05-18 Thread Mark Engelberg

On Mon, May 18, 2009 at 1:17 AM, Adrian Cuthbertson
 wrote:
> (alter-var-root (var say-grav) (fn [_] (fn [x] (prn "my-version-grav:" x

But this only works if you only want one variation, and you no longer
care about the original version, right?.  If you want to benchmark
your variation against the original, or explore two variations, you
can't use this approach, I believe.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-18 Thread Adrian Cuthbertson

> ... signs a contributor agreement.  If he wants to create his own
> version of the module for his own personal use, in which he swaps out
> my function for his faster one, there appears to be no good way to do
> this, short of copying my entire file, commenting out my function, ...

I think Stuart's idea (rather than binding) might be the recipe for a
solution to this. Using the canonical gravity example;

(use 'gravity)

(alter-var-root (var say-grav) (fn [_] (fn [x] (prn "my-version-grav:" x

(say-grav 3.0)
"my-version-grav:" 3.0

The alter-var-root could be wrapped in one or more functions or macros
to make the "overriding" a bit more friendly.

Adrian.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-18 Thread Mark Engelberg

On Sun, May 17, 2009 at 11:48 PM, Konrad Hinsen
 wrote:
>  It's the approach of "cloning and
> mutating" something that smells of "quick and dirty", although I
> agree it is quite convenient in the prototyping phase.

I disagree that incremental extension of a module is a "quick and
dirty" prototyping technique, and would argue that this is a
fundamentally desirable feature.

As an example, I authored clojure.contrib.math.  Someone came up with
a slightly faster algorithm for one of the functions (which is used in
turn by other functions in the library), but I can't include it unless
he signs a contributor agreement.  If he wants to create his own
version of the module for his own personal use, in which he swaps out
my function for his faster one, there appears to be no good way to do
this, short of copying my entire file, commenting out my function, and
replacing it with his.  Clearly this is not an acceptable solution,
because then he won't benefit from any future updates I make to the
module.  He can't use the "load" trick, all because of the (ns
clojure.contrib.math) declaration at the top of the file.

Based on this discussion, it sounds like I (and all library authors)
should have provided all of my math functions in one file (say,
math_functions.clj), and then had a separate file (math.clj)
containing:
(ns clojure.contrib.math
  (:load "math_functions"))

just to make it possible for users to get at my code in its
uncompiled, unlinked-to-clojure.contrib.math-namespace form for the
purposes of incremental extension.

If all library authors want to start doing this, I guess that's one
solution.  I'm just hoping there is a better way.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-17 Thread Konrad Hinsen

On 18.05.2009, at 08:05, Mark Engelberg wrote:

> David, that seems to work.  I think I can achieve my objectives with
> this strategy.

David provided a much better implementation of the idea that I had  
for this. I hadn't thought of  the "load" function.

> However, I must admit, I find it rather unsettling that collections of
> functions written inside of namespaces are fundamentally less
> composable than those that are not.

That's not how I would describe it. Every function (in the sense of a  
function object) is in some namespace. What you consider functions  
outside of a namespace are actually forms representing functions. The  
difference between importing a namespace and loading its source code  
file is analogous to the difference between using functions vs.  
macros. In fact, you could replace (load ...) by a macro that expands  
into the contents of the loaded file. It is well accepted in the Lisp  
world that some problems are best solved by macros, so this is just  
one more.

> It means that to remain extensible, I need to write two files for  
> every group of functions --
> one to hold the actual functions, and one to load the first file  
> and wrap it inside of a namespace.

In terms of modularity, that makes sense. You have a more symmetric  
situation: one file holds the common definitions, and any number of  
files import these and add to them. It's the approach of "cloning and  
mutating" something that smells of "quick and dirty", although I  
agree it is quite convenient in the prototyping phase.

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: Question about building modular code in Clojure

2009-05-17 Thread Mark Engelberg

BTW, for those of you interested in reading academic papers about
modules in functional programming langs, I found this list of
articles:
http://www.readscheme.org/modules/

I remember reading about PLT Scheme's units several years ago, and I
think it's pretty much what I'm looking for, with the ability to
import defined variables and functions from various modules, relink
them to point at each other or things newly defined in the new module
(in contrast to the problem I had with David's immigrate example where
the functions were still hard-linked to the things in the namespace
where they were defined), and then export the result.

I still hope there are more clever solutions using Clojure's existing
feature set.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-17 Thread Konrad Hinsen

On 17.05.2009, at 21:24, Mark Engelberg wrote:

> For many years, my primary language for doing these sorts of programs
> has been Python.  In my first pass, I just have a bunch of functions
> in a file with global variables at the top.  For exploring simple
> changes, I can just import a file and then mutate the global
> parameters.  When things get too complex for that, I reorganize into
> objects, and express the variation through inheritance and overriding
> the things I want to change.

This approach doesn't work in Clojure because the global symbols are  
resolved at namespace evaluation time (compile time, more or less),  
not at run time as it does in Python. The conclusion is that  
namespaces are not the right level to do such modifications.

One rather straightforward solution is to work at the level of source  
code files. Your gravity_variation1.clj would read in the source code  
of gravity.clj and evaluate it together with its modifications.

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: Question about building modular code in Clojure

2009-05-17 Thread Mark Engelberg

David, that seems to work.  I think I can achieve my objectives with
this strategy.

However, I must admit, I find it rather unsettling that collections of
functions written inside of namespaces are fundamentally less
composable than those that are not.  It means that to remain
extensible, I need to write two files for every group of functions --
one to hold the actual functions, and one to load the first file and
wrap it inside of a namespace.

Perhaps Clojure needs a variation of load that ignores the namespace,
to make it possible to load the contents of one namespace into a new
namespace?  Or perhaps there is still a better way?

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-17 Thread David Nolen
Oops your right. Perhaps this will work for you then.
;; gravity.clj (note we don't define an ns)
;; ===
(def *gravity* 1.0)
(defn say-grav [grav]
 (prn "Gravity is:" grav))

(defn halve-grav []
 (/ *gravity* 2.0))

(defn mult-grav [x]
 (* *gravity* x))

(defn print-grav-stats []
 (say-grav *gravity*)
 (say-grav (halve-grav))
 (say-grav (mult-grav 2)))

;; module_a.clj
;; ===
(ns module-a)
(load "gravity")

;; module_b.clj
;; ===
(ns module-b)
(load "gravity")

(def *gravity* 0.38)
(defn say-grav [grav]
 (prn "Gravity on Mars is:" grav))

;; consumer.clj
;; ===
(ns consumer
  (:require [module-a :as a])
  (:require [module-b :as b]))

(a/print-grav-stats)
(b/print-grav-stats)


On Mon, May 18, 2009 at 12:11 AM, Mark Engelberg
wrote:

>
> On Sun, May 17, 2009 at 8:12 PM, David Nolen 
> wrote:
> > Have you looked at the immigrate function in Compojure? This imports
> public
> > vars from a different namespace into a namespace as if they were defined
> > there.  Maybe this is enough to get the behavior that you want?
>
> Not really.  Consider the following:
> (ns testns1)
> (def a 2)
> (defn b [] a)
>
> Then:
> (ns testns2)
> (immigrate 'testns1)
> ; Let's try to redefine global variable a
> (def a 4)
>
> (testns2/b) will still return 2.  That's because even though b has
> been "immigrated" to the testns2 namespace, the var a in the body of b
> still refers to testns1/a.
>
> So no, I don't really see how immigrate helps.
>
> >
>

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-17 Thread Mark Engelberg

On Sun, May 17, 2009 at 8:12 PM, David Nolen  wrote:
> Have you looked at the immigrate function in Compojure? This imports public
> vars from a different namespace into a namespace as if they were defined
> there.  Maybe this is enough to get the behavior that you want?

Not really.  Consider the following:
(ns testns1)
(def a 2)
(defn b [] a)

Then:
(ns testns2)
(immigrate 'testns1)
; Let's try to redefine global variable a
(def a 4)

(testns2/b) will still return 2.  That's because even though b has
been "immigrated" to the testns2 namespace, the var a in the body of b
still refers to testns1/a.

So no, I don't really see how immigrate helps.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-17 Thread David Nolen
Have you looked at the immigrate function in Compojure? This imports public
vars from a different namespace into a namespace as if they were defined
there.  Maybe this is enough to get the behavior that you want?
On Sun, May 17, 2009 at 9:12 PM, Mark Engelberg wrote:

>
> On Sun, May 17, 2009 at 2:18 PM, mikel  wrote:
> > I'm still not quite clear on exactly what you're trying to accomplish.
> > You showed how to accomplish your purpose in Clojure, but then
> > suggested that the result was not 'clean'. It's not quite clear what
> > you mean by 'clean'--that is, what features of the solution you
> > presented do you want to change?
>
> What's not clean about it is that copying and pasting all the
> unchanged code from one file to another is unacceptable.
>
> The question here is how to create one file/namespace which is mostly
> the same as another, with only a couple global variables and/or
> functions different.
>
> >
>

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-17 Thread Mark Engelberg

On Sun, May 17, 2009 at 2:18 PM, mikel  wrote:
> I'm still not quite clear on exactly what you're trying to accomplish.
> You showed how to accomplish your purpose in Clojure, but then
> suggested that the result was not 'clean'. It's not quite clear what
> you mean by 'clean'--that is, what features of the solution you
> presented do you want to change?

What's not clean about it is that copying and pasting all the
unchanged code from one file to another is unacceptable.

The question here is how to create one file/namespace which is mostly
the same as another, with only a couple global variables and/or
functions different.

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-17 Thread Stuart Sierra

Hi Mark,
Not sure if this helps, but I've found it useful to mediate access to
global vars through a single function.  Then I can swap in another
function to change the behavior.  Here's an example from 
http://tinyurl.com/qm8pj4

(defn get-property-function [name]
  (System/getProperty name))

(defn use-property-function [f]
  (alter-var-root #'get-property-function (fn [_] f)))

(defn get-property [name]
  (or (get-property-function name)
  (throw (Exception. (str "Missing property " name)

The public interface is (get-property name).  Additional functions
like (get-gravity) provide short aliases for individual properties.
The default definitions are returned by get-property-function, but I
can call use-property-function to globally replace those with a
different set of properties.

If I were to use (binding ...) on get-property-function, I could use
set! instead of alter-var-root, and the changes would only affect the
current thread.

-Stuart Sierra


On May 17, 3:24 pm, Mark Engelberg  wrote:
> Thanks for your questions.  I'll try to explain better.
>
> First, I'll explain that my line of work is to build tools to generate
> puzzles.  I often have a module which generates the puzzles through
> various random processes, using certain probabilities and parameters.
> Then, I have another module that solves the puzzles.  Another module
> analyzes the solving process to measure its difficulty.  A final
> module filters and sorts the puzzles based on the analysis.
>
> For an initial rapid prototyping programming session, it often
> suffices to just express each "module" as a separate file/namespace,
> with the key parameters as globals at the top of the file.  These
> modules expressly refer to each other, with no indirection.
>
> But then, as I want to explore variations, it gets more complicated.
> What if I want to try a different set of parameters in the generator?
> What if I want to swap out the printing function in the analyzer?
> What if I want to swap out the whole analysis module with something
> different?
>
> For many years, my primary language for doing these sorts of programs
> has been Python.  In my first pass, I just have a bunch of functions
> in a file with global variables at the top.  For exploring simple
> changes, I can just import a file and then mutate the global
> parameters.  When things get too complex for that, I reorganize into
> objects, and express the variation through inheritance and overriding
> the things I want to change.
>
> Right now, I'm working on my first sizeable project in Clojure.
> Again, I began by expressing each "module" as a file with some global
> parameters at the top.  But now, I'm beginning to get to the point
> where I need to explore variations, and it's not clear to me how to
> reorganize.
>
> I don't want to post my actual code here, so let's run with this
> *gravity* example based off of what Adrian posted as a simple
> illustration.
>
> gravity.clj:
> (ns gravity)
> (def *gravity* 1.0)
> (defn say-grav [grav]
>  (prn "Gravity is:" grav))
>
> (defn halve-grav []
>  (/ *gravity* 2.0))
>
> (defn mult-grav [x]
>  (* *gravity* x))
>
> (defn print-grav-stats []
>   (say-grav *gravity*)
>   (say-grav (halve-grav))
>   (say-grav (mult-grav 2)))
>
> Now, let's say I want to explore the following:
>
> gravity_variation1.clj:
> (ns gravity-variation1)
> -- Copy of everything in gravity.clj except with the following changes --
> (def *gravity* 0.38)
> (defn say-grav [grav]
>   (prn "Gravity on Mars is:" grav))
>
> And now I want to compare the two variations in one consumer file:
> consumer.clj:
> (ns consumer)
> (gravity/print-grav-stats)
> (gravity-variation1/print-grav-stats)
>
> So, how to do this in a clean way?  And then, if I have other consumer
> files that use the gravity module, how do I set it up so that it is a
> parameter as to which gravity module they use?
>
> I've explored some of the dynamic rebinding techniques that Adrian
> suggested, but haven't been satisfied with the results.  It's hard to
> constantly rebind things at the point of function call, and difficult
> to analyze what's going to happen as the code gets more complex, and
> you're using a mixture of functions from both "variations".  I can
> start passing more and more things around as parameters, but that gets
> to be a rather complicated refactoring, and then these modules get
> much harder to use.
>
> So how to do this in other languages?:
>
> In Python, I might refactor as follows:
> class Gravity:
>   gravity = 1.0
>   def halveGravity(self):
>      return self.gravity/2.0
>   etc.
>
> One nuisance of refactoring a module written as globals-plus-functions
> into classes in Python is you have to explicitly insert self
> everywhere, but at least it's a very straightforward translation.  In
> a language where the self reference is implied, it would be even
> easier (although most OO languages force you to use objects from the
> get-go, so there wouldn't really be any ref

Re: Question about building modular code in Clojure

2009-05-17 Thread mikel



On May 17, 2:24 pm, Mark Engelberg  wrote:
> Thanks for your questions.  I'll try to explain better.

I'm still not quite clear on exactly what you're trying to accomplish.
You showed how to accomplish your purpose in Clojure, but then
suggested that the result was not 'clean'. It's not quite clear what
you mean by 'clean'--that is, what features of the solution you
presented do you want to change?

Let me take a wild stab at enumerating your requirements, and you can
tell me where I got them wrong.

1. You want a set of named values, each defined once per 'module'.

2. You want code from two or more 'modules' to run in the same
session, and for each 'module' to see its own definitions for the
named values.

3. You don't want to pass the values or names as parameters to
functions in a 'module'.

Is that right? Perhaps not, because if it were, then this should do
the trick:

(ns 'gravity1)
(def *gravity* 1.0)

(ns 'gravity2)
(def *gravity* 2.0)

user> gravity1/*gravity*
1.0
user> gravity2/*gravity*
2.0

What is it that you want to do that this solution doesn't accomplish?

--~--~-~--~~~---~--~~
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: Question about building modular code in Clojure

2009-05-17 Thread Mark Engelberg

Thanks for your questions.  I'll try to explain better.

First, I'll explain that my line of work is to build tools to generate
puzzles.  I often have a module which generates the puzzles through
various random processes, using certain probabilities and parameters.
Then, I have another module that solves the puzzles.  Another module
analyzes the solving process to measure its difficulty.  A final
module filters and sorts the puzzles based on the analysis.

For an initial rapid prototyping programming session, it often
suffices to just express each "module" as a separate file/namespace,
with the key parameters as globals at the top of the file.  These
modules expressly refer to each other, with no indirection.

But then, as I want to explore variations, it gets more complicated.
What if I want to try a different set of parameters in the generator?
What if I want to swap out the printing function in the analyzer?
What if I want to swap out the whole analysis module with something
different?

For many years, my primary language for doing these sorts of programs
has been Python.  In my first pass, I just have a bunch of functions
in a file with global variables at the top.  For exploring simple
changes, I can just import a file and then mutate the global
parameters.  When things get too complex for that, I reorganize into
objects, and express the variation through inheritance and overriding
the things I want to change.

Right now, I'm working on my first sizeable project in Clojure.
Again, I began by expressing each "module" as a file with some global
parameters at the top.  But now, I'm beginning to get to the point
where I need to explore variations, and it's not clear to me how to
reorganize.

I don't want to post my actual code here, so let's run with this
*gravity* example based off of what Adrian posted as a simple
illustration.

gravity.clj:
(ns gravity)
(def *gravity* 1.0)
(defn say-grav [grav]
 (prn "Gravity is:" grav))

(defn halve-grav []
 (/ *gravity* 2.0))

(defn mult-grav [x]
 (* *gravity* x))

(defn print-grav-stats []
  (say-grav *gravity*)
  (say-grav (halve-grav))
  (say-grav (mult-grav 2)))


Now, let's say I want to explore the following:

gravity_variation1.clj:
(ns gravity-variation1)
-- Copy of everything in gravity.clj except with the following changes --
(def *gravity* 0.38)
(defn say-grav [grav]
  (prn "Gravity on Mars is:" grav))

And now I want to compare the two variations in one consumer file:
consumer.clj:
(ns consumer)
(gravity/print-grav-stats)
(gravity-variation1/print-grav-stats)

So, how to do this in a clean way?  And then, if I have other consumer
files that use the gravity module, how do I set it up so that it is a
parameter as to which gravity module they use?

I've explored some of the dynamic rebinding techniques that Adrian
suggested, but haven't been satisfied with the results.  It's hard to
constantly rebind things at the point of function call, and difficult
to analyze what's going to happen as the code gets more complex, and
you're using a mixture of functions from both "variations".  I can
start passing more and more things around as parameters, but that gets
to be a rather complicated refactoring, and then these modules get
much harder to use.

So how to do this in other languages?:

In Python, I might refactor as follows:
class Gravity:
  gravity = 1.0
  def halveGravity(self):
 return self.gravity/2.0
  etc.

One nuisance of refactoring a module written as globals-plus-functions
into classes in Python is you have to explicitly insert self
everywhere, but at least it's a very straightforward translation.  In
a language where the self reference is implied, it would be even
easier (although most OO languages force you to use objects from the
get-go, so there wouldn't really be any refactoring to do anyway).

Then, you can express the variation through inheritance and
overriding.  The consumer code might look like:
gravity = Gravity()
gravityVariation1 = GravityVariation1()

gravity.printGravStats()
gravityVariation1.printGravStats()

There are some tricks you can do to make these behave more like static
methods, so they can be called without an instance, but that's not
idiomatic Python.

I haven't done a whole lot of Java, but I imagine that you could
accomplish the same thing by using a class with static methods to
represent a "module" of code.  I've recently been reading the Scala
book, and it seems like they've taken the idea of singleton objects as
modules one step further, along with traits to handle mixins of
partial implementations, in order to address a lot of these issues
even better than vanilla Java.

And what about functional languages?  Well, I'm pretty sure that PLT
Scheme has a sophisticated modular mechanism called Units which handle
these sorts of issues.   And I think that ML can parameterize modules
in the form of functors (or is that only a parameterization over
types?).

So please, I'd love to hear more ideas about how to write my Clojur

Re: Question about building modular code in Clojure

2009-05-17 Thread Rich Hickey



On May 16, 10:45 pm, Mark Engelberg  wrote:
> So I've built a file/namespace with several functions.  There are
> several globals defined at the top of the file (for example,
> *gravity*) which many of the functions refer to.  I made them globals
> precisely because it would have been a pain to thread them through
> every single function that uses them.
>
> Now, I need to maintain two versions of this module.  For example,
> let's say I want one module where the *gravity* constant is defined to
> be 1.0, and one where it is defined as 2.0.
>

Could be more specific about what it means to "maintain two versions
of this module". With the same name? Or, you want a namespace to
behave like an object?

> I know how to do this in other languages, especially OO ones, but I'm
> scratching my head trying to think of a clean solution in Clojure for
> this seemingly simple problem.  I've tried various namespace trickery
> with vars and bindings, but I haven't found a workable solution yet.
> What am I missing?  Thanks.

Could you give an example of how you would do this in Java?

Thanks,

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: Question about building modular code in Clojure

2009-05-17 Thread Adrian Cuthbertson

Hi Mark, I've used the following macro to achieve something like what
you're doing;

In the file/namespace module (say eg_globs/fns.clj);

(ns eg-globs.fns)
(declare *gravity*)

(defmacro with-grav
  [grav & body]
  `(let [gr# ~grav]
 (binding [*gravity* gr#]
   ~...@body)))

(defn say-grav []
  (prn "Gravity is:" *gravity*))

(defn halve-grav []
  (/ *gravity* 2.0))

(defn mult-grav [x]
  (* *gravity* x))

Then in the calling module;

(use 'eg-globs.fns)

(with-grav 2.0
   (say-grav)
   (prn "half:" (halve-grav))
   (mult-grav 2.5))
"Gravity is:" 2.0
"half:" 1.0
5.0

(with-grav 1.5
   (mult-grav 3.0))
4.5


Hth, Adrian.




On Sun, May 17, 2009 at 4:45 AM, Mark Engelberg
 wrote:
>
> So I've built a file/namespace with several functions.  There are
> several globals defined at the top of the file (for example,
> *gravity*) which many of the functions refer to.  I made them globals
> precisely because it would have been a pain to thread them through
> every single function that uses them.
>
> Now, I need to maintain two versions of this module.  For example,
> let's say I want one module where the *gravity* constant is defined to
> be 1.0, and one where it is defined as 2.0.
>
> I know how to do this in other languages, especially OO ones, but I'm
> scratching my head trying to think of a clean solution in Clojure for
> this seemingly simple problem.  I've tried various namespace trickery
> with vars and bindings, but I haven't found a workable solution yet.
> What am I missing?  Thanks.
>
> >
>

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