Tapestry and Clojure

classic Classic list List threaded Threaded
26 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Tapestry and Clojure

Howard Lewis Ship
People who run into me are always asking me "Are you going to rewrite
Tapestry in Scala?  Or Clojure?"  Well, I'm not going to be rewriting
Tapestry at this point, just improving it in place.

However, I do want to do some more work with Clojure; I'm really
excited by http://datomic.com/ for example, and the best way to
leverage Datomic is, in my not very informed honest opinion, to use
Clojure code to interface with the Datomic APIs.

To that end, I've wanted to make it easy to combine Tapestry view
logic with Clojure service logic.

The challenge is that, to Java code, the Clojure space is basically a
giant collection of objects all implementing the IFn interface;  it's
not clear what to inject or how to represent it in a meaningful way to
Tapestry.  Sure I could whip something together that would allow you
to inject a function as IFn and you could call one of its many
overloaded invoke() methods, but that doesn't feel right.

Instead, the new alpha tapestry-clojure library (in the master branch)
lets you do the following:

Define an interface

Map the interface to a Clojure namespace:  simply add the @Namespace annotation

Build a proxy so that each method invokes a Clojure function

Each method name is mapped to a Clojure function in the namespace. It
converts camel case to inline dashes .. thus a method named
"updateDatastore" will be mapped to a function named
"update-datastore".  If that's not sufficient, or you want to expose a
function from elsewhere, the @FunctionName annotation can be used on a
method to provide its specific name, or even a fully qualified name in
another namespace.

The ClojureBuilder service can be injected; it has a single method:

  <T> T build(Class<T> interfaceType)

The interface must have the @Namespace annotation. All of the methods
must have non-void return types.

You'll typically use it in a service builder method of a module:

  public static DatastoreAPI buildDatastoreAPI(ClojureBuilder builder)
{ return builder.build(DataStoreAPI.class); }

That's it ... DatastoreAPI is now a service like any other, and can be
injected into any service, page, component, or whatever.

Currently, this in in 5.4, which is very early alpha.

The code for this is very small, and could easily be ported back to
5.3, for 5.3.4.  Any interest?

--
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Thiago H de Paula Figueiredo
On Tue, 05 Jun 2012 14:56:17 -0300, Howard Lewis Ship <[hidden email]>  
wrote:

> People who run into me are always asking me "Are you going to rewrite
> Tapestry in Scala?  Or Clojure?"

I really don't get the point of rewriting Tapestry, which is written in  
Java, in Java-the-platform languages as Scala and Clojure, specially them,  
as they can interface with Java code very well (at least as far as I  
know). People have been able to write Tapestry pages and components in  
Scala for years already.

On the other hand, making it easier for writing Tapestry pages,  
components, etc in other languages is something very interesting IMHO. :)

> Well, I'm not going to be rewriting
> Tapestry at this point, just improving it in place.

Agreed. ;)

--
Thiago H. de Paula Figueiredo

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

David Woods
In reply to this post by Howard Lewis Ship
I'm just learning Clojure, but I see a lot of potential and intend to move
more of my back-end functionality to it over time.  A way to use Clojure
services in a Tapestry webapp would be ideal, and will fit great into a
project I'm just planning at the moment.  Since I'm considering it for
future projects, I'm not concerned about porting back to past versions of
Tapestry.

Here is my enthusiastic vote for this direction!

David


On 6 June 2012 03:56, Howard Lewis Ship <[hidden email]> wrote:

> People who run into me are always asking me "Are you going to rewrite
> Tapestry in Scala?  Or Clojure?"  Well, I'm not going to be rewriting
> Tapestry at this point, just improving it in place.
>
> However, I do want to do some more work with Clojure; I'm really
> excited by http://datomic.com/ for example, and the best way to
> leverage Datomic is, in my not very informed honest opinion, to use
> Clojure code to interface with the Datomic APIs.
>
> To that end, I've wanted to make it easy to combine Tapestry view
> logic with Clojure service logic.
>
> The challenge is that, to Java code, the Clojure space is basically a
> giant collection of objects all implementing the IFn interface;  it's
> not clear what to inject or how to represent it in a meaningful way to
> Tapestry.  Sure I could whip something together that would allow you
> to inject a function as IFn and you could call one of its many
> overloaded invoke() methods, but that doesn't feel right.
>
> Instead, the new alpha tapestry-clojure library (in the master branch)
> lets you do the following:
>
> Define an interface
>
> Map the interface to a Clojure namespace:  simply add the @Namespace
> annotation
>
> Build a proxy so that each method invokes a Clojure function
>
> Each method name is mapped to a Clojure function in the namespace. It
> converts camel case to inline dashes .. thus a method named
> "updateDatastore" will be mapped to a function named
> "update-datastore".  If that's not sufficient, or you want to expose a
> function from elsewhere, the @FunctionName annotation can be used on a
> method to provide its specific name, or even a fully qualified name in
> another namespace.
>
> The ClojureBuilder service can be injected; it has a single method:
>
>  <T> T build(Class<T> interfaceType)
>
> The interface must have the @Namespace annotation. All of the methods
> must have non-void return types.
>
> You'll typically use it in a service builder method of a module:
>
>  public static DatastoreAPI buildDatastoreAPI(ClojureBuilder builder)
> { return builder.build(DataStoreAPI.class); }
>
> That's it ... DatastoreAPI is now a service like any other, and can be
> injected into any service, page, component, or whatever.
>
> Currently, this in in 5.4, which is very early alpha.
>
> The code for this is very small, and could easily be ported back to
> 5.3, for 5.3.4.  Any interest?
>
> --
> Howard M. Lewis Ship
>
> Creator of Apache Tapestry
>
> The source for Tapestry training, mentoring and support. Contact me to
> learn how I can get you up and productive in Tapestry fast!
>
> (971) 678-5210
> http://howardlewisship.com
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Jochen Berger
In reply to this post by Howard Lewis Ship
Am 05.06.2012 19:56, schrieb Howard Lewis Ship:
> The code for this is very small, and could easily be ported back to
> 5.3, for 5.3.4.  Any interest?

