Re: ANN: Om 0.8.0-alpha1, Reference Cursors!

2014-10-18 Thread Jonas Enlund
Hi

Interesting work as usual! One quick question: What is the difference between 

(let [xs (om/observe owner (items))]
  ...)

as seen in the sub-view component versus the one in main-view which doesn't use 
`om/observe`:

(let [xs (items)]
   ...)


/Jonas


On Saturday, October 18, 2014 6:53:50 PM UTC+3, David Nolen wrote:
> I'm happy to announce the release of Om 0.8.0-alpha1. This release
> 
> includes the single biggest conceptual enhancement since its initial
> 
> release - Reference Cursors.
> 
> 
> 
> As we begin to build larger and larger applications with Om, we
> 
> often run afoul of the need to organize our application around a
> 
> hierarchical tree. This is more problematic than in React itself as Om
> 
> emphasizes a programming model that supports full snapshotting of the
> 
> application state. This seemingly beneficial property actually
> 
> exacerbates the hierachical issue and often leads to an incredible
> 
> amount non-modular programming!
> 
> 
> 
> The introduction of Reference Cursors allow Om programmers to stop
> 
> thinking in terms of trees and return to a more natural mode of UI
> 
> programming - simply calling out into shared APIs around application
> 
> data precisely where you need it. No need to pass data through
> 
> intermediate components on way to the target child component -
> 
> Reference Cursors allow you to get at the data exactly where it is
> 
> required and this without abandoning the ability to time travel over
> 
> your application state.
> 
> 
> 
> There are more thoughts and details here:
> 
> https://github.com/swannodette/om/wiki/Advanced-Tutorial#reference-cursors
> 
> 
> 
> Please give Reference Cursors a try in your application and send lots
> 
> of feedback!
> 
> 
> 
> This is an alpha release. No previous Om APIs should be affected,
> 
> however the Reference Cursor feature is largely untested beyond
> 
> a simple example in the repo.
> 
> 
> 
> https://github.com/swannodette/om
> 
> 
> 
> Cheers,
> 
> David

-- 
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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: How can I improve this?

2014-01-10 Thread Jonas Enlund
On Fri, Jan 10, 2014 at 9:39 PM, Mark Engelberg wrote:

> Technically, all these solutions are flawed.
>
> With the input
> ["a" "a" "a_1"]
> you'll get back
> ["a" "a_1" "a_1"]
>
> To truly address this, you need to also add the newly formatted filename
> into the "seen" map, which none of the suggested solutions do.
>

That's why I wrote my solution like I did, i.e., concatenate "_1" when a
new string is found. This would result in the vector ["a_1" "a_2" "a_1_1"]


>  --
> --
> 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 a topic in the
> Google Groups "Clojure" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/clojure/rt-l_X3gK-I/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>

-- 
-- 
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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [ClojureScript] Please test CLJS-418, fixing browser REPL

2013-02-09 Thread Jonas Enlund
On Thursday, February 7, 2013 7:11:35 PM UTC+2, David Nolen wrote:
> http://dev.clojure.org/jira/browse/CLJS-418
> 
> 
> 
> Some of you may have encountered bizarre problems when trying to use browser 
> REPL with the latest releases of ClojureScript. This ticket contains a patch 
> that should resolve the issue but we need people to test.
> 
> 
> 
> Thanks,
> David

Hi

I tested this with the following approach and got the repl to work without 
issues:

* I modified cljsbuild[1] to use [org.clojure/google-closure-library 
"0.0-2029-2"] instead of [org.clojure/google-closure-library-third-party 
"0.0-2029"].
* AFAIK google-closure-library "0.0-2029-2" will be used by clojurescript in a 
new release so the above change (should) confirm that the transitive dependency 
on google-closure-library-third-party is indeed working as expected.

I also tried to test the browser repl without cljsbuild but script/bootstrap 
pulls in different closure-library deps than are specified in the pom.xml. The 
browser repl works without cljsbuild out of the box. 

If more testing concerning this issue is required please tell me because I'd 
like to see a new clojurescript release soon.

Jonas

[1] https://github.com/emezeske/lein-cljsbuild/blob/master/support/project.clj

-- 
-- 
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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.




Re: proxy and java.io.Writer

