Re: clojure.contrib.sql insert id

2010-04-21 Thread Saul Hazledine
On Apr 20, 8:51 pm, Remco van 't Veer  wrote:
> I am doing the following after an insert for a Derby database:
>
>   (sql/with-query-results res
>     ["VALUES IDENTITY_VAL_LOCAL()"]
>     (first (vals (first res
>
> For MySQL it would be something like:
>
>   (sql/with-query-results res
>     ["SELECT LAST_INSERT_ID()"]
>     (first (vals (first res
>

Thanks Remco. I'm using H2 and its seems possible to do something
similar by accessing the INFORMATION_SCHEMA. However, this also feels
wrong to me so I'm trying the JDBC route which should be more
consistent across databases. My first working attempt is at:

http://gist.github.com/373564#file_sql.clj

It contains a alternative to insert-records called 'insert-record'
which returns a database id and a macro that wraps up multiple inserts
in a transaction. The macro doesn't feel very idiomatic so I'd welcome
any feedback on how to change it.

-
extended.sql/insert-record
([table record])
  Equivalent of clojure.contrib.sql/insert-records that only inserts a
single
   record but returns the autogenerated id of that record if
available.

-
extended.sql/insert-with-id
([db & table-records])
Macro
  Insert records within a single transaction into the database
described by
   the given db spec. The record format is :table  { record-hash }.
   The record hashes can optionally access a hashmap 'id' which holds
the
   autogenerated ids of previous inserts keyed by the table name. e.g.

  (insert-with-id db-spec
  :department {:name "xfiles"
   :location "secret"}
  :employee   {:department (id :department)
   :name "Mr X"})

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: clojure.contrib.sql insert id

2010-04-21 Thread Remco van 't Veer
Nice!  That's a lot better than depending on some quirky sql construct.

Thanks,
Remco


Saul Hazledine  writes:

> On Apr 20, 8:51 pm, Remco van 't Veer  wrote:
>> I am doing the following after an insert for a Derby database:
>>
>>   (sql/with-query-results res
>>     ["VALUES IDENTITY_VAL_LOCAL()"]
>>     (first (vals (first res
>>
>> For MySQL it would be something like:
>>
>>   (sql/with-query-results res
>>     ["SELECT LAST_INSERT_ID()"]
>>     (first (vals (first res
>>
>
> Thanks Remco. I'm using H2 and its seems possible to do something
> similar by accessing the INFORMATION_SCHEMA. However, this also feels
> wrong to me so I'm trying the JDBC route which should be more
> consistent across databases. My first working attempt is at:
>
> http://gist.github.com/373564#file_sql.clj
>
> It contains a alternative to insert-records called 'insert-record'
> which returns a database id and a macro that wraps up multiple inserts
> in a transaction. The macro doesn't feel very idiomatic so I'd welcome
> any feedback on how to change it.
>
> -
> extended.sql/insert-record
> ([table record])
>   Equivalent of clojure.contrib.sql/insert-records that only inserts a
> single
>record but returns the autogenerated id of that record if
> available.
>
> -
> extended.sql/insert-with-id
> ([db & table-records])
> Macro
>   Insert records within a single transaction into the database
> described by
>the given db spec. The record format is :table  { record-hash }.
>The record hashes can optionally access a hashmap 'id' which holds
> the
>autogenerated ids of previous inserts keyed by the table name. e.g.
>
>   (insert-with-id db-spec
>   :department {:name "xfiles"
>:location "secret"}
>   :employee   {:department (id :department)
>:name "Mr X"})

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: clojure.contrib.sql insert id

2010-04-21 Thread Joost
On Apr 21, 11:48 am, Remco van 't Veer  wrote:
> Nice!  That's a lot better than depending on some quirky sql construct.

Agreed. There's just one potential issue (which is the same issue I
have with
clojure.contrib.sql): it doesn't quote the column or table names,
meaning you
can't use such nice column keys as :user-id

I smashed all of it into my modified version of clojure.contrib.sql:

http://gist.github.com/373677

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Try + finally question

2010-04-21 Thread ka
Hi,

I'm using an API to connect to a server which does not provide
constructors, just static methods to get & close connections.

How can I do something like ...

(try
  (let [conn (API/getConnection ..)]
())
  (catch ..)
  (finally (if conn (API/closeConnection conn

Problem is that conn is unavailable in the finally context.

Is there any easy workaround which doesn't involve defing a global
conn.

- 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
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


duck-streams missing from clojure-contrib.jar file

2010-04-21 Thread Neal
Hi,

I'm new to Clojure.  I've been trying to go through the Programming
Clojure book and have run into a problem that I hope someone can fix.

I'm trying to use duck-streams, but it is missing from the clojure-
contrib JAR file (at least in build #81).  I have listed the contents
of the JAR file and confirmed that it is not in there.

All the documentation that I read seems to indicate that duck-streams
is not deprecated.

Thanks for any help,

Neal

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Arguments for < and > et al

2010-04-21 Thread Bill Allen
I've been writing a program that requires the use of java.util.Calendar and
its descendent java.util.GregorianCalendar. One thing I'd hoped to do was
compare two Calendar objects with <, but the compiler complained that the
arguments to < didn't inherit from Number which was a surprise to me because
Calendar does inherit from java.lang.Comparable which in java land would be
sufficient to enable it to be compared with other members of its class using
the built in java comparison operators. Since I know that clojure has other
operations that deal with comparable, I assume this is a conscious decision,
but I question why it should be so.

Regards,
Bill

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Interesting Facebook blog post on Concurrency (mentions Clojure)

2010-04-21 Thread Carlos Bueno
H! :D -- Clojure uses MVCC, which may help with this.
http://en.wikipedia.org/wiki/Multiversion_concurrency_control

But as Hickey points out, no one really knows yet because there aren't
enough high-core machines doing real work in the field.
http://groups.google.com/group/clojure/msg/cd3e77afb75441d8

I put that second sentence in more as a joke than a Deep Insight; it's
a reference to a silly song I like called "The Sweater Song":
"If you want to destroy my sweater / Hold this thread as I walk away."

Cheers,
  Carlos

On Apr 13, 12:02 am, Baishampayan Ghose  wrote:
> Hi,
>
> This is an interesting article on the problems associated with
> concurrency and some of the current solutions.
>
> http://www.facebook.com/notes/facebook-engineering/a-dismal-guide-to-...
>
> It mentions Clojure for a bit and says this about the general idea
> behind STMs -
>
> "... STM has its own special problems, like how to perform those
> commit/abort/retry cycles efficiently on thousands of threads. It's fun
> to imagine pathological conflict scenarios in which long chains of
> transactions unravel like a cheap sweater."
>
> Would anyone like to comment on how that affects the Clojure STM (if at
> all)?
>
> Regards,
> BG
>
> --
> Baishampayan Ghose 

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Try + finally question

2010-04-21 Thread Alex Osborne
ka  writes:

> How can I do something like ...
>
> (try
>   (let [conn (API/getConnection ..)]
> ())
>   (catch ..)
>   (finally (if conn (API/closeConnection conn
>
> Problem is that conn is unavailable in the finally context.

Why not just have two try blocks?

(try
 (let [conn (API/getConnection ..)]
   (try
()
(finally (API/closeConnection conn
 (catch ...))

For these sorts of things I usually try to use with-open, or if
with-open is not applicable do my own similar macro:

(defmacro with-api-connection [conn-sym arg1 arg2 & body]
  `(let [~conn-sym (API/getConnection ~arg1 ~arg2)]
 (try
  ~...@body
  (finally (API/closeConnection ~conn-sym)

So then you never forget to close the connection:

(try
 (with-api-connection conn ...
   (... do something with conn ...))
 (catch ...))

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: duck-streams missing from clojure-contrib.jar file

2010-04-21 Thread Meikel Brandmeyer
Hi,

On 21 Apr., 01:37, Neal  wrote:

> All the documentation that I read seems to indicate that duck-streams
> is not deprecated.

c.c.ducks-streams is now named c.c.io.

Sincerely
Meikel

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: duck-streams missing from clojure-contrib.jar file

2010-04-21 Thread Alex Osborne
Hi Neal,

Neal  writes:

> I'm trying to use duck-streams, but it is missing from the clojure-
> contrib JAR file (at least in build #81).  I have listed the contents
> of the JAR file and confirmed that it is not in there.

It sounds like you're using a 1.2 pre-release snapshot build of
clojure-contrib.  There's currently some refactoring going on to better
organize contrib, now that it's a little more mature.  Most of
clojure.contrib.duck-streams has now become clojure.contrib.io.

I suggest you use the stable 1.1 releases of both Clojure and contrib
for your initial learning as it will better match the book.  When 1.2 is
released stable I'm sure there will be a document written that explains
the differences.

I really wish the 1.1.0 release builds were more prominently linked on
the clojure.org website, but you can download them here: 

http://build.clojure.org/releases/org/clojure/clojure/1.1.0/clojure-1.1.0.jar
http://build.clojure.org/releases/org/clojure/clojure-contrib/1.1.0/clojure-contrib-1.1.0.jar

Hope that helps,

Alex

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Slides for short (45 minutes) presentation of clojure for java devs

2010-04-21 Thread Laurent PETIT
Hello,

I've consulted a lot of already made presentations of clojure.
They are great, but I guess they may not suit my needs because it
seems to me that either:
  * they are more 1 1/2 to 2 hours talks than 45 minutes
  * they assume the "public" will not be relunctant to some terms like
"Lisp", "Functional Programming" and directly present these as
advantages

My goal is to raise interest into clojure in the mind of a public of
people having used java for a long time. They may have Scala already
in their "radar", but not clojure, or may have seen it and immediately
dismissed it for what seemed to them good reasons (mainly aversion for
lisp syntax), though we all know this is not true after the "normal"
adaptation period.

Say this presentation could be the presentation that leads people, at
its end, asking you for giving all those great other presentations
already available that I mentioned before ...

Any references I missed that already solve my problem ? :-)

Thanks in advance,

-- 
Laurent

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Arguments for < and > et al

2010-04-21 Thread Stuart Halloway
The built-in Java comparison operators don't honor Comparable either.   
In Clojure, it's about keeping (pure number) math fast.


If you are doing any nontrivial date work, I recommend you look at clj- 
time (http://github.com/clj-sys/clj-time), a Clojure wrapper for Joda  
Time. Then, if you really want "<" and ">" to work, you can define  
them in your own namespace to wrap clj-time's "after?" and "before?".


Stu

I've been writing a program that requires the use of  
java.util.Calendar and its descendent java.util.GregorianCalendar.  
One thing I'd hoped to do was compare two Calendar objects with <,  
but the compiler complained that the arguments to < didn't inherit  
from Number which was a surprise to me because Calendar does inherit  
from java.lang.Comparable which in java land would be sufficient to  
enable it to be compared with other members of its class using the  
built in java comparison operators. Since I know that clojure has  
other operations that deal with comparable, I assume this is a  
conscious decision, but I question why it should be so.


Regards,
Bill

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient  
with your first post.

To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Try + finally question

2010-04-21 Thread ka
Thanks for the reply Alex,

I thought of 2 try blocks, but seems over engineering doesn't it ?  I
actually need to open 2 connections simultaneously, which would amount
to 3 nested try blocks. The whole code gets cluttered with all these
try finally (and one catch) statements.

  (try
(let [conn1 (API1/getConnection ..)]
  (try
(let [conn2 (API2/getConnection ..)]
  (try
( ... Do something with conn1 conn2 )
(finally
  (API2/closeConnection conn2
(finally
  (API1/closeConnection conn1
(catch Exception ex (.printStackTrace ex)))

The macro solution looks good.  But with 2 different APIs for 2
connections, I would need to write 2 macros right?

(defmacro with-api1-connection [conn-sym arg1 arg2 & body]
  `(let [~conn-sym (API1/getConnection ~arg1 ~arg2)]
 (try
  ~...@body
  (finally (API1/closeConnection ~conn-sym)

(defmacro with-api2-connection [conn-sym arg1 arg2 arg3 & body]
  `(let [~conn-sym (API2/getConnection ~arg1 ~arg2 ~arg3)]
 (try
  ~...@body
  (finally (API2/closeConnection ~conn-sym)

Also coming back to the original requirement, wanted to know what are
the problems with providing support (somehow) for something like -

(try
  (let [conn1 (API1/getConnection ..)
 conn2 (API2/getConnection ..)]
())
  (catch ..)
  (finally
(if conn1 (API1/closeConnection conn1))
(if conn2 (API2/closeConnection conn2


Coming from Java, this would be implemented as -

Connection1 conn1 = null;
Connection2 conn2 = null;
try {
  conn1 = API1.getConnection ..;
  conn2 = API2.getConnection ..;
  ...
}
catch (){}
finally {
  if (conn1 != null)
API1.closeConnection(conn1);
  if (conn2 != null)
API2.closeConnection(conn2);
}

I agree that this code doesn't look good from a purist pov, but any
issues besides that?

- Thanks!

On Apr 21, 4:58 pm, Alex Osborne  wrote:
> ka  writes:
> > How can I do something like ...
>
> > (try
> >   (let [conn (API/getConnection ..)]
> >     ())
> >   (catch ..)
> >   (finally (if conn (API/closeConnection conn
>
> > Problem is that conn is unavailable in the finally context.
>
> Why not just have two try blocks?
>
> (try
>  (let [conn (API/getConnection ..)]
>    (try
>     ()
>     (finally (API/closeConnection conn
>  (catch ...))
>
> For these sorts of things I usually try to use with-open, or if
> with-open is not applicable do my own similar macro:
>
> (defmacro with-api-connection [conn-sym arg1 arg2 & body]
>   `(let [~conn-sym (API/getConnection ~arg1 ~arg2)]
>      (try
>       ~...@body
>       (finally (API/closeConnection ~conn-sym)
>
> So then you never forget to close the connection:
>
> (try
>  (with-api-connection conn ...
>    (... do something with conn ...))
>  (catch ...))
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: duck-streams missing from clojure-contrib.jar file

2010-04-21 Thread Douglas Philips

On 2010 Apr 21, at 8:11 AM, Alex Osborne wrote:

I suggest you use the stable 1.1 releases of both Clojure and contrib
for your initial learning as it will better match the book.  When  
1.2 is
released stable I'm sure there will be a document written that  
explains

the differences.


That isn't as helpful as you might think.

(I'm using 1.1, as conveniently provided by macports.)

Nothing that I can find on either clojure.org or the contrib site http://richhickey.github.com/clojure-contrib/ 
 says what version it is/applies-to.


How would I know if I'm using the stable 1.1 release that I need to  
replace clojure.contrib.seq with clojure.contrib.seq-utils, or  
clojure.contrib.io with clojure.contrib.duck-stream?


http://richhickey.github.com/clojure-contrib/io-api.html doesn't say:
   This document applies to 1.2 (pending), for 1.1 or older see: 
nor:
   This document applies to 1.2 (pending), it was renamed from  
clojure.contrib.duck-stream



--Doug

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Try + finally question

2010-04-21 Thread Mark J. Reed
On Wed, Apr 21, 2010 at 9:06 AM, ka  wrote:

> Connection1 conn1 = null;
> Connection2 conn2 = null;
> try {
>  conn1 = API1.getConnection ..;
>  conn2 = API2.getConnection ..;
>  ...
> }


You can't do that without using atoms or something, because you're assigning
to conn1 and conn2 twice.  That's not legal in Clojure because what "let"
gives you aren't variables, but local constants.

One solution would be to add a new construct to the language:

(try-let [bindings] (body) (catch...) (finally...))

where any exception during evaluation of the [bindings] would be caught just
as if it happened inside the body, and of course the bound variables would
be visible to both the catch blocks and the finally block.

It could be implemented as a macro that duplicated the catch/finally blocks
within and outside a let...

-- 
Mark J. Reed 

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: duck-streams missing from clojure-contrib.jar file

2010-04-21 Thread Stuart Halloway
The second level header tells you the branch (e.g. master). On the  
left hand side is a list of branches (so you can click on e.g. 1.1.x).


Some ways I see this might be better:

(1) make clear what master currently equals (right now it is 1.2 alpha)
(2) highlight the branch info more with css
(3) push the branch info into the top-level header (and page title)
(4) The overview section for c.c.io could tell about the lineage back  
to 1.1.


Which of these (or what else?) would have helped you the most?

Stu


On 2010 Apr 21, at 8:11 AM, Alex Osborne wrote:

I suggest you use the stable 1.1 releases of both Clojure and contrib
for your initial learning as it will better match the book.  When  
1.2 is
released stable I'm sure there will be a document written that  
explains

the differences.


That isn't as helpful as you might think.

(I'm using 1.1, as conveniently provided by macports.)

Nothing that I can find on either clojure.org or the contrib site http://richhickey.github.com/clojure-contrib/ 
 says what version it is/applies-to.


How would I know if I'm using the stable 1.1 release that I need to  
replace clojure.contrib.seq with clojure.contrib.seq-utils, or  
clojure.contrib.io with clojure.contrib.duck-stream?


http://richhickey.github.com/clojure-contrib/io-api.html doesn't say:
  This document applies to 1.2 (pending), for 1.1 or older see: 
nor:
  This document applies to 1.2 (pending), it was renamed from  
clojure.contrib.duck-stream



--Doug

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient  
with your first post.

To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Try + finally question

2010-04-21 Thread Laurent PETIT
Hi,

Something I don't understand: if the call to (API/getConnection ...)
fails, there is nothing to close, right ?

So for the problem of ensuring that any open connection is always
closed, the following pattern seems enough:

(try
  (let [conn (API/getConnection ..)]
 XXX)
  (finally (API/closeConnection conn)))

In XXX you can do your business job, maybe catching exceptions, etc.,
but that is not the same intent as ensuring pairs of open/close calls
in any case.

Smart java frameworks such as SpringFramework do the exact same thing
by using Interface callbacks encapsulating the XXX "real interesting
code".

The less verbose way of doing this is clojure's with-open macro.
Though you would have, as Alex pointed out, to create your own variant
of with-open to accomodate your particular API for closing the
connection.

Or, if you use master, you could write the protocol-aware version of
with-open :-)


2010/4/21 ka :
> Hi,
>
> I'm using an API to connect to a server which does not provide
> constructors, just static methods to get & close connections.
>
> How can I do something like ...
>
> (try
>  (let [conn (API/getConnection ..)]
>    ())
>  (catch ..)
>  (finally (if conn (API/closeConnection conn
>
> Problem is that conn is unavailable in the finally context.
>
> Is there any easy workaround which doesn't involve defing a global
> conn.
>
> - 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
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Try + finally question

2010-04-21 Thread Laurent PETIT
Oh, also see the source code for with-open :
http://github.com/richhickey/clojure/blob/master/src/clj/clojure/core.clj#L2542

and also note that it allows you to declare bindings for opening
connections in sequence, and will take care of closing them in the
reverse order.

And to answer your question about writing 2 macros if you have
different APIs, no no :

  * either use protocols if you work on the master branch
  * either use multimethods

that is, use polymorphism :-)

2010/4/21 Laurent PETIT :
> Hi,
>
> Something I don't understand: if the call to (API/getConnection ...)
> fails, there is nothing to close, right ?
>
> So for the problem of ensuring that any open connection is always
> closed, the following pattern seems enough:
>
> (try
>  (let [conn (API/getConnection ..)]
>     XXX)
>  (finally (API/closeConnection conn)))
>
> In XXX you can do your business job, maybe catching exceptions, etc.,
> but that is not the same intent as ensuring pairs of open/close calls
> in any case.
>
> Smart java frameworks such as SpringFramework do the exact same thing
> by using Interface callbacks encapsulating the XXX "real interesting
> code".
>
> The less verbose way of doing this is clojure's with-open macro.
> Though you would have, as Alex pointed out, to create your own variant
> of with-open to accomodate your particular API for closing the
> connection.
>
> Or, if you use master, you could write the protocol-aware version of
> with-open :-)
>
>
> 2010/4/21 ka :
>> Hi,
>>
>> I'm using an API to connect to a server which does not provide
>> constructors, just static methods to get & close connections.
>>
>> How can I do something like ...
>>
>> (try
>>  (let [conn (API/getConnection ..)]
>>    ())
>>  (catch ..)
>>  (finally (if conn (API/closeConnection conn
>>
>> Problem is that conn is unavailable in the finally context.
>>
>> Is there any easy workaround which doesn't involve defing a global
>> conn.
>>
>> - 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
>> Note that posts from new members are moderated - please be patient with your 
>> first post.
>> To unsubscribe from this group, send email to
>> clojure+unsubscr...@googlegroups.com
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Try + finally question

2010-04-21 Thread Mark J. Reed
On Wed, Apr 21, 2010 at 9:37 AM, Laurent PETIT wrote:

> Hi,
>
> Something I don't understand: if the call to (API/getConnection ...)
> fails, there is nothing to close, right ?
>
> So for the problem of ensuring that any open connection is always
> closed, the following pattern seems enough:
>
> (try
>  (let [conn (API/getConnection ..)]
>  XXX)
>  (finally (API/closeConnection conn)))
>

That would be great, but it doesn't work, because "conn" doesn't exist any
more by the time you get to the finally block. That's the problem being
addressed in this thread.

So you can do this:

(let [conn (API/getConnection ...)]
   (try
  XXX
   (finally (API/closeConnection conn

But then any exception thrown by API/getConnection is not caught.

So you have to do this:

(try
(let [conn (API/getConnection ...)]
  (try
XXX
  (finally (API/closeConnection conn
   (catch ...))

But that still won't work if the catch block also needs access to "conn".
 So you wind up with something like this:

(try
(let [conn (API/getConnection ...)]
  (try
XXX
  (catch ExceptionAfterConnect x (do-something-with conn))
  (finally (API/closeConnection conn
   (catch .ExceptionDuringConnect x (do-something-without-conn

-- 
Mark J. Reed 

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Try + finally question

2010-04-21 Thread Laurent PETIT
2010/4/21 Mark J. Reed :
> On Wed, Apr 21, 2010 at 9:37 AM, Laurent PETIT 
> wrote:
>>
>> Hi,
>>
>> Something I don't understand: if the call to (API/getConnection ...)
>> fails, there is nothing to close, right ?
>>
>> So for the problem of ensuring that any open connection is always
>> closed, the following pattern seems enough:
>>
>> (try
>>  (let [conn (API/getConnection ..)]
>>     XXX)
>>  (finally (API/closeConnection conn)))

Of course, My code was wrong, and I meant


  (let [conn (API/getConnection ..)]
(try
  XXX
  (finally (API/closeConnection conn)))

And really, catching exceptions thrown by API/getConnection is not in
the problem domain of ensuring balanced pairs of opened/closed
connections, e.g. should be outside the abstraction you put in place
for handling this (e.g. with-open).

Ensuring that opened connections are closed is a resource (I/O)
management problem.
Handling the case where you were not able to open a connection is an
application problem. You might place the try/catch right around the
let, have a global handling very high in the call stack, or even have
no try/catch at all.

HTH,

-- 
Laurent

>
> That would be great, but it doesn't work, because "conn" doesn't exist any
> more by the time you get to the finally block. That's the problem being
> addressed in this thread.
> So you can do this:
> (let [conn (API/getConnection ...)]
>    (try
>       XXX
>    (finally (API/closeConnection conn
> But then any exception thrown by API/getConnection is not caught.
>
> So you have to do this:
> (try
>     (let [conn (API/getConnection ...)]
>       (try
>         XXX
>       (finally (API/closeConnection conn
>    (catch ...))
> But that still won't work if the catch block also needs access to "conn".
>  So you wind up with something like this:
> (try
>     (let [conn (API/getConnection ...)]
>       (try
>         XXX
>       (catch ExceptionAfterConnect x (do-something-with conn))
>       (finally (API/closeConnection conn
>    (catch .ExceptionDuringConnect x (do-something-without-conn
> --
> Mark J. Reed 
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Try + finally question

2010-04-21 Thread Alex Osborne
ka  writes:

> The whole code gets cluttered with all these try finally (and one
> catch) statements.
>
>   (try
> (let [conn1 (API1/getConnection ..)]
>   (try
> (let [conn2 (API2/getConnection ..)]
>   (try
> ( ... Do something with conn1 conn2 )
> (finally
>   (API2/closeConnection conn2
> (finally
>   (API1/closeConnection conn1
> (catch Exception ex (.printStackTrace ex)))

I guess the main difference in this compared to your java example is the
levels of nesting.  This may look messy but it's semantically exactly
what you're trying to express.

> The macro solution looks good.  But with 2 different APIs for 2
> connections, I would need to write 2 macros right?
>
> (defmacro with-api1-connection [conn-sym arg1 arg2 & body]
>   `(let [~conn-sym (API1/getConnection ~arg1 ~arg2)]
>  (try
>   ~...@body
>   (finally (API1/closeConnection ~conn-sym)
>
> (defmacro with-api2-connection [conn-sym arg1 arg2 arg3 & body]
>   `(let [~conn-sym (API2/getConnection ~arg1 ~arg2 ~arg3)]
>  (try
>   ~...@body
>   (finally (API2/closeConnection ~conn-sym)

You could make things more general:

(with-cleanup [conn1 (API1/getConnection ...) API1/closeConnection
   conn2 (API2/openConnection ...) #(.disconnect %)]
 ...)

I'll leave implementation as an exercise, it's not much more complicated
than the previous ones, the main trick would just be to make the macro
recursive, have it expand into:

(let [conn1 (API1/getConnection ...)]
  (try
(with-cleanup [conn2 (API2/openConnection ...) #(.disconnect %)]
  ...)
(finally
  (API1/closeConnection conn1

I'd probably start with a signature like this:

(defmacro with-cleanup [[sym create cleanup & more] & body]
  ...)

Take a look at the source for with-open if you get stuck.

> Coming from Java, this would be implemented as -
>
> Connection1 conn1 = null;
> Connection2 conn2 = null;
> try {
>   conn1 = API1.getConnection ..;
>   conn2 = API2.getConnection ..;
>   ...
> }
> catch (){}
> finally {
>   if (conn1 != null)
> API1.closeConnection(conn1);
>   if (conn2 != null)
> API2.closeConnection(conn2);
> }
>
> I agree that this code doesn't look good from a purist pov, but any
> issues besides that?

The problem here is that this breaks lexical scope, conn1 and
conn2 aren't defined outside their let block.  The Java example dodges
this with mutation.  Python/Ruby/JavaScript etc dodge it by having
special scoping rules: variables are scoped to functions rather than the
enclosing block.

Clojure's opinion, as I understand it, is that it's not worthwhile
introducing mutation or special scoping rules simply to avoid some
nesting, when we have perfectly good tools (macros) for doing purely
syntactic transformations and removing boilerplate.

There's nothing semantically wrong with nesting, it's just harder
to read.  The Clojure idiom for reducing nesting is usually to use a
macro like ->, ->> or with-open to flatten it.  In this case those
aren't applicable, so I suggest defining your own.

I'm not sure I phrased that clearly, please let me know if I'm not
making sense. :-)

Alex

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Try + finally question

2010-04-21 Thread Tassilo Horn
On Wednesday 21 April 2010 15:06:40 ka wrote:

Hi!

> The macro solution looks good.  But with 2 different APIs for 2
> connections, I would need to write 2 macros right?

No, not really.  You could also make the symbols for the API class an
additional arg to the macro, like:

 (defmacro with-api-connection [conn-sym api arg1 arg2 & body]
   `(let [~conn-sym (. ~api getConnection ~arg1 ~arg2)]
  (try
   ~...@body
   (finally (. ~api closeConnection ~conn-sym)

but then the macre application would be longer.

  (with-api-connection [c API1 "localhost" 12345]
(with-api-connection [c2 API2 "141.55.22.1" 13321]
  (do-stuff-with c c2))
(do-stuff-with c))

Bye,
Tassilo

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: duck-streams missing from clojure-contrib.jar file

2010-04-21 Thread Alex Osborne
Stuart Halloway  writes:

> The second level header tells you the branch (e.g. master). On the
> left hand side is a list of branches (so you can click on e.g. 1.1.x).
>
> Some ways I see this might be better:
>
> (1) make clear what master currently equals (right now it is 1.2 alpha)
> (2) highlight the branch info more with css
> (3) push the branch info into the top-level header (and page title)
> (4) The overview section for c.c.io could tell about the lineage back
> to 1.1.

I think it might also help to make the stable versions the default
view.  I think people new to the language should really be guided to
using the stable releases and documentation rather than snapshots, as
the snapshots may well be in flux and cause lots of confusion.
People choosing to use the bleeding edge git snapshots will know what
the branches are and can specify the one they want.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: duck-streams missing from clojure-contrib.jar file

2010-04-21 Thread Laurent PETIT
2010/4/21 Alex Osborne :
> Stuart Halloway  writes:
>
>> The second level header tells you the branch (e.g. master). On the
>> left hand side is a list of branches (so you can click on e.g. 1.1.x).
>>
>> Some ways I see this might be better:
>>
>> (1) make clear what master currently equals (right now it is 1.2 alpha)
>> (2) highlight the branch info more with css
>> (3) push the branch info into the top-level header (and page title)
>> (4) The overview section for c.c.io could tell about the lineage back
>> to 1.1.
>
> I think it might also help to make the stable versions the default
> view.  I think people new to the language should really be guided to
> using the stable releases and documentation rather than snapshots, as
> the snapshots may well be in flux and cause lots of confusion.
> People choosing to use the bleeding edge git snapshots will know what
> the branches are and can specify the one they want.


#(swap! % inc)

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Try + finally question

2010-04-21 Thread ka
Thanks all for replies.

Laurent, Alex you guys are right, the problem is only with aesthetics
of nesting / boilerplate.  The nesting implementation semantically
expresses exactly what is required.

The with-cleanup macro seems really neat.  Guess I'll learn macros
first and try to implement one.

One more interesting perspective to exceptional handling is the way
Perl 6 is doing it - http://feather.perl6.nl/syn/S04.html#Exception_handlers

See this -

{
my $s = '';
die 3;
CATCH {
when 1 {$s ~= 'a';}
when 2 {$s ~= 'b';}
when 3 {$s ~= 'c';}
when 4 {$s ~= 'd';}
default {$s ~= 'z';}
}

is $s, 'c', 'Caught number';
};

Thanks!

On Apr 21, 7:05 pm, Alex Osborne  wrote:
> ka  writes:
> > The whole code gets cluttered with all these try finally (and one
> > catch) statements.
>
> >   (try
> >     (let [conn1 (API1/getConnection ..)]
> >       (try
> >         (let [conn2 (API2/getConnection ..)]
> >           (try
> >             ( ... Do something with conn1 conn2 )
> >             (finally
> >               (API2/closeConnection conn2
> >         (finally
> >           (API1/closeConnection conn1
> >     (catch Exception ex (.printStackTrace ex)))
>
> I guess the main difference in this compared to your java example is the
> levels of nesting.  This may look messy but it's semantically exactly
> what you're trying to express.
>
> > The macro solution looks good.  But with 2 different APIs for 2
> > connections, I would need to write 2 macros right?
>
> > (defmacro with-api1-connection [conn-sym arg1 arg2 & body]
> >   `(let [~conn-sym (API1/getConnection ~arg1 ~arg2)]
> >      (try
> >       ~...@body
> >       (finally (API1/closeConnection ~conn-sym)
>
> > (defmacro with-api2-connection [conn-sym arg1 arg2 arg3 & body]
> >   `(let [~conn-sym (API2/getConnection ~arg1 ~arg2 ~arg3)]
> >      (try
> >       ~...@body
> >       (finally (API2/closeConnection ~conn-sym)
>
> You could make things more general:
>
> (with-cleanup [conn1 (API1/getConnection ...) API1/closeConnection
>                conn2 (API2/openConnection ...) #(.disconnect %)]
>  ...)
>
> I'll leave implementation as an exercise, it's not much more complicated
> than the previous ones, the main trick would just be to make the macro
> recursive, have it expand into:
>
> (let [conn1 (API1/getConnection ...)]
>   (try
>     (with-cleanup [conn2 (API2/openConnection ...) #(.disconnect %)]
>       ...)
>     (finally
>       (API1/closeConnection conn1
>
> I'd probably start with a signature like this:
>
> (defmacro with-cleanup [[sym create cleanup & more] & body]
>   ...)
>
> Take a look at the source for with-open if you get stuck.
>
>
>
> > Coming from Java, this would be implemented as -
>
> > Connection1 conn1 = null;
> > Connection2 conn2 = null;
> > try {
> >   conn1 = API1.getConnection ..;
> >   conn2 = API2.getConnection ..;
> >   ...
> > }
> > catch (){}
> > finally {
> >   if (conn1 != null)
> >     API1.closeConnection(conn1);
> >   if (conn2 != null)
> >     API2.closeConnection(conn2);
> > }
>
> > I agree that this code doesn't look good from a purist pov, but any
> > issues besides that?
>
> The problem here is that this breaks lexical scope, conn1 and
> conn2 aren't defined outside their let block.  The Java example dodges
> this with mutation.  Python/Ruby/JavaScript etc dodge it by having
> special scoping rules: variables are scoped to functions rather than the
> enclosing block.
>
> Clojure's opinion, as I understand it, is that it's not worthwhile
> introducing mutation or special scoping rules simply to avoid some
> nesting, when we have perfectly good tools (macros) for doing purely
> syntactic transformations and removing boilerplate.
>
> There's nothing semantically wrong with nesting, it's just harder
> to read.  The Clojure idiom for reducing nesting is usually to use a
> macro like ->, ->> or with-open to flatten it.  In this case those
> aren't applicable, so I suggest defining your own.
>
> I'm not sure I phrased that clearly, please let me know if I'm not
> making sense. :-)
>
> Alex
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Try + finally question

2010-04-21 Thread Laurent PETIT
Hi,

I don't know for sure, but it seems to me that perl 6 way of "writing"
exception handling is just a syntactic difference.

For an interesting shift in the possibilities of exception
handling/recovery, have a look at how Common Lisp does this with
conditions/restart :
http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html

Which has been ported to clojure by chouser:
http://richhickey.github.com/clojure-contrib/error-kit-api.html

In a nutshell, with this you can simulate handlers placed higher in
the call stack, but those handlers could compute a "recovery value"
that would replace the value returned by the innermost from which the
exception originated (though this is totally off topic with your
original post :-) ).

2010/4/21 ka :
> Thanks all for replies.
>
> Laurent, Alex you guys are right, the problem is only with aesthetics
> of nesting / boilerplate.  The nesting implementation semantically
> expresses exactly what is required.
>
> The with-cleanup macro seems really neat.  Guess I'll learn macros
> first and try to implement one.
>
> One more interesting perspective to exceptional handling is the way
> Perl 6 is doing it - http://feather.perl6.nl/syn/S04.html#Exception_handlers
>
> See this -
>
> {
>    my $s = '';
>    die 3;
>    CATCH {
>        when 1 {$s ~= 'a';}
>        when 2 {$s ~= 'b';}
>        when 3 {$s ~= 'c';}
>        when 4 {$s ~= 'd';}
>        default {$s ~= 'z';}
>    }
>
>    is $s, 'c', 'Caught number';
> };
>
> Thanks!
>
> On Apr 21, 7:05 pm, Alex Osborne  wrote:
>> ka  writes:
>> > The whole code gets cluttered with all these try finally (and one
>> > catch) statements.
>>
>> >   (try
>> >     (let [conn1 (API1/getConnection ..)]
>> >       (try
>> >         (let [conn2 (API2/getConnection ..)]
>> >           (try
>> >             ( ... Do something with conn1 conn2 )
>> >             (finally
>> >               (API2/closeConnection conn2
>> >         (finally
>> >           (API1/closeConnection conn1
>> >     (catch Exception ex (.printStackTrace ex)))
>>
>> I guess the main difference in this compared to your java example is the
>> levels of nesting.  This may look messy but it's semantically exactly
>> what you're trying to express.
>>
>> > The macro solution looks good.  But with 2 different APIs for 2
>> > connections, I would need to write 2 macros right?
>>
>> > (defmacro with-api1-connection [conn-sym arg1 arg2 & body]
>> >   `(let [~conn-sym (API1/getConnection ~arg1 ~arg2)]
>> >      (try
>> >       ~...@body
>> >       (finally (API1/closeConnection ~conn-sym)
>>
>> > (defmacro with-api2-connection [conn-sym arg1 arg2 arg3 & body]
>> >   `(let [~conn-sym (API2/getConnection ~arg1 ~arg2 ~arg3)]
>> >      (try
>> >       ~...@body
>> >       (finally (API2/closeConnection ~conn-sym)
>>
>> You could make things more general:
>>
>> (with-cleanup [conn1 (API1/getConnection ...) API1/closeConnection
>>                conn2 (API2/openConnection ...) #(.disconnect %)]
>>  ...)
>>
>> I'll leave implementation as an exercise, it's not much more complicated
>> than the previous ones, the main trick would just be to make the macro
>> recursive, have it expand into:
>>
>> (let [conn1 (API1/getConnection ...)]
>>   (try
>>     (with-cleanup [conn2 (API2/openConnection ...) #(.disconnect %)]
>>       ...)
>>     (finally
>>       (API1/closeConnection conn1
>>
>> I'd probably start with a signature like this:
>>
>> (defmacro with-cleanup [[sym create cleanup & more] & body]
>>   ...)
>>
>> Take a look at the source for with-open if you get stuck.
>>
>>
>>
>> > Coming from Java, this would be implemented as -
>>
>> > Connection1 conn1 = null;
>> > Connection2 conn2 = null;
>> > try {
>> >   conn1 = API1.getConnection ..;
>> >   conn2 = API2.getConnection ..;
>> >   ...
>> > }
>> > catch (){}
>> > finally {
>> >   if (conn1 != null)
>> >     API1.closeConnection(conn1);
>> >   if (conn2 != null)
>> >     API2.closeConnection(conn2);
>> > }
>>
>> > I agree that this code doesn't look good from a purist pov, but any
>> > issues besides that?
>>
>> The problem here is that this breaks lexical scope, conn1 and
>> conn2 aren't defined outside their let block.  The Java example dodges
>> this with mutation.  Python/Ruby/JavaScript etc dodge it by having
>> special scoping rules: variables are scoped to functions rather than the
>> enclosing block.
>>
>> Clojure's opinion, as I understand it, is that it's not worthwhile
>> introducing mutation or special scoping rules simply to avoid some
>> nesting, when we have perfectly good tools (macros) for doing purely
>> syntactic transformations and removing boilerplate.
>>
>> There's nothing semantically wrong with nesting, it's just harder
>> to read.  The Clojure idiom for reducing nesting is usually to use a
>> macro like ->, ->> or with-open to flatten it.  In this case those
>> aren't applicable, so I suggest defining your own.
>>
>> I'm not sure I phrased that 

Re: Try + finally question

2010-04-21 Thread Mark J. Reed
The main thing about Perl6 in this case is that the catch/finally blocks are
inside the same scope as the try.   But that's true in Clojure as well!
The difference is that Clojure's try is not itself a lexical binding scope;
you have to wrap one around it or within it via let.  That's why I thought a
combination of try and let would be useful, if only as syntactic sugar.

On Wed, Apr 21, 2010 at 10:43 AM, ka  wrote:

> Thanks all for replies.
>
> Laurent, Alex you guys are right, the problem is only with aesthetics
> of nesting / boilerplate.  The nesting implementation semantically
> expresses exactly what is required.
>
> The with-cleanup macro seems really neat.  Guess I'll learn macros
> first and try to implement one.
>
> One more interesting perspective to exceptional handling is the way
> Perl 6 is doing it -
> http://feather.perl6.nl/syn/S04.html#Exception_handlers
>
> See this -
>
> {
>my $s = '';
>die 3;
>CATCH {
>when 1 {$s ~= 'a';}
>when 2 {$s ~= 'b';}
>when 3 {$s ~= 'c';}
>when 4 {$s ~= 'd';}
>default {$s ~= 'z';}
>}
>
>is $s, 'c', 'Caught number';
> };
>
> Thanks!
>
> On Apr 21, 7:05 pm, Alex Osborne  wrote:
> > ka  writes:
> > > The whole code gets cluttered with all these try finally (and one
> > > catch) statements.
> >
> > >   (try
> > > (let [conn1 (API1/getConnection ..)]
> > >   (try
> > > (let [conn2 (API2/getConnection ..)]
> > >   (try
> > > ( ... Do something with conn1 conn2 )
> > > (finally
> > >   (API2/closeConnection conn2
> > > (finally
> > >   (API1/closeConnection conn1
> > > (catch Exception ex (.printStackTrace ex)))
> >
> > I guess the main difference in this compared to your java example is the
> > levels of nesting.  This may look messy but it's semantically exactly
> > what you're trying to express.
> >
> > > The macro solution looks good.  But with 2 different APIs for 2
> > > connections, I would need to write 2 macros right?
> >
> > > (defmacro with-api1-connection [conn-sym arg1 arg2 & body]
> > >   `(let [~conn-sym (API1/getConnection ~arg1 ~arg2)]
> > >  (try
> > >   ~...@body
> > >   (finally (API1/closeConnection ~conn-sym)
> >
> > > (defmacro with-api2-connection [conn-sym arg1 arg2 arg3 & body]
> > >   `(let [~conn-sym (API2/getConnection ~arg1 ~arg2 ~arg3)]
> > >  (try
> > >   ~...@body
> > >   (finally (API2/closeConnection ~conn-sym)
> >
> > You could make things more general:
> >
> > (with-cleanup [conn1 (API1/getConnection ...) API1/closeConnection
> >conn2 (API2/openConnection ...) #(.disconnect %)]
> >  ...)
> >
> > I'll leave implementation as an exercise, it's not much more complicated
> > than the previous ones, the main trick would just be to make the macro
> > recursive, have it expand into:
> >
> > (let [conn1 (API1/getConnection ...)]
> >   (try
> > (with-cleanup [conn2 (API2/openConnection ...) #(.disconnect %)]
> >   ...)
> > (finally
> >   (API1/closeConnection conn1
> >
> > I'd probably start with a signature like this:
> >
> > (defmacro with-cleanup [[sym create cleanup & more] & body]
> >   ...)
> >
> > Take a look at the source for with-open if you get stuck.
> >
> >
> >
> > > Coming from Java, this would be implemented as -
> >
> > > Connection1 conn1 = null;
> > > Connection2 conn2 = null;
> > > try {
> > >   conn1 = API1.getConnection ..;
> > >   conn2 = API2.getConnection ..;
> > >   ...
> > > }
> > > catch (){}
> > > finally {
> > >   if (conn1 != null)
> > > API1.closeConnection(conn1);
> > >   if (conn2 != null)
> > > API2.closeConnection(conn2);
> > > }
> >
> > > I agree that this code doesn't look good from a purist pov, but any
> > > issues besides that?
> >
> > The problem here is that this breaks lexical scope, conn1 and
> > conn2 aren't defined outside their let block.  The Java example dodges
> > this with mutation.  Python/Ruby/JavaScript etc dodge it by having
> > special scoping rules: variables are scoped to functions rather than the
> > enclosing block.
> >
> > Clojure's opinion, as I understand it, is that it's not worthwhile
> > introducing mutation or special scoping rules simply to avoid some
> > nesting, when we have perfectly good tools (macros) for doing purely
> > syntactic transformations and removing boilerplate.
> >
> > There's nothing semantically wrong with nesting, it's just harder
> > to read.  The Clojure idiom for reducing nesting is usually to use a
> > macro like ->, ->> or with-open to flatten it.  In this case those
> > aren't applicable, so I suggest defining your own.
> >
> > I'm not sure I phrased that clearly, please let me know if I'm not
> > making sense. :-)
> >
> > Alex
> >
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clojure@googlegroups.com
> > Note

Missing fns: rotate & rotate-while

2010-04-21 Thread Sean Devlin
Hey everyone,

I've had to code these guys up a few times:

(defn rotate
  "Take a collection and left rotates it n steps. If n is negative,
the
collection is rotated right. Executes in O(n) time."
  [n coll]
  (let [c (count coll)]
(take c (drop (mod n c) (cycle coll)

(defn rotate-while
  "Rotates a collection left while (pred item) is true. Will return a
unrotated
sequence if (pred item) is never true. Executes in O(n) time."
  [pred coll]
  (let [head (drop-while pred coll)]
(take (count coll) (concat head coll

Have other people had this 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
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Coordinated, asynchronous modification of state?

2010-04-21 Thread Garth Sheldon-Coulson
Hi All,

This e-mail is the product of some musing about refs, agents, and atoms. I
would like to offer some thoughts on a possible fourth reference type that
allows coordinated, asynchronous modification of state.

I would greatly appreciate comments from the community. Maybe some of these
ideas have already been discussed on the list or incorporated into
development, in which case I'm sorry for repeating what is already
known---and please point me in the right direction so I can read more. I
hope the ideas are not too far off base, but please let me know if you think
they are.

Let me start at the beginning. In Clojure, we have standard reference types
for:

* uncoordinated, synchronous state change,
* coordinated, synchronous state change,
* uncoordinated, asynchronous state change.

Most Clojure users are familiar with the following diagram expressing the
reference type taxonomy. (The ASCII diagrams in this e-mail are best viewed
in a fixed-width font.)

  | Synchronous  | Asynchronous
--+--+-
Uncoordinated | Atoms| Agents
Coordinated   | Refs |

It occurred to me recently that there is no built-in reference type for the
final quadrant: coordinated, asynchronous change. There is no reference
type, in other words, allowing one to write a "doasync" block similar to a
dosync block:

(doasync   ;short for do asynchronously
  (send a inc)
  (send b inc))

causing a and b to change together atomically in the background. I thought
to myself that it would be nice to have this ability in some applications,
especially simulation, artificial life, and agent-based modeling. It allows
one thread to effect coordinated change in other threads while getting on
with its own work.

I pondered more and realized that, although there is no built-in reference
type for this purpose, one can make a first stab at the same effect using a
combination of futures and refs:

(future
  (dosync
(alter a inc)
(alter b inc)))

The future wraps the atomic transaction and causes it to take place in a
background thread.

This solution satisfied me for a day or two. Upon some more thought,
however, I realized that combining refs with futures is a recipe for
livelock disaster. Here is why. In a massively concurrent program with heavy
asynchronous state change, it is unlikely that any one ref will stay the
same for very long. The kind of coordinated change offered by a ref
transaction is unlikely to be successful in this kind of constantly-changing
environment, because the values of the refs are constantly being changed out
from under the transaction attempts. Consider the following illustration, in
which I try to modify a ref at the same time that it is being changed
continually from another thread:

 begin example 
(def a (ref 1))

; the code for start-frequent-changes is at
; http://gist.github.com/373143
(start-frequent-changes a)

; this code will never print its message
(let [done? (agent nil)]
  (future
(dosync
  (alter a (fn negate [val] (Thread/sleep 300) (- val)))
; negate is a long-running function of its argument
  (send done? (fn [_] (println "Done!"))
 end example 

The principle illustrated by this example is the following: when one or more
other threads are changing a ref, a computationally expensive transaction on
that ref is likely to encounter livelock. The more expensive the transaction
and the more frequent the changes, the less likely it is that the
transaction will ever go through. It will retry over and over, consuming
resources and potentially retrying forever.

Rich introduced ensure in part to try to mitigate this problem. Livelock can
be avoided in the example above by placing a simple "(ensure a)" call at the
beginning of the dosync block. Ensure ensures that the transaction holds
"write permissions" on the ref during the transaction, so that other threads
cannot modify it.

However, the combination of futures, refs, and ensure is not a terribly good
solution to coordinated asynchronicity, either, because it has a problem of
its own: The order in which futures are executed is not deterministic. Race
conditions will occur, and this is a big problem when dealing with state.

To illustrate this, suppose one has three refs, a, b, and c. (In a real
scenario, instead of just three refs one might have three groups of 20 refs,
but three refs is enough to illustrate.) One wants to complete three
asynchronous transactions on these refs in the following order: first,
modify a, then modify both a and b, then modify both a and c.

The problem is this: There is no way, using futures, refs, and ensure, to
guarantee that the three asynchronous transactions will happen in the order
one intends. Running the following code will usually print 3, but sometimes
it will print 2, because there is a race condition affecting the second and
third futures.

 begin example ;;;

Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Michał Marczyk
On 21 April 2010 17:23, Sean Devlin  wrote:
> I've had to code these guys up a few times:

Nice functions!

I'd replace "collection" with "sequence" in the docstrings, though.
(And rename the args accordingly.)

You can also rewrite rotate as

(defn rotate [n s]
  (lazy-cat (drop n s)
(take n s)))

which has the built-in assumption that n doesn't exceed the length of
s, but won't force more than (inc n) elements of s before producing
the first item of the result. (Additional forcing might happen due to
chunking issues, of course.)

As a final remark, I believe that rotate takes constant time to
execute, followed by O(n) time to produce the first element. This is
petty nitpicking, of course. ;-)

Sincerely,
Michał

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Documentation (was: Re: duck-streams missing from clojure-contrib.jar file)

2010-04-21 Thread Douglas Philips

On 2010 Apr 21, at 9:31 AM, Stuart Halloway wrote:

The second level header tells you the branch (e.g. master). On the  
left hand side is a list of branches (so you can click on e.g. 1.1.x).


Wow, that is quite subtle. As you click into contrib from clojure.org  
it isn't very noticeable.
It also isn't something you notice if you are, for example, clicking  
through from the unversioned clojure.org pages.

An example at random:
Start at: http://clojure.org/macros
then click on the lazy-cat link, which takes you to: http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/ 
lazy-cat

and start browsing.

With your focus down 'into' that page you have no idea that you've  
jumped into versioned information.


If you start as a beginner, as I did, the stuff on clojure.org is not  
versioned (there is no master/1.1.x link in the side bar) and so  
having version info appear only in contrib pages is not easy to  
notice, particularly if you get there via links from the main page.




Some ways I see this might be better:

(1) make clear what master currently equals (right now it is 1.2  
alpha)


That would help. Master is pretty generic.



(2) highlight the branch info more with css


Couldn't hurt, but it it'd be nice if showed in the page title too,  
the sidebars are lost when scrolling down into the various pages.




(3) push the branch info into the top-level header (and page title)


Yup.


(4) The overview section for c.c.io could tell about the lineage  
back to 1.1.


Not having been along for the ride since (nearly) the beginning,  
having those breadcrumbs would be helpful to me.




Which of these (or what else?) would have helped you the most?


I think having the default, as Alex Osburne suggested, be the stable  
release would have made my exploration of 1.1 a lot less painful.


And along those lines, distinguishing between core and contrib is  
something that might be important to the maintainers, but not so much  
to the users. And, very less useful to newbies trying to get something  
useful done.


Trying to figure out that spit is in a contrib library and slurp  
isn't? C'mon. I finally broke down and used google, and then when I  
saw a thread back in '08 about that, and it still isn't addressed?  
Really, easy file I/O is that unimportant to most clojure users?


Having a unified and comprehensive index of functions/macros  
(annotated with core/contrib) would also go a long way to making the  
clojure documentation environment a lot more useful. Oh, and then  
there is the distinction between http://clojure.org/libraries and the  
contrib libraries. Yet another place to look? Great, I really don't  
have anything better to do than internalize these distinctions? (In  
case you can't tell, having burned -hours- of spare time trying to  
find my way around docs has been exceptionally frustrating.)


At least for someone like me who is exploring on their own and isn't  
getting paid to make this work, having to lose my train of thought for  
5-10 minutes while trying to figure out if something is core or  
contrib is hugely frustrating and demotivating. Then throw in a "wtf?  
why isn't this working in the stable release" only makes it more so  
when I'm looking at the wrong docs and didn't even know that there  
were versioned docs.


If you want an example of the kind of structure that I do find  
helpful, look at docs.python.org. How many times on that page do you  
see that you're lookin at the 2.6 docs and that there are links to  
others? I'm not saying to make an exact clone, but I think it is fair,  
if I am going to complain about this, that I also provide, at least,  
an example of something that works and has worked well for years. (I  
come to clojure from Lisp and Python, not Java, so I don't have any  
Java documentation familiarity to compare/contrast).


-Doug



--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Sean Devlin
You're right about changing the docstring to read ""sequence"

I think the lazy-cat version looses the ability to rotate in reverse,
which I've come to love from Ruby.  Also, I have found use cases where
I want to rotate a period longer than the sequence length.

Thanks for the feedback, though.
Sean

On Apr 21, 11:37 am, Michał Marczyk  wrote:
> On 21 April 2010 17:23, Sean Devlin  wrote:
>
> > I've had to code these guys up a few times:
>
> Nice functions!
>
> I'd replace "collection" with "sequence" in the docstrings, though.
> (And rename the args accordingly.)
>
> You can also rewrite rotate as
>
> (defn rotate [n s]
>   (lazy-cat (drop n s)
>             (take n s)))
>
> which has the built-in assumption that n doesn't exceed the length of
> s, but won't force more than (inc n) elements of s before producing
> the first item of the result. (Additional forcing might happen due to
> chunking issues, of course.)
>
> As a final remark, I believe that rotate takes constant time to
> execute, followed by O(n) time to produce the first element. This is
> petty nitpicking, of course. ;-)
>
> Sincerely,
> Michał
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Coordinated, asynchronous modification of state?

2010-04-21 Thread Garth Sheldon-Coulson
Hi All,

The moment one sends a post one starts thinking about it from a critical
perspective.

I think I may have grown so used to the idea that nothing in Clojure can
deadlock that I completely overlooked the possibility of deadlock in the
idea I proposed. If two serfs are the targets of two different transactions,
and those transactions happen to enter the serfs' queues in different
orders, the serfs will wait forever for each other to become free. Classic
deadlock.

So, this stands as a challenge: Is there any way to get coordinated,
asynchronous, guaranteed-in-order modification of state? Or is it a pick-two
situation?

Thanks,
Garth

On Wed, Apr 21, 2010 at 11:29 AM, Garth Sheldon-Coulson wrote:

> Hi All,
>
> This e-mail is the product of some musing about refs, agents, and atoms. I
> would like to offer some thoughts on a possible fourth reference type that
> allows coordinated, asynchronous modification of state.
>
> I would greatly appreciate comments from the community. Maybe some of these
> ideas have already been discussed on the list or incorporated into
> development, in which case I'm sorry for repeating what is already
> known---and please point me in the right direction so I can read more. I
> hope the ideas are not too far off base, but please let me know if you think
> they are.
>
> Let me start at the beginning. In Clojure, we have standard reference types
> for:
>
> * uncoordinated, synchronous state change,
> * coordinated, synchronous state change,
> * uncoordinated, asynchronous state change.
>
> Most Clojure users are familiar with the following diagram expressing the
> reference type taxonomy. (The ASCII diagrams in this e-mail are best viewed
> in a fixed-width font.)
>
>   | Synchronous  | Asynchronous
> --+--+-
> Uncoordinated | Atoms| Agents
> Coordinated   | Refs |
>
> It occurred to me recently that there is no built-in reference type for the
> final quadrant: coordinated, asynchronous change. There is no reference
> type, in other words, allowing one to write a "doasync" block similar to a
> dosync block:
>
> (doasync   ;short for do asynchronously
>   (send a inc)
>   (send b inc))
>
> causing a and b to change together atomically in the background. I thought
> to myself that it would be nice to have this ability in some applications,
> especially simulation, artificial life, and agent-based modeling. It allows
> one thread to effect coordinated change in other threads while getting on
> with its own work.
>
> I pondered more and realized that, although there is no built-in reference
> type for this purpose, one can make a first stab at the same effect using a
> combination of futures and refs:
>
> (future
>   (dosync
> (alter a inc)
> (alter b inc)))
>
> The future wraps the atomic transaction and causes it to take place in a
> background thread.
>
> This solution satisfied me for a day or two. Upon some more thought,
> however, I realized that combining refs with futures is a recipe for
> livelock disaster. Here is why. In a massively concurrent program with heavy
> asynchronous state change, it is unlikely that any one ref will stay the
> same for very long. The kind of coordinated change offered by a ref
> transaction is unlikely to be successful in this kind of constantly-changing
> environment, because the values of the refs are constantly being changed out
> from under the transaction attempts. Consider the following illustration, in
> which I try to modify a ref at the same time that it is being changed
> continually from another thread:
>
>  begin example 
> (def a (ref 1))
>
> ; the code for start-frequent-changes is at
> ; http://gist.github.com/373143
> (start-frequent-changes a)
>
> ; this code will never print its message
> (let [done? (agent nil)]
>   (future
> (dosync
>   (alter a (fn negate [val] (Thread/sleep 300) (- val)))
> ; negate is a long-running function of its argument
>   (send done? (fn [_] (println "Done!"))
>  end example 
>
> The principle illustrated by this example is the following: when one or
> more other threads are changing a ref, a computationally expensive
> transaction on that ref is likely to encounter livelock. The more expensive
> the transaction and the more frequent the changes, the less likely it is
> that the transaction will ever go through. It will retry over and over,
> consuming resources and potentially retrying forever.
>
> Rich introduced ensure in part to try to mitigate this problem. Livelock
> can be avoided in the example above by placing a simple "(ensure a)" call at
> the beginning of the dosync block. Ensure ensures that the transaction holds
> "write permissions" on the ref during the transaction, so that other threads
> cannot modify it.
>
> However, the combination of futures, refs, and ensure is not a terribly
> good solution to coordinated asynchronicity, either

Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Michał Marczyk
On 21 April 2010 17:46, Sean Devlin  wrote:
> I think the lazy-cat version looses the ability to rotate in reverse,
> which I've come to love from Ruby.  Also, I have found use cases where
> I want to rotate a period longer than the sequence length.

Right. I don't mind rotate being strict, actually, I'm just playing
around and being silly:

(defn rotate [n s]
  (if-let [remaining (and (not (neg? n))
  (seq (drop n s)))]
(lazy-cat remaining
  (take n s))
(let [c (count s)]
  (take c (drop (mod n c) (cycle s))

Seriously though, I'd vote for your original versions to go into c.c.seq.

Sincerely,
Michał

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: sharing multiple jogl opengl contexts in clojure

2010-04-21 Thread Joel Gluth
On Apr 20, 4:46 pm, Josh Stratton  wrote:
> But I can't seem to call createGLPbuffer w/o getting an exception.

> Caused by: java.lang.IllegalArgumentException: No matching method:
> createGLPbuffer

This one is because the createGLPbuffer method is not static; you need
to have created a GLDrawableFactory first using getFactory():

(.createGLPbuffer (GLDrawableFactory/getFactory (GLProfile/
getDefault)) nil nil 1 1 nil)

The GLCapabilities argument needs to be set, otherwise you'll get a
NullPointerException at this point.

The simplest invocation I could come up with that returned a
GLPbufferImpl was this:

(let [profile (GLProfile/getDefault)]
(.createGLPbuffer (GLDrawableFactory/getFactory profile)
(GLCapabilities. profile) nil 1 1 nil))

You can take it from here with different profiles, capabilities,
choosers etc.

J

PS I'm using Clojure 1.1 and JOGL 2.0.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Mark Engelberg
On Wed, Apr 21, 2010 at 8:46 AM, Sean Devlin  wrote:
> You're right about changing the docstring to read ""sequence"
>
> I think the lazy-cat version looses the ability to rotate in reverse,
> which I've come to love from Ruby.  Also, I have found use cases where
> I want to rotate a period longer than the sequence length.
>
> Thanks for the feedback, though.
> Sean

The use of concatenation as opposed to cycle does not affect the
ability to rotate in reverse or more than the sequence length provided
you use mod to get the number in range first:

(defn rotate [n s]
  (let [shift (mod n (count s))]
(concat (drop shift s)
(take shift s

[could use lazy-cat instead of concat, but I doubt it's worthwhile here]

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


How do I destructure this?

2010-04-21 Thread Base
Hi All -

I am having a hard time destructuring a nested data structure.

I am starting out with:

{:tag :column,
 :attrs nil,
 :content
 [{:tag :name, :attrs nil, :content ["agecat"]}
  {:tag :value, :attrs nil, :content ["nil"]}
  {:tag :threshold, :attrs nil, :content ["0.05"]}]}

and am looking to get:

{:column "agecat", :value "nil", :threshold "0.05"}

I genearlly 'get' the destructuring and it is very cool, but the
highly nested aspect of this is throwing me off.

Any thoughts would be most appreciated.

Thanks

Bassel

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Sean Devlin
Hmmm...  good point.  Now that I think about it, cycle is an artifact
of an early implementation.

On Apr 21, 1:01 pm, Mark Engelberg  wrote:
> On Wed, Apr 21, 2010 at 8:46 AM, Sean Devlin  wrote:
> > You're right about changing the docstring to read ""sequence"
>
> > I think the lazy-cat version looses the ability to rotate in reverse,
> > which I've come to love from Ruby.  Also, I have found use cases where
> > I want to rotate a period longer than the sequence length.
>
> > Thanks for the feedback, though.
> > Sean
>
> The use of concatenation as opposed to cycle does not affect the
> ability to rotate in reverse or more than the sequence length provided
> you use mod to get the number in range first:
>
> (defn rotate [n s]
>   (let [shift (mod n (count s))]
>     (concat (drop shift s)
>             (take shift s
>
> [could use lazy-cat instead of concat, but I doubt it's worthwhile here]
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: How do I destructure this?

2010-04-21 Thread Sean Devlin
Hmmm... I'm not sure destructuring is possible here.  Would it be
easier to put an extractor fn in place?

(defn extract
 [arg]
 (apply hash-map (map (juxt :tag :content) (:content arg

Just a thought.  I'm sure someone will have a better idea, though.

On Apr 21, 1:02 pm, Base  wrote:
> Hi All -
>
> I am having a hard time destructuring a nested data structure.
>
> I am starting out with:
>
> {:tag :column,
>  :attrs nil,
>  :content
>  [{:tag :name, :attrs nil, :content ["agecat"]}
>   {:tag :value, :attrs nil, :content ["nil"]}
>   {:tag :threshold, :attrs nil, :content ["0.05"]}]}
>
> and am looking to get:
>
> {:column "agecat", :value "nil", :threshold "0.05"}
>
> I genearlly 'get' the destructuring and it is very cool, but the
> highly nested aspect of this is throwing me off.
>
> Any thoughts would be most appreciated.
>
> Thanks
>
> Bassel
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Michał Marczyk
One could also do

(defn rotate [n s]
  (let [[front back] (split-at (mod n (count s)) s)]
(concat back front)))

I was hoping for a moment to avoid calculating (count s) up front, but
that definitely does interfere with negative / large shifts, so never
mind that.

Sincerely,
Michał

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Examples of Clojure in production?

2010-04-21 Thread Heinz N. Gies

On Apr 19, 2010, at 5:55 , Daniel Glauser wrote:

> I would like to start a thread about Clojure use in production.  Who
> is using it?  And for what?  What kind of load do you have on the
> system in terms of approximate transactions per day?  Would you mind
> if your example was featured in a presentation?

Not a big webapp and not many transactions but we use clojure in a final 
factory test tool I wrote for my team that checks if our installations went 
well. Works like a charm :). The big + of clojure here is that we don't need to 
install anything on the machines just copy a jar and run it.

Regards,
Heinz

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: How do I destructure this?

2010-04-21 Thread Base
Damn!  This looks pretty good to me.

BTW - Love your blog and tutorial videos.  they are incredibly helpful
and instructive. I have watched many of them more than once.

I really appreciate them.

Thanks Sean!!!

Bassel

On Apr 21, 12:07 pm, Sean Devlin  wrote:
> Hmmm... I'm not sure destructuring is possible here.  Would it be
> easier to put an extractor fn in place?
>
> (defn extract
>  [arg]
>  (apply hash-map (map (juxt :tag :content) (:content arg
>
> Just a thought.  I'm sure someone will have a better idea, though.
>
> On Apr 21, 1:02 pm, Base  wrote:
>
>
>
> > Hi All -
>
> > I am having a hard time destructuring a nested data structure.
>
> > I am starting out with:
>
> > {:tag :column,
> >  :attrs nil,
> >  :content
> >  [{:tag :name, :attrs nil, :content ["agecat"]}
> >   {:tag :value, :attrs nil, :content ["nil"]}
> >   {:tag :threshold, :attrs nil, :content ["0.05"]}]}
>
> > and am looking to get:
>
> > {:column "agecat", :value "nil", :threshold "0.05"}
>
> > I genearlly 'get' the destructuring and it is very cool, but the
> > highly nested aspect of this is throwing me off.
>
> > Any thoughts would be most appreciated.
>
> > Thanks
>
> > Bassel
>
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clojure@googlegroups.com
> > Note that posts from new members are moderated - please be patient with 
> > your first post.
> > To unsubscribe from this group, send email to
> > clojure+unsubscr...@googlegroups.com
> > For more options, visit this group 
> > athttp://groups.google.com/group/clojure?hl=en
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Sean Devlin
I like that version :)

On Apr 21, 1:11 pm, Michał Marczyk  wrote:
> One could also do
>
> (defn rotate [n s]
>   (let [[front back] (split-at (mod n (count s)) s)]
>     (concat back front)))
>
> I was hoping for a moment to avoid calculating (count s) up front, but
> that definitely does interfere with negative / large shifts, so never
> mind that.
>
> Sincerely,
> Michał
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: How do I destructure this?

2010-04-21 Thread Michał Marczyk
On 21 April 2010 19:02, Base  wrote:
> I am having a hard time destructuring a nested data structure.
>
> I am starting out with:
>
> {:tag :column,
>  :attrs nil,
>  :content
>  [{:tag :name, :attrs nil, :content ["agecat"]}
>  {:tag :value, :attrs nil, :content ["nil"]}
>  {:tag :threshold, :attrs nil, :content ["0.05"]}]}
>
> and am looking to get:
>
> {:column "agecat", :value "nil", :threshold "0.05"}

If I understand correctly, you want to take the :tag from the
top-level map, then reach into the :content vector and extract the
maps with either :name or :threshold bound to the :tag key and get
something out of their content, right?

If so, then you probably don't want to use destructuring, because you
don't want to depend on the order in which the submaps occur in the
:content of the top-level map.

If you can depend on the ordering, then the following would produce
your desired result (with your example map previously bound to
#'test-map):

(let [{tag :tag
   [{[tag-val] :content}
{[value] :content}
{t :tag [t-val] :content}]
   :content}
  test-map]
  {tag tag-val :value value t t-val})

This attempts to be somewhat smart in that it figures out that the
final key to be put in the result map is :threshold based on the :tag
extracted from the last sub-map. So, with consistent structure, that's
possible with destructuring -- but it is a bit tedious and fragile.
Best to reserve it for the simpler cases, where the exact format of
data is likely to remain fixed. (Actually that last part is a must
with destructuring.)

All in all, I agree with Sean's opinion that an extractor function
would be a better fit.

Sincerely,
Michał

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Michał Marczyk
On 21 April 2010 19:35, Sean Devlin  wrote:
> I like that version :)

:-)

In this case, rotate-while could be rewritten like so:

(defn rotate-with [pred s]
  (let [[front back] (split-with pred s)]
(concat back front)))

And to round it off with ridiculous overengineering ;-) --

(defn rotate* [n-or-pred s]
  (let [with? (ifn? n-or-pred)
[front back] ((if with?
split-with
split-at)
  (if with?
n-or-pred
(mod n-or-pred (count s)))
  s)]
(concat back front)))

Sincerely,
Michał

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


wget replacement code review

2010-04-21 Thread Brent Millare
Hey all,

I wrote a clojure version of the simplest functionality of wget. I
basically translated the java version into clojure code, but I'm not
quite happy with the wget-binary function because I use a loop, and I
feel like someone else has a more idiomatic solution to iterating
through a java-array. Also, I don't know if my way of handling the no
filename case is best. Please tell me how to improve my code,
especially in the interop sections.

(ns dj
  (:import [java.io File FileOutputStream BufferedInputStream
BufferedReader InputStreamReader])
  (:import [java.net URL])
  (:require [clojure.contrib [duck-streams :as duck-streams]]))

(defn blank?
  "True if s is nil, empty, or contains only whitespace."
  [#^String s]
  (every? (fn [#^Character c] (Character/isWhitespace c)) s))

(defn- extract-url-filename [url]
  (let [filename (.getFile url)]
(if (blank? filename)
  "index.html"
  (subs filename 1

(defn- wget-binary [con content-length]
  (with-open [stream (BufferedInputStream. (.getInputStream con))]
(let [data (make-array Byte/TYPE content-length)]
  (loop [offset 0]
(if (< offset content-length)
  (let [bytesRead (.read stream
 data
 offset
 (- content-length
offset))]
(if (= bytesRead -1)
  data
  (recur (+ offset bytesRead
  data)

(defn- wget-text [url-obj]
  (with-open [buf (-> url-obj
  (.openStream)
  (InputStreamReader.)
  (BufferedReader.))]
(apply str (line-seq buf

(defn wget [url-address]
  (let [url (URL. url-address)
filename (extract-url-filename url)
con (.openConnection url)
content-length (.getContentLength con)]
(if (or (= -1 content-length)
(.startsWith (.getContentType con) "text/"))
  (duck-streams/spit filename (wget-text url))
  (with-open [out-file (FileOutputStream. filename)]
(.write out-file (wget-binary con content-length))

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Sean Devlin
If you're gonna over engineer use a protocol :-p

On Apr 21, 1:43 pm, Michał Marczyk  wrote:
> On 21 April 2010 19:35, Sean Devlin  wrote:
>
> > I like that version :)
>
> :-)
>
> In this case, rotate-while could be rewritten like so:
>
> (defn rotate-with [pred s]
>   (let [[front back] (split-with pred s)]
>     (concat back front)))
>
> And to round it off with ridiculous overengineering ;-) --
>
> (defn rotate* [n-or-pred s]
>   (let [with? (ifn? n-or-pred)
>         [front back] ((if with?
>                         split-with
>                         split-at)
>                       (if with?
>                         n-or-pred
>                         (mod n-or-pred (count s)))
>                       s)]
>     (concat back front)))
>
> Sincerely,
> Michał
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: wget replacement code review

2010-04-21 Thread Sean Devlin
At first glance, you should be requiring c.c.string, and don't write
your own blank? fn.  That's the only low hanging fruit I see.

On Apr 21, 1:47 pm, Brent Millare  wrote:
> Hey all,
>
> I wrote a clojure version of the simplest functionality of wget. I
> basically translated the java version into clojure code, but I'm not
> quite happy with the wget-binary function because I use a loop, and I
> feel like someone else has a more idiomatic solution to iterating
> through a java-array. Also, I don't know if my way of handling the no
> filename case is best. Please tell me how to improve my code,
> especially in the interop sections.
>
> (ns dj
>   (:import [java.io File FileOutputStream BufferedInputStream
> BufferedReader InputStreamReader])
>   (:import [java.net URL])
>   (:require [clojure.contrib [duck-streams :as duck-streams]]))
>
> (defn blank?
>   "True if s is nil, empty, or contains only whitespace."
>   [#^String s]
>   (every? (fn [#^Character c] (Character/isWhitespace c)) s))
>
> (defn- extract-url-filename [url]
>   (let [filename (.getFile url)]
>     (if (blank? filename)
>       "index.html"
>       (subs filename 1
>
> (defn- wget-binary [con content-length]
>   (with-open [stream (BufferedInputStream. (.getInputStream con))]
>     (let [data (make-array Byte/TYPE content-length)]
>       (loop [offset 0]
>         (if (< offset content-length)
>           (let [bytesRead (.read stream
>                                  data
>                                  offset
>                                  (- content-length
>                                     offset))]
>             (if (= bytesRead -1)
>               data
>               (recur (+ offset bytesRead
>           data)
>
> (defn- wget-text [url-obj]
>   (with-open [buf (-> url-obj
>                       (.openStream)
>                       (InputStreamReader.)
>                       (BufferedReader.))]
>     (apply str (line-seq buf
>
> (defn wget [url-address]
>   (let [url (URL. url-address)
>         filename (extract-url-filename url)
>         con (.openConnection url)
>         content-length (.getContentLength con)]
>     (if (or (= -1 content-length)
>             (.startsWith (.getContentType con) "text/"))
>       (duck-streams/spit filename (wget-text url))
>       (with-open [out-file (FileOutputStream. filename)]
>         (.write out-file (wget-binary con content-length))
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: wget replacement code review

2010-04-21 Thread Brent Millare
Technically I didn't write my own cause I just copied pasted it ;)

For the purposes of this review, just consider that library code or a
reference so everyone knows what it does. :)

Sean Devlin wrote:
> At first glance, you should be requiring c.c.string, and don't write
> your own blank? fn.  That's the only low hanging fruit I see.
>
> On Apr 21, 1:47 pm, Brent Millare  wrote:
> > Hey all,
> >
> > I wrote a clojure version of the simplest functionality of wget. I
> > basically translated the java version into clojure code, but I'm not
> > quite happy with the wget-binary function because I use a loop, and I
> > feel like someone else has a more idiomatic solution to iterating
> > through a java-array. Also, I don't know if my way of handling the no
> > filename case is best. Please tell me how to improve my code,
> > especially in the interop sections.
> >
> > (ns dj
> >   (:import [java.io File FileOutputStream BufferedInputStream
> > BufferedReader InputStreamReader])
> >   (:import [java.net URL])
> >   (:require [clojure.contrib [duck-streams :as duck-streams]]))
> >
> > (defn blank?
> >   "True if s is nil, empty, or contains only whitespace."
> >   [#^String s]
> >   (every? (fn [#^Character c] (Character/isWhitespace c)) s))
> >
> > (defn- extract-url-filename [url]
> >   (let [filename (.getFile url)]
> >     (if (blank? filename)
> >       "index.html"
> >       (subs filename 1
> >
> > (defn- wget-binary [con content-length]
> >   (with-open [stream (BufferedInputStream. (.getInputStream con))]
> >     (let [data (make-array Byte/TYPE content-length)]
> >       (loop [offset 0]
> >         (if (< offset content-length)
> >           (let [bytesRead (.read stream
> >                                  data
> >                                  offset
> >                                  (- content-length
> >                                     offset))]
> >             (if (= bytesRead -1)
> >               data
> >               (recur (+ offset bytesRead
> >           data)
> >
> > (defn- wget-text [url-obj]
> >   (with-open [buf (-> url-obj
> >                       (.openStream)
> >                       (InputStreamReader.)
> >                       (BufferedReader.))]
> >     (apply str (line-seq buf
> >
> > (defn wget [url-address]
> >   (let [url (URL. url-address)
> >         filename (extract-url-filename url)
> >         con (.openConnection url)
> >         content-length (.getContentLength con)]
> >     (if (or (= -1 content-length)
> >             (.startsWith (.getContentType con) "text/"))
> >       (duck-streams/spit filename (wget-text url))
> >       (with-open [out-file (FileOutputStream. filename)]
> >         (.write out-file (wget-binary con content-length))
> >
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clojure@googlegroups.com
> > Note that posts from new members are moderated - please be patient with 
> > your first post.
> > To unsubscribe from this group, send email to
> > clojure+unsubscr...@googlegroups.com
> > For more options, visit this group 
> > athttp://groups.google.com/group/clojure?hl=en
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Mark Engelberg
In some languages, split-at is more performant than doing take and
drop separately.  But in Clojure, split-at is simply defined as:
(defn split-at
  "Returns a vector of [(take n coll) (drop n coll)]"
  [n coll]
[(take n coll) (drop n coll)])

So by using split-at, you gain nothing other than the additional
overhead of constructing a vector and then turning around and
destructuring it.

On Wed, Apr 21, 2010 at 10:11 AM, Michał Marczyk
 wrote:
> One could also do
>
> (defn rotate [n s]
>  (let [[front back] (split-at (mod n (count s)) s)]
>    (concat back front)))
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Coordinated, asynchronous modification of state?

2010-04-21 Thread Kevin Livingston
What you are talking about is commonly referred to as a "barrier" in
parallel processing.  All processes coordinated on a given barrier
must each reach the barrier before any one may cross it.

Simply putting a barrier check into the message queue of an Clojure
agent would not be sufficient as I understand the agents to be free to
re-order message processing.  You could build an ordered message queue
with one of the other types like ref, and have threads for processing
each queue, that will appropriately block on barriers.  That seems
straightforward (it's possible there is some other feature in clojure
I'm unaware of that will give you this)

Kevin



On Apr 21, 9:56 am, Garth Sheldon-Coulson  wrote:
> Hi All,
>
> The moment one sends a post one starts thinking about it from a critical
> perspective.
>
> I think I may have grown so used to the idea that nothing in Clojure can
> deadlock that I completely overlooked the possibility of deadlock in the
> idea I proposed. If two serfs are the targets of two different transactions,
> and those transactions happen to enter the serfs' queues in different
> orders, the serfs will wait forever for each other to become free. Classic
> deadlock.
>
> So, this stands as a challenge: Is there any way to get coordinated,
> asynchronous, guaranteed-in-order modification of state? Or is it a pick-two
> situation?
>
> Thanks,
> Garth
>
> On Wed, Apr 21, 2010 at 11:29 AM, Garth Sheldon-Coulson wrote:
>
>
>
> > Hi All,
>
> > This e-mail is the product of some musing about refs, agents, and atoms. I
> > would like to offer some thoughts on a possible fourth reference type that
> > allows coordinated, asynchronous modification of state.
>
> > I would greatly appreciate comments from the community. Maybe some of these
> > ideas have already been discussed on the list or incorporated into
> > development, in which case I'm sorry for repeating what is already
> > known---and please point me in the right direction so I can read more. I
> > hope the ideas are not too far off base, but please let me know if you think
> > they are.
>
> > Let me start at the beginning. In Clojure, we have standard reference types
> > for:
>
> > * uncoordinated, synchronous state change,
> > * coordinated, synchronous state change,
> > * uncoordinated, asynchronous state change.
>
> > Most Clojure users are familiar with the following diagram expressing the
> > reference type taxonomy. (The ASCII diagrams in this e-mail are best viewed
> > in a fixed-width font.)
>
> >               | Synchronous  | Asynchronous
> > --+--+-
> > Uncoordinated | Atoms        | Agents
> > Coordinated   | Refs         |
>
> > It occurred to me recently that there is no built-in reference type for the
> > final quadrant: coordinated, asynchronous change. There is no reference
> > type, in other words, allowing one to write a "doasync" block similar to a
> > dosync block:
>
> > (doasync   ;short for do asynchronously
> >   (send a inc)
> >   (send b inc))
>
> > causing a and b to change together atomically in the background. I thought
> > to myself that it would be nice to have this ability in some applications,
> > especially simulation, artificial life, and agent-based modeling. It allows
> > one thread to effect coordinated change in other threads while getting on
> > with its own work.
>
> > I pondered more and realized that, although there is no built-in reference
> > type for this purpose, one can make a first stab at the same effect using a
> > combination of futures and refs:
>
> > (future
> >   (dosync
> >     (alter a inc)
> >     (alter b inc)))
>
> > The future wraps the atomic transaction and causes it to take place in a
> > background thread.
>
> > This solution satisfied me for a day or two. Upon some more thought,
> > however, I realized that combining refs with futures is a recipe for
> > livelock disaster. Here is why. In a massively concurrent program with heavy
> > asynchronous state change, it is unlikely that any one ref will stay the
> > same for very long. The kind of coordinated change offered by a ref
> > transaction is unlikely to be successful in this kind of constantly-changing
> > environment, because the values of the refs are constantly being changed out
> > from under the transaction attempts. Consider the following illustration, in
> > which I try to modify a ref at the same time that it is being changed
> > continually from another thread:
>
> >  begin example 
> > (def a (ref 1))
>
> > ; the code for start-frequent-changes is at
> > ;http://gist.github.com/373143
> > (start-frequent-changes a)
>
> > ; this code will never print its message
> > (let [done? (agent nil)]
> >   (future
> >     (dosync
> >       (alter a (fn negate [val] (Thread/sleep 300) (- val)))
> >         ; negate is a long-running function of its argument
> >       (send done? (fn [_] (println "Done!"))
> >  end example 
>
> > The

Re: How do I destructure this?

2010-04-21 Thread Base
Thanks Michal -

I have done a little digging into juxt (reading the great write up
that Sean previously posted here - great post by the way) and it is a
very slick way to deal with this issue.  I am always amazed at the
createive and concise solutions that Clojure enables.

Thanks much for all of your help guys.

On Apr 21, 12:36 pm, Michał Marczyk  wrote:
> On 21 April 2010 19:02, Base  wrote:
>
> > I am having a hard time destructuring a nested data structure.
>
> > I am starting out with:
>
> > {:tag :column,
> >  :attrs nil,
> >  :content
> >  [{:tag :name, :attrs nil, :content ["agecat"]}
> >  {:tag :value, :attrs nil, :content ["nil"]}
> >  {:tag :threshold, :attrs nil, :content ["0.05"]}]}
>
> > and am looking to get:
>
> > {:column "agecat", :value "nil", :threshold "0.05"}
>
> If I understand correctly, you want to take the :tag from the
> top-level map, then reach into the :content vector and extract the
> maps with either :name or :threshold bound to the :tag key and get
> something out of their content, right?
>
> If so, then you probably don't want to use destructuring, because you
> don't want to depend on the order in which the submaps occur in the
> :content of the top-level map.
>
> If you can depend on the ordering, then the following would produce
> your desired result (with your example map previously bound to
> #'test-map):
>
> (let [{tag :tag
>        [{[tag-val] :content}
>         {[value] :content}
>         {t :tag [t-val] :content}]
>        :content}
>       test-map]
>   {tag tag-val :value value t t-val})
>
> This attempts to be somewhat smart in that it figures out that the
> final key to be put in the result map is :threshold based on the :tag
> extracted from the last sub-map. So, with consistent structure, that's
> possible with destructuring -- but it is a bit tedious and fragile.
> Best to reserve it for the simpler cases, where the exact format of
> data is likely to remain fixed. (Actually that last part is a must
> with destructuring.)
>
> All in all, I agree with Sean's opinion that an extractor function
> would be a better fit.
>
> Sincerely,
> Michał
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Sean Devlin
Hmmm...  we could talk about what's faster or measure it.  Time to eat
my own damn dog food, I guess :)

Traveling now, I'll run the experiments in a few days when I get back
to my normal setup.

Sean

On Apr 21, 2:09 pm, Mark Engelberg  wrote:
> In some languages, split-at is more performant than doing take and
> drop separately.  But in Clojure, split-at is simply defined as:
> (defn split-at
>   "Returns a vector of [(take n coll) (drop n coll)]"
>   [n coll]
>     [(take n coll) (drop n coll)])
>
> So by using split-at, you gain nothing other than the additional
> overhead of constructing a vector and then turning around and
> destructuring it.
>
> On Wed, Apr 21, 2010 at 10:11 AM, Michał Marczyk
>
>  wrote:
> > One could also do
>
> > (defn rotate [n s]
> >  (let [[front back] (split-at (mod n (count s)) s)]
> >    (concat back front)))
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Michał Marczyk
On 21 April 2010 19:57, Sean Devlin  wrote:
> If you're gonna over engineer use a protocol :-p

You're absolutely right, of course; I stand corrected! Here's my new
attempt at overengineering then:

(defprotocol Rotator
  (rotate [self s]))

(extend-protocol Rotator
  Number
  (rotate
   [self s]
   (let [[front back] (split-at (mod self (count s)) s)]
 (concat back front)))
  clojure.lang.IFn
  (rotate
   [self s]
   (let [[front back] (split-with self s)]
 (concat back front

Funnily enough, I actually find this vaguely reasonable. :-)

Sincerely,
Michał

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Arguments for < and > et al

2010-04-21 Thread ataggart
== < <= > >= are all numeric equality/comparison functions.

= and 'compare are object equality/comparison functions.



On Apr 20, 6:47 pm, Bill Allen  wrote:
> I've been writing a program that requires the use of java.util.Calendar and
> its descendent java.util.GregorianCalendar. One thing I'd hoped to do was
> compare two Calendar objects with <, but the compiler complained that the
> arguments to < didn't inherit from Number which was a surprise to me because
> Calendar does inherit from java.lang.Comparable which in java land would be
> sufficient to enable it to be compared with other members of its class using
> the built in java comparison operators. Since I know that clojure has other
> operations that deal with comparable, I assume this is a conscious decision,
> but I question why it should be so.
>
> Regards,
> Bill
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Michał Marczyk
On 21 April 2010 20:09, Mark Engelberg  wrote:
> In some languages, split-at is more performant than doing take and
> drop separately.  But in Clojure, split-at is simply defined as:
> (defn split-at
>  "Returns a vector of [(take n coll) (drop n coll)]"
>  [n coll]
>    [(take n coll) (drop n coll)])
>
> So by using split-at, you gain nothing other than the additional
> overhead of constructing a vector and then turning around and
> destructuring it.

I realise that, however I find that there is also a slight gain in
readability / aesthetic appeal of the code; buying that at the minute
cost incurred due to creating and destructuring a vector seems
acceptable to me.

As an aside, it might actually be possible to write a more efficient
split-at -- perhaps exploiting the nature of the sequence being split
(e.g. you could use (seq (subvec ...)) with vectors) -- should the
need arise, so maybe it will become beneficial from the performance
POV at some point...

Sincerely,
Michał

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: request for comments/code-review - clojure implementation of unifier

2010-04-21 Thread Kevin Livingston
Thank you for taking the time to provide feedback.

> I can't think of a direct equivalent now, but it's straightforward
> enough to supply your own equivalent, like my compound? function
> (basically #(and (seq? %) (seq %))). This won't work on arrays and
> other things which seq can operate upon, but which respond with a
> false to seq?, though. If that could be a problem, you can just use
> seq and for non-seqables catch the exception and return false.

intentionally driving into an exception seems like a very bad idea.
but yes I can define my own equivalent of consp I was just hoping
there was something I was over looking.


> You could perform a CPS transform by hand (which I haven't (yet) done
> with the code in the Gist). For occurs-check this would mean having an
> extra to-do argument (or maybe just [... & to-do]); whenever false
> would normally be returned, you'd first check if to-do is empty,
> returning false if so and doing (recur 
> (rest to-do)) otherwise. true should short-circuit and disregard
> to-do, of course. Finally, whenever occurs-check would normally branch
> on first / rest, it would recur with first *and* an extended to-do
> including rest.

That'll trade some heap for stack space, presumably worthwhile.  I
haven't had to do much hand optimization of recursion so I'm a little
rusty (the Franz Allegro compiler was fairly amazing in that
regard)... I was hoping there was some even better trick (like the
trampoline) to save me even more.  That's a good idea though, I'll
just to estimate how close I'm getting to blowing the stack, and the
overhead of tracking to-do.

> Not at all. next is basically #(seq (rest %)); you might want to use
> it when the extra bit of strictness is beneficial to your code and you
> shouldn't use it when it isn't.

oh, ok.  I saw some posts on using the new super-lazy lists / code and
it implied that next was necessary over rest, but I didn't quite read
it in excruciating detail.

> Good question. I really prefer the fully parenthesised cond clauses
> from Scheme / CL / elisp, in good part because of the nicer
> indentation without particularly elaborate rules... :-(

that "extra" paren is there too because the body of the clause is an
implicit progn in common lisp.


> I think that your code would benefit from direct use of Clojure data
> structure literals and such facilities as the IFn implementation
> available on maps; see my gist for examples of what I have in mind.

on some issues I agree others I disagree, regarding your code:

regarding removing the helper functions, that's not necessarily ideal,
while bindings may always be a map putting in literals like {} or nil
instead of fail or no-bindings actually obfuscates the code, and makes
it harder to change later if what bindings is needs to fundamentally
change.  similarly with truncating variable names, it detracts from
readability - although with one interesting caveat -- "var" is a
particularly unique as it is now a language keyword in clojure.

in general it's bad style to wrap a cond with another test if
trivially avoidable (at least this is coming from best practice common
lisp style) so for example, in your code line 24, there's no reason to
pull that out of the cond, especially since you are also using the
return value of the when, it's better to be explicit about the test
and what it's resulting return value is -- in this case that the
unification fails.  the if-let's are a little more interesting as it
potentially saves one lookup, but it seems to make  the code far more
"disjoint" or at least increase the number of paths.

the changing of a cond to a some with the identity function on line 48
seems like a very odd choice to me.  while still correct code I see no
reason why this would be preferred to a cond.


thanks for the subst code.

I'm torn about the simplify-bindings -- I think it's a cool function
to have, because if what you are subbing into is large compared to
bindings, this is probably a win, but if you have a lot of bindings
and are only using some, you could spend a lot of time to pack them
down.  it'd probably be good to have around if someone knew where they
were in the trade-off.

 I left out Norvig's code, I have a need for binding/substituting with
multiple binding lists so I ended up with this (which requires
clojure.walk)

(defn recursive-replace
  ([expr l-bindings] (recursive-replace expr l-bindings #{expr}))
  ([expr l-bindings past-vals]
 (let [applicable-bindings
   (some (fn [b] (if (contains? b expr) b nil)) l-bindings)
   bind-val (get applicable-bindings expr)]
   (if (or (not applicable-bindings)
   (contains? past-vals bind-val)) ;don't enter replace
loop
 expr
 (recur bind-val l-bindings (conj past-vals bind-val))

(defn subst-bindings-int [x l-bindings]
  (prewalk (fn [expr] (recursive-replace expr l-bindings)) x))

(defn subst-bindings-list [x list-of-bindings]
  (cond (some (partial = fail) list-of

Re: Documentation (was: Re: duck-streams missing from clojure-contrib.jar file)

2010-04-21 Thread Tom Faulhaber
Hi all,

(For those who don't know, I'm the one who maintains the autodoc API
documentation.)

There are some great suggestions here and I'll try to pick up as many
as I can. More useful branch names and having the branch in the title
are no brainers and I'll try to get them in soon.

One resource to use is the index included with each API. (See the
index link in the left sidebar.) This has every function, macro and
var in the whole library with a snippet of their doc. I find this to
be pretty useful sometimes, especially when I don't remember which
namespace something's in. I've always wished the Python doc had this
feature!

A couple things I've also been thinking about are building in a search
capability and building a "super-index" of not only core and contrib
but various other external libraries that would link back to their
doc.

Please also understand that Clojure is a young language and things are
still very much under development. We're still understanding what our
"best practice" is and how to approach it. As you point out,
clojure.contrib.io is an example where we're not there yet, but it is
happening. clojure.contrib.io is a precursor for a clojure.io
namespace that will unify these things.

Thanks for the ideas! Keep 'em coming.

Tom

On Apr 21, 8:39 am, Douglas Philips  wrote:
> On 2010 Apr 21, at 9:31 AM, Stuart Halloway wrote:
>
> > The second level header tells you the branch (e.g. master). On the  
> > left hand side is a list of branches (so you can click on e.g. 1.1.x).
>
> Wow, that is quite subtle. As you click into contrib from clojure.org  
> it isn't very noticeable.
> It also isn't something you notice if you are, for example, clicking  
> through from the unversioned clojure.org pages.
> An example at random:
>      Start at:http://clojure.org/macros
>      then click on the lazy-cat link, which takes you 
> to:http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/
> lazy-cat
>      and start browsing.
>
> With your focus down 'into' that page you have no idea that you've  
> jumped into versioned information.
>
> If you start as a beginner, as I did, the stuff on clojure.org is not  
> versioned (there is no master/1.1.x link in the side bar) and so  
> having version info appear only in contrib pages is not easy to  
> notice, particularly if you get there via links from the main page.
>
> > Some ways I see this might be better:
>
> > (1) make clear what master currently equals (right now it is 1.2  
> > alpha)
>
> That would help. Master is pretty generic.
>
> > (2) highlight the branch info more with css
>
> Couldn't hurt, but it it'd be nice if showed in the page title too,  
> the sidebars are lost when scrolling down into the various pages.
>
> > (3) push the branch info into the top-level header (and page title)
>
> Yup.
>
> > (4) The overview section for c.c.io could tell about the lineage  
> > back to 1.1.
>
> Not having been along for the ride since (nearly) the beginning,  
> having those breadcrumbs would be helpful to me.
>
> > Which of these (or what else?) would have helped you the most?
>
> I think having the default, as Alex Osburne suggested, be the stable  
> release would have made my exploration of 1.1 a lot less painful.
>
> And along those lines, distinguishing between core and contrib is  
> something that might be important to the maintainers, but not so much  
> to the users. And, very less useful to newbies trying to get something  
> useful done.
>
> Trying to figure out that spit is in a contrib library and slurp  
> isn't? C'mon. I finally broke down and used google, and then when I  
> saw a thread back in '08 about that, and it still isn't addressed?  
> Really, easy file I/O is that unimportant to most clojure users?
>
> Having a unified and comprehensive index of functions/macros  
> (annotated with core/contrib) would also go a long way to making the  
> clojure documentation environment a lot more useful. Oh, and then  
> there is the distinction betweenhttp://clojure.org/librariesand the  
> contrib libraries. Yet another place to look? Great, I really don't  
> have anything better to do than internalize these distinctions? (In  
> case you can't tell, having burned -hours- of spare time trying to  
> find my way around docs has been exceptionally frustrating.)
>
> At least for someone like me who is exploring on their own and isn't  
> getting paid to make this work, having to lose my train of thought for  
> 5-10 minutes while trying to figure out if something is core or  
> contrib is hugely frustrating and demotivating. Then throw in a "wtf?  
> why isn't this working in the stable release" only makes it more so  
> when I'm looking at the wrong docs and didn't even know that there  
> were versioned docs.
>
> If you want an example of the kind of structure that I do find  
> helpful, look at docs.python.org. How many times on that page do you  
> see that you're lookin at the 2.6 docs and that there are links to  
> o

Re: request for comments/code-review - clojure implementation of unifier

2010-04-21 Thread Alex Osborne
Kevin Livingston  writes:

>> Not at all. next is basically #(seq (rest %)); you might want to use
>> it when the extra bit of strictness is beneficial to your code and you
>> shouldn't use it when it isn't.
>
> oh, ok.  I saw some posts on using the new super-lazy lists / code and
> it implied that next was necessary over rest, but I didn't quite read
> it in excruciating detail.

Likely what you were reading was referring to nil-punning.  In very
early versions of Clojure, empty seqs were nil, so you could do:

(when some-seq
   ...)

Of course this has the problem that you can't have a completely lazy
seq, the first element is always evaluated (to see whether the seq is
empty or not in order to return nil).  They were made fully lazy by
introducing empty seqs, thus you now need to explicitly check with one
is empty use 'seq.  So next is a shorthand for doing this on rest and
replacing instances of rest with next in old code that relied on
nil-punning was a simple way to upgrade.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: getting compiler-like meta data from read

2010-04-21 Thread Kevin Livingston
Thank you the LineNumberingPushbackReader is exactly what is needed.
The other metadata I can add fairly straightforwardly so good, this is
*far* more sane than that monstrosity I conjured up.

Kevin



On Apr 20, 3:15 am, Ilia Ablamonov  wrote:
> I've encountered the same problem (as far as I understood) in Fleet.
>
> My solution 
> ishttp://github.com/Flamefork/fleet/blob/master/src/fleet/loader.clj#L55
>
> There code comes from String, but you can use FileReader instead of
> StringReader.
> File path must be specified additionally, but this should be obvious.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Documentation (was: Re: duck-streams missing from clojure-contrib.jar file)

2010-04-21 Thread Glen Stampoultzis
On Thursday, April 22, 2010, Tom Faulhaber  wrote:

>
> A couple things I've also been thinking about are building in a search
> capability and building a "super-index" of not only core and contrib
> but various other external libraries that would link back to their
> doc.

I think building a super index is a great idea and would be very
useful.  The current indexes are great because you can easily search
for a function on one page.  Anything that reduces the number of pages
you need to visit to find stuff is useful in my opinion.

The ultimate would be something that let's users contribute their own
comments but that may be going beyond the scope of what you want
autodoc to be.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Which version of Netbeans to use Compojure on OSX?

2010-04-21 Thread Sophie
I see downloads named
  - Java SE (45MB)
  - Java FX (76MB)
  - Java (146MB) - apparently includes Sun Glassfish Server & what-not

I'm using OSX 10.5.8, and just want to install the easiest Netbeans
(with Enclojure) to for development with Compojure.

Would I use Compojure with Jetty? Apache (built into OSX)?

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
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Which version of Netbeans to use Compojure on OSX?

2010-04-21 Thread Sean Devlin
If you've got the HD space, grab the most inclusive options.  I
*think* the SE one will work, but I haven't tested it.  Space is cheap
and all that.

On Apr 21, 7:55 pm, Sophie  wrote:
> I see downloads named
>   - Java SE (45MB)
>   - Java FX (76MB)
>   - Java (146MB) - apparently includes Sun Glassfish Server & what-not
>
> I'm using OSX 10.5.8, and just want to install the easiest Netbeans
> (with Enclojure) to for development with Compojure.
>
> Would I use Compojure with Jetty? Apache (built into OSX)?
>
> 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
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group 
> athttp://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Which version of Netbeans to use Compojure on OSX?

2010-04-21 Thread Antony Blakey

On 22/04/2010, at 10:48 AM, Sean Devlin wrote:

> I think* the SE one will work, but I haven't tested it.

Yes it does.

Antony Blakey
--
CTO, Linkuistics Pty Ltd
Ph: 0438 840 787

If at first you don’t succeed, try, try again. Then quit. No use being a damn 
fool about it
  -- W.C. Fields

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Per Vognsen
Yet another variation:

(defn conjugate [f g & [g-inv]]
  (comp (or g-inv g) f g))

(defn composite [f f-inv n x]
  (nth (iterate (if (pos? n) f f-inv) x) (abs n)))

(defn rotate-left [xs]
  (when (seq xs) (concat (rest xs) [(first xs)])))

(def rotate-right (conjugate rotate-left reverse))

(defn rotate [n xs]
  (composite rotate-left rotate-right n xs))

This is intended to expose certain symmetries.

One of the basic ideas in mathematics is that an invertible
transformation T acts on elements by application, so that x becomes
T(x), and on functions by conjugation, so that f becomes T^(-1) . f .
T.

Another basic idea is that iterated compositions are like powers: f^n
is the n-fold composition of f. This is what iterate tries to capture.
This is meaningful for negative values of n when f is invertible. This
is what composite tries to capture.

If there were more direct support for doubly-infinite sequences (a fun
little programming exercise) then composite could return a
doubly-infinite sequence (much like iterate returns a singly-infinite
sequence), take would work with negative arguments, next would have a
counterpart prev, etc. Another fun exercise is to provide more direct
support for invertible functions. An invertible function can be
represented by a pair of functions. It implements IFn by applying the
first element of the pair. Inverting is just a matter of swapping the
elements.

Food for thought. :)

-Per

On Wed, Apr 21, 2010 at 10:23 PM, Sean Devlin  wrote:
> Hey everyone,
>
> I've had to code these guys up a few times:
>
> (defn rotate
>  "Take a collection and left rotates it n steps. If n is negative,
> the
> collection is rotated right. Executes in O(n) time."
>  [n coll]
>  (let [c (count coll)]
>    (take c (drop (mod n c) (cycle coll)
>
> (defn rotate-while
>  "Rotates a collection left while (pred item) is true. Will return a
> unrotated
> sequence if (pred item) is never true. Executes in O(n) time."
>  [pred coll]
>  (let [head (drop-while pred coll)]
>    (take (count coll) (concat head coll
>
> Have other people had this 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
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: request for comments/code-review - clojure implementation of unifier

2010-04-21 Thread Michał Marczyk
On 21 April 2010 22:58, Kevin Livingston
 wrote:
> Thank you for taking the time to provide feedback.

Thank you for the insightful response!

I've posted the current state of my code -- which uses clojure.zip and
clojure.walk, among other things -- here:

http://gist.github.com/374764

> intentionally driving into an exception seems like a very bad idea.
> but yes I can define my own equivalent of consp I was just hoping
> there was something I was over looking.

Right. I've aliased clojure.contrib.core/seqable? to compound? for
now... which I hadn't known about earlier. I guess this was bound to
be a solved problem. Agreed on the use of exceptions.

> That'll trade some heap for stack space, presumably worthwhile.  I
> haven't had to do much hand optimization of recursion so I'm a little
> rusty (the Franz Allegro compiler was fairly amazing in that
> regard)... I was hoping there was some even better trick (like the
> trampoline) to save me even more.

I did write a version of occurs-check -- which I seem to have renamed
to occurs? at some point -- which uses the CPS approach (it's included
in the Gist, commented out); then I realised that its a natural use
case for clojure.zip (the same basic idea, but with a different
packaging). See if you like the current version.

> that "extra" paren is there too because the body of the clause is an
> implicit progn in common lisp.

And an implicit begin in Scheme, I know... Plus the Scheme version
handles unary clauses and a special kind of ternary clauses (with '=>
in the middle) in special ways, which is useful at times. However, the
reason I personally prefer to have those extra parens in cond has much
more to do with the shape of the code than those other things. :-)

> on some issues I agree others I disagree, regarding your code:

Thanks again for your remarks. A few points that came to my mind:

> regarding removing the helper functions, that's not necessarily ideal,
> while bindings may always be a map putting in literals like {} or nil
> instead of fail or no-bindings actually obfuscates the code, and makes
> it harder to change later if what bindings is needs to fundamentally
> change.

I'm in two minds w.r.t. the second point above. On the one hand, I'm
loathe to pass on using such facilities as the IFn implementation on
maps, sets and vectors in an attempt to make easier some fundamental
change which might possibly happen in the future (and who knows what
else it might involve besides what I might think of now). On the
other, I can already see a different data structure being useful for
representing bindings (more on that further down), so I'm also
disinclined to hand-wave your argument away.

However, I do believe that said different data structure could be made
to act like a map fairly transparently (hopefully through the protocol
facility; or, if some functionality's missing as of yet, reify), so
I'd still prefer to use the map-specific niceties and refactor to
remove them only when the need actual comes (and it becomes clear what
sort of changes are really needed).

> in general it's bad style to wrap a cond with another test if
> trivially avoidable (at least this is coming from best practice common
> lisp style) so for example, in your code line 24, there's no reason to
> pull that out of the cond, especially since you are also using the
> return value of the when, it's better to be explicit about the test
> and what it's resulting return value is -- in this case that the
> unification fails.

Well, I was trying to treat failure specially, as it were, but I take
your point. Changed now.

> the if-let's are a little more interesting as it
> potentially saves one lookup, but it seems to make  the code far more
> "disjoint" or at least increase the number of paths.

I've included my cond-let macro in the Gist now (and refactored
unify-variable to take advantage of it); do you think it's acceptable?

> the changing of a cond to a some with the identity function on line 48
> seems like a very odd choice to me.  while still correct code I see no
> reason why this would be preferred to a cond.

Ouch, I don't know what I was thinking. Changed now.

> I'm torn about the simplify-bindings -- I think it's a cool function
> to have, because if what you are subbing into is large compared to
> bindings, this is probably a win, but if you have a lot of bindings
> and are only using some, you could spend a lot of time to pack them
> down.  it'd probably be good to have around if someone knew where they
> were in the trade-off.

Perhaps using some kind of local memoization would be a good
compromise? There was a cool thread on memoization here a short while
ago; see Meikel Brandmeyer's summary here:

http://kotka.de/blog/2010/03/memoize_done_right.html

I took a shot at that with subst-memo. Additionally, this function
leaves unbound variables intact, while the other versions use nil
instead. There are two other (simpler) versions of subst included in
the curren

Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Michał Marczyk
On 22 April 2010 03:51, Per Vognsen  wrote:
> Yet another variation:
>
> [...]
>
> Food for thought. :)

This is absolutely beautiful. I feel a tremendous joy now. :-)

Sincerely,
Michał

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Which version of Netbeans to use Compojure on OSX?

2010-04-21 Thread Brian Schlining
Get the SE version. You can add other parts that are included in the other
versions (JavaFX, JEE, etc) using the NetBean's plugin mechanism if you find
that you need them. (In the menu bar select Tools -> Plugins)

On Wed, Apr 21, 2010 at 18:18, Sean Devlin  wrote:

> If you've got the HD space, grab the most inclusive options.  I
> *think* the SE one will work, but I haven't tested it.  Space is cheap
> and all that.
>
> On Apr 21, 7:55 pm, Sophie  wrote:
> > I see downloads named
> >   - Java SE (45MB)
> >   - Java FX (76MB)
> >   - Java (146MB) - apparently includes Sun Glassfish Server & what-not
> >
> > I'm using OSX 10.5.8, and just want to install the easiest Netbeans
> > (with Enclojure) to for development with Compojure.
> >
> > Would I use Compojure with Jetty? Apache (built into OSX)?
> >
> > 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
> > Note that posts from new members are moderated - please be patient with
> your first post.
> > To unsubscribe from this group, send email to
> > clojure+unsubscr...@googlegroups.com
> > For more options, visit this group athttp://
> groups.google.com/group/clojure?hl=en
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>



-- 
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Brian Schlining
bschlin...@gmail.com

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Documentation (was: Re: duck-streams missing from clojure-contrib.jar file)

2010-04-21 Thread Douglas Philips

On 2010 Apr 21, at 5:04 PM, Tom Faulhaber wrote:

(For those who don't know, I'm the one who maintains the autodoc API
documentation.)


Cool, thank you!



One resource to use is the index included with each API. (See the
index link in the left sidebar.)


I saw that, but you know, after finding out that "Branches" and  
"Overview" and "Namespaces" don't do anything, I had just assumed that  
"API Index" didn't do anything either; based on clicking those headers  
when first landing on the contrib page. Sigh.





This has every function, macro and
var in the whole library with a snippet of their doc. I find this to
be pretty useful sometimes, especially when I don't remember which
namespace something's in. I've always wished the Python doc had this
feature!


Python does come close: http://docs.python.org/genindex-all.html
(It takes a few clicks from the main docs page: library -> index ->  
full-index-on-one-page.
It does show you the library location, but not any part of the  
individual documentation.)
(I'm used to using the Python 2.4 docs since my day job situation uses  
that older version:

http://docs.python.org/release/2.4.4/lib/genindex.html)




A couple things I've also been thinking about are building in a search
capability and building a "super-index" of not only core and contrib
but various other external libraries that would link back to their
doc.


Having one index that spans the core and the contrib library would be  
a huge step forward.
Adding in other stuff would be cool, but I would hope that would not  
delay work unifying core/contrib.




Please also understand that Clojure is a young language and things are
still very much under development.


Yup.




We're still understanding what our
"best practice" is and how to approach it. As you point out,
clojure.contrib.io is an example where we're not there yet, but it is
happening. clojure.contrib.io is a precursor for a clojure.io
namespace that will unify these things.


Looking at the clojure.org front page, there is no "roadmap" link, or  
anything that seems to be like that, to know what is on the radar,  
etc. The "news" link points to: http://clojure.blogspot.com/ but that  
seems to be a few months old. Clicking through the 'dev' link and  
bouncing around, I eventually found:

http://www.assembla.com/spaces/clojure/milestones/149827-release-1-2
and it seems that there are only a handful of issues to be resolved  
before 1.2 is cut?
Poking around a bit more, I found bug 282 having to do with fixing the  
already changed duck-streams to io in test comments. Maybe I missed  
some other link(s) that would show a higher level view of what is  
planned?





Thanks for the ideas! Keep 'em coming.


Thank you for listening.

-Doug

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Missing fns: rotate & rotate-while

2010-04-21 Thread Per Vognsen
By the way, once you start looking for conjugation in common code
patterns, you see it everywhere. A less trivial example is the
Schwartzian transform for caching sorting keys:

(defn schwartz [key-fn] #(map (fn [x] [(key-fn x) x]) %))

(def unschwartz #(map second %))

(defn schwartz-sort [key-fn] (conjugate sort (schwartz key-fn) unschwartz))

If you implement first-class support for invertible functions
(surprisingly easy), you can capture important properties such as:

- composing invertible functions gives an invertible function.
- the inverse of an invertible function is an invertible function.

>From this, it follows (with no extra work) that the conjugate
transformation of an invertible function is an invertible function.

-Per

On Thu, Apr 22, 2010 at 10:38 AM, Michał Marczyk
 wrote:
> On 22 April 2010 03:51, Per Vognsen  wrote:
>> Yet another variation:
>>
>> [...]
>>
>> Food for thought. :)
>
> This is absolutely beautiful. I feel a tremendous joy now. :-)
>
> Sincerely,
> Michał
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en