Definitely! I already did this and successfully called the doubler fn
from a 5.3.3 webapps's page. Very useful stuff. ;-)
I think I'm going to like the way this is going. I instantly had the
idea of being able to pass a t5-func Mapper and a Collection to clojure
and be able to use partition and pmap to have the mapping done in
parallel. Awesome! There's still some work to be done to get there, but
I'm really happy that the first step is taken.

Jochen

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Howard Lewis Ship
Possibilities for the future:

tapestry-clojure might be able to access type hints on the function
and use the TypeCoercer to convert method parameters to the correct
function argument type.

Likewise, it could (and probably should) use the method return type as
a guide to TypeCoerce the function return value into the method return
value.

On Wed, Jun 6, 2012 at 12:02 AM, Jochen Berger <[hidden email]> wrote:

> Am 05.06.2012 19:56, schrieb Howard Lewis Ship:
>
>> The code for this is very small, and could easily be ported back to
>> 5.3, for 5.3.4.  Any interest?
>
>
> Definitely! I already did this and successfully called the doubler fn from a
> 5.3.3 webapps's page. Very useful stuff. ;-)
> I think I'm going to like the way this is going. I instantly had the idea of
> being able to pass a t5-func Mapper and a Collection to clojure and be able
> to use partition and pmap to have the mapping done in parallel. Awesome!
> There's still some work to be done to get there, but I'm really happy that
> the first step is taken.
>
> Jochen
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>



--
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Massimo Lusetti
On Wed, Jun 6, 2012 at 9:19 PM, Howard Lewis Ship <[hidden email]> wrote:

> Possibilities for the future:
>
> tapestry-clojure might be able to access type hints on the function
> and use the TypeCoercer to convert method parameters to the correct
> function argument type.
>
> Likewise, it could (and probably should) use the method return type as
> a guide to TypeCoerce the function return value into the method return
> value.

This is a cool feature I would like to test soon but honestly I don't
have particular use case for this and I don't see the needs for this
to be backported to 5.3 branch

Cheers
--
Massimo
http://meridio.blogspot.com

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

freizl
In reply to this post by Howard Lewis Ship
This sounds a very interesting topic.

Because of clojure Java Interp, getting tapestry work with clojure seems not difficult.
I have set up a tutorial project at https://github.com/freizl/clojure-tapestry.

I did not tested all tapestry functionality but I think it should be working well.

PS: I'm new to both Tapestry and Clojure.
Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Howard Lewis Ship
I see Clojure use with Tapestry as an extension of the (largely
stateless) services layer; although you can use :gen-class to create
class-like things with readable/writable properties, that will not
work very will with Tapestry that expects to be able to read bytecode
from a .class file and enhance it in multiple ways.

Tapestry pages and components are inherently stateful and mutable;
trying to implement them in Clojure is a bit off-base.

On Sun, Jul 1, 2012 at 10:05 PM, freizl <[hidden email]> wrote:

> This sounds a very interesting topic.
>
> Because of clojure Java Interp, getting tapestry work with clojure seems not
> difficult.
> I have set up a tutorial project at
> https://github.com/freizl/clojure-tapestry.
>
> I did not tested all tapestry functionality but I think it should be working
> well.
>
> PS: I'm new to both Tapestry and Clojure.
>
>
> --
> View this message in context: http://tapestry.1045711.n5.nabble.com/Tapestry-and-Clojure-tp5713643p5714226.html
> Sent from the Tapestry - User mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>



--
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Ilya Obshadko-2
I have a question regarding potential Clojure integration in my application
service layer. As of now, standard Tapestry mechanism of dependency
injection won't work for Clojure-based services, because it's constructed
using ServiceBuilder and there is no implementation class.

I understand that it probably cannot be solved directly, but what
alternative scenarios do we have at our disposal?

One of them is probably a custom service builder. Any others?

Ideally, I would like to have something like:

