Re: proposal for core arithmatic functions

2010-03-13 Thread Konrad Hinsen

On 13 Mar 2010, at 03:32, Jonathan Shore wrote:

Could + and other operators be changed to a macro mapping rather  
than the current defn, mapping the argument list to a binary  
expression tree  (+ (+ (+ ...  instead of the list style application  
(I'm guessing yes, not being familiar with CL-style macros).


This would not be a good idea for the arithmetic functions in  
clojure.core, as macros come with their own restrictions. For example,  
if + were a macro, you couldn't pass it as an argument to map, reduce,  
or apply. All of these occur very frequently.


I don't really share your worries at this time because the kind of  
performance problem you describe can always be fixed in a later  
optimized implementation. Clojure is still a very young and evolving  
language, so that level of optimization cannot be expected in my  
opinion.


What is nice about Lisp is that everything that Clojure does, you can  
do yourself. If you are not happy with how + works, write your own.  
You can make it a function that is more efficient in general, or more  
efficient just for your use cases, or you can make it a macro. All you  
need to change in your code to use your own version is the ns form at  
the beginning which specifies which symbols to take from where. For an  
example, see



http://code.google.com/p/clj-nstools/source/browse/src/nstools/generic_math.clj

That does exactly the opposite of what you want: it replaces  
arithmetic by a generic and thus slower implementation. But the same  
approach would work for whatever other implementation you might want.  
Of course, if you come up with a clearly improved arithmetic without  
restrictions, it would be nice to propose it for inclusion into  
Clojure itself.



Secondly, if one has code like:

(let [
x  (int a)  
y  (int b)]
(+ (* x 2) (* y 3) (* x y 5))

(* x 2) ->  a function of (int, Object), as the literal 2 is not  
assumed to be a primitive type.This instead needs to be mapped to:


(let [
x  (int a)  
y  (int b)]
(+ (+ (* x (int 2)) (* y (int 3)) (* (* x y) (int 5


I don't know if type hints can be interrogated or known at the time  
of macro evaluation (I'm guessing not), but if so, would like to see  
that in such a macro.


Yes, a macro has access to everything. It is perfectly possible, and  
even not very difficult, to write a macro that does the transformation  
you describe. The tricky part is knowing when it is a good idea to  
apply it - but if you leave that decision to the programmer using it,  
the problem becomes a quite straightforward one to solve.


Automatically decorating literals that are used in the context of  
arithmetic with a primitive would make clojure a lot more usable for  
performance-concerned arithmetic.


Perhaps. I find it very hard to predict what can be gained by a  
specific optimization, since it's so hard to predict what the JIT  
compiler will take care of automatically.


I think I saw mention that #^int (and other primitive types) will be  
supported at some point in argument declarations as well?


That has been mentioned on this list, but I don't expect it to happen  
before the rewrite of the Clojure compiler in Clojure itself.


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


Re: proposal for core arithmatic functions

2010-03-13 Thread Jonathan Shore

Thanks for your thoughtful reply, see below.

On Mar 13, 2010, at 3:03 AM, Konrad Hinsen wrote:

> On 13 Mar 2010, at 03:32, Jonathan Shore wrote:
> 
>> Could + and other operators be changed to a macro mapping rather than the 
>> current defn, mapping the argument list to a binary expression tree  (+ (+ 
>> (+ ...  instead of the list style application (I'm guessing yes, not being 
>> familiar with CL-style macros).
> 
> This would not be a good idea for the arithmetic functions in clojure.core, 
> as macros come with their own restrictions. For example, if + were a macro, 
> you couldn't pass it as an argument to map, reduce, or apply. All of these 
> occur very frequently.

ic your point.   Then really what I am asking for is for the compiler to 
decompose these into binary operations in a future release.

> 
> I don't really share your worries at this time because the kind of 
> performance problem you describe can always be fixed in a later optimized 
> implementation.

Perhaps not, but most of my work would have to be done in Java, which for me 
would be unacceptabe.   I'm thinking Clojure is premature for my work at the 
moment.


> Clojure is still a very young and evolving language, so that level of 
> optimization cannot be expected in my opinion.

I recognize that Clojure is a smaller effort.   It may well be that users in 
the clojure community use clojure in situations that are not as performance 
sensitive.For possible adopters with issues such as mine, clojure 
competitors are much ahead on the performance angle.I do hope that the 
compiler rewrite is to put  focus on perf.

> 
> Yes, a macro has access to everything. It is perfectly possible, and even not 
> very difficult, to write a macro that does the transformation you describe. 
> The tricky part is knowing when it is a good idea to apply it - but if you 
> leave that decision to the programmer using it, the problem becomes a quite 
> straightforward one to solve.
> 
>> Automatically decorating literals that are used in the context of arithmetic 
>> with a primitive would make clojure a lot more usable for 
>> performance-concerned arithmetic.
> 
> Perhaps. I find it very hard to predict what can be gained by a specific 
> optimization, since it's so hard to predict what the JIT compiler will take 
> care of automatically.

I could be wrong, but would think that:

static public int intCast(Object x){
if(x instanceof Number)
return ((Number) x).intValue();
return ((Character) x).charValue();
}

the "if" statement is not going to be optimised away by JIT.   (This is what 
gets called on the literals).


> 
>> I think I saw mention that #^int (and other primitive types) will be 
>> supported at some point in argument declarations as well?
> 
> That has been mentioned on this list, but I don't expect it to happen before 
> the rewrite of the Clojure compiler in Clojure itself.
> 
> 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

filter sequence until false result

2010-03-13 Thread Glen Rubin
Hey all!

I am trying to filter a sequence until a false value is returned.  Is
there a control-flow form to do this?  ( I know I could write a loop
statement to do it)

Here are more details of what I am actually trying to do, in case
above is not clear.


input is the lazy sequence of primes:

(use '[clojure.contrib.lazy-seqs :only (primes)])

I would like to filter the lazy sequence of primes for all of the
primes less than 2,000,000

If I try:

(filter #(while (< % 20)) primes)

It gets hung up since filter keeps testing primes, despite the fact
that they have grown too large.  So, I would like filter to stop at
the first false result.

-- 
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: filter sequence until false result

2010-03-13 Thread CuppoJava
You can use either take-while or for to do what you want.

(take-while #(< % 20) primes)

(for [p primes :while (< p 20)] p)

Hope that helps
 -Patrick

-- 
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: filter sequence until false result

2010-03-13 Thread Michał Marczyk
On 13 March 2010 15:49, Glen Rubin  wrote:
> If I try:
>
> (filter #(while (< % 20)) primes)
>
> It gets hung up since filter keeps testing primes, despite the fact
> that they have grown too large.  So, I would like filter to stop at
> the first false result.

Actually that's not what happens. Execution never leaves the first
application of #(while (< % 20)), since it expands (performing
macro-expansion and substituting the concrete parameter for the formal
%) to

(loop []
  (when (< 2 20)
(recur)))

See the docs on while (e.g. through (doc while) at the REPL) and its
source (e.g. through (c.c.repl-utils/source while) at the REPL).

Sincerely,
Michał

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


[ANN] clj-native 0.8.1

2010-03-13 Thread mac
Hello all.
I have had some time lately to work on my C FFI for Clojure and I
think it's pretty much feature complete now.
It has support for functions, callbacks, structures, unions and
globals.
For structures there is support for different alignments.

The library has two main namespaces: clj-native.direct and clj-
native.dynamic.
The direct namespace uses the "direct mapping" feature of JNA in order
to be as efficient and arity and type safe as possible. However, it
does not support varargs functions since they require reflection and
dynamic translation of the parameters. That's what the dynamic
namespace is for: It can map any C function into clojure, even vararg
functions like printf but at a higher cost in call time and less
safety (it's easy to crash the jvm by sending the wrong type or number
of parameters). Access to global variables through the JNA Pointer
class is also available in the dynamic namespace.

The library is available from github: http://github.com/bagucode/clj-native
and clojars: http://clojars.org/clj-native

Example usage of the direct namespace can be found here:
http://github.com/bagucode/clj-native/blob/master/src/examples/c_lib.clj

Please report issues or make requests to my github account or by mail.

Enjoy!

/Markus

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


Achieving high performance, mutable primitives?

2010-03-13 Thread CuppoJava
Hi,
I just ran these two microbenchmarks, where I attempted to measure the
overhead in Clojure's loop-recur form as compared to just mutating an
array.

;;loop-recur (5300 msecs)
(time
  (dotimes [n 5000]
(loop [accum (int 0) i (int 0)]
  (if (< i 5)
(recur (+ accum i) (inc i))
accum

;;int-array (2910 msecs)
(time
  (dotimes [n 5000]
(let [a (int-array 1)]
  (dotimes [i 5]
(aset a 0 (+ i (aget a 0)))

Because of these results, I think it's worthwhile to be able to access
a mutable location directly from within Clojure, such as a mutable
primitive.

Right now, I'm making do with a set of macros for creating and
manipulating 1 element arrays. But this incurs a cost of creating
those arrays when I really just want a mutable primitive.

What is everyone's opinion on this? Are mutable primitives still seen
as unnecessary? Or are they seen as necessary but not an immediate
concern?

  -Patrick

-- 
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: Achieving high performance, mutable primitives?

2010-03-13 Thread David Nolen
On Sat, Mar 13, 2010 at 1:59 PM, CuppoJava wrote:

> Hi,
> I just ran these two microbenchmarks, where I attempted to measure the
> overhead in Clojure's loop-recur form as compared to just mutating an
> array.
>
> ;;loop-recur (5300 msecs)
> (time
>  (dotimes [n 5000]
>(loop [accum (int 0) i (int 0)]
>  (if (< i 5)
>(recur (+ accum i) (inc i))
>accum
>

; ~720ms
(time
 (dotimes [n 5000]
   (loop [accum (int 0) i (int 0)]
 (if (< i (int 5))
   (recur (+ accum i) (inc i))
   accum

You have to remember that even number literals need to be type-hinted.

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

Re: Achieving high performance, mutable primitives?

2010-03-13 Thread Jason Wolfe
BTW your "5" literal is boxed, which is causing slowness:

user> (time
  (dotimes [n 5000]
(loop [accum (int 0) i (int 0)]
   (if (< i (int 5))
(recur (+ accum i) (inc i))
accum
"Elapsed time: 861.027 msecs"



On Mar 13, 10:59 am, CuppoJava  wrote:
> Hi,
> I just ran these two microbenchmarks, where I attempted to measure the
> overhead in Clojure's loop-recur form as compared to just mutating an
> array.
>
> ;;loop-recur (5300 msecs)
> (time
>   (dotimes [n 5000]
>     (loop [accum (int 0) i (int 0)]
>       (if (< i 5)
>         (recur (+ accum i) (inc i))
>         accum
>
> ;;int-array (2910 msecs)
> (time
>   (dotimes [n 5000]
>     (let [a (int-array 1)]
>       (dotimes [i 5]
>         (aset a 0 (+ i (aget a 0)))
>
> Because of these results, I think it's worthwhile to be able to access
> a mutable location directly from within Clojure, such as a mutable
> primitive.
>
> Right now, I'm making do with a set of macros for creating and
> manipulating 1 element arrays. But this incurs a cost of creating
> those arrays when I really just want a mutable primitive.
>
> What is everyone's opinion on this? Are mutable primitives still seen
> as unnecessary? Or are they seen as necessary but not an immediate
> concern?
>
>   -Patrick

-- 
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: binary representation + operators

2010-03-13 Thread Michał Marczyk
On 12 March 2010 23:26, Scott  wrote:
> How do I write a function 'bit' that converts an integer to binary
> representation:
>
> (bit 0) -> 2r0
> (bit 1) -> 2r1
> (bit 2) -> 2r10
> (bit 3) -> 2r11

I understand that you want a way to obtain a string representation of
a number in binary. I think you need to dispatch on class:

(Integer/toBinaryString (int 5)) ; => "101"
(Integer/toBinaryString (Integer. 5)) => "101"
(Long/toBinaryString (long 5)) ; => "101"
(Long/toBinaryString (Long. (long 5))) ; => "101"

(.toString (bigint 5) 2) ; the "2" indicates the radix; => "101"
(.toString (BigInteger. "5") 2) ; => "101"

As far as I can tell, you can't use the int/long method with bigints
or the other way around.

If you'd like to add the "2r" in front, just use str:

(str "2r" "101") ; => "2r101"

> As well, as function 'bit-concat' with the following behavior:
>
> (bit-concat 2r1 2r00) -> 2r100
> (bit-concat 2r0 2r00) -> 2r000
> (bit-concat 2r011 2r1100) -> 2r000

I'd prefer to have bit-concat operate on actual numbers, not on
strings; you can convert the result later. To that end, here's a
possible solution (I'm *sure* there must be a better way... but it
works):

(let [ls (zipmap (map #(loop [n % r 1]
 (if (zero? n)
   r
   (recur (dec n) (* 2 r
  (range 0 128))
 (map inc (range 0 128)))]
  (defn bit-length [n]
(if (zero? n)
  0
  (condp = (class n)
Integer(ls (Integer/highestOneBit n))
Long   (ls (Long/highestOneBit n))
BigInteger (.bitLength n)

(comment
  ; this returns true
  (every? #(== (bit-length %) (.bitLength %))
  (map bigint (range 0 1000

(defn bit-concat [n m]
  (bit-or (bit-shift-left n (bit-length m))
  m))

This will work as expected unless you use unboxed ints:

user> (bit-shift-left (int 1) 63)
-2147483648
user> (bit-shift-left (Integer. 1) 63)
9223372036854775808
user> (bit-shift-left (long 1) 128)
340282366920938463463374607431768211456
user> (bit-shift-left (long 1) 200)
1606938044258990275541962092341162602522202993782792835301376
user> (class (bit-shift-left (long 1) 200))
java.math.BigInteger

Sincerely,
Michał

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


Good practice for documenting structmaps?

2010-03-13 Thread Matt Lehman
Is there a good practice for documenting the structure basis object
for structmaps?

As I'm using more Clojure code on a production, I'm finding it useful
to document structmaps, but the only way I can find to do it is using
the following pattern to add the doc meta to a var:

  (def #^{:doc "..."} mystruct (create-struct :name :description))

I'm not sure the actual basis object ( I think
clojure.lang.PersistentStructMap$Def) implements IObj to be able to
hold its own metadata.

I've found some interest in the idea of adding doc-string to
defstruct: http://www.mail-archive.com/clojure@googlegroups.com/msg14121.html

-- 
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: Something similar to (match) from scheme?

2010-03-13 Thread Luka
thanx, that's a start. It seems that plt-scheme's match is a bit more
powerful, but I think I can manage with this as well. So far the
biggest annoyance is the fact that I can match a number or a string,
but not a symbol (I can in :when condition, I know...) which is
something I can live with.

-- 
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: Something similar to (match) from scheme?

2010-03-13 Thread Luka
I just found clojure.contrib.types match which maybe fits more with
what I'm trying to do... I'll check it out tomorrow, almost 3am here...

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


Re: proposal for core arithmatic functions

2010-03-13 Thread Per Vognsen
On Sat, Mar 13, 2010 at 9:32 AM, Jonathan Shore
 wrote:
> Hi,
>
> I've been evaluating clojure with a bias around performance (I do a lot of 
> numerical work).   I don't need to the metal, but want to see that 
> fundamental operations are comparable to java in performance and that 
> performance can be had not at the expense of conciseness.   In particular, 
> I've noted that arithmetic such as:
>
>        (+ a b c d)
>
> is not equivalent to:
>
>        (+ (+ (+ a b) c) d)
>
> in performance, because the former form applies + on a list or array form (I 
> forget which).    This is regardless of whether all of the above values have 
> primitive type hints.   At least this is what I observe in debugging (correct 
> me if I am wrong).
>
> Could + and other operators be changed to a macro mapping rather than the 
> current defn, mapping the argument list to a binary expression tree  (+ (+ (+ 
> ...  instead of the list style application (I'm guessing yes, not being 
> familiar with CL-style macros).

Yes. It's a simple matter of changing the current run-time reduce in
(defn + ...) to a compile-time reduce:

  ([x y & more]
   (reduce (fn [a b] `(+ ~a ~b)) (cons x (cons y more

-Per

-- 
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: proposal for core arithmatic functions

2010-03-13 Thread Per Vognsen
On Sat, Mar 13, 2010 at 3:03 PM, Konrad Hinsen
 wrote:
> On 13 Mar 2010, at 03:32, Jonathan Shore wrote:
>
>> Could + and other operators be changed to a macro mapping rather than the
>> current defn, mapping the argument list to a binary expression tree  (+ (+
>> (+ ...  instead of the list style application (I'm guessing yes, not being
>> familiar with CL-style macros).
>
> This would not be a good idea for the arithmetic functions in clojure.core,
> as macros come with their own restrictions. For example, if + were a macro,
> you couldn't pass it as an argument to map, reduce, or apply. All of these
> occur very frequently.

I wrote my reply to him before drinking coffee, so I hadn't considered
this (obvious) issue.

Common Lisp's has compiler macros. These are macros associated with a
function which will be called only when calls to the function are
resolvable at compile time. While nicer than plain macros (as you can
still treat the function as a first-class value at run time) they are
still not semantically transparent because of the possibility of var
rebinding.

-Per

-- 
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: proposal for core arithmatic functions

2010-03-13 Thread Per Vognsen
As a mea culpa for my earlier stupidity, here's a proposed solution
that is semantically transparent if somewhat inelegantly brute force
in its approach:

http://gist.github.com/331211

If need be, it could also define entries for :inline and
:inline-entries for the auto-generated arity overloads.

-Per

On Sat, Mar 13, 2010 at 3:23 PM, Per Vognsen  wrote:
> On Sat, Mar 13, 2010 at 3:03 PM, Konrad Hinsen
>  wrote:
>> On 13 Mar 2010, at 03:32, Jonathan Shore wrote:
>>
>>> Could + and other operators be changed to a macro mapping rather than the
>>> current defn, mapping the argument list to a binary expression tree  (+ (+
>>> (+ ...  instead of the list style application (I'm guessing yes, not being
>>> familiar with CL-style macros).
>>
>> This would not be a good idea for the arithmetic functions in clojure.core,
>> as macros come with their own restrictions. For example, if + were a macro,
>> you couldn't pass it as an argument to map, reduce, or apply. All of these
>> occur very frequently.
>
> I wrote my reply to him before drinking coffee, so I hadn't considered
> this (obvious) issue.
>
> Common Lisp's has compiler macros. These are macros associated with a
> function which will be called only when calls to the function are
> resolvable at compile time. While nicer than plain macros (as you can
> still treat the function as a first-class value at run time) they are
> still not semantically transparent because of the possibility of var
> rebinding.
>
> -Per
>

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


Zip function

2010-03-13 Thread Marmaduke
Hello,

I'm new to Clojure, but in other languages, zip is a workhorse, and I
didn't find it, so I

(defn zip [& ss]
  (partition (count ss) (apply interleave ss)))

but because I didn't find it, I am suspicious: is there a better way?

Marmaduke

ps. As a first-poster: thanks to Rich Hickey and Stuart Halloway for
the language and the book, respectively.

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


Newbie question: Why does clojure prefer java.lang.Exception?

2010-03-13 Thread CloudiDust
Greetings everyone!

I am currently beginning to learn clojure, and here's one thing that I
don't quite understand, that many exceptions thrown by clojure are the
most generic java.lang.Exception's (e.g. when a symbol cannot be
resolved). Why aren't more specific exception classes used, like
clojure.lang.SymbolResolutionException? (Having a more specific
exception class seems useful when doing exception handling.)

As far as I know, clojure throws exceptions defined in the standard
Java library only, like the IllegalStateException when updating refs
outside a transaction. So there are no appropriate exception classes
for some errors occurred in clojure, which may be the reason it falls
back to java.lang.Exception.

Is the standard-exception-only thing intentional? If so, would you
please tell me the rationale behind such a decision?

I have only played with clojure for one day, so there's a huge
possibility that I missed or misunderstood something.

Please enlighten me. Thanks in advance. :)

Regards,
Ruochen

-- 
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: quote versus backquote

2010-03-13 Thread Felix Breuer
Thank you, this has been very helpfull.

The reason I came across this problem is that I never intended to
evaluate the symbols in the expression trees. I rather wanted to use
them to represent symbolic constants in an abstract expression tree. I
am now convinced that using keywords throughout is the better
approach.

Thanks,
Felix

On 12 Mrz., 15:01, Konrad Hinsen  wrote:
> On 12.03.2010, at 10:32, Felix Breuer wrote:
>
> > I guess I have to rephrase my previous questions to make them more
> > clear: Why was this particular behavior chosen? What is the benefit of
> > having quote and syntax-quote behaving differently in this regard?
>
> Quote and syntax-quote serve very different purposes, despite the similar 
> name an a superficial resemblance in functionality.
>
> Quote is for writing unevaluated literals. You just want nothing changed in 
> its argument, which is exactly what it does.
>
> Syntax-quote is used for writing code templates, mostly inside macro 
> definitions. In that situation, you want symbols be resolved in namespaces, 
> just as they would if the form being constructed were used literally in the 
> same place. To make code templates work correctly across namespaces 
> (typically a macro is expanded in another namespace than the one it was 
> defined in), it is thus preferable to have symbols converted to their 
> namespace-qualified counterparts.
>
> You might want to look at this blog post, whose topic is an exceptional 
> situation where syntax-quote is not the most convenient way to write code 
> templates:
>
>        http://onclojure.com/2010/02/23/generating-deftype-forms-in-macros/
>
> > Suppose I wanted to write my own version of = called (myeql a b) such
> > that
>
> > user> (myeql '(v 1) `(v 1))
> > true
>
> > I would have to walk the expression tree in both expressions and
> > replace all unqualified symbols with the respective qualified symbols.
> > How would I go about this? Is there an idomatic way to achieve this?
>
> I don't see why you would ever want to do this, but here is one approach (not 
> idiomatic):
> - use clojure.walk to apply a transformation all over a form
> - for each leaf of the tree, check if it is a symbol and if so, convert it to 
> its namespace-qualified equivalent.
>
> What is rather strange in my opinion is the fact that there is no utility 
> function in clojure. core that does the second step, i.e. there is no 
> function that will map 'x to `x. However, it is not difficult to write such a 
> function:
>
> (defn qualified-symbol
>   [s]
>   (symbol (str *ns*) (str s)))
>
> 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


Re: bounded memoize

2010-03-13 Thread Meikel Brandmeyer
Hello Christophe,

On Fri, Mar 12, 2010 at 08:27:15PM +0100, Christophe Grand wrote:

> See my memoize5: the call isn't computed inside the swap!s

That doesn't mean, that it is not computed several times!

user=> (defn f
 [x]
 (println "Got" x "from" (Thread/currentThread))
 (Thread/sleep 5000)
 (case x
   3 (f 2)
   2 (f 1)
   1 :done))
#'user/f
user=> (def f (memoize5 f))
#'user/f
user=> (-> #(do (f 3) (println "Done for" (Thread/currentThread))) Thread. 
.start)
   (Thread/sleep 2500)
   (-> #(do (f 3) (println "Done for" (Thread/currentThread))) Thread. 
.start)
Got 3 from #
Got 3 from #
Got 2 from #
Got 2 from #
Got 1 from #
Got 1 from #
Done for #
Done for #

Hmm? Wasn't f supposed to memoized? The problem is, that the call to f
is not guarded.

> Since you use a lock I think some clever combination of memoized functions
> can create a deadlock.

No. In the protected area we simply create a promise and fire off a
thread, which does the computation. Then we return immediatelly. So no
deadlock possibility here. However we trade one lock for the „other“
(the promise). What is the possibility of a deadlock here? Well, the
computation of f never completes. But this is not a problem of memoize.
The only way memoize could cause a problem here is that the computation
of f somehow calls f again with the same arguments. Then it would
deadlock on the promise, but without memoize we would also have a
infinite loop here...

Sincerely
Meikel

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


Re: Leiningen, Clojure and libraries: what am I missing?

2010-03-13 Thread Meikel Brandmeyer
Hi,

On Thu, Mar 11, 2010 at 01:32:36PM -0800, Phil Hagelberg wrote:

> Historically this has been because calculating the classpath couldn't
> be done in Clojure itself since it needed to be done before the JVM
> booted. Having to figure this kind of thing out in a shell script or
> in elisp is a headache if the rules are not simple. But now with the
> subclassloader approach that lein and mvn use it's less of an issue.
> But it would mean deprecating the pure-elisp swank launcher, and I
> don't know how it would affect other tools (IDEs, etc), so I'm still
> hesitant.

I think this is a typical emacs misconception. Vim is an editor. Why
should it have to know how a JVM classpath works? Setting this up is the
responsibility of the developer. Put everything in lib/? No problem.
Let maven/gradle/lein handle the classpath? No Problem. Have an esoteric
shell script doing some voodoo incatations? No Problem.

Putting this logic into the editor was the failure in the first place.

Sincerely
Meikel

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


Re: (seq? x) vr.s (not (empty? x))

2010-03-13 Thread Meikel Brandmeyer
Hi,

On Fri, Mar 12, 2010 at 08:25:23AM +1100, Alex Osborne wrote:

> The list equivalent to the vec or set functions is (apply list ...) --
> there's no shorthand for it as you shouldn't be using lists much
> explicitly, use a vector instead.

In fact there is a short-hand:

user=> (seq [])
nil
user=> (vec [])
[]
user=> (set [])
#{}
user=> (sequence [])
()

Sincerely
Meikel

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


Re: Achieving high performance, mutable primitives?

2010-03-13 Thread CuppoJava
I see, so that's what I was missing.
Thanks for your help!
  -Patrick

-- 
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: filter sequence until false result

2010-03-13 Thread Matt
I think what you want is take-while instead of filter:

(take-while %(< % 20) primes)

-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: filter sequence until false result

2010-03-13 Thread Matt
Hmm.. I should re-read messages before sending them. The correct code
is:

(take-while #(< % 20) primes)

-- 
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: Zip function

2010-03-13 Thread Meikel Brandmeyer
Hi,

On Sat, Mar 13, 2010 at 06:55:56AM -0800, Marmaduke wrote:

> I'm new to Clojure, but in other languages, zip is a workhorse, and I
> didn't find it, so I
> 
> (defn zip [& ss]
>   (partition (count ss) (apply interleave ss)))
> 
> but because I didn't find it, I am suspicious: is there a better way?

(defn zip
  [& colls]
  (apply map vector colls))

Sincerely
Meikel

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


Re: Zip function

2010-03-13 Thread Vagif Verdi
In clojure map works like zipWith.
So you can pass to it vector if you want just plain zip: (map vector
colls)

That makes making a special named function unnesessary.


On Mar 13, 6:55 am, Marmaduke  wrote:
> Hello,
>
> I'm new to Clojure, but in other languages, zip is a workhorse, and I
> didn't find it, so I
>
> (defn zip [& ss]
>   (partition (count ss) (apply interleave ss)))
>
> but because I didn't find it, I am suspicious: is there a better way?
>
> Marmaduke
>
> ps. As a first-poster: thanks to Rich Hickey and Stuart Halloway for
> the language and the book, respectively.

-- 
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: bounded memoize

2010-03-13 Thread Christophe Grand
Hi Meikel,

On Sat, Mar 13, 2010 at 10:51 PM, Meikel Brandmeyer  wrote:

> On Fri, Mar 12, 2010 at 08:27:15PM +0100, Christophe Grand wrote:
>
> > See my memoize5: the call isn't computed inside the swap!s
>
> That doesn't mean, that it is not computed several times!
>


I agree: it can be concurrently computed several times (but a given thread
would only compute it at most once).
I'm sory: I read too quickly and didn't understand that you were concerned
about the computation happening only once for all threads.



> > Since you use a lock I think some clever combination of memoized
> functions
> > can create a deadlock.
>
> No. In the protected area we simply create a promise and fire off a
> thread, which does the computation. Then we return immediatelly. So no
> deadlock possibility here. However we trade one lock for the „other“
> (the promise). What is the possibility of a deadlock here? Well, the
> computation of f never completes. But this is not a problem of memoize.
> The only way memoize could cause a problem here is that the computation
> of f somehow calls f again with the same arguments. Then it would
> deadlock on the promise, but without memoize we would also have a
> infinite loop here...
>


You're right of course. I apologize.
As a minor note: couldn't a future replace your promise? Or couldn't you get
rid of the other thread and deliver the promise in the same thread but
outside of the (locking ..) form?
Hmm or even a delay!?

Ok I tried to used delays. So I slightly modified my memoize5 (see memoize6)
and I built on that a memoize7 which enforces (through delays) that a value
is onlycomputed once (except if the strategy previously removed it from the
cache of course).

Do you see a problem in my latest implementation?
http://gist.github.com/330644#LID153

Thank you,

Christophe

-- 
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: binary representation + operators

2010-03-13 Thread Scott
java to the rescue!

Thanks to all for your suggestions

Scott

On Mar 13, 3:45 pm, Michał Marczyk  wrote:
> On 12 March 2010 23:26, Scott  wrote:
>
> > How do I write a function 'bit' that converts an integer to binary
> > representation:
>
> > (bit 0) -> 2r0
> > (bit 1) -> 2r1
> > (bit 2) -> 2r10
> > (bit 3) -> 2r11
>
> I understand that you want a way to obtain a string representation of
> a number in binary. I think you need to dispatch on class:
>
> (Integer/toBinaryString (int 5)) ; => "101"
> (Integer/toBinaryString (Integer. 5)) => "101"
> (Long/toBinaryString (long 5)) ; => "101"
> (Long/toBinaryString (Long. (long 5))) ; => "101"
>
> (.toString (bigint 5) 2) ; the "2" indicates the radix; => "101"
> (.toString (BigInteger. "5") 2) ; => "101"
>
> As far as I can tell, you can't use the int/long method with bigints
> or the other way around.
>
> If you'd like to add the "2r" in front, just use str:
>
> (str "2r" "101") ; => "2r101"
>
> > As well, as function 'bit-concat' with the following behavior:
>
> > (bit-concat 2r1 2r00) -> 2r100
> > (bit-concat 2r0 2r00) -> 2r000
> > (bit-concat 2r011 2r1100) -> 2r000
>
> I'd prefer to have bit-concat operate on actual numbers, not on
> strings; you can convert the result later. To that end, here's a
> possible solution (I'm *sure* there must be a better way... but it
> works):
>
> (let [ls (zipmap (map #(loop [n % r 1]
>  (if (zero? n)
>r
>(recur (dec n) (* 2 r
>   (range 0 128))
>  (map inc (range 0 128)))]
>   (defn bit-length [n]
> (if (zero? n)
>   0
>   (condp = (class n)
> Integer(ls (Integer/highestOneBit n))
> Long   (ls (Long/highestOneBit n))
> BigInteger (.bitLength n)
>
> (comment
>   ; this returns true
>   (every? #(== (bit-length %) (.bitLength %))
>   (map bigint (range 0 1000
>
> (defn bit-concat [n m]
>   (bit-or (bit-shift-left n (bit-length m))
>   m))
>
> This will work as expected unless you use unboxed ints:
>
> user> (bit-shift-left (int 1) 63)
> -2147483648
> user> (bit-shift-left (Integer. 1) 63)
> 9223372036854775808
> user> (bit-shift-left (long 1) 128)
> 340282366920938463463374607431768211456
> user> (bit-shift-left (long 1) 200)
> 1606938044258990275541962092341162602522202993782792835301376
> user> (class (bit-shift-left (long 1) 200))
> java.math.BigInteger
>
> Sincerely,
> Michał

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


extending protocol

2010-03-13 Thread aria42
Is there a way to say that a protocol extends another protocol or
interface? I.e. can i specify that a given protocol must also support
the "seq" method from  clojure.lang.Seqable?

-- 
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: bounded memoize

2010-03-13 Thread Eugen Dück
On Mar 13, 4:51 pm, Christophe Grand  wrote:
> My variations on memoize use a single atom: your bounded-memoize id roughly
> equivalent to my memoize2 + fifo-strategy, 
> seehttp://gist.github.com/330644#LID19.

I finally found the time to fully read your gist, and I see you are
indeed doing the same there. It's just a little less obvious due to
the indirection introduced by strategies.

> Two quick notes:
> * a PersistentQueue is a better fit there (conj at one end, pop/peek at the
> other) than a vector,
> * by padding it to the desired length (capacity) with dummy items, you are
> sure that the queue (or the vector) is always full, so you always have to
> remove an item: no more need for the (> (count v) capacity) test.

Agree, this simplifies the code a bit, and once we reach full
capacity, the "if" will always be true anyway.

> That's why Meikel tests twice if the value is already in the cache (the
> first time outside of a transactio, the second time inside) and why I
> introduce hit-or-assoc in memoize4/memoize5.

Still, with bad luck or just enough concurrency, simultaneous calls to
memoize6 with the same args can result in multiple computations, as
the computation (apply f args) is done outside of the swap:

(let [ret (if-let [e (find (cached @mem) args)] (val e) (apply f
args))
  m (swap! mem hit-or-assoc args ret)]

This gap shrinks when using memoize7 thanks to the use of delays, but
it is not completely closed and can still lead to multiple delays of
the same computation. If we want to get rid off this gap and make it
truely atomic, we have to make the decision whether or not to compute
inside the swap! block.

My memoizer with the hard-coded fifo strategy thus turns into
something like this:

(defn bounded-memoize
  [f capacity]
  (let [mem (atom [{} []])]
(fn [& args]
  (deref ((first
   (swap! mem #(if (contains? (first %) args)
 %
 (let [new-cache (assoc (first %) args (delay 
(apply f args)))
   new-v (conj (second %) args)]
   (if (> (count new-v) capacity)
 [(dissoc new-cache (first new-v)) (subvec 
new-v 1)]
 [new-cache new-v])
  args)

Using a padded queue (and getting rid of the anonymous % param names),
it can be (slightly) simplified to:

(defn bounded-memoize
  [f capacity]
  (let [mem (atom [{} (into clojure.lang.PersistentQueue/EMPTY (repeat
capacity :dummy))])]
(fn [& args]
  (deref ((first
   (swap! mem (fn [[m q :as cache]]
(if (contains? m args)
 cache
 [(dissoc (assoc m args (delay (apply f args))) 
(peek q))
  (-> q pop (conj args))]
  args)

-- 
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: bounded memoize

2010-03-13 Thread Eugen Dück
On Mar 14, 11:57 am, Eugen Dück  wrote:

> This gap shrinks when using memoize7 thanks to the use of delays, but
> it is not completely closed and can still lead to multiple delays of
> the same computation. If we want to get rid off this gap and make it

Actually, I take that back. The delay might be created multiple times,
but only one of them will be deref'ed (multiple times).

-- 
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: extending protocol

2010-03-13 Thread Konrad Hinsen

aria42 a écrit :

Is there a way to say that a protocol extends another protocol or
interface? I.e. can i specify that a given protocol must also support
the "seq" method from  clojure.lang.Seqable?

No. There is no hierarchy to protocols. This fits pretty well with the 
dynamic nature of Clojure, in my opinion: all checks of the type "does 
this value fit with that function" are done at runtime.


Konrad


__ Information provenant d'ESET NOD32 Antivirus, version de la base des 
signatures de virus 4942 (20100313) __

Le message a été vérifié par ESET NOD32 Antivirus.

http://www.eset.com


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


Re: proposal for core arithmatic functions

2010-03-13 Thread Konrad Hinsen

Jonathan Shore a écrit :

I don't really share your worries at this time because the kind of 
performance problem you describe can always be fixed in a later 
optimized implementation. 


Perhaps not, but most of my work would have to be done in Java, which 
for me would be unacceptabe.   I'm thinking Clojure is premature for my 
work at the moment.


I am in a similar situation in that most of my computing needs involve 
number crunching. However, my experience (after 15 years of using Python 
as my main programming language) is that I can always concentrate 
time-critical code in a very few routines that I can then optimize by 
switching to a more performance-oriented languange (Pyrex for Python, 
probably Java for Clojure). That's why I am not worried about such 
issues at the moment. I am interested in Clojure for large-scale program 
structure and for dealing with concurrency, which I think are harder 
problems than optimizing an inner loop.


Of course I am not claiming that this is good for everyone, I am just 
pointing out why I think Clojure is of interest for number crunchig 
right now.


I recognize that Clojure is a smaller effort.   It may well be that 


Exactly, and that comes with good and bad aspects, as so often. Th good 
part is that Clojure is much more innovative than anything designed by a 
committee could ever be, in particular in the way it deals with concurrency.



I could be wrong, but would think that:

*static* *public* *int* intCast(Object x){
*if*(x *instanceof* Number)
*return* ((Number) x).intValue();
*return* ((Character) x).charValue();
}

the "if" statement is not going to be optimised away by JIT.   (This is 
what gets called on the literals).


The JIT compiler does special-casing of functions for particular 
argument types. I don't know if it handles that particular kind of 
optimization, but it's not impossible.


That is actually something I worry more about than raw performance, in 
the long run. Portable performance optimization seems pretty much 
impossible in any JVM language.


Konrad.


__ Information provenant d'ESET NOD32 Antivirus, version de la base des 
signatures de virus 4942 (20100313) __

Le message a été vérifié par ESET NOD32 Antivirus.

http://www.eset.com


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


Re: bounded memoize

2010-03-13 Thread Eugen Dück
Hi Christophe,

your fifo-strategy (the one that uses "identity" as the hit method)
does not work:

user=> (def g (memoize7 identity (fifo-strategy 3)))
#'user/g
user=> (g 1)
1
user=> (g 1)
java.lang.IllegalArgumentException: Wrong number of args passed to:
core$identity (NO_SOURCE_FILE:0)

You have to use something like #(first %&) instead of identity.

memoize7 looks fine to me in terms of avoiding extra computation. I'm
not sure though why memoize6 exists as a fn in its own right. I guess
you wouldn't use it without something like delays, as the whole point
of memoize is to avoid multiple costly computations of the same thing,
and memoize6 does not always do that, unless you give it a fn f that
takes care of it, as memoize7 does.

If you don't rely on memoize6, you can write memoize7 even more
compact than memoize6, like this:

(defn memoize7-variant
 ([f] (memoize7-variant f [{} identity (fn [mem args] mem) assoc]))
 ([f [init cached hit assoc]]
  (let [mem (atom init)]
(fn [& args]
  (deref ((cached
   (swap! mem (fn [mem]
(if (contains? (cached mem) args)
 (hit mem args)
 (assoc mem args (delay (apply f args)))
  args))

It's more compact, as we do the contains? (or in your original
version: "find") check only once inside the swap! function. This has
the (admittedly not really huge) added benefit that we don't create
multiple delays in the case of "bad luck", as mentioned in my earlier
post.

Any downsides to this?

Cheers
Eugen

On Mar 14, 9:26 am, Christophe Grand  wrote:
> Hi Meikel,
>
> On Sat, Mar 13, 2010 at 10:51 PM, Meikel Brandmeyer  wrote:
> > On Fri, Mar 12, 2010 at 08:27:15PM +0100, Christophe Grand wrote:
>
> > > See my memoize5: the call isn't computed inside the swap!s
>
> > That doesn't mean, that it is not computed several times!
>
> I agree: it can be concurrently computed several times (but a given thread
> would only compute it at most once).
> I'm sory: I read too quickly and didn't understand that you were concerned
> about the computation happening only once for all threads.
>
> > > Since you use a lock I think some clever combination of memoized
> > functions
> > > can create a deadlock.
>
> > No. In the protected area we simply create a promise and fire off a
> > thread, which does the computation. Then we return immediatelly. So no
> > deadlock possibility here. However we trade one lock for the „other“
> > (the promise). What is the possibility of a deadlock here? Well, the
> > computation of f never completes. But this is not a problem of memoize.
> > The only way memoize could cause a problem here is that the computation
> > of f somehow calls f again with the same arguments. Then it would
> > deadlock on the promise, but without memoize we would also have a
> > infinite loop here...
>
> You're right of course. I apologize.
> As a minor note: couldn't a future replace your promise? Or couldn't you get
> rid of the other thread and deliver the promise in the same thread but
> outside of the (locking ..) form?
> Hmm or even a delay!?
>
> Ok I tried to used delays. So I slightly modified my memoize5 (see memoize6)
> and I built on that a memoize7 which enforces (through delays) that a value
> is onlycomputed once (except if the strategy previously removed it from the
> cache of course).
>
> Do you see a problem in my latest 
> implementation?http://gist.github.com/330644#LID153
>
> Thank you,
>
> Christophe

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