Monad problems: finding an m-zero

2009-11-20 Thread samppi
I'm writing a maybe/state monad using clojure.contrib.monads. I've
gotten by fine with using just (state-t maybe-m), but now I need
different behavior:
  I need a monad that behaves precisely like (state-t maybe-m), except
that when a monadic value mv is called on a state s and fails, (mv s)
returns [::failure s] *instead of nil* (as maybe-m normally does).
This is the difference.

Now I'm basically done, except I can't figure out a value of m-zero
that fulfills the required axioms:
  - (m-bind m-zero f) produces m-zero
  - (m-bind mv (fn [x] m-zero)) produces m-zero

This is what I have so far:

  (defmonad parser-m
"The monad that FnParse uses."
[m-zero (fn [state] [::failure state])
 m-result (fn m-result-parser [product]
(fn [state] [product state]))
 m-bind (fn m-bind-parser [rule product-fn]
  (fn [state]
(let [result (rule state)]
  (if (failure? result)
result
(let [[product new-state] result]
  ((product-fn product) new-state))
 m-plus (fn m-plus-parser [& rules]
  (fn [state]
(or (first (drop-while failure? (map #(% state)
rules)))
(m-zero state])

The first axiom is fulfilled:
user=> (def a (m-bind m-zero (constantly [5 [2 3]])))
#'user/a
user=> (a [0 1])
[:user/failure [0 1]]
user=> (m-zero [0 1])
[:user/failure [0 1]]

But the second is not:
user=> (def b (m-bind (constantly [:x [1 2]]) m-zero))
#'user/b
user=> (b [0 1])

And no matter what I do, I can't fulfill that second axiom. Has anyone
created this type of monad before? It seems like it should be a common
pattern: exactly like (state-t maybe-m), only failures are vector
pairs too.

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

2009-11-20 Thread Mark Engelberg
On Fri, Nov 20, 2009 at 8:02 PM, Mark Engelberg
 wrote:
> Dynamic binding is confusing, and should be used with care.

Elaborating on my previous point: it's especially confusing because
dynamic binding interacts poorly with lazy data structures, which is
predominantly what you deal with in Clojure.  If your lazy data
structure depends on something that is dynamically bound using
binding, there is a good chance it won't get evaluated until after you
exit the scope of the binding and the global variable is restored to
its earlier state, so your lazy data structure ends up not using the
value that was set with binding.  It can get messy fast.

There were a couple times I used dynamic binding, and I was really
excited about it.  I had never used a language with a dynamic binding
construct, and it seemed like a perfect fit for what I was doing.  I
was threading a couple of values through a bunch of mutually recursive
functions that generated a tree.  The values I was threading
controlled certain aspects of the tree generation.  I realized that by
making these generation parameters global values, and just wrapping
binding to set the parameters around the call to my tree generator, I
could avoid all these extra inputs on a whole slew of functions that
were just passing these parameters around so they'd be available in
the functions that really needed them.  But my tree generator used
laziness in some non-obvious places, and it took me a long time to
notice that when I didn't fully evaluate the tree right away, I was
getting very different results.  It was hard to track down the
problem, and ultimately I had to go back to threading all the
parameters through the functions explicitly.  The experience really
turned me off of dynamic binding in Clojure, since it has such a
strong laziness focus.

Which reminds me, every once in a while I see people talking about
this here, and brainstorming up some alternatives to binding that
might interact better with lazy data structures.  Has there been any
real progress on this, or has every proposed solution been equally
problematic?

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

2009-11-20 Thread Mark Engelberg
Conceptually, the best way to think about it is that your binding sets
the global x to 100 and restores the global x to 1 when exiting the
scope of the binding construct.  It has no effect on your local x.

Dynamic binding is confusing, and should be used with care.  If you
stick with the lexical scoping of function closures and lets, things
should behave the way you expect.

--Mark

On Fri, Nov 20, 2009 at 7:40 PM, kunjaan  wrote:
> Even though I have used Clojure, I hadn't looked at the scoping rules
> in detail. I am getting more confused as I read the documentations. I
> made a small test to try out the scoping resolutions and am apalled at
> the complexity. Could somebody explain the intent and various rules
> that Clojure uses?
>
> (def x 1)
>
> (defn dummy-fn2[]
>    (+ x 1))
>
> (defn dummy-fn[]
>    (println "entering function: " x)
>      (let [x 100]
>         (println "after let: " x)
>         (let [x (dummy-fn2)]
>            (println "after let and dummy2: " x)
>            (binding [x 100]
>             (println "after binding: " x)
>             (let [x (dummy-fn2)]
>               (println "after binding and dummy2: " x))
>
> 1:2 foo=> (dummy-fn)
> entering function:  1
> after let:  100
> after let and dummy2:  2
> after binding:  2
> after binding and dummy2:  101
> 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

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


Clojure Scoping Rules

2009-11-20 Thread kunjaan
Even though I have used Clojure, I hadn't looked at the scoping rules
in detail. I am getting more confused as I read the documentations. I
made a small test to try out the scoping resolutions and am apalled at
the complexity. Could somebody explain the intent and various rules
that Clojure uses?

(def x 1)

(defn dummy-fn2[]
(+ x 1))

(defn dummy-fn[]
(println "entering function: " x)
  (let [x 100]
 (println "after let: " x)
 (let [x (dummy-fn2)]
(println "after let and dummy2: " x)
(binding [x 100]
 (println "after binding: " x)
 (let [x (dummy-fn2)]
   (println "after binding and dummy2: " x))

1:2 foo=> (dummy-fn)
entering function:  1
after let:  100
after let and dummy2:  2
after binding:  2
after binding and dummy2:  101
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: "Oh, yeah, transients are fast!"

2009-11-20 Thread John Harrop
On Fri, Nov 20, 2009 at 5:16 PM, Raoul Duke  wrote:

> > Try with a 1.6 JVM...
>
> wow. it actually got worse than when i was using 1.5. ... so much for
> hallowed write-once-run-the-same-anywhere-ish of the jvm, d'oh.
>
> Clojure 1.1.0-alpha-SNAPSHOT
> user=> (load-file "/tmp/test.clj")
> #'user/vrange2
> user=> (. System getProperty "java.version")
> "1.6.0_15"
> user=> (time (def v2 (vrange2 100)))
> "Elapsed time: 329.906 msecs"
> #'user/v2
> user=> (time (def v2 (vrange2 100)))
> "Elapsed time: 888.734 msecs"
> #'user/v2
> user=> (time (def v2 (vrange2 100)))
> "Elapsed time: 546.982 msecs"
> #'user/v2
> user=> (time (def v2 (vrange2 100)))
> "Elapsed time: 517.969 msecs"
> #'user/v2
> user=> (time (def v (vrange 100)))
> "Elapsed time: 1649.449 msecs"
> #'user/v
> user=> (time (def v (vrange 100)))
> --- never came back, i had to ^C^C (in emacs buffer)!!


You've got some kind of system problem confounding your results, I'll bet.
It got slower? One test actually hung?

My suspicion, of course, lies with the emacs environment you've just
confessed to using. Half the traffic on this list at times is from people
having problems with configuring either emacs or vi to work well with
Clojure.

Try it in a modern IDE, or from the command line, and see if the problem
goes away. If it does, then you know the likely culprit and it isn't
Clojure's transients. :)

-- 
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: tree-shaking a jarred Clojure app?

2009-11-20 Thread John Harrop
On Fri, Nov 20, 2009 at 2:28 PM, Richard Newman  wrote:

> > But I should be able to know, through class inspection, whether my
> > 'main' program depends on a class which uses, say, the clojure.zip
> > namespace, and decide whether or not to include it. Or so I am
> > wondering.
>
> There are impediments to that, too -- your namespace might require
> another, and so on, and your namespace can refer to symbols further
> down the chain without itself including the necessary `require` form.
>

There's the possibility of a macro expanding to a nonobvious require or use
form. Also of "eval" being used. Even in the Java world, class names that
get dynamically loaded sometimes come from XML files rather than being in
the Java source anywhere.

But there is an alternative to static analysis, at least in theory. One
could, in principle, run one's new app or servlet or whatever on a JVM with
a modified class-loading infrastructure set up to log all loaded classes,
then put it through its paces in typical usage scenarios and the anticipated
atypical situations. If you have good test coverage, you could simply run
the test suite with class-loading logging enabled, and make any appropriate
substitutions of real classes (and their dependencies) for mock-object
classes. Or if the tests don't use any mock objects in really obscure cases
whose real counterparts aren't also used in the typical situation, just log
a normal run and a run through the test suite and dump all the mock object
classes and test-harness classes.

Sun probably provides debug tools that can log classes loaded on a JVM
session, so everything needed for this is in theory available off-the-shelf.

End product: a list of every used class. At least in theory.

-- 
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: Weird Java Interop Behaviour

2009-11-20 Thread Alex Osborne
Matt Brown wrote:

> Why does (. System getProperty "java.version") work when
> (. (identity System) getProperty "java.version") does not work, given
> that
> (identity System) should be the same as System ?

It's because the . special form treats class names specially.  In Java 
there's unfortunately a difference between instances of the 
java.lang.Class object and the class itself.  So:

Clojure: (. System getProperty "java.version")
Java: System.getProperty("java.version");

While:

Clojure: (. (identity System) getProperty "java.version") ; error!
Java: System.class.getProperty("java.version"); // error!

But if you call a method that exists on a java.lang.Class object it's okay:

(. (identity System) getMethods)

It's preferred style in Clojure to use this form to access static 
methods and fields as it prevents this sort of confusion:

   (System/getProperty "java.version")

-- 
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: Weird Java Interop Behaviour

2009-11-20 Thread Mike Hinchey
It's the . special form that makes the difference.  In (. System
(getProperty)), the dot interprets System as a class and looks for a static
method (at read/compile time).  With (identity System), System resolves to a
value, a Class object, returned by identity, then your outside dot looks for
a getProperty instance method on that object(fallback to reflection, which
fails) - it's like writing System.class.getProperty in java.  There is no
syntax for clojure to lookup a static method on a dynamically resolved class
object because that is inherently reflection - dot is not about reflection,
though it will do it as a last resort.

Hope that helps.

-Mike

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

Weird Java Interop Behaviour

2009-11-20 Thread Matt Brown
Hi.

I can't find the answer to this anywhere. (It seems it should be
posted somewhere already ...)

This works:
(. System getProperty "java.version")
  -> "1.6.0_15"

This does not work:
(. (identity System) getProperty "java.version")
  -> java.lang.IllegalArgumentException: No matching method found:
getProperty for class java.lang.Class (NO_SOURCE_FILE:0)

BUT (identity System) returns System as we see here:
(.equals (identity System) System)
  -> true

Why does (. System getProperty "java.version") work when
(. (identity System) getProperty "java.version") does not work, given
that
(identity System) should be the same as System ?

Thanks for any insight here!
Matt

-- 
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: ANN: Clojuratica v2 -- Seamless Mathematica-within-Clojure!

2009-11-20 Thread Garth Sheldon-Coulson
P.S. I have been told that Clojuratica works with the free Mathematica
Player. I haven't tried this myself.

On Fri, Nov 20, 2009 at 5:57 PM, Garth Sheldon-Coulson  wrote:

> Dear Clojurians,
>
> I am very happy to announce Clojuratica version 2.
>
> Clojuratica now offers the **syntactic** integration of Clojure and
> Mathematica.
>
> What does this mean? It means you can write Clojure code that looks like
> this:
>
> => (FactorInteger 12345)
> [[3 1] [5 1] [823 1]]
>
> You guessed it. FactorInteger is a Mathematica function. And that's a
> Clojure REPL.
>
> Symbolic math in Clojure? Syntax-unquoting to feed in Clojure data
> structures? Absolutely.
>
> => (Sqrt (* 9 a))
> (* 3 (Power a 1/2))
>
> => (let [x [[2 1] [1 2]]]
>  (CholeskyDecomposition ~x))
> [[(Power 2 1/2) (Power 2 -1/2)] [0 (Power 3/2 1/2)]]
>
> Note that the Clojure "matrix" (vector of vectors) is converted on the fly
> to a Mathematica matrix, and vice versa. Automatic conversions take place
> for all Clojure and Mathematica data structures.
>
> There's more. Mathematica functions are now Clojure functions. The
> following is a Mathematica function written in Clojure that finds the n
> shortest genes in the human genome. (Mathematica has some cool functions
> like GenomeData to try out.)
>
> => (Function [n]
>  (Take
>(Sort
>  (Map
>   (Function [gene] [(GenomeData gene "SequenceLength") gene])
>(GenomeData)))
>n))
> # 1234 clojuratica.base.parse$parse_fn__1230$fn__1...@19fa0b5>
>
> What's that ugly return value? It's a first-class Clojure function. We
> evaluated a Mathematica function in Clojure and got back a Clojure function
> which, when we call it, hands off the computation to Mathematica and returns
> the result:
>
> => (*1 4)
> [[11 "IGHD727"] [16 "IGHD411"] [16 "IGHD417"] [16 "IGHD44"]]
>
> All the power of Mathematica is now seamlessly available in Clojure. If you
> like, you can think of Mathematica as a particularly mature Clojure library
> for linear algebra, matrix decomposition, symbolic mathematics,
> optimization, differential equations, symbolic and numerical integration,
> Fourier analysis, 2D and 3D visualization, image and photo manipulation,
> exploratory data analysis, probability and statistics, graph theory, number
> theory, geodesy, and access to the Wolfram Research internet data feeds on
> finance, chemistry, geometry, meteorology, astronomy, protein structure,
> and, as we've seen, the human genome.
>
> Let's take a step back and see how it all works.
>
> Observe: Clojure and Mathematica are remarkably similar languages despite
> their different areas of strength.
>
> Constant-lookup arrays:
>
> Clj vectors:  [1 2 3]
> Mma lists:{1, 2, 3}
>
> Matrices as nested arrays:
>
> Clj:  [[1 0] [0 1]]
> Mma:  {{1, 0}, {0, 1}}
>
> Function calls *always* use prefix notation:
>
> Clj:  (func arg1 arg2 arg3)
> Mma:  Func[arg1, arg2, arg3]
>
> In Mathematica, common functions do have syntactic sugar, but it always is
> just syntactic sugar:
>
> Clj:  none
> Mma:  1 + 1   is just   Plus[1, 1]
>   !foo && (bar > baz)   is just   And[Not[foo], Greater[bar, baz]]
>
> Homoiconicity:
>
> Clj:  (nth '(func arg1 arg2) 1)   ==>   arg1
> Mma:  Part[Func[arg1, arg2], 1]   ==>   arg1
>
> The similarities suggest the core idea: Mathematica expressions can be
> written as Clojure expressions without any loss of information, and vice
> versa. There is perfect correspondence. Happily, Mathematica functions are
> PascalCase by convention. This allows the interning of Mathematica functions
> right into your Clojure namespace without conflict.
>
> Mma:  FactorInteger[1091]
> Clj:  (FactorInteger 1091)
>
> Mma:  Function[{x}, x + 1]
> Clj:  (Function [x] (Plus x 1))
>
> The heart of Clojuratica is simple. Convert Clojure expressions to
> Mathematica expressions, evaluate them in Mathematica, and parse the result
> back into Clojure expressions.
>
> As you will see in the tutorial on the Clojuratica web page <
> http://clojuratica.weebly.com>, you are not forced to intern Mathematica
> functions directly into your namespace. You may, but you do not have to. The
> generic way to call Mathematica code is using the math macro (which you
> yourself define, so it need not be called "math"):
>
> => (let [x "World"]
>  (math (StringJoin "Hello, " ~x "! This is some Mathematica code's
> output.")))
> "Hello, World! This is some Mathematica code's output."
>
> => (def hello
>  (math
>(Function [x]
>  (StringJoin "Hello, " x "! This is a Mathematica function's
> output."
> #'user/hello
>
> => (hello "World")
> "Hello, World! This is a Mathematica function's output."
>
> There are other features, too:
>
> * A concurrency framework for multithreaded, parallel computation.
> Mathematica is not designed for threads or concurrency. It has excellent
> support for parallel computation, but parallel evaultions are initiated from
> a single-threaded master kernel whic

ANN: Clojuratica v2 -- Seamless Mathematica-within-Clojure!

2009-11-20 Thread Garth Sheldon-Coulson
Dear Clojurians,

I am very happy to announce Clojuratica version 2.

Clojuratica now offers the **syntactic** integration of Clojure and
Mathematica.

What does this mean? It means you can write Clojure code that looks like
this:

=> (FactorInteger 12345)
[[3 1] [5 1] [823 1]]

You guessed it. FactorInteger is a Mathematica function. And that's a
Clojure REPL.

Symbolic math in Clojure? Syntax-unquoting to feed in Clojure data
structures? Absolutely.

=> (Sqrt (* 9 a))
(* 3 (Power a 1/2))

=> (let [x [[2 1] [1 2]]]
 (CholeskyDecomposition ~x))
[[(Power 2 1/2) (Power 2 -1/2)] [0 (Power 3/2 1/2)]]

Note that the Clojure "matrix" (vector of vectors) is converted on the fly
to a Mathematica matrix, and vice versa. Automatic conversions take place
for all Clojure and Mathematica data structures.

There's more. Mathematica functions are now Clojure functions. The following
is a Mathematica function written in Clojure that finds the n shortest genes
in the human genome. (Mathematica has some cool functions like GenomeData to
try out.)

=> (Function [n]
 (Take
   (Sort
 (Map
  (Function [gene] [(GenomeData gene "SequenceLength") gene])
   (GenomeData)))
   n))
#

What's that ugly return value? It's a first-class Clojure function. We
evaluated a Mathematica function in Clojure and got back a Clojure function
which, when we call it, hands off the computation to Mathematica and returns
the result:

=> (*1 4)
[[11 "IGHD727"] [16 "IGHD411"] [16 "IGHD417"] [16 "IGHD44"]]

All the power of Mathematica is now seamlessly available in Clojure. If you
like, you can think of Mathematica as a particularly mature Clojure library
for linear algebra, matrix decomposition, symbolic mathematics,
optimization, differential equations, symbolic and numerical integration,
Fourier analysis, 2D and 3D visualization, image and photo manipulation,
exploratory data analysis, probability and statistics, graph theory, number
theory, geodesy, and access to the Wolfram Research internet data feeds on
finance, chemistry, geometry, meteorology, astronomy, protein structure,
and, as we've seen, the human genome.

Let's take a step back and see how it all works.

Observe: Clojure and Mathematica are remarkably similar languages despite
their different areas of strength.

Constant-lookup arrays:

Clj vectors:  [1 2 3]
Mma lists:{1, 2, 3}

Matrices as nested arrays:

Clj:  [[1 0] [0 1]]
Mma:  {{1, 0}, {0, 1}}

Function calls *always* use prefix notation:

Clj:  (func arg1 arg2 arg3)
Mma:  Func[arg1, arg2, arg3]

In Mathematica, common functions do have syntactic sugar, but it always is
just syntactic sugar:

Clj:  none
Mma:  1 + 1   is just   Plus[1, 1]
  !foo && (bar > baz)   is just   And[Not[foo], Greater[bar, baz]]

Homoiconicity:

Clj:  (nth '(func arg1 arg2) 1)   ==>   arg1
Mma:  Part[Func[arg1, arg2], 1]   ==>   arg1

The similarities suggest the core idea: Mathematica expressions can be
written as Clojure expressions without any loss of information, and vice
versa. There is perfect correspondence. Happily, Mathematica functions are
PascalCase by convention. This allows the interning of Mathematica functions
right into your Clojure namespace without conflict.

Mma:  FactorInteger[1091]
Clj:  (FactorInteger 1091)

Mma:  Function[{x}, x + 1]
Clj:  (Function [x] (Plus x 1))

The heart of Clojuratica is simple. Convert Clojure expressions to
Mathematica expressions, evaluate them in Mathematica, and parse the result
back into Clojure expressions.

As you will see in the tutorial on the Clojuratica web page <
http://clojuratica.weebly.com>, you are not forced to intern Mathematica
functions directly into your namespace. You may, but you do not have to. The
generic way to call Mathematica code is using the math macro (which you
yourself define, so it need not be called "math"):

=> (let [x "World"]
 (math (StringJoin "Hello, " ~x "! This is some Mathematica code's
output.")))
"Hello, World! This is some Mathematica code's output."

=> (def hello
 (math
   (Function [x]
 (StringJoin "Hello, " x "! This is a Mathematica function's
output."
#'user/hello

=> (hello "World")
"Hello, World! This is a Mathematica function's output."

There are other features, too:

* A concurrency framework for multithreaded, parallel computation.
Mathematica is not designed for threads or concurrency. It has excellent
support for parallel computation, but parallel evaultions are initiated from
a single-threaded master kernel which blocks until all parallel evaluations
return. By contrast, Clojuratica includes a concurrency framework that lets
multiple Clojure threads execute Mathematica expressions without blocking
others. The computations will be farmed out to as many Mathematica kernels
as are parallelized on the local machine or across a cluster or grid. The
computations will return asynchronously, and some threads will go about
their business while others continue to wait. I have worked t

Re: repeatedly forcing the evaluation of a lazy seq

2009-11-20 Thread ataggart
The sequence returned from the filter would need to be rescanned to
get the nth element, but the filtering itself should only need to
happen when the "next" element in the sequence is sought.

For cases such as the one you describe, I think it's common to fully
realize the sequence into a vector, e.g. (vec (filter ...)) to avoid
rescanning.



On Nov 20, 5:00 am, bOR_  wrote:
> Hi all,
>
> Just ran into a small gotcha: I had an atom which contained a lazyseq
> (e.g. (filter males world)). Later on I would be repeatedly calling
> random elements from this atom, using clojure contrib rand-elt. That
> was surprisingly slow. I figured out that count was the culprit.
> Apparently, the lazyseq atom stayed a lazyseq atom (immutability), and
> each time I called for a random element, count had to do the whole
> filtering to figure out 'count'.
>
> Is there any way that I can get a warning printed out that would let
> me know when I am doing something stupid like this? for example:
> (repeatedly evaluating identical full lazy sequence @world)?

-- 
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: "Oh, yeah, transients are fast!"

2009-11-20 Thread Raoul Duke
> user=> (time (def v (vrange 100)))
> --- never came back, i had to ^C^C (in emacs buffer)!!

p.s. so at least the transient version never did that ;-)

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
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: "Oh, yeah, transients are fast!"

2009-11-20 Thread Raoul Duke
> Try with a 1.6 JVM...

wow. it actually got worse than when i was using 1.5. ... so much for
hallowed write-once-run-the-same-anywhere-ish of the jvm, d'oh.

Clojure 1.1.0-alpha-SNAPSHOT
user=> (load-file "/tmp/test.clj")
#'user/vrange2
user=> (. System getProperty "java.version")
"1.6.0_15"
user=> (time (def v2 (vrange2 100)))
"Elapsed time: 329.906 msecs"
#'user/v2
user=> (time (def v2 (vrange2 100)))
"Elapsed time: 888.734 msecs"
#'user/v2
user=> (time (def v2 (vrange2 100)))
"Elapsed time: 546.982 msecs"
#'user/v2
user=> (time (def v2 (vrange2 100)))
"Elapsed time: 517.969 msecs"
#'user/v2
user=> (time (def v (vrange 100)))
"Elapsed time: 1649.449 msecs"
#'user/v
user=> (time (def v (vrange 100)))
--- never came back, i had to ^C^C (in emacs buffer)!!

-- 
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-20 Thread Krukow


On Nov 20, 8:51 pm, Chouser  wrote:
> On Thu, Nov 19, 2009 at 12:39 PM, Krukow  wrote:
[snip]
> > I guess I am just asking if the performance guarantees are those I
> > would expect of Clojure (i.e., "too fast" ;-))
>
> This is definitely still too fast.  In fact, it keeps getting worse.
>
> --Chouser

We gotta stop him ;-)

No, more seriously, I really like these new features. Not just for the
speed, but for the modeling support.

I'm wondering if I could get some feed-back on a defprotocol/deftype
example. I am wondering if I am thinking "too object oriented" here
and misusing the features, or if I am inline with the intended use of
protocols and types.

The example code is a "Circuit Breaker" (the stability pattern
mentioned in Michael Nygaard's "Release It!").

Code:
Circuit breaker states and transitions
http://gist.github.com/239797


Circuit breaker
http://gist.github.com/239798

Git repository:
http://github.com/krukow/clojure-circuit-breaker

The circuit breaker has a wrap function that takes another function
and returns a wrapped version of that function that uses the circuit
breaker. Right now there is only one circuit breaker instance, but
that's easy to generalize.

Feedback very welcome!

/Karl

-- 
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-20 Thread Chouser
On Thu, Nov 19, 2009 at 12:39 PM, Krukow  wrote:
> On Nov 19, 12:01 am, samppi  wrote:
>> Question: are the general mechanisms for accessing and setting fields
>> their keywords and assoc respectively:
>>   (deftype Bar [a b c d e])
>>   (def b (Bar 1 2 3 4 5))
>>   (:c b)
>>   (def c (assoc b :e 2))
>> Does (:c b) and (assoc b :e 2) take advantage of Bar's field
>> information? Is it any faster than using an array map? Are there any
>> equivalents to struct maps' accessor functions?

My understanding is that if you have (:c b) somewhere in your
code, and "b" is always an object of the same deftype with
a field "c", you're getting Java field-speed access (once hotspot
has done what it does).  Yes, that's faster than array map
lookup.  It's even faster than struct map accessor function lookup.

> You can use the ability to implement interfaces, specifically
> automatic support for IPersistentMap:
>
> ser=> (deftype Bar [a b] [clojure.lang.IPersistentMap])
> #'user/Bar
> user=> (assoc (Bar 1 2) :a 42)
> #:Bar{:a 42, :b 2}
> user=>
>
> I have a question here, though: what is this?
>
> ser=> (assoc (Bar 1 2) :c 42)
> #:Bar{:a 1, :b 2, :c 42}
> user=> #:Bar{:a 1, :b 2, :c 42}
>
> Is it a "Bar" with field-speed access to :a and :b and map-speed
> access to :c?

Yes, I think that's correct.

> Also can I assume that
>
> (assoc (Bar 1 2) :a 42)
> #:Bar{:a 42, :b 2}
>
> will share structure with the (Bar 1 2) and still has fast access
> to :a? Is the assoc function using that :a is a field?

There will be no shared structure between your two Bar object.
That is, the reference to 2 (or the value 2 itself if it were
a primitive) will be copied to the new object.

> I guess I am just asking if the performance guarantees are those I
> would expect of Clojure (i.e., "too fast" ;-))

This is definitely still too fast.  In fact, it keeps getting worse.

--Chouser

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
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: tree-shaking a jarred Clojure app?

2009-11-20 Thread Graham Fawcett
On Fri, Nov 20, 2009 at 2:28 PM, Richard Newman  wrote:
>> I suppose a better question might be: would a tree-shaker have a
>> reasonable chance of shaking a typical Clojure jar, or are there too
>> many dynamic obstacles to a good analysis.
>
> I'm not sure it's worth solving this through low-level analysis. Far
> better, IMO, is to rely on correct descriptors and namespace
> definitions -- convention and configuration can save the day. If you
> can sweep the hard parts under the proverbial rug, the rest can be
> solved in a handful of lines of code!

That's a great point.

Thanks Richard and Jim for your thoughts!

Best,
Graham

-- 
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: tree-shaking a jarred Clojure app?

2009-11-20 Thread Richard Newman
> But I should be able to know, through class inspection, whether my
> 'main' program depends on a class which uses, say, the clojure.zip
> namespace, and decide whether or not to include it. Or so I am
> wondering.

There are impediments to that, too -- your namespace might require  
another, and so on, and your namespace can refer to symbols further  
down the chain without itself including the necessary `require` form.

If you had the entire classpath available, and were willing to  
transitively examine the entire tree (probably including code-walking)  
then you might be able to solve this problem... but as soon as you hit  
a call to `read` where *read-eval* is not known to be false, or a call  
to `eval`, or maybe even some uses of reflection, you have to give up.

Furthermore, some code adjusts itself at compile-time according to its  
environment (e.g., clojure.contrib.logging, which generates different  
functions depending on which logging libraries are available). That's  
not very amenable to static analysis.

> I suppose a better question might be: would a tree-shaker have a
> reasonable chance of shaking a typical Clojure jar, or are there too
> many dynamic obstacles to a good analysis.

I'm not sure it's worth solving this through low-level analysis. Far  
better, IMO, is to rely on correct descriptors and namespace  
definitions -- convention and configuration can save the day. If you  
can sweep the hard parts under the proverbial rug, the rest can be  
solved in a handful of lines of code!

-- 
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: tree-shaking a jarred Clojure app?

2009-11-20 Thread Graham Fawcett
On Fri, Nov 20, 2009 at 1:37 PM, Jim Downing  wrote:
> Hi Graham
>
> 2009/11/20 Graham Fawcett :
>> Hi folks,
>>
>> This is somewhat a Java question, but it's in the context of Clojure,
>> so here goes. Playing with Leiningen got me thinking about bundling a
>> Clojure application as a JAR, which might include a host of classes
>> that are loaded but never used. Is it possible to "tree-shake" such a
>> jarfile, and eliminate any classes that are not required for the
>> main-class' operation? (Assuming the program doesn't need 'eval' with
>> access to all of those classes at runtime.)
>>
>> This might not save a lot of startup time, but where startup time
>> matters, maybe it might shave off a meaningful fraction. I'm just
>> curious whether there is enough dependency information in a set of
>> class files to calculate a tree-shaking plan; and whether there are
>> existing tools to do the job.
>
> I might have misunderstood, but isn't the problem the same as in Java;
> you can't know from a static analysis which classes are going to be
> loaded?

If it's not possible in Java, then yes, it wouldn't be any different
in Clojure. But after an admittedly casual search, I don't know what
the specific blockers are to tree-shaking in Java.

I know there are dynamic load-class-by-name facilities in the JVM, and
of course that would be a barrier for static analysis. I've only ever
seen these called with literal strings, though (e.g. in setting a JDBC
driver), and that could be statically analyzed.

But I should be able to know, through class inspection, whether my
'main' program depends on a class which uses, say, the clojure.zip
namespace, and decide whether or not to include it. Or so I am
wondering.

I suppose a better question might be: would a tree-shaker have a
reasonable chance of shaking a typical Clojure jar, or are there too
many dynamic obstacles to a good analysis.

Just curious,
Graham


>
> Best regards,
>
> jim
>
> --
> 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: [ANN] Clojars - a Clojure community jar repository

2009-11-20 Thread Phil Hagelberg
Alex Osborne  writes:

> I looks like Maven does this, it puts two files in the jar:
>
> META-INF/maven/$groupId/$artifactId/pom.xml
> META-INF/maven/$groupId/$artifactId/pom.properties
>
> So it looks like you can use that to figure out what version a library 
> is just using the java properties system.  We should make Leiningen do 
> the same.

This is a solid idea; I will target it for leiningen 1.0.

-Phil

-- 
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: leiningen - a Clojure build tool

2009-11-20 Thread Phil Hagelberg
Sean Devlin  writes:

> Something tells me we'll just be calling it 'lein'.  Is that okay
> Phil?

Yeah, there's a reason the bin script is called "lein"... I was
misspelling it myself for the first few days of working on it. =)

-Phil

-- 
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: tree-shaking a jarred Clojure app?

2009-11-20 Thread Jim Downing
Hi Graham

2009/11/20 Graham Fawcett :
> Hi folks,
>
> This is somewhat a Java question, but it's in the context of Clojure,
> so here goes. Playing with Leiningen got me thinking about bundling a
> Clojure application as a JAR, which might include a host of classes
> that are loaded but never used. Is it possible to "tree-shake" such a
> jarfile, and eliminate any classes that are not required for the
> main-class' operation? (Assuming the program doesn't need 'eval' with
> access to all of those classes at runtime.)
>
> This might not save a lot of startup time, but where startup time
> matters, maybe it might shave off a meaningful fraction. I'm just
> curious whether there is enough dependency information in a set of
> class files to calculate a tree-shaking plan; and whether there are
> existing tools to do the job.

I might have misunderstood, but isn't the problem the same as in Java;
you can't know from a static analysis which classes are going to be
loaded?

Best regards,

jim

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


tree-shaking a jarred Clojure app?

2009-11-20 Thread Graham Fawcett
Hi folks,

This is somewhat a Java question, but it's in the context of Clojure,
so here goes. Playing with Leiningen got me thinking about bundling a
Clojure application as a JAR, which might include a host of classes
that are loaded but never used. Is it possible to "tree-shake" such a
jarfile, and eliminate any classes that are not required for the
main-class' operation? (Assuming the program doesn't need 'eval' with
access to all of those classes at runtime.)

This might not save a lot of startup time, but where startup time
matters, maybe it might shave off a meaningful fraction. I'm just
curious whether there is enough dependency information in a set of
class files to calculate a tree-shaking plan; and whether there are
existing tools to do the job.

Best,
Graham

-- 
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: take repeatedly alternative?

2009-11-20 Thread Raoul Duke
as an aside, sometimes you want the rng to be truly pure so you can
easily recreate situations. take a look at randomness in haskell for
fun. :-)

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


clojure-jsr223

2009-11-20 Thread Armando Blancas
Without knowing of Niels Mayer's work (until just now) I wrote an
implementation of the Java Scripting API for Clojure --and even named
it the same. Indeed great minds think alike. Though I didn't think of
isolating the runtime in different instances of the engine.

The distribution ZIP file has the clojure-jsr223.jar that goes alog
with clojure.jar, the javadoc, sources and samples. You may get it
here:
http://code.google.com/p/clojure-jsr223/downloads/list

You can run code, set bindings, call functions, get interface
implementations, compile libs, and get some info from the factory. The
engine will redirect in/out/err according to what's in the
SimpleScriptContext argument, whose defaults have no effect on the RT.

I hope this will be useful. I'll check-in the source in google code as
soon as they resolve some issue with the repository.

Will appreciate suggestions on how to better do the work of wrapping
the RT. For example, to get an implementation of a Java interface, the
library requires that something like this has bee previously
evaluated:
...
(def ActionListenerImpl
  (proxy [ActionListener] []
(actionPerformed [evt]
  (println \"button pushed\"

and then you do:
...
button.addActionListener(invoke.getInterface(ActionListener.class));

So with this convention, the library looks for a var named after the
required interface plus the Impl suffix. (Or invoke.getInterface
("other.ns", ActionListener.class) if it's in a namespace other than
user.) Why a var and not a function? I'm not so sure why now; it may
was well be a function. I guess I thought it'd help to make it a bit
different than your other functions.

Here's some sample from the JDK but changed for Clojure:

ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("Clojure");

engine.eval("(println \"Hello, World\")");
engine.eval(new java.io.FileReader("code.clj");

String script = "(defn hello [name] (println \"Hello\" name))";
engine.eval(script);
Invocable inv = (Invocable) engine;
inv.invokeFunction("hello", "Scripting!!" );

File f = new File("samples/jsr223/ScriptVars.java");
engine.put("file", f);
engine.eval("(println (.getAbsolutePath file))");

engine.eval(
"(import java.awt.event.ActionListener)" +
"  (def ActionListenerImpl " +
"(proxy [ActionListener] []" +
"  (actionPerformed [evt]  " +
"(println \"button pushed\"");

Invocable invoke = (Invocable) engine;

JFrame frame = new JFrame();
JButton button = new JButton("Push");
button.addActionListener(invoke.getInterface(ActionListener.class));
frame.getContentPane().add(button);
frame.pack();
frame.setVisible(true);

Compilable compile = (Compilable) engine;
compile.compile("reader.snake");

-- 
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 macro for flexible keyword argument handling

2009-11-20 Thread nchubrich
No, I'd rather not, but I have to take this in bite-size pieces.  I'm
still a bit of a noob at writing macros.  I want to make it so that
the user does not have to do anything aside from deal with the
argument lists directly, so that means writing different macros for
defn, letfn, defmethod, etc.  Might as well try this on for size \one
way first, and if nobody (including me) likes it, then there's no
reason to continue the crusade

-- 
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: [ANN] Clojars - a Clojure community jar repository

2009-11-20 Thread Laurent PETIT
FYI: http://www.infoq.com/news/2009/11/clojars-leiningen-clojure

2009/11/19 Alex Osborne :
> Laurent PETIT wrote:
>> Hello,
>>
>> Just an idea out of my head : could it be possible for the pom.xml to be
>> included in the jar, in the META-INF/ directory ?
>>
>> This would even further simplify the process, wouldn't it ? :)
>
> That's a great idea!  Can't believe it didn't occur to me. :-)
>
> I looks like Maven does this, it puts two files in the jar:
>
> META-INF/maven/$groupId/$artifactId/pom.xml
> META-INF/maven/$groupId/$artifactId/pom.properties
>
> pom.properties contains:
>
> version=1.0.0
> groupId=mygroup
> artifactId=myjar
>
> So it looks like you can use that to figure out what version a library
> is just using the java properties system.  We should make Leiningen do
> the same.
>
> 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

-- 
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: leiningen - a Clojure build tool

2009-11-20 Thread Laurent PETIT
FYI: http://www.infoq.com/news/2009/11/clojars-leiningen-clojure

2009/11/20 Sean Devlin :
> Something tells me we'll just be calling it 'lein'.  Is that okay
> Phil?
>
> Sean
>
> On Nov 20, 11:21 am, Graham Fawcett  wrote:
>> On Fri, Nov 20, 2009 at 11:11 AM, Sean Devlin  
>> wrote:
>> > The Incanter guys put something up:
>>
>> >http://incanter-blog.org/2009/11/20/leiningen-clojars/
>>
>> Excellent, thanks!
>>
>> Leiningen + Clojars is a game-changer for Clojure. I'm very excited.
>>
>> Will-need-to-practice-spelling-leiningen'ly yours,
>> Graham
>>
>>
>>
>> > On Nov 20, 11:06 am, Graham Fawcett  wrote:
>> >> On Wed, Nov 18, 2009 at 2:29 AM, Phil Hagelberg  wrote:
>>
>> >> > With Leiningen, your build is described using Clojure. You can put any
>> >> > code you like in your project.clj file; the only requirement is that
>> >> > it includes a call to defproject. You can define your own tasks in
>> >> > there if you need to, but the majority of projects should be able to
>> >> > get by on the tasks that are provided with Leiningen. If you do find a
>> >> > common task that you need to add, you can implement it as a plugin
>> >> > rather than copying and pasting among each of your projects.
>>
>> >> This is outstanding; thank you!
>>
>> >> I'd love to see a short recipe on how to deploy a simple application
>> >> (hello-world) into an executable jar using Leiningen. I've tried, but
>> >> seem to be messing something up.
>>
>> >> Best,
>> >> Graham
>>
>> > --
>> > 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

-- 
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: leiningen - a Clojure build tool

2009-11-20 Thread Sean Devlin
Something tells me we'll just be calling it 'lein'.  Is that okay
Phil?

Sean

On Nov 20, 11:21 am, Graham Fawcett  wrote:
> On Fri, Nov 20, 2009 at 11:11 AM, Sean Devlin  
> wrote:
> > The Incanter guys put something up:
>
> >http://incanter-blog.org/2009/11/20/leiningen-clojars/
>
> Excellent, thanks!
>
> Leiningen + Clojars is a game-changer for Clojure. I'm very excited.
>
> Will-need-to-practice-spelling-leiningen'ly yours,
> Graham
>
>
>
> > On Nov 20, 11:06 am, Graham Fawcett  wrote:
> >> On Wed, Nov 18, 2009 at 2:29 AM, Phil Hagelberg  wrote:
>
> >> > With Leiningen, your build is described using Clojure. You can put any
> >> > code you like in your project.clj file; the only requirement is that
> >> > it includes a call to defproject. You can define your own tasks in
> >> > there if you need to, but the majority of projects should be able to
> >> > get by on the tasks that are provided with Leiningen. If you do find a
> >> > common task that you need to add, you can implement it as a plugin
> >> > rather than copying and pasting among each of your projects.
>
> >> This is outstanding; thank you!
>
> >> I'd love to see a short recipe on how to deploy a simple application
> >> (hello-world) into an executable jar using Leiningen. I've tried, but
> >> seem to be messing something up.
>
> >> Best,
> >> Graham
>
> > --
> > 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: leiningen - a Clojure build tool

2009-11-20 Thread Graham Fawcett
On Fri, Nov 20, 2009 at 11:11 AM, Sean Devlin  wrote:
> The Incanter guys put something up:
>
> http://incanter-blog.org/2009/11/20/leiningen-clojars/

Excellent, thanks!

Leiningen + Clojars is a game-changer for Clojure. I'm very excited.

Will-need-to-practice-spelling-leiningen'ly yours,
Graham


>
> On Nov 20, 11:06 am, Graham Fawcett  wrote:
>> On Wed, Nov 18, 2009 at 2:29 AM, Phil Hagelberg  wrote:
>>
>> > With Leiningen, your build is described using Clojure. You can put any
>> > code you like in your project.clj file; the only requirement is that
>> > it includes a call to defproject. You can define your own tasks in
>> > there if you need to, but the majority of projects should be able to
>> > get by on the tasks that are provided with Leiningen. If you do find a
>> > common task that you need to add, you can implement it as a plugin
>> > rather than copying and pasting among each of your projects.
>>
>> This is outstanding; thank you!
>>
>> I'd love to see a short recipe on how to deploy a simple application
>> (hello-world) into an executable jar using Leiningen. I've tried, but
>> seem to be messing something up.
>>
>> Best,
>> Graham
>
> --
> 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: leiningen - a Clojure build tool

2009-11-20 Thread Sean Devlin
The Incanter guys put something up:

http://incanter-blog.org/2009/11/20/leiningen-clojars/

On Nov 20, 11:06 am, Graham Fawcett  wrote:
> On Wed, Nov 18, 2009 at 2:29 AM, Phil Hagelberg  wrote:
>
> > With Leiningen, your build is described using Clojure. You can put any
> > code you like in your project.clj file; the only requirement is that
> > it includes a call to defproject. You can define your own tasks in
> > there if you need to, but the majority of projects should be able to
> > get by on the tasks that are provided with Leiningen. If you do find a
> > common task that you need to add, you can implement it as a plugin
> > rather than copying and pasting among each of your projects.
>
> This is outstanding; thank you!
>
> I'd love to see a short recipe on how to deploy a simple application
> (hello-world) into an executable jar using Leiningen. I've tried, but
> seem to be messing something up.
>
> Best,
> Graham

-- 
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: [ANN] leiningen - a Clojure build tool

2009-11-20 Thread Graham Fawcett
On Wed, Nov 18, 2009 at 2:29 AM, Phil Hagelberg  wrote:
>
> With Leiningen, your build is described using Clojure. You can put any
> code you like in your project.clj file; the only requirement is that
> it includes a call to defproject. You can define your own tasks in
> there if you need to, but the majority of projects should be able to
> get by on the tasks that are provided with Leiningen. If you do find a
> common task that you need to add, you can implement it as a plugin
> rather than copying and pasting among each of your projects.

This is outstanding; thank you!

I'd love to see a short recipe on how to deploy a simple application
(hello-world) into an executable jar using Leiningen. I've tried, but
seem to be messing something up.

Best,
Graham

-- 
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 macro for flexible keyword argument handling

2009-11-20 Thread Constantine Vetoshev
On Nov 20, 8:33 am, nchubrich  wrote:
> I guess this is getting to be a pretty epic macro!  I figured it was
> worth inviting boos and/or cheers and suggestions before setting out...

Far be it from me to discourage making function invocation semantics
more flexible! Just one thing: you've been calling your macro
"defnsk", which makes it sound like a wrapper for the def form. Don't
leave defmethod, fn, letfn, and every other way of making a function
in the dust. :)

-- 
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: Suggestion: Add should_cache? flag to lazy-seq

2009-11-20 Thread Jarkko Oranen
On Nov 19, 11:52 am, Gabi  wrote:
> This would solve the "holding to the head" problem.
> Many times, lazy-seq would be used without the need to get the same
> cell twice.
> In this case, avoiding cashing would both enhance performance and more
> importantly would avoid OutOfMemoryError Exceptions like in:
>
> (def r (repeatedly #(rand)))
> (last r)
>
> So, something like:
> (defn lazy-seq [should_cache? &body] ..
> would be beneficial (I think :)

I can see how that would be useful in some cases, but I think it also
would break the contract for seqs. They are supposed to be persistent.
I think a stream abstraction was considered at one point, but scrapped
in favour of chunked seqs.

The solution is simply to avoid defining a global reference to a seq
that might grow without bounds. Instead, define a function and just
create a new seq every time you want fresh values.

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

2009-11-20 Thread nchubrich
If you think about it, the tower of sequence types is like this:

seq
 |
gathered seq
   /\
 multiset permutation

   \   /
set

The way to do the various options I pointed out is to mix types: the
keep-likes-with-likes would be (union  ).
take-away-all would be (difference  ), while take-
away-some would be (difference  ).

The problem is once you add seq on top, it gets a little defective, as
Alex pointed out.  (multiset ) is easy, as is (permutation
), but there's no unambiguous way of going from a seq to
a permutation or to a gathered seq.  The 'left' side of the tower is
much happier than the right.

It's also hard to sign an interpretation to all the combinations on
the tower; for instance, what is the union of two permutations?  This
needs a little TLC from a category theorist...

Nevertheless, this might be a good way of grouping functionalities
into an API.  The set API can be extended to all these types, and
branch into additional combination operators as it moves up the tower
(with really an infinite number for seqs).

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


Suggestion: Add should_cache? flag to lazy-seq

2009-11-20 Thread Gabi
This would solve the "holding to the head" problem.
Many times, lazy-seq would be used without the need to get the same
cell twice.
In this case, avoiding cashing would both enhance performance and more
importantly would avoid OutOfMemoryError Exceptions like in:

(def r (repeatedly #(rand)))
(last r)

So, something like:
(defn lazy-seq [should_cache? &body] ..
would be beneficial (I think :)

-- 
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 macro for flexible keyword argument handling

2009-11-20 Thread nchubrich
I should also add something I alluded to in another discussion (under
'positions'); this is the idea of making \any parameter into a rest
parameter.  For instance, if you had

(defnsk add [addend augend] ...)

you could call it like (add :addend 1 2 3 :augend 1 2) or (add [1 2 3]
[1 2 3 4]).

Must the poor programmer now check \all of his parameters to see if
they have been magically turned into rest parameters without his
knowing?  Of course not!  The function body is simply executed
repeatedly, and the results put in a list:

(add [1 2 3] [1 2 3 4]) -> [2 4 6]

If we were being \really permissive, we might want to return \two
results, one the straightforward element-by-element adding, the other
the 'cartesian' adding: [[2 4 6],[[2 3 4 5][3 4 5 6][4 5 6 7]]].  Or
we might allow a flag passed to all functions :cartesian :sequential
to turn this behavior on or off.

If function writers want to explicitly manipulate these sequences, of
course, that is fine; all I am saying is that if they do nothing, the
function \caller gets his sequence code for free.

To assist this way of programming, it might be a good idea to have
another type of 'permissive' sequence abstraction, which you might
call for old time's sake car and cdr:

(car [1 2 3]) -> 1
(cdr [1 2 3]) -> [2 3]
(car 1) -> 1
(cdr 1) -> nil

A direct reference to a sequence as if it were a singular element,
meanwhile, is an invitation to deal with the sequence at the level of
the function caller as we do above (who if he passes elements as a
sequence, presumably knows what he is doing).

I guess this is getting to be a pretty epic macro!  I figured it was
worth inviting boos and/or cheers and suggestions before setting 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


repeatedly forcing the evaluation of a lazy seq

2009-11-20 Thread bOR_
Hi all,

Just ran into a small gotcha: I had an atom which contained a lazyseq
(e.g. (filter males world)). Later on I would be repeatedly calling
random elements from this atom, using clojure contrib rand-elt. That
was surprisingly slow. I figured out that count was the culprit.
Apparently, the lazyseq atom stayed a lazyseq atom (immutability), and
each time I called for a random element, count had to do the whole
filtering to figure out 'count'.

Is there any way that I can get a warning printed out that would let
me know when I am doing something stupid like this? for example:
(repeatedly evaluating identical full lazy sequence @world)?

-- 
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 macro for flexible keyword argument handling

2009-11-20 Thread nchubrich
I don't see why you couldn't simply check to make sure that there are
no arguments without either default or supplied values.  As I wrote
above, "If you left the arguments incomplete and unkeyworded it would
apply what you put preferentially to the first arguments in the list
without a default value."  If there are any null arguments left over,
the macro could throw an exception.

The basic rule is, "accept what you can, and only error our if you
absolutely must."

(Of course this variable application rule might get confusing in
practice, at least without help from the IDE.)

I think it's better than just a flat arguments list, because 1) it
allows you to specify defaults and 2) it gives you the option of
naming arguments by keyword.  How can you do that with flat argument
lists?

My point is that the option of naming arguments is implicitly there
any time you write a function, because variables have names; and there
is no way to mistake a default value for a variable.  So you might as
well use these built-in distinctors.

You could even do a little branching from within argument lists.
Suppose for instance you had something like

(dfnsk demo-branch [x 0 0 1 y 0 1 0] )

There can be only one default per variable, so what are the other
values?  These could only be possible passed-in values.  x=0, y=1 is
the first branch, x=1, y=0 is the second.  Within the function body,
you would have a predicate available that tells you what branch you
are on, so for instance you could write something like

   (cond (branch? 1) ...
 (branch? 2) ...)

or, if you passed in multiple function bodies after the argument list,
(kind of like the variable arity thing), the first would be for the
first branch, the second for the second, etc.

Another 'generality' that could be added is to match arguments by type
whenever there is a type annotation in the function definition and a
discrepancy in the call; so for instance if you had a number of
symbols that were supposed to be passed last, and you passed a symbol
somewhere else, it would be applied to the first symbol-type argument
in the function list without throwing an error.

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

2009-11-20 Thread nchubrich
My 'requirements' were not so much for any particular need, but to try
to think up a logical and complete API for dealing with multisets.  I
agree that there should be an actual collection type for multisets
(implemented as an underlying map of values to frequencies I presume);
but you might as well also be allowed to pass any kind of collections
and have it do something order-preserving with them.  It makes a good
gathering point for sequence functionalities as \well as handling
multisets.

Alex is right that the keep-likes-with-likes option is a little
weird.  I'm not sure whether to just conj them next to the first
instance, or try to equally distribute them as much as possible
throughout the instances, leaving any remainders on the initial ones.
Probably the latter.  Of course when you have this kind of
questioning, maybe it is not a good fundamental functionality to
add.

(My original spur for this was in merging argument lists in a
permissive argument list macro I'm working on; the idea was you would
get 'rest' type parameters anywhere in the list there is a repetition
of variables under a keyword.  Obviously you wouldn't want to have
disparate instances of the same thing here.  (My initial thoughts on
this macro are at the bottom of the most recent discussion of keyword
arguments.  (How, by the way, do you do "show quoted text"?))

There is a sort of hierarchy of sequences for being sensible for
multiset operations.  First we have multisets themselves.  Then we
have sequences that are ordered but have no dislocated repetition of
elements.  Then we have arbitrary sequences.  I'm inclined to want an
API that handles all three.

Maybe someone who does a lot of statistical work would have a better
idea of how this API should work.

Sean, regarding doall, the reason I wanted to have an internal
override is to be able to preserve the collection type of the
arguments.  Sometimes it gets a little annoying to cast these back
every time; and when you're dealing with small sequences, laziness is
not really necessary.  If you wanted to be \really evil about it, you
could have a bind-able variable *lazy* that sets it one way or the
other.

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