(with-tapestry
   (def service1 (tapestry-inject 'com.myapp.Service1))
   (def service2 (tapestry-inject 'com.myapp.Service2))
 ...
)

Thanks for any suggestions.


On Mon, Jul 2, 2012 at 7:31 PM, Howard Lewis Ship <[hidden email]> wrote:

> I see Clojure use with Tapestry as an extension of the (largely
> stateless) services layer; although you can use :gen-class to create
> class-like things with readable/writable properties, that will not
> work very will with Tapestry that expects to be able to read bytecode
> from a .class file and enhance it in multiple ways.
>
> Tapestry pages and components are inherently stateful and mutable;
> trying to implement them in Clojure is a bit off-base.
>
> On Sun, Jul 1, 2012 at 10:05 PM, freizl <[hidden email]> wrote:
> > This sounds a very interesting topic.
> >
> > Because of clojure Java Interp, getting tapestry work with clojure seems
> not
> > difficult.
> > I have set up a tutorial project at
> > https://github.com/freizl/clojure-tapestry.
> >
> > I did not tested all tapestry functionality but I think it should be
> working
> > well.
> >
> > PS: I'm new to both Tapestry and Clojure.
> >
> >
> > --
> > View this message in context:
> http://tapestry.1045711.n5.nabble.com/Tapestry-and-Clojure-tp5713643p5714226.html
> > Sent from the Tapestry - User mailing list archive at Nabble.com.
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [hidden email]
> > For additional commands, e-mail: [hidden email]
> >
>
>
>
> --
> Howard M. Lewis Ship
>
> Creator of Apache Tapestry
>
> The source for Tapestry training, mentoring and support. Contact me to
> learn how I can get you up and productive in Tapestry fast!
>
> (971) 678-5210
> http://howardlewisship.com
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>


--
Ilya Obshadko
Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Thiago H de Paula Figueiredo
On Sat, 13 Dec 2014 17:48:09 -0200, Ilya Obshadko  
<[hidden email]> wrote:

> I have a question regarding potential Clojure integration in my  
> application
> service layer. As of now, standard Tapestry mechanism of dependency
> injection won't work for Clojure-based services, because it's constructed
> using ServiceBuilder and there is no implementation class.

ServiceBuilder's buildService() receives a ServiceResources instance as a  
parameter. ServiceResources is an ObjectLocator (i.e. Tapestry-IoC  
registry).

> I understand that it probably cannot be solved directly, but what
> alternative scenarios do we have at our disposal?
>
> One of them is probably a custom service builder. Any others?

You can use builder methods (YourService buildYourService()) or  
bind(Class<T> serviceInterface, ServiceBuilder<T> builder). Pass the  
services you want to your Clojure code as objects.

--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Ilya Obshadko-2
On Sun, Dec 14, 2014 at 9:17 PM, Thiago H de Paula Figueiredo <
[hidden email]> wrote:

> On Sat, 13 Dec 2014 17:48:09 -0200, Ilya Obshadko <[hidden email]>
> wrote:
>
>  I have a question regarding potential Clojure integration in my
>> application
>> service layer. As of now, standard Tapestry mechanism of dependency
>> injection won't work for Clojure-based services, because it's constructed
>> using ServiceBuilder and there is no implementation class.
>>
>
> ServiceBuilder's buildService() receives a ServiceResources instance as a
> parameter. ServiceResources is an ObjectLocator (i.e. Tapestry-IoC
> registry).


The wording of my question was not fully correct. tapestry-clojure doesn't
use ServiceBuilder, but rather its own ClojureBuilder (which does the job
of creating service proxy and binding service interface methods to Clojure
functions in a given namespace).

One way to do that is to have special interface method, bound to Clojure
function, which can perform necessary injection by using mutable objects in
Clojure code. But that doesn't look like a functional way.

I would like Howard to elaborate on this topic, because I'm currently
researching various options and yet none of them looks quite right. But I
don't have much experience in Clojure, so I might be missing something
obvious.


> I understand that it probably cannot be solved directly, but what
>> alternative scenarios do we have at our disposal?
>>
>> One of them is probably a custom service builder. Any others?
>>
>
> You can use builder methods (YourService buildYourService()) or
> bind(Class<T> serviceInterface, ServiceBuilder<T> builder). Pass the
> services you want to your Clojure code as objects.



--
Ilya Obshadko
Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Thiago H de Paula Figueiredo
On Mon, 15 Dec 2014 17:34:10 -0200, Ilya Obshadko  
<[hidden email]> wrote:

>> ServiceBuilder's buildService() receives a ServiceResources instance as  
>> a parameter. ServiceResources is an ObjectLocator (i.e. Tapestry-IoC
>> registry).
>
> The wording of my question was not fully correct. tapestry-clojure  
> doesn't use ServiceBuilder, but rather its own ClojureBuilder (which  
> does the job
> of creating service proxy and binding service interface methods to  
> Clojure> functions in a given namespace).

I also noticed, after sending my answer, that it wasn't very good, due to  
my lack of Clojure knowledge (yet! :)).

> One way to do that is to have special interface method, bound to Clojure
> function, which can perform necessary injection by using mutable objects  
> in Clojure code. But that doesn't look like a functional way.

How are Java objects usually passed to Clojure code? The recommended way?

> I would like Howard to elaborate on this topic, because I'm currently
> researching various options and yet none of them looks quite right. But I
> don't have much experience in Clojure, so I might be missing something
> obvious.

Your suggested code hints at a Clojure function, provided by Tapestry,  
that would somehow provide access to services through the registry. I  
guess you're in the right path.

--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Ilya Obshadko-2
On Mon, Dec 15, 2014 at 10:12 PM, Thiago H de Paula Figueiredo <
[hidden email]> wrote:

> On Mon, 15 Dec 2014 17:34:10 -0200, Ilya Obshadko <[hidden email]>
> wrote:
>
>  ServiceBuilder's buildService() receives a ServiceResources instance as a
>>> parameter. ServiceResources is an ObjectLocator (i.e. Tapestry-IoC
>>> registry).
>>>
>>
>> The wording of my question was not fully correct. tapestry-clojure
>> doesn't use ServiceBuilder, but rather its own ClojureBuilder (which does
>> the job
>> of creating service proxy and binding service interface methods to
>> Clojure> functions in a given namespace).
>>
>
> I also noticed, after sending my answer, that it wasn't very good, due to
> my lack of Clojure knowledge (yet! :)).
>
>  One way to do that is to have special interface method, bound to Clojure
>> function, which can perform necessary injection by using mutable objects
>> in Clojure code. But that doesn't look like a functional way.
>>
>
> How are Java objects usually passed to Clojure code? The recommended way?


Java objects are passed to Clojure functions in exactly the same way they
are passed to Java method (because internally Clojure function is just an
implementation of IFn interface, and function call is invoke(...) on its
instance).

But I don't want to pass services to Clojure functions, I'd like to inject
them into Clojure namespace when clojure.core/require is executed. By
itself, clojure.core/require doesn't allow passing arbitrary arguments that
might be used later inside the namespace.

So I'm not yet sure about correct way to approach this.


I would like Howard to elaborate on this topic, because I'm currently
>> researching various options and yet none of them looks quite right. But I
>> don't have much experience in Clojure, so I might be missing something
>> obvious.
>>
>
> Your suggested code hints at a Clojure function, provided by Tapestry,
> that would somehow provide access to services through the registry. I guess
> you're in the right path.




--
Ilya Obshadko
Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Thiago H de Paula Figueiredo
On Mon, 15 Dec 2014 18:29:22 -0200, Ilya Obshadko  
<[hidden email]> wrote:


>> How are Java objects usually passed to Clojure code? The recommended  
>> way?
>
> Java objects are passed to Clojure functions in exactly the same way they
> are passed to Java method (because internally Clojure function is just an
> implementation of IFn interface, and function call is invoke(...) on its
> instance).

Now I was the one who hasn't made a clear question. :) I'm not asking  
about how Clojure passes function arguments. I meant when you call Clojure  
code from Java code, how do you pass a Java object so it can be used  
inside Clojure code?

> But I don't want to pass services to Clojure functions, I'd like to  
> inject them into Clojure namespace when clojure.core/require is executed.

Got it. I have no idea how to do that given my almost no knowledge of  
Clojure. But I guess there's some way of doing that.