2011-01-30 Thread Jonas Enlund
On Sun, Jan 30, 2011 at 8:39 PM, Ken Wesson  wrote:
> On Sun, Jan 30, 2011 at 1:35 PM, Jonas Enlund  wrote:
>> On Sun, Jan 30, 2011 at 7:01 PM, Ken Wesson  wrote:
>>> On Sun, Jan 30, 2011 at 9:26 AM, Jonas Enlund  
>>> wrote:
>>>> Hi.
>>>> I'm trying to create a java.io.Writer proxy (which writes to a
>>>> JTextArea) but I can't get it to work.
>>>> Here is my clojure code so far:
>>>>
>>>> (def text-area (javax.swing.JTextArea.))
>>>>
>>>> (def frame
>>>>      (let [f (javax.swing.JFrame.)]
>>>>        (.. f getContentPane (add text-area))
>>>>        (.setMinimumSize f (java.awt.Dimension. 200 200))
>>>>        (.setVisible f true)
>>>>        f))
>>>>
>>>> (def text-area-writer
>>>>      (proxy [java.io.Writer] []
>>>>        (close [])
>>>>        (flush [])
>>>>        (write [^chars chrs ^int offs ^int len]
>>>>          (.append text-area (String. chrs offs len)
>>>>
>>>> When I load the code above I get an "IllegalArgumentException: Unable
>>>> to resolve classname: int" so I think I'm not type hinting correctly.
>>>
>>> Indeed. You can't (in 1.2 at least) type hint "int" though you can
>>> "ints" (array of int). Note that int is a primitive type while array
>>> of int is a reference type.
>>>
>>> Type hinting as Integer shouldn't throw exceptions, but you can
>>> probably omit all but the chars hint and have the correct String
>>> constructor overload selected.
>>
>> I tried with 1.3.0-alpha5. With type hints I get "CompilerException
>> java.lang.IllegalArgumentException: Only long and double primitives
>> are supported". If I only keep the ^chars hint I get an ArityException
>> when I do (.write text-area-writer "hello").
>
> Does it work with 1.2? Where exactly is the ArityException being
> thrown -- for what function or method?

It didn't work in 1.2 either. Here is some more info on the exception
thrown (this is with 1.3.0-alpha5)

user=> (.write text-area-writer "Hello, World!")
ArityException Wrong number of args (2) passed to: user$fn--38$fn
clojure.lang.AFn.throwArity (AFn.java\
:439)
user=> (pst)
ArityException Wrong number of args (2) passed to: user$fn--38$fn
user.proxy$java.io.Writer$0.write (:-1)
sun.reflect.NativeMethodAccessorImpl.invoke0
(NativeMethodAccessorImpl.java:-2)
sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke (Method.java:616)
clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:90)
clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:28)
user/eval47 (NO_SOURCE_FILE:4)
clojure.lang.Compiler.eval (Compiler.java:6223)
clojure.lang.Compiler.eval (Compiler.java:6190)
clojure.core/eval (core.clj:2680)
clojure.main/repl/read-eval-print--5617 (main.clj:180)
nil
user=>

Thanks for helping out with this Ken!

>
> --
> 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: proxy and java.io.Writer

2011-01-30 Thread Jonas Enlund
On Sun, Jan 30, 2011 at 7:01 PM, Ken Wesson  wrote:
> On Sun, Jan 30, 2011 at 9:26 AM, Jonas Enlund  wrote:
>> Hi.
>> I'm trying to create a java.io.Writer proxy (which writes to a
>> JTextArea) but I can't get it to work.
>> Here is my clojure code so far:
>>
>> (def text-area (javax.swing.JTextArea.))
>>
>> (def frame
>>      (let [f (javax.swing.JFrame.)]
>>        (.. f getContentPane (add text-area))
>>        (.setMinimumSize f (java.awt.Dimension. 200 200))
>>        (.setVisible f true)
>>        f))
>>
>> (def text-area-writer
>>      (proxy [java.io.Writer] []
>>        (close [])
>>        (flush [])
>>        (write [^chars chrs ^int offs ^int len]
>>          (.append text-area (String. chrs offs len)
>>
>> When I load the code above I get an "IllegalArgumentException: Unable
>> to resolve classname: int" so I think I'm not type hinting correctly.
>
> Indeed. You can't (in 1.2 at least) type hint "int" though you can
> "ints" (array of int). Note that int is a primitive type while array
> of int is a reference type.
>
> Type hinting as Integer shouldn't throw exceptions, but you can
> probably omit all but the chars hint and have the correct String
> constructor overload selected.

I tried with 1.3.0-alpha5. With type hints I get "CompilerException
java.lang.IllegalArgumentException: Only long and double primitives
are supported". If I only keep the ^chars hint I get an ArityException
when I do (.write text-area-writer "hello").

Is this problem unsolvable with proxy? Should I look into gen-class
and AOT compilation instead?

>
> Also note that while text area .append is safe to call from off the
> EDT, other Swing methods mostly aren't, and it's something to watch
> for if you do anything similar to this with other Swing components,
> and wherever you construct your text area and its surrounds.
>
> --
> 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


proxy and java.io.Writer

2011-01-30 Thread Jonas Enlund
Hi.
I'm trying to create a java.io.Writer proxy (which writes to a
JTextArea) but I can't get it to work.
Here is my clojure code so far:

(def text-area (javax.swing.JTextArea.))

(def frame
     (let [f (javax.swing.JFrame.)]
       (.. f getContentPane (add text-area))
       (.setMinimumSize f (java.awt.Dimension. 200 200))
       (.setVisible f true)
       f))

(def text-area-writer
     (proxy [java.io.Writer] []
       (close [])
       (flush [])
       (write [^chars chrs ^int offs ^int len]
         (.append text-area (String. chrs offs len)

When I load the code above I get an "IllegalArgumentException: Unable
to resolve classname: int" so I think I'm not type hinting correctly.

Here is a similar piece of java code which works as expected:

public class Main extends JFrame {
  private JTextArea text;
  public Writer writer;

  public Main() {
text = new JTextArea();
getContentPane().add(text);
setVisible(true);
setMinimumSize(new Dimension(200, 200));
writer = new TextAreaWriter();
  }

  class TextAreaWriter extends Writer {
public void close() throws IOException {}
public void flush() throws IOException {}

public void write(char[] chrs, int offs, int len) throws IOException {
  String str = new String(chrs, offs, len);
  text.append(str);
}
  }

  public static void main(String[] args) throws IOException {
Main m = new Main();
m.writer.write("Hello, World!");
  }
}

Any help is much appreciated!

/Jonas

-- 
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: A simple csv parsing library

2010-06-11 Thread Jonas Enlund
On Thu, Jun 10, 2010 at 1:01 AM, Daniel Werner
 wrote:
> Jonas,
>
> Thanks for stepping forward and publishing your work. From the short
> glance I had at it already, your code seems very low-level (probably
> for performance), but sound. The only thing that, compared to other
> CSV libraries I've used, I miss somewhat is explicit support for
> "dialects". While the developer can set the separator, quote and
> newline chars herself, it would be nice if there were a number of pre-
> made maps for commonly used CSV dialects, e.g. Excel, whose values can
> just be passed to the read and write functions.
>
> To give an example, Python's approach is quite simple yet effective.
> Their use of class inheritance to define new dialects that are similar
> to old ones would translate well to Clojure maps, by assoc'ing or
> merge'ing the changes in.
>
> http://docs.python.org/library/csv.html#csv-fmt-params

I'll take a look at how python does things. Dialects sounds like a good idea.

I have now added the lib to clojars so it should be ready for use with
either leiningen or maven.

-- 
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: A simple csv parsing library

2010-06-09 Thread Jonas Enlund
On Wed, Jun 9, 2010 at 3:47 PM, Kyle R. Burton  wrote:
>> When I say that it supports the RFC I mean that the library should be
>> able to read any file that follows that standard. It might (and it
>> does) read files that do not follow the standard. Here are some
>> examples:
>>
>> 1) quotes can appear anywhere, not only as the first and last
>> character in a cell.
>> 2) records can be of different length.
>> 3) any character can be used as quote or separator.
>> 4) The problem you raised, i.e., that the file might end in a "quoted"
>> state and still be read without exceptions.
>>
>> I'll consider adding a :strict flag which would throw an exception for
>> points 2 and 4. However, I don't want to sacrifice performance since I
>> consider that to be the most important feature in any csv reading
>> library (people often have Gb+ sized csv files).
>
> I appreciate your needs, mine differ a bit, in some circumstances I
> want strictness for the format.  Ideally for my own use cases I'd like
> to be able to know about or reject the entire file if #4 occurs, but
> allow #2.  I'd imagine adding in the additional logic will have some
> impact on performance.

Checking #4 wouldn't have a performance hit, so I'll probably add
that. I have to think about the other points.

>
> Regarding performance, have you considered adding a benchmarking
> harness to the project?

Yes, I have thought about it. It would be fun to compare cljcsv,
clojure-csv, OpenCSV and SuperCSV (are there others?). I have looked
into it a bit, and if my measurements are correct it's faster than
clojure-csv and within 10% of OpenCSV.


>
> Thank you for publishing the library.
>

Thanks for showing interest!

Jonas

>
> Regards,
>
> Kyle
>
> --
> 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: A simple csv parsing library

2010-06-09 Thread Jonas Enlund
When I say that it supports the RFC I mean that the library should be
able to read any file that follows that standard. It might (and it
does) read files that do not follow the standard. Here are some
examples:

1) quotes can appear anywhere, not only as the first and last
character in a cell.
2) records can be of different length.
3) any character can be used as quote or separator.
4) The problem you raised, i.e., that the file might end in a "quoted"
state and still be read without exceptions.