--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Howard Lewis Ship
Actually, Clojure interop with Java is very good, so a Clojure function
could be passed a Java object:

(defn frobnicate-the-request
  [^Request request]
  (.setAttribute request "xyzzyx" (compute-the-magic-name)))

The ^Request part is a type hint, it allows the Clojure compiler to
generate proper bytecode to access the methods of the request without using
reflection.

You quickly get used to the leading dot (which itself is sugar syntax over
the more primitive interop special form).

Now, in terms of Clojure interop ... the library I put together ago on a
whim was about efficiently exposing Clojure functions bundled together as
an arbitrary Java interface.

If you pass the Registry to a Clojure function, it will be quite capable of
pulling out whatever it needs.

A lot of the capabilities of Clojure are very familiar to Tapestry users:
thread bound values (inside Clojure vars) for example.

My primary thought about integrating Clojure would be to allow a Tapestry
app to jump into Clojure to work with the Datomic APIs natively, rather
than the Java API to Datomic, which is decidedly second class.

On Tue, Dec 16, 2014 at 5:24 AM, Thiago H de Paula Figueiredo <
[hidden email]> wrote:

>
> On Mon, 15 Dec 2014 18:29:22 -0200, Ilya Obshadko <[hidden email]>
> wrote:
>
>
>  How are Java objects usually passed to Clojure code? The recommended way?
>>>
>>
>> Java objects are passed to Clojure functions in exactly the same way they
>> are passed to Java method (because internally Clojure function is just an
>> implementation of IFn interface, and function call is invoke(...) on its
>> instance).
>>
>
> Now I was the one who hasn't made a clear question. :) I'm not asking
> about how Clojure passes function arguments. I meant when you call Clojure
> code from Java code, how do you pass a Java object so it can be used inside
> Clojure code?
>
>  But I don't want to pass services to Clojure functions, I'd like to
>> inject them into Clojure namespace when clojure.core/require is executed.
>>
>
> Got it. I have no idea how to do that given my almost no knowledge of
> Clojure. But I guess there's some way of doing that.
>
>
> --
> Thiago H. de Paula Figueiredo
> Tapestry, Java and Hibernate consultant and developer
> http://machina.com.br
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>

--
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com
@hlship
Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Ilya Obshadko-2
Thanks Howard, that's making a lot of sense.

However my initial though was about injecting Clojure globals
(specifically, one global containing service registry) during the call to
"require" IFn. I still couldn't find any ways to manipulate initial Clojure
environment, although there are obvious workarounds (for example I could
have a specific function inside Clojure namespace that could be used to
inject necessary objects using mutable globals). I'm still looking for more
concise and accurate way to do that.

On Thu, Dec 18, 2014 at 7:35 AM, Howard Lewis Ship <[hidden email]> wrote:

> Actually, Clojure interop with Java is very good, so a Clojure function
> could be passed a Java object:
>
> (defn frobnicate-the-request
>   [^Request request]
>   (.setAttribute request "xyzzyx" (compute-the-magic-name)))
>
> The ^Request part is a type hint, it allows the Clojure compiler to
> generate proper bytecode to access the methods of the request without using
> reflection.
>
> You quickly get used to the leading dot (which itself is sugar syntax over
> the more primitive interop special form).
>
> Now, in terms of Clojure interop ... the library I put together ago on a
> whim was about efficiently exposing Clojure functions bundled together as
> an arbitrary Java interface.
>
> If you pass the Registry to a Clojure function, it will be quite capable of
> pulling out whatever it needs.
>
> A lot of the capabilities of Clojure are very familiar to Tapestry users:
> thread bound values (inside Clojure vars) for example.
>
> My primary thought about integrating Clojure would be to allow a Tapestry
> app to jump into Clojure to work with the Datomic APIs natively, rather
> than the Java API to Datomic, which is decidedly second class.
>
> On Tue, Dec 16, 2014 at 5:24 AM, Thiago H de Paula Figueiredo <
> [hidden email]> wrote:
> >
> > On Mon, 15 Dec 2014 18:29:22 -0200, Ilya Obshadko <
> [hidden email]>
> > wrote:
> >
> >
> >  How are Java objects usually passed to Clojure code? The recommended
> way?
> >>>
> >>
> >> Java objects are passed to Clojure functions in exactly the same way
> they
> >> are passed to Java method (because internally Clojure function is just
> an
> >> implementation of IFn interface, and function call is invoke(...) on its
> >> instance).
> >>
> >
> > Now I was the one who hasn't made a clear question. :) I'm not asking
> > about how Clojure passes function arguments. I meant when you call
> Clojure
> > code from Java code, how do you pass a Java object so it can be used
> inside
> > Clojure code?
> >
> >  But I don't want to pass services to Clojure functions, I'd like to
> >> inject them into Clojure namespace when clojure.core/require is
> executed.
> >>
> >
> > Got it. I have no idea how to do that given my almost no knowledge of
> > Clojure. But I guess there's some way of doing that.
> >
> >
> > --
> > Thiago H. de Paula Figueiredo
> > Tapestry, Java and Hibernate consultant and developer
> > http://machina.com.br
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [hidden email]
> > For additional commands, e-mail: [hidden email]
> >
> >
>
> --
> Howard M. Lewis Ship
>
> Creator of Apache Tapestry
>
> The source for Tapestry training, mentoring and support. Contact me to
> learn how I can get you up and productive in Tapestry fast!
>
> (971) 678-5210
> http://howardlewisship.com
> @hlship
>



--
Ilya Obshadko
Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Ilya Obshadko-2
So, my solution for this is actually quite simple:

(ns com.xdance.tapestry.serviceregistry

  (:import (org.apache.tapestry5.ioc ObjectLocator)))


(def ^:dynamic ^ObjectLocator *tapestry-registry-ref* (promise))


(defn init-registry [^ObjectLocator registry]

  "Must be called during service initialization to set up Tapestry registry
object"

  (deliver *tapestry-registry-ref* registry))


(defmacro with-tapestry-services [service-bindings & body]

  "Apply service bindings to body"

  (let [service-binding-pairs (partition-all 2 service-bindings)

        service-binding-exprs (map #(vector (first %1) `(.getService (deref
*tapestry-registry*) ~(second %1))) service-binding-pairs)

        service-binding-final (vec (reduce concat service-binding-exprs))]

    `(let ~service-binding-final ~@body)))


The only thing I need to do is to bind init-registry function to Tapestry
service interface and call it during startup phase. There might be better
approaches probably.

On Thu, Dec 18, 2014 at 6:49 PM, Ilya Obshadko <[hidden email]>
wrote:

> Thanks Howard, that's making a lot of sense.
>
> However my initial though was about injecting Clojure globals
> (specifically, one global containing service registry) during the call to
> "require" IFn. I still couldn't find any ways to manipulate initial Clojure
> environment, although there are obvious workarounds (for example I could
> have a specific function inside Clojure namespace that could be used to
> inject necessary objects using mutable globals). I'm still looking for more
> concise and accurate way to do that.
>
> On Thu, Dec 18, 2014 at 7:35 AM, Howard Lewis Ship <[hidden email]>
> wrote:
>
>> Actually, Clojure interop with Java is very good, so a Clojure function
>> could be passed a Java object:
>>
>> (defn frobnicate-the-request
>>   [^Request request]
>>   (.setAttribute request "xyzzyx" (compute-the-magic-name)))
>>
>> The ^Request part is a type hint, it allows the Clojure compiler to
>> generate proper bytecode to access the methods of the request without
>> using
>> reflection.
>>
>> You quickly get used to the leading dot (which itself is sugar syntax over
>> the more primitive interop special form).
>>
>> Now, in terms of Clojure interop ... the library I put together ago on a
>> whim was about efficiently exposing Clojure functions bundled together as
>> an arbitrary Java interface.
>>
>> If you pass the Registry to a Clojure function, it will be quite capable
>> of
>> pulling out whatever it needs.
>>
>> A lot of the capabilities of Clojure are very familiar to Tapestry users:
>> thread bound values (inside Clojure vars) for example.
>>
>> My primary thought about integrating Clojure would be to allow a Tapestry
>> app to jump into Clojure to work with the Datomic APIs natively, rather
>> than the Java API to Datomic, which is decidedly second class.
>>
>> On Tue, Dec 16, 2014 at 5:24 AM, Thiago H de Paula Figueiredo <
>> [hidden email]> wrote:
>> >
>> > On Mon, 15 Dec 2014 18:29:22 -0200, Ilya Obshadko <
>> [hidden email]>
>> > wrote:
>> >
>> >
>> >  How are Java objects usually passed to Clojure code? The recommended
>> way?
>> >>>
>> >>
>> >> Java objects are passed to Clojure functions in exactly the same way
>> they
>> >> are passed to Java method (because internally Clojure function is just
>> an
>> >> implementation of IFn interface, and function call is invoke(...) on
>> its
>> >> instance).
>> >>
>> >
>> > Now I was the one who hasn't made a clear question. :) I'm not asking
>> > about how Clojure passes function arguments. I meant when you call
>> Clojure
>> > code from Java code, how do you pass a Java object so it can be used
>> inside
>> > Clojure code?
>> >
>> >  But I don't want to pass services to Clojure functions, I'd like to
>> >> inject them into Clojure namespace when clojure.core/require is
>> executed.
>> >>
>> >
>> > Got it. I have no idea how to do that given my almost no knowledge of
>> > Clojure. But I guess there's some way of doing that.
>> >
>> >
>> > --
>> > Thiago H. de Paula Figueiredo
>> > Tapestry, Java and Hibernate consultant and developer
>> > http://machina.com.br
>> >
>> > ---------------------------------------------------------------------
>> > To unsubscribe, e-mail: [hidden email]
>> > For additional commands, e-mail: [hidden email]
>> >
>> >
>>
>> --
>> Howard M. Lewis Ship
>>
>> Creator of Apache Tapestry
>>
>> The source for Tapestry training, mentoring and support. Contact me to
>> learn how I can get you up and productive in Tapestry fast!
>>
>> (971) 678-5210
>> http://howardlewisship.com
>> @hlship
>>
>
>
>
> --
> Ilya Obshadko
>
>


--
Ilya Obshadko
Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Ilya Obshadko-2
One more question regarding ObjectLocator.
Turns out it cannot resolve services like Logger, complaining that no
service implements its interface.
Could you suggest how to solve it?

On Thu, Dec 18, 2014 at 11:20 PM, Ilya Obshadko <[hidden email]>
wrote:

> So, my solution for this is actually quite simple:
>
> (ns com.xdance.tapestry.serviceregistry
>
>   (:import (org.apache.tapestry5.ioc ObjectLocator)))
>
>
> (def ^:dynamic ^ObjectLocator *tapestry-registry-ref* (promise))
>
>
> (defn init-registry [^ObjectLocator registry]
>
>   "Must be called during service initialization to set up Tapestry
> registry object"
>
>   (deliver *tapestry-registry-ref* registry))
>
>
> (defmacro with-tapestry-services [service-bindings & body]
>
>   "Apply service bindings to body"
>
>   (let [service-binding-pairs (partition-all 2 service-bindings)
>
>         service-binding-exprs (map #(vector (first %1) `(.getService (
> deref *tapestry-registry*) ~(second %1))) service-binding-pairs)
>
>         service-binding-final (vec (reduce concat service-binding-exprs))]
>
>     `(let ~service-binding-final ~@body)))
>
>
> The only thing I need to do is to bind init-registry function to Tapestry
> service interface and call it during startup phase. There might be better
> approaches probably.
>
> On Thu, Dec 18, 2014 at 6:49 PM, Ilya Obshadko <[hidden email]>
> wrote:
>
>> Thanks Howard, that's making a lot of sense.
>>
>> However my initial though was about injecting Clojure globals
>> (specifically, one global containing service registry) during the call to
>> "require" IFn. I still couldn't find any ways to manipulate initial Clojure
>> environment, although there are obvious workarounds (for example I could
>> have a specific function inside Clojure namespace that could be used to
>> inject necessary objects using mutable globals). I'm still looking for more
>> concise and accurate way to do that.
>>
>> On Thu, Dec 18, 2014 at 7:35 AM, Howard Lewis Ship <[hidden email]>
>> wrote:
>>
>>> Actually, Clojure interop with Java is very good, so a Clojure function
>>> could be passed a Java object:
>>>
>>> (defn frobnicate-the-request
>>>   [^Request request]
>>>   (.setAttribute request "xyzzyx" (compute-the-magic-name)))
>>>
>>> The ^Request part is a type hint, it allows the Clojure compiler to
>>> generate proper bytecode to access the methods of the request without
>>> using
>>> reflection.
>>>
>>> You quickly get used to the leading dot (which itself is sugar syntax
>>> over
>>> the more primitive interop special form).
>>>
>>> Now, in terms of Clojure interop ... the library I put together ago on a
>>> whim was about efficiently exposing Clojure functions bundled together as
>>> an arbitrary Java interface.
>>>
>>> If you pass the Registry to a Clojure function, it will be quite capable
>>> of
>>> pulling out whatever it needs.
>>>
>>> A lot of the capabilities of Clojure are very familiar to Tapestry users:
>>> thread bound values (inside Clojure vars) for example.
>>>
>>> My primary thought about integrating Clojure would be to allow a Tapestry
>>> app to jump into Clojure to work with the Datomic APIs natively, rather
>>> than the Java API to Datomic, which is decidedly second class.
>>>
>>> On Tue, Dec 16, 2014 at 5:24 AM, Thiago H de Paula Figueiredo <
>>> [hidden email]> wrote:
>>> >
>>> > On Mon, 15 Dec 2014 18:29:22 -0200, Ilya Obshadko <
>>> [hidden email]>
>>> > wrote:
>>> >
>>> >
>>> >  How are Java objects usually passed to Clojure code? The recommended
>>> way?
>>> >>>
>>> >>
>>> >> Java objects are passed to Clojure functions in exactly the same way
>>> they
>>> >> are passed to Java method (because internally Clojure function is
>>> just an
>>> >> implementation of IFn interface, and function call is invoke(...) on
>>> its
>>> >> instance).
>>> >>
>>> >
>>> > Now I was the one who hasn't made a clear question. :) I'm not asking
>>> > about how Clojure passes function arguments. I meant when you call
>>> Clojure
>>> > code from Java code, how do you pass a Java object so it can be used
>>> inside
>>> > Clojure code?
>>> >
>>> >  But I don't want to pass services to Clojure functions, I'd like to
>>> >> inject them into Clojure namespace when clojure.core/require is
>>> executed.
>>> >>
>>> >
>>> > Got it. I have no idea how to do that given my almost no knowledge of
>>> > Clojure. But I guess there's some way of doing that.
>>> >
>>> >
>>> > --
>>> > Thiago H. de Paula Figueiredo
>>> > Tapestry, Java and Hibernate consultant and developer
>>> > http://machina.com.br
>>> >
>>> > ---------------------------------------------------------------------
>>> > To unsubscribe, e-mail: [hidden email]
>>> > For additional commands, e-mail: [hidden email]
>>> >
>>> >
>>>
>>> --
>>> Howard M. Lewis Ship
>>>
>>> Creator of Apache Tapestry
>>>
>>> The source for Tapestry training, mentoring and support. Contact me to
>>> learn how I can get you up and productive in Tapestry fast!
>>>
>>> (971) 678-5210
>>> http://howardlewisship.com
>>> @hlship
>>>
>>
>>
>>
>> --
>> Ilya Obshadko
>>
>>
>
>
> --
> Ilya Obshadko
>
>


--
Ilya Obshadko
Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Thiago H de Paula Figueiredo
On Thu, 18 Dec 2014 20:01:11 -0200, Ilya Obshadko  
<[hidden email]> wrote:

> One more question regarding ObjectLocator.
> Turns out it cannot resolve services like Logger, complaining that no
> service implements its interface.
> Could you suggest how to solve it?

Have you tried getObject() instead of getService()? Logger isn't a  
Tapestry-IoC service (unless you create it, of course), so you cannot use  
getService() to get it.

By the way, as someone who wants to learn Clojure, could you please  
explain your Clojure snippet? :)

>
> On Thu, Dec 18, 2014 at 11:20 PM, Ilya Obshadko <[hidden email]>
> wrote:
>
>> So, my solution for this is actually quite simple:
>>
>> (ns com.xdance.tapestry.serviceregistry
>>
>>   (:import (org.apache.tapestry5.ioc ObjectLocator)))
>>
>>
>> (def ^:dynamic ^ObjectLocator *tapestry-registry-ref* (promise))
>>
>>
>> (defn init-registry [^ObjectLocator registry]
>>
>>   "Must be called during service initialization to set up Tapestry
>> registry object"
>>
>>   (deliver *tapestry-registry-ref* registry))
>>
>>
>> (defmacro with-tapestry-services [service-bindings & body]
>>
>>   "Apply service bindings to body"
>>
>>   (let [service-binding-pairs (partition-all 2 service-bindings)
>>
>>         service-binding-exprs (map #(vector (first %1) `(.getService (
>> deref *tapestry-registry*) ~(second %1))) service-binding-pairs)
>>
>>         service-binding-final (vec (reduce concat  
>> service-binding-exprs))]
>>
>>     `(let ~service-binding-final ~@body)))
>>
>>
>> The only thing I need to do is to bind init-registry function to  
>> Tapestry
>> service interface and call it during startup phase. There might be  
>> better
>> approaches probably.
>>
>> On Thu, Dec 18, 2014 at 6:49 PM, Ilya Obshadko <[hidden email]>
>> wrote:
>>
>>> Thanks Howard, that's making a lot of sense.
>>>
>>> However my initial though was about injecting Clojure globals
>>> (specifically, one global containing service registry) during the call  
>>> to
>>> "require" IFn. I still couldn't find any ways to manipulate initial  
>>> Clojure
>>> environment, although there are obvious workarounds (for example I  
>>> could
>>> have a specific function inside Clojure namespace that could be used to
>>> inject necessary objects using mutable globals). I'm still looking for  
>>> more
>>> concise and accurate way to do that.
>>>
>>> On Thu, Dec 18, 2014 at 7:35 AM, Howard Lewis Ship <[hidden email]>
>>> wrote:
>>>
>>>> Actually, Clojure interop with Java is very good, so a Clojure  
>>>> function
>>>> could be passed a Java object:
>>>>
>>>> (defn frobnicate-the-request
>>>>   [^Request request]
>>>>   (.setAttribute request "xyzzyx" (compute-the-magic-name)))
>>>>
>>>> The ^Request part is a type hint, it allows the Clojure compiler to
>>>> generate proper bytecode to access the methods of the request without
>>>> using
>>>> reflection.
>>>>
>>>> You quickly get used to the leading dot (which itself is sugar syntax
>>>> over
>>>> the more primitive interop special form).
>>>>
>>>> Now, in terms of Clojure interop ... the library I put together ago  
>>>> on a
>>>> whim was about efficiently exposing Clojure functions bundled  
>>>> together as
>>>> an arbitrary Java interface.
>>>>
>>>> If you pass the Registry to a Clojure function, it will be quite  
>>>> capable
>>>> of
>>>> pulling out whatever it needs.
>>>>
>>>> A lot of the capabilities of Clojure are very familiar to Tapestry  
>>>> users:
>>>> thread bound values (inside Clojure vars) for example.
>>>>
>>>> My primary thought about integrating Clojure would be to allow a  
>>>> Tapestry
>>>> app to jump into Clojure to work with the Datomic APIs natively,  
>>>> rather
>>>> than the Java API to Datomic, which is decidedly second class.
>>>>
>>>> On Tue, Dec 16, 2014 at 5:24 AM, Thiago H de Paula Figueiredo <
>>>> [hidden email]> wrote:
>>>> >
>>>> > On Mon, 15 Dec 2014 18:29:22 -0200, Ilya Obshadko <
>>>> [hidden email]>
>>>> > wrote:
>>>> >
>>>> >
>>>> >  How are Java objects usually passed to Clojure code? The  
>>>> recommended
>>>> way?
>>>> >>>
>>>> >>
>>>> >> Java objects are passed to Clojure functions in exactly the same  
>>>> way
>>>> they
>>>> >> are passed to Java method (because internally Clojure function is
>>>> just an
>>>> >> implementation of IFn interface, and function call is invoke(...)  
>>>> on
>>>> its
>>>> >> instance).
>>>> >>
>>>> >
>>>> > Now I was the one who hasn't made a clear question. :) I'm not  
>>>> asking
>>>> > about how Clojure passes function arguments. I meant when you call
>>>> Clojure
>>>> > code from Java code, how do you pass a Java object so it can be used
>>>> inside
>>>> > Clojure code?
>>>> >
>>>> >  But I don't want to pass services to Clojure functions, I'd like to
>>>> >> inject them into Clojure namespace when clojure.core/require is
>>>> executed.
>>>> >>
>>>> >
>>>> > Got it. I have no idea how to do that given my almost no knowledge  
>>>> of
>>>> > Clojure. But I guess there's some way of doing that.
>>>> >
>>>> >
>>>> > --
>>>> > Thiago H. de Paula Figueiredo
>>>> > Tapestry, Java and Hibernate consultant and developer
>>>> > http://machina.com.br
>>>> >
>>>> >  
>>>> ---------------------------------------------------------------------
>>>> > To unsubscribe, e-mail: [hidden email]
>>>> > For additional commands, e-mail: [hidden email]
>>>> >
>>>> >
>>>>
>>>> --
>>>> Howard M. Lewis Ship
>>>>
>>>> Creator of Apache Tapestry
>>>>
>>>> The source for Tapestry training, mentoring and support. Contact me to
>>>> learn how I can get you up and productive in Tapestry fast!
>>>>
>>>> (971) 678-5210
>>>> http://howardlewisship.com
>>>> @hlship
>>>>
>>>
>>>
>>>
>>> --
>>> Ilya Obshadko
>>>
>>>
>>
>>
>> --
>> Ilya Obshadko
>>
>>
>
>


--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Tapestry and Clojure

Ilya Obshadko-2
No, I didn't try getObject() yet. That means the code for injection would
be a little bit more complex, but I'll explain using "simple" version from
the previous message:

https://gist.github.com/xfyre/f6a62b3f63ed01929054

Line 4: define dynamic global variable as (promise) - it's not available at
the time of compilation.

Lines 6-8: this is a Tapestry-mapped function that will be called during
@Startup phase to "deliver" ObjectLocator instance (after promise was
delivered, it becomes immutable and can't be mutated anymore).

Lines 10-15: macro that accepts service-bindings in a usual Clojure
bindings format, like [hibernate-session Session my-service MyService],
when odd entries are variable names and even entries are class names (in
Clojure you don't need to use .class). The macro reconstructs this list so
Class names are
converted to getService() calls, and then during let binding (syntax
unquote on line 15) those services are finally bound to variables for the
later use.

Lines 19-23 is an example of using this macro.


On Sun, Dec 21, 2014 at 10:22 PM, Thiago H de Paula Figueiredo <
[hidden email]> wrote:

> On Thu, 18 Dec 2014 20:01:11 -0200, Ilya Obshadko <[hidden email]>
> wrote:
>
>  One more question regarding ObjectLocator.
>> Turns out it cannot resolve services like Logger, complaining that no
>> service implements its interface.
>> Could you suggest how to solve it?
>>
>
> Have you tried getObject() instead of getService()? Logger isn't a
> Tapestry-IoC service (unless you create it, of course), so you cannot use
> getService() to get it.
>
> By the way, as someone who wants to learn Clojure, could you please
> explain your Clojure snippet? :)
>
>
>
>> On Thu, Dec 18, 2014 at 11:20 PM, Ilya Obshadko <[hidden email]>
>> wrote:
>>
>>  So, my solution for this is actually quite simple:
>>>
>>> (ns com.xdance.tapestry.serviceregistry
>>>
>>>   (:import (org.apache.tapestry5.ioc ObjectLocator)))
>>>
>>>
>>> (def ^:dynamic ^ObjectLocator *tapestry-registry-ref* (promise))
>>>
>>>
>>> (defn init-registry [^ObjectLocator registry]
>>>
>>>   "Must be called during service initialization to set up Tapestry
>>> registry object"
>>>
>>>   (deliver *tapestry-registry-ref* registry))
>>>
>>>
>>> (defmacro with-tapestry-services [service-bindings & body]
>>>
>>>   "Apply service bindings to body"
>>>
>>>   (let [service-binding-pairs (partition-all 2 service-bindings)
>>>
>>>         service-binding-exprs (map #(vector (first %1) `(.getService (
>>> deref *tapestry-registry*) ~(second %1))) service-binding-pairs)
>>>
>>>         service-binding-final (vec (reduce concat
>>> service-binding-exprs))]
>>>
>>>     `(let ~service-binding-final ~@body)))
>>>
>>>
>>> The only thing I need to do is to bind init-registry function to Tapestry
>>> service interface and call it during startup phase. There might be better
>>> approaches probably.
>>>
>>> On Thu, Dec 18, 2014 at 6:49 PM, Ilya Obshadko <[hidden email]>
>>> wrote:
>>>
>>>  Thanks Howard, that's making a lot of sense.
>>>>
>>>> However my initial though was about injecting Clojure globals
>>>> (specifically, one global containing service registry) during the call
>>>> to
>>>> "require" IFn. I still couldn't find any ways to manipulate initial
>>>> Clojure
>>>> environment, although there are obvious workarounds (for example I could
>>>> have a specific function inside Clojure namespace that could be used to
>>>> inject necessary objects using mutable globals). I'm still looking for
>>>> more
>>>> concise and accurate way to do that.
>>>>
>>>> On Thu, Dec 18, 2014 at 7:35 AM, Howard Lewis Ship <[hidden email]>
>>>> wrote:
>>>>
>>>>  Actually, Clojure interop with Java is very good, so a Clojure function
>>>>> could be passed a Java object:
>>>>>
>>>>> (defn frobnicate-the-request
>>>>>   [^Request request]
>>>>>   (.setAttribute request "xyzzyx" (compute-the-magic-name)))
>>>>>
>>>>> The ^Request part is a type hint, it allows the Clojure compiler to
>>>>> generate proper bytecode to access the methods of the request without
>>>>> using
>>>>> reflection.
>>>>>
>>>>> You quickly get used to the leading dot (which itself is sugar syntax
>>>>> over
>>>>> the more primitive interop special form).
>>>>>
>>>>> Now, in terms of Clojure interop ... the library I put together ago on
>>>>> a
>>>>> whim was about efficiently exposing Clojure functions bundled together
>>>>> as
>>>>> an arbitrary Java interface.
>>>>>
>>>>> If you pass the Registry to a Clojure function, it will be quite
>>>>> capable
>>>>> of
>>>>> pulling out whatever it needs.
>>>>>
>>>>> A lot of the capabilities of Clojure are very familiar to Tapestry
>>>>> users:
>>>>> thread bound values (inside Clojure vars) for example.
>>>>>
>>>>> My primary thought about integrating Clojure would be to allow a
>>>>> Tapestry
>>>>> app to jump into Clojure to work with the Datomic APIs natively, rather
>>>>> than the Java API to Datomic, which is decidedly second class.
>>>>>
>>>>> On Tue, Dec 16, 2014 at 5:24 AM, Thiago H de Paula Figueiredo <
>>>>> [hidden email]> wrote:
>>>>> >
>>>>> > On Mon, 15 Dec 2014 18:29:22 -0200, Ilya Obshadko <
>>>>> [hidden email]>
>>>>> > wrote:
>>>>> >
>>>>> >
>>>>> >  How are Java objects usually passed to Clojure code? The recommended
>>>>> way?
>>>>> >>>
>>>>> >>
>>>>> >> Java objects are passed to Clojure functions in exactly the same way
>>>>> they
>>>>> >> are passed to Java method (because internally Clojure function is
>>>>> just an
>>>>> >> implementation of IFn interface, and function call is invoke(...) on
>>>>> its
>>>>> >> instance).
>>>>> >>
>>>>> >
>>>>> > Now I was the one who hasn't made a clear question. :) I'm not asking
>>>>> > about how Clojure passes function arguments. I meant when you call
>>>>> Clojure
>>>>> > code from Java code, how do you pass a Java object so it can be used
>>>>> inside
>>>>> > Clojure code?
>>>>> >
>>>>> >  But I don't want to pass services to Clojure functions, I'd like to
>>>>> >> inject them into Clojure namespace when clojure.core/require is
>>>>> executed.
>>>>> >>
>>>>> >
>>>>> > Got it. I have no idea how to do that given my almost no knowledge of
>>>>> > Clojure. But I guess there's some way of doing that.
>>>>> >
>>>>> >
>>>>> > --
>>>>> > Thiago H. de Paula Figueiredo
>>>>> > Tapestry, Java and Hibernate consultant and developer
>>>>> > http://machina.com.br
>>>>> >
>>>>> > ------------------------------------------------------------
>>>>> ---------
>>>>> > To unsubscribe, e-mail: [hidden email]
>>>>> > For additional commands, e-mail: [hidden email]
>>>>> >
>>>>> >
>>>>>
>>>>> --
>>>>> Howard M. Lewis Ship
>>>>>
>>>>> Creator of Apache Tapestry
>>>>>
>>>>> The source for Tapestry training, mentoring and support. Contact me to
>>>>> learn how I can get you up and productive in Tapestry fast!
>>>>>
>>>>> (971) 678-5210
>>>>> http://howardlewisship.com
>>>>> @hlship
>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> Ilya Obshadko
>>>>
>>>>
>>>>
>>>
>>> --
>>> Ilya Obshadko
>>>
>>>
>>>
>>
>>
>
> --
> Thiago H. de Paula Figueiredo
> Tapestry, Java and Hibernate consultant and developer
> http://machina.com.br
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>


--
Ilya Obshadko
12