I'll consider adding a :strict flag which would throw an exception for
points 2 and 4. However, I don't want to sacrifice performance since I
consider that to be the most important feature in any csv reading
library (people often have Gb+ sized csv files).

Jonas



On Wed, Jun 9, 2010 at 6:54 AM, Kyle R. Burton  wrote:
>> I've added my work on the csv reader/writer library to github
>> (http://github.com/jonase/cljcsv). Please let me know If anyone finds
>> it useful.
>
> Thanks for the implementation, I'm very encouraged that you followed
> the RFC (I've seen lots of implementations that haven't).
>
> I took a quick look at both yours and clojure-csv [1].  I'm not using
> the 1.2 snapshots so I wasn't able to try out your implementation, but
> I did notice clojure-csv is lax about invalidly formatted files - if a
> quoted field ends the file but is not terminated before eof, it does
> not signal an error.  I think I recognize the same behavior in cljcsv
> as well (though as I said I could not try it).  It might be nice to at
> least have an option which allows an unterminated field to be
> recognized.
>
> Best Regards,
>
> Kyle
>
> [1] http://github.com/davidsantiago/clojure-csv
>
>> On Wed, May 26, 2010 at 6:40 AM, Jonas Enlund  wrote:
>>> Hi there
>>>
>>> I built a simple csv parsing library[1] last weekend which I want to
>>> show you guys. It follows the RFC 4180[2] pretty closely but it allows
>>> for any character as separator and quote mark. It would be great if
>>> someone would take time and read the code. I would like to know:
>>>
>>> a) Can performance still be improved?
>>> b) Is it idiomatically written?
>>> c) What should an idiomatic csv parsing API look like in Clojure?
>>> Currently there is only one public function, 'parse' (like
>>> clojure.xml).
>>>
>>> The end of the file contains a few usage examples.
>>>
>>> happy hacking!
>>> /Jonas
>>>
>>> [1] http://gist.github.com/414023
>>> [2] http://tools.ietf.org/html/rfc4180
>>>
>>
>> --
>> 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
>
>
>
> --
> --
> kyle.bur...@gmail.com                            http://asymmetrical-view.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

-- 
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: A simple csv parsing library

2010-06-08 Thread Jonas Enlund
I've added my work on the csv reader/writer library to github
(http://github.com/jonase/cljcsv). Please let me know If anyone finds
it useful.

Thanks,
Jonas

On Wed, May 26, 2010 at 6:40 AM, Jonas Enlund  wrote:
> Hi there
>
> I built a simple csv parsing library[1] last weekend which I want to
> show you guys. It follows the RFC 4180[2] pretty closely but it allows
> for any character as separator and quote mark. It would be great if
> someone would take time and read the code. I would like to know:
>
> a) Can performance still be improved?
> b) Is it idiomatically written?
> c) What should an idiomatic csv parsing API look like in Clojure?
> Currently there is only one public function, 'parse' (like
> clojure.xml).
>
> The end of the file contains a few usage examples.
>
> happy hacking!
> /Jonas
>
> [1] http://gist.github.com/414023
> [2] http://tools.ietf.org/html/rfc4180
>

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


Recur on a function which uses keyword arguments?

2010-06-06 Thread Jonas Enlund
The function definition below fails with
"java.lang.IllegalArgumentException: Mismatched argument count to
recur, expected: 1 args, got: 2"

(defn countdown [& {:keys [from]
:or {from 10}}]
  (println from)
  (when (pos? from)
(recur :from (dec from

Is it not possible to recur on a function which uses keyword
arguments? If so, is using loop/recur the correct workaround?

- Jonas

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


A simple csv parsing library

2010-05-25 Thread Jonas Enlund
Hi there

I built a simple csv parsing library[1] last weekend which I want to
show you guys. It follows the RFC 4180[2] pretty closely but it allows
for any character as separator and quote mark. It would be great if
someone would take time and read the code. I would like to know:

a) Can performance still be improved?
b) Is it idiomatically written?
c) What should an idiomatic csv parsing API look like in Clojure?
Currently there is only one public function, 'parse' (like
clojure.xml).

The end of the file contains a few usage examples.

happy hacking!
/Jonas

[1] http://gist.github.com/414023
[2] http://tools.ietf.org/html/rfc4180

-- 
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 to use with-bindings*

2010-02-15 Thread Jonas Enlund
On Mon, Feb 15, 2010 at 7:25 AM, Аркадий Рост  wrote:
> Hi!
> I was playing a bit with with-bindings* function, but I got error
> every time.
>
> I've tried:
>
> (def a 5)
>
> (with-bindings* {a 3} println a) ;; got java.lang.Integer cannot be
> cast to clojure.lang.Var
>
> (with-bindings* [{a 3}] println a) ;;got
> clojure.lang.PersistentArrayMap cannot be cast to
> clojure.lang.IMapEntry
>
> (with-bindings* [a 3] println a) ;;got java.lang.Integer cannot be
> cast to clojure.lang.IMapEntry
>
> and others variants...So what's the syntaxes of this function?
>
> Someone show code example, please.

Hi,

Try one of the following:

user=> (with-bindings* {#'a 3} println a)
5 ; It seems as if args doesn't have the new bindings yet since this prints 5
nil

user=> (with-bindings {#'a 3} (println a))
3
nil

user=> (with-bindings* {#'a 3} #(println a))
3
nil

-- 
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: am i the only one with deftype/defprotocol problems?

2010-01-04 Thread Jonas Enlund
I think you simply need to get the syntax right. The following works
fine for me:

user=>  (defprotocol p (foo [this]))
p
user=>  (deftype a [f] p (foo []))
#'user/a
user=> (foo (a nil))
nil
user=> (deftype a [f] :as this p (foo [] [this]))
#'user/a
user=> (foo (a nil))
[#:a{:f nil}]




On Mon, Jan 4, 2010 at 6:37 AM, Raoul Duke  wrote:
> hi,
>
> i've only heard crickets so far, am i really the only one who can't
> get this to work? help? :-} thanks. i figure i must be doing something
> dirt simple wrong?
>
> Clojure 1.1.0-new-SNAPSHOT
> user=> (defprotocol p (foo [this]))
> p
> user=> (deftype a [f] [p] (.foo [this]))
> java.lang.RuntimeException: java.lang.ClassCastException:
> clojure.lang.PersistentVector cannot be cast to clojure.lang.Symbol
> (NO_SOURCE_FILE: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

-- 
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: Creating deftype instance from inside a protocol method

2010-01-02 Thread Jonas Enlund
Sorry, I think my reply got lost...

Inside deftype methods the symbol "Bar" is the name of the class. You
can use the constructor (Bar. (inc i)) instead. Again, note the "."
after Bar.

On Sat, Jan 2, 2010 at 1:23 PM, Konrad Hinsen
 wrote:
> On 01.01.2010, at 23:56, Hugo Duncan wrote:
>
>>> I want to create a new instance of a deftype from inside one of its
>>> methods.
>>
>> I ended-up using extend-type for this case.
>
> That's probably the cleanest solution, but you lose the performance
> benefit of defining methods right in the type definition.
>
> After looking at the deftype code, I came up with the following
> solution:
>
> (defprotocol Foo
>   (foo [x]))
>
> (deftype Bar
>   [i]
>   Foo
>     (foo [] (new Bar (inc i
>
> (foo (Bar 0))
>
>
> Its drawback is relying on an undocumented feature: the value of Foo
> inside the methods is the class Foo being defined.
>
> Konrad.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> 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: Creating deftype instance from inside a protocol method

2010-01-02 Thread Jonas Enlund
(note the .)

(deftype Bar
  [i]
  Foo
(foo [] (Bar. (inc i

/Jonas

-- 
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: Datatypes and Protocols - early experience program

2009-11-16 Thread Jonas Enlund
On Mon, Nov 16, 2009 at 6:27 PM, Stuart Sierra
 wrote:
> On Nov 14, 8:28 am, Jonas Enlund  wrote:
>> I have built a simple Matrix datatype with defprotocol and deftype.
>> You can take a look at it athttp://gist.github.com/234535
>> (constructive criticism welcome!).
>
> Small thing: I would expect (count a-matrix) to return rows*columns,
> not the number of rows.

I made count return the number of rows because that way (count
a-matrix) == (count (seq a-matrix)). I don't know if it's the right
thing to do, maybe rows*cols would make more sense.

/Jonas

>
> -SS
>
> --
> 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: Datatypes and Protocols - early experience program

2009-11-14 Thread Jonas Enlund
Hi there!

I have built a simple Matrix datatype with defprotocol and deftype.
You can take a look at it at http://gist.github.com/234535
(constructive criticism welcome!). Some simple examples are provided
at the end of the file.

I have a few questions.

- Why must i write (matrix/Matrix ...) instead of (Matrix ...) inside
the deftype body? Is this a bug? I didn't have to write it that way in
earlier versions of the new-branch.
- Am I supposed to have all the interface implementations inside the
deftype body? I didn't figure out how to move the implementation of
the clojure.lang.* interfaces to (extends ...).

/Jonas

-- 
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: transient quicksort

2009-08-05 Thread Jonas Enlund

Hi,

Thank's for pointing this out for me. I didn't realize how to use
these constructs correctly. Seeing the !-mark i just thought that
assoc! was to be used like set! set-car! set-cdr! in Scheme... my
mistake.

On Tue, Aug 4, 2009 at 8:49 PM, Jarkko Oranen wrote:
>
> On Aug 4, 11:08 am, Jonas  wrote:
>> Hi
>>
>> I'm playing with the new transient/persistent! features in Clojure. I
>> have implemented quicksort as described on wikipedia (http://
>> en.wikipedia.org/wiki/Quicksort#Algorithm). Here is the code:
>>
>> (defn swap-index! [v i j]
>>   (let [tmp (v i)]
>>     (assoc! v i (v j))
>>     (assoc! v j tmp)))
>
> I think Rich mentioned on IRC that you should not reuse the transient
> vector binding after an operation; that it works is merely an
> implementation detail. The transient documentation page also says
> tells to "capture return value, use for next call". So:
>
> (defn swap-index! [tv i j]
>  (let [tmp (tv i)]
>    (-> tv
>      (assoc! i (v j))
>      (assoc! j tmp
>
> And similar modifications for the quicksort below.
>
>>
>> (defn partition! [v left-index right-index pivot-index]
>>     (let [pivot-value (v pivot-index)]
>>       (swap-index! v pivot-index right-index)
>>       (loop [i left-index store-index left-index]
>>         (if (< i right-index)
>>           (if (<= (v i) pivot-value)
>>             (do (swap-index! v i store-index)
>>                 (recur  (inc i) (inc store-index)))
>>             (recur (inc i) store-index))
>>           (do (swap-index! v store-index right-index)
>>               store-index)
>>
>> (defn qsort! [v left right]
>>   (when (> right left)
>>     (let [pivot-index left
>>           pivot-new-index (partition! v left right pivot-index)]
>>       (qsort! v left (dec pivot-new-index))
>>       (qsort! v (inc pivot-new-index) right
>>
>> (defn qsort [v]
>>   (let [tv (transient v)]
>>     (qsort! tv 0 (dec (count v)))
>>     (persistent! tv)))
>>
>> This sorts a vector of doubles in about 6000-7000 msec on my machine:
>>
>> user=> (def s (time (qsort (rvector 100
>> "Elapsed time: 6681.35889 msecs"
>>
>> This is much faster than the classical functional programming
>> "quicksort":
>>
>> ; Fromhttp://rosettacode.org/wiki/Quicksort#Clojure
>> (defn qsort-rs [[pivot & xs]]
>>   (when pivot
>>     (let [smaller #(< % pivot)]
>>       (lazy-cat (qsort (filter smaller xs))
>>                 [pivot]
>>                 (qsort (remove smaller xs))
>>
>> user=> (def s (time (doall (qsort-rs (rvector 100)
>> "Elapsed time: 32565.537389 msecs"
>>
>> The Java sort however is about 5 times faster then the transient
>> version:
>>
>> user=> (def s (time (sort (rvector 100
>> "Elapsed time: 1354.427239 msecs"
>>
>> Can you give any hints on how I can make the transient sort faster? I
>> would like to get as close as possible to the native Java speed.
>
> This is partially comparing apples to oranges though: sort returns a
> lazy seq, while
> the quicksort algorithm produces a proper vector.
>
> Anyway, (nth v i) might be somewhat faster than (v i) because it gets
> inlined. I did not try, though.
Ok, I will try that

>
> Below is code that avoids reusing the reference to v:
>
> (defn swap-index! [v i j]
>  (let [tmp (nth v i)]
>    (-> v
>        (assoc! i (nth v j))
>        (assoc! j tmp
>
> (defn partition! [v left-index right-index pivot-index]
>    (let [pivot-value (nth v pivot-index)
>           new-v (swap-index! v pivot-index right-index)]
>      (loop [v new-v, i left-index, store-index left-index]
>        (if (< i right-index)
>          (if (<= (nth v i) pivot-value)
>            (recur (swap-index! v i store-index) (inc i) (inc store-
> index))
>            (recur v (inc i) store-index))
>          [(swap-index! v store-index right-index)
>           store-index]
>
> (defn qsort! [v left right]
>  (if (> right left)
>    (let [pivot-index left
>           [new-v pivot-new-index] (partition! v left right pivot-
> index)]
>      (-> new-v
>          (qsort! left (dec pivot-new-index))
>          (qsort! (inc pivot-new-index) right
>    v)
>
> (defn qsort [v]
>  (let [tv (transient v)]
>    (qsort! tv 0 (dec (count v)))
>    (persistent! tv)))
Nice, thank you!

>
> --
> Jarkko
> >
>

--~--~-~--~~~---~--~~
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: transient quicksort

2009-08-04 Thread Jonas Enlund

On Tue, Aug 4, 2009 at 3:55 PM, Albert Cardona wrote:
>
> Jonas wrote:
>>  Can you give any hints on how I can make the transient sort faster? I
>>  would like to get as close as possible to the native Java speed.
>
>
> My guess is that you need primitive type hints. For example:
>
>     (let [pivot-value (v pivot-index)]
>
>
>
> could be:
>
>    (let [pivot-value (int (v pivot-index))]
>
>
> ... and so on.
>
> Albert
>

I have tried to add type hints but they don't seem to speed things up.
For example, if I add type hints to the partition! loop (where I would
have thought that
type hints would make the biggest difference) I don't see a speedup at all:

(defn partition! []
   ...
   (loop [i (int left-index) store-index (int left-index)]
   ...)

--~--~-~--~~~---~--~~
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: transient quicksort

2009-08-04 Thread Jonas Enlund

I get ~8% performance boost by turning swap-index! into a macro:

(defmacro swap-index! [v i j]
  `(let [tmp# (~v ~i)]
(assoc! ~v ~i (~v ~j))
(assoc! ~v ~j tmp#)))

--~--~-~--~~~---~--~~
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: The :while modifier (list comprehensions)

2009-08-03 Thread Jonas Enlund

> When you put the :while at the `x` clause you get the expected empty
> seq.
>
> user=> (for [x (range 1 10) :while (= x 2) y (range 1 10)] [x y])
> ()

Interesting, I didn't know that.

Still, the behavior of :while feels strange. I guess I'll get used to it.

In the following example :while and :when are interchangeable, which
is often the case when :while is used last in the list comprehension:

user=> (for [x (range 1 10) y (range 1 10) :while (< (+ x y) 5)] [x y])
([1 1] [1 2] [1 3] [2 1] [2 2] [3 1])

user=> (for [x (range 1 10) y (range 1 10) :when (< (+ x y) 5)] [x y])
([1 1] [1 2] [1 3] [2 1] [2 2] [3 1])

--~--~-~--~~~---~--~~
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: Newbie macro problems

2009-07-08 Thread Jonas Enlund

2. http://gist.github.com/142939

On Wed, Jul 8, 2009 at 7:19 PM, Jonas Enlund wrote:
> 1. Ok, I'll consider that.
>
> 2. Yes, I'll post a link when I have uploaded the code somewhere.
>
> 3. It has not yet arrived
>
> 4. No. I have two sources of inspiration. Pattern matching in PLT
> Scheme and this link:
> http://groups.csail.mit.edu/mac/users/gjs/6.945/psets/ps05/ps.txt
> (which is almost SICP as it is written by Sussman)
>
> On Wed, Jul 8, 2009 at 7:15 PM, Sean Devlin wrote:
>>
>> 4.  Is this example from SICP?
>>
>> On Jul 8, 12:12 pm, Sean Devlin  wrote:
>>> This seems like a good use for a macro.  A couple of thoughts:
>>>
>>> 1.  Use arrays instead of lists
>>> In clojure, it is "best practice" to use arrays for data.  So, your
>>> macro call should look like this.
>>>
>>> (match [1 2 3]
>>>        [1 x]   (+ x x)
>>>        [1 x y] (+ x y))
>>>
>>> 2.  Could you post the source to match maker?  That would help my play
>>> around in a REPL
>>>
>>> 3.  As for books go, get yourself a copy of "Programming Clojure" by
>>> Stuart Holloway
>>>
>>> Sean
>>>
>>> On Jul 8, 11:42 am, Jonas  wrote:
>>>
>>> > Hi.
>>>
>>> > I'm developing a simple pattern matching library for clojure but I am
>>> > having
>>> > trouble with macros (which I have almost zero experience with).
>>>
>>> > I have a function `make-matcher`
>>>
>>> > (make-matcher )
>>>
>>> > which returns a function that can pattern match on data and returns a
>>> > map of bindings (or nil in case of a non-match).
>>>
>>> > ((make-matcher '(list x y z w)) (list 1 2 3 4))
>>> > ; => {x 1 y 2 z 3 w 4}
>>> > ((make-matcher '(list x y z x)) (list 1 2 3 4))
>>> > ; => nil
>>> > ((make-matcher '(list 1 x 2 _)) (list 1 2 3 4))
>>> > ; => nil
>>> > ((make-matcher '(list 1 x 2 _)) (list 1 3 2 9))
>>> > ; => {x 3}
>>>
>>> > I have been trying to write the following 'match' macro:
>>>
>>> > (match 
>>> >    
>>> >    )
>>>
>>> > The macro should work like this:
>>>
>>> > (match (list 1 2 3)
>>> >        (list 1 x)   (+ x x)
>>> >        (list 1 x y) (+ x y))
>>> > ; => 5
>>>
>>> > I have the following macros (none of which works correctly):
>>>
>>> > ; (letmap {a 1 b 2} (+ a b))
>>> > ; =(should) expand to=>
>>> > ; (let [a 1 b 2] (+ a b))
>>> > (defmacro letmap [dict & body]
>>> >   `(let ~(into [] (reduce concat (eval dict)))
>>> >      (do ~...@body)))
>>>
>>> > ; (match (list 1 2 3)
>>> > ;       (list 1 x)   (+ x x)
>>> > ;       (list 1 x y) (+ x y))
>>> > ; =should expand to something like=>
>>> > ; (let [dict ( (list 1 2 3))]
>>> > ;   (if dict
>>> > ;      (letmap dict (+ 1 x))
>>> > ;      (match (list 1 2 3) (list 1 x y) (+ x y
>>> > (defmacro match [data & clauses]
>>> >   (when clauses
>>> >     (let [pattern    (first clauses)
>>> >           body       (second clauses)
>>> >           matcher (make-matcher pattern)]
>>> >       `(let [dict# (~matcher ~data)]
>>> >          (if dict#
>>> >            (letmap dict# ~body)
>>> >            (match ~data (next (next ~clauses
>>>
>>> > Any help is appreciated. Also pointers to documents and books where I
>>> > can
>>> > learn more about macros.
>>>
>>> > 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: Newbie macro problems

2009-07-08 Thread Jonas Enlund

1. Ok, I'll consider that.

2. Yes, I'll post a link when I have uploaded the code somewhere.

3. It has not yet arrived

4. No. I have two sources of inspiration. Pattern matching in PLT
Scheme and this link:
http://groups.csail.mit.edu/mac/users/gjs/6.945/psets/ps05/ps.txt
(which is almost SICP as it is written by Sussman)

On Wed, Jul 8, 2009 at 7:15 PM, Sean Devlin wrote:
>
> 4.  Is this example from SICP?
>
> On Jul 8, 12:12 pm, Sean Devlin  wrote:
>> This seems like a good use for a macro.  A couple of thoughts:
>>
>> 1.  Use arrays instead of lists
>> In clojure, it is "best practice" to use arrays for data.  So, your
>> macro call should look like this.
>>
>> (match [1 2 3]
>>        [1 x]   (+ x x)
>>        [1 x y] (+ x y))
>>
>> 2.  Could you post the source to match maker?  That would help my play
>> around in a REPL
>>
>> 3.  As for books go, get yourself a copy of "Programming Clojure" by
>> Stuart Holloway
>>
>> Sean
>>
>> On Jul 8, 11:42 am, Jonas  wrote:
>>
>> > Hi.
>>
>> > I'm developing a simple pattern matching library for clojure but I am
>> > having
>> > trouble with macros (which I have almost zero experience with).
>>
>> > I have a function `make-matcher`
>>
>> > (make-matcher )
>>
>> > which returns a function that can pattern match on data and returns a
>> > map of bindings (or nil in case of a non-match).
>>
>> > ((make-matcher '(list x y z w)) (list 1 2 3 4))
>> > ; => {x 1 y 2 z 3 w 4}
>> > ((make-matcher '(list x y z x)) (list 1 2 3 4))
>> > ; => nil
>> > ((make-matcher '(list 1 x 2 _)) (list 1 2 3 4))
>> > ; => nil
>> > ((make-matcher '(list 1 x 2 _)) (list 1 3 2 9))
>> > ; => {x 3}
>>
>> > I have been trying to write the following 'match' macro:
>>
>> > (match 
>> >    
>> >    )
>>
>> > The macro should work like this:
>>
>> > (match (list 1 2 3)
>> >        (list 1 x)   (+ x x)
>> >        (list 1 x y) (+ x y))
>> > ; => 5
>>
>> > I have the following macros (none of which works correctly):
>>
>> > ; (letmap {a 1 b 2} (+ a b))
>> > ; =(should) expand to=>
>> > ; (let [a 1 b 2] (+ a b))
>> > (defmacro letmap [dict & body]
>> >   `(let ~(into [] (reduce concat (eval dict)))
>> >      (do ~...@body)))
>>
>> > ; (match (list 1 2 3)
>> > ;       (list 1 x)   (+ x x)
>> > ;       (list 1 x y) (+ x y))
>> > ; =should expand to something like=>
>> > ; (let [dict ( (list 1 2 3))]
>> > ;   (if dict
>> > ;      (letmap dict (+ 1 x))
>> > ;      (match (list 1 2 3) (list 1 x y) (+ x y
>> > (defmacro match [data & clauses]
>> >   (when clauses
>> >     (let [pattern    (first clauses)
>> >           body       (second clauses)
>> >           matcher (make-matcher pattern)]
>> >       `(let [dict# (~matcher ~data)]
>> >          (if dict#
>> >            (letmap dict# ~body)
>> >            (match ~data (next (next ~clauses
>>
>> > Any help is appreciated. Also pointers to documents and books where I
>> > can
>> > learn more about macros.
>>
>> > 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
-~--~~~~--~~--~--~---