Re: Is game development Clojure(functional in general) friendly?

2012-10-30 Thread nicolas.o...@gmail.com
The usual approach to this kind of things is to have a Functional
representation of the world, that contains the game logic. To have
pure functions that modifies the world with the time and inputs of
players.
And everytime you want to render a frame to call a render function
that does all the work.

It is not clear whether you can have maximal performance with this
approach, in Clojure, on the JVM, but you can surely do something
decent.

This kind of appraoch is used in How To Design Program, v. 2. This
link shows the idea in Racket (another Lisp variant)
but it could give idea on how to do that in Clojure:

http://docs.racket-lang.org/teachpack/2htdpuniverse.html

They also did a free book:
http://world.cs.brown.edu/

As a rule of thumb, the idea with FP is always to pull out effects
towards the spine of the program and keep the remainder pure. (This
is, of course, not a law and should be adapted to practice)
Here instead of mixing your game logic and your rendering, which put
effects everywhere, you work only on pure data and at the very top you
use your data to draw a 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: monads

2012-10-30 Thread nicolas.o...@gmail.com
In a few lines:
Monads are a common framework to represent any sequential computation.
What is a sequential computation?
- either no computation at all.
   return :: a - m a
   does that.
- or I have already a computation and want to go on with my computation.
  But then, I need to be able to look at the result of the first part
of the computation
  to now what to do next:
  bind :: m a - (a - m b) - m b
  This tells: If I have a computation returning a value of type a, and
when I will know a, I will be
   able to create a computation returning some b, then I can sequence
those and make a computation
  returning some b. When I want to run it, I will run the first and
use the result to construct the second
   and then run it. *

What is interesting is that you have a representation of sequential
computations and can use a common libraries of
functions to work with any kind of sequential things. And there are a
lot of things that corresponds to this:
side-effects, logic programming, parsing...

Nicolas.

* The monadic notion of sequential computation allows to look at
intermediate results to determine what to do next.
  You obtain other notion of computations like Arrows or Applicative
functors if you restrict this right.

-- 
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: About code help: is it ok to ask for how to improve?

2012-10-30 Thread nicolas.o...@gmail.com
I would think so.

But to maximise your chances of getting useful help, it is often
better to post small pieces of codes and explain what
you are trying to achieve with them.

Best,

Nicolas.

-- 
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: best practices for small RAM usage

2012-10-04 Thread nicolas.o...@gmail.com
You have 2 distinct problems:
 - allocating many short-lived objects. It can affect performance but
does not matter for long-term memory occupation
 - keeping too many things in memory. Then you have to resolve an
algorithmic question, quite independent of
  the technology you use.

On Wed, Oct 3, 2012 at 8:17 PM, Thomas th.vanderv...@gmail.com wrote:
 try and use a 32bit JVM. I found that a 64bit JVM uses almost twice as much
 memory. YMMV

There is a flag for that:
 -XX:+UseCompressedOops

It is enabled by default in Java 6u23 and more recent (including Java
7), when your max heap is less than 32Go.
http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html

It uses a 32 bits representation for pointer in a 64 bits VM.

-- 
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: Does Clojure support efficient coroutines?

2012-09-27 Thread nicolas.o...@gmail.com
Depending of the code they have to write, you can walk their code at
compile time and transform it to
monadic normal form or CPS style, which would allow to do what you want.

I would tend to think that with a lot of threads you will win with
closures and not native threads.
And would only a few threads, threads would be faster.

-- 
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 : a good start for non-programmers?

2012-09-26 Thread nicolas.o...@gmail.com
Clojure is a good language to start.
The only thing is that there are more ressource for beginners in other
languages.

For Racket (another Lisp), you have the very good:
How to design programs.

http://www.ccs.neu.edu/home/matthias/HtDP2e/

(this is the second edition, you might have to peak in the first at
some points as the second is not totally finished yet, at least last
time I checked.)

It is free, beginner friendly and teach things properly.
Should not be difficult to jump to Clojure from there.

The other opportunity is the current coursera course:

Functional Programming Principles in Scala, on coursera.org

It teaches in Scala but most principles would apply to clojure 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: Does Clojure support efficient coroutines?

2012-09-26 Thread nicolas.o...@gmail.com
No continuations or coroutines support on the JVM, as far as I know.
However, there are a few monad libraries for clojure with which you
would probably
 be able to do what you want. (Using the continuation monad...)
http://www.intensivesystems.net/tutorials/monads_101.html , for example.

Delimited continuations also allows to mimic coroutines (and more).
There is this:

https://github.com/swannodette/delimc

There is another slight problem: the JVM do not have proper tail
recursions which makes
working with continuations trickier.
So you should know about trampolining.
http://pramode.net/clojure/2010/05/08/clojure-trampoline/

The best thing would be to tell us what you want to use coroutines for
and we could answer better on
what would be the best choice in clojure.

-- 
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: quick question about #'

2012-09-02 Thread nicolas.o...@gmail.com
I tend to like 1 better. I do not like working with vars without a good reason.

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


Re: how to translate this snippet from Scheme to Clojure

2012-08-31 Thread nicolas.o...@gmail.com
It is quite easy to write a macro define in clojure that does that:

(defmacro define [head   body]
   (if (sequential? head)
   `(define ~(first head) (fn [ ~@(rest head)] ~@body))
   `(def ~head ~@body)))

(define ((A [p1 p2]) [p3 p4]) [p2 p4]))

((A [1 2]) [3 4]) = [2 4]

-- 
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 Performance Comparison of SBCL Clojure

2012-08-26 Thread nicolas.o...@gmail.com
On Sun, Aug 26, 2012 at 3:07 PM, David Nolen dnolen.li...@gmail.com wrote:
 I haven't found this to be the case. Java fares pretty well on Alioth.

http://shootout.alioth.debian.org/help.php#java

Shows that it does not change much on programs that run for mor than a
few seconds.

-- 
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: 'functional' performance VS 'imperative' complexity

2012-08-26 Thread nicolas.o...@gmail.com

 1. Gary Bernhardt has been playing with a new approach he calls
 Functional Core, Imperative Shell. Essentially, it's another take on
 the question of how to limit the scope of mutation in order to get the
 most out of the correctness of mutation-free algorithms and the
 performance of mutating data instead of replicating it.


It seems to be this treats of another question: how to have IO in a
functional world.
And it gives the classic answer: write the functional core and wrap s
small IO shell around.

Jim is asking another question: what if you can't get good enough
performance in a given algorithm
with persistent functional data structures.

My views is that state is difficult. Every state makes your program
harder to maintain and less modular.
However, a localised state to a function or a group of functions is
perfectly fine.

In the case of your checkers problem, you can encapsulate in a
protocol the notion of being an undoable move:

(defprotocol UndoableMove
   (move [this b]  return the board or nil if it can't be applied)
   (undo [this b]  returns the board. Fails if it cannot be undone))

Then create a protocol for boards:

(defprotocol BoardLike
(apply-move [b m] Apply move m. Keep it in undo stack. Returns a board.)
(undo-last-move [b] Undo last move if any, else fails. Return a board))

(Note: I like better threading the board, even if it is updated in place.
It offers more flexibility: you can use persistent/transient or
mutable data-structures.
You can also decide to change representation of the board, if you want.)

What is essential though, is that if I use that to explore the game
tree, I would NOT use it
to represent the state of the game in rest of the program. Too many
way to stumble later.
I would convert the board into the mutable representation, and the
explore the game tree.
And copy back into an immutable board once done.

Transients are a good way to do this.

But the key is mutable state works for me for mono-thread, small localised 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: problem 58 on 4clojure

2012-08-25 Thread nicolas.o...@gmail.com
Here's my take:

We want to define a function my-comp. It takes n functions and return
their composition.
We want to return a function of any number of arguments, so let's
start by working with a given
set of argument args, and returning the value of the composition
applied to those arguments.

- If I compose only one function, you get the value of the function itself:
  (value-my-comp f)  = (apply f args)

- By definition of composition:
 (value-my-comp f1 f2  fn)  = (f1 (value-my-comp f2  fn))
(Take all the arguments, apply it to the composition of function f2
 fn, and then apply the result to f1).

Then you remove the dots:

(value-my-comp f1  f2-fn) =  (f1  (apply value-my-comp f2-fn))

Then you can just put them all together:


(fn [ fs] ;; we take a bunch of functions in
 (fn [  args ]  ;; we take the arguments of the resulting function in.
   (letfn [(value-my-comp ;; the value of the result in term of the
functions is:
   ([f] (apply f args))   ;; only one function
   ([f1  f2-fn] (f1 (apply value-my-comp f2-fn]  ;;
more than one function
  (apply value-my-comp fs  ;; we compute the value of the
actual function we got.

If you don't like (apply value-my-comp f2-fn), you can make
value-my-comp actually takes a sequence
of functions:

(fn [ fs] ;; take the functions
 (fn [  args ]  ;; the arguments of the resulting functions
   (letfn [(value-my-comp
[[f1  f2-fn]]  ;; a list of functions
  (if (empty? f2-fn)  ;; only one function?
  (apply f1 args)  ;; then we apply the args to it
  (f1 (value-my-comp f2-fn] ;; else we compose
  (value-my-comp fs
This one is another way of writing the one you posted.
(Using a let instead of applying it directly, and not using a
non-varying argument a.)

If you want to see how this function can be written to be very
performant look at
comp source code, it is very interesting.

Best,

Nicolas.

-- 
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: real-world usage of reducers?

2012-08-24 Thread nicolas.o...@gmail.com
More optimsation ideas:

 (defn next-level [b dir]

   (r/map #(Move-Board. % (core/try-move %))
  (core/team-moves @curr-game b dir))) ;;curr-game is a promise

 (definline team-moves
  [game b dir]
 `(let [team# (gather-team ~b ~dir)
tmvs# (r/mapcat (fn [p#] (r/map #(dest-Move ~game p# %) (getMoves
 p#))) team#)]
  (into [] tmvs#)) )

You should return tmvs# and not (into [] ...).
The beauty of reducers is that they are composable without putting
results in intermediate sequence.
So, as tmvs# is going to be passed to another reducer transformer, you
don't need to
convert it to a seq.


 (definline gather-team Returns all the pieces with same direction dir on
 this board b.
 [b dir]
 `(into [] (r/filter #(= ~dir (:direction %)) ~b))) ;all the team-mates (with
 same direction)

Same here, remove the (into []).
(Less important, you have only two directions, so you can compute the
closures for the two directions in advance
and use direction to choose. But it won't be a dramatic improvement.
For example:
(def gather-team
  (let [closure-up   #(= :up (:direction % ;; use the name of your
direction here
closure-down #(= :down (:direction %]
 (fn  [b dir]
   (r/filter (if (=dir :up) closure-up closure-down) ~b
)


 (definline dest-Move Helper fn for creating moves.
 [dm p dest]  `(Move. ~p (partial move ~dm) ~dest))
You might want to see if replacing (partial move dm)
by  #(move dm %1 %2) helps a bit.
I doubt it won't change much though.

 (defn move
 The function responsible for moving Pieces. Each piece knows how to move
 itself. Returns the resulting board without making any state changes. 
 [game-map p coords]
 ;;{:pre [(satisfies? Piece p)]}  ;safety comes first
 ;;(if  (some #{coords} (:mappings game-map)) ;check that the position exists
 on the grid
 (let [newPiece (update-position p coords) ;the new piece as a result of
 moving
   old-pos  (getListPosition p)
   new-pos  (getListPosition newPiece)]   ;;piece is a record
 (- @(:board-atom game-map) ;deref the appropriate board atom
Why do you need an atom 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


Performance of concatenating two vectors

2012-08-24 Thread nicolas.o...@gmail.com
Dear all,

After reading this:

http://infoscience.epfl.ch/record/169879/files/RMTrees.pdf

I was wondering what was the current performance characteristics of
the different ways to
concatenate arrays in clojure?

Best regards,

Nicolas.

-- 
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: profiler help...

2012-08-24 Thread nicolas.o...@gmail.com
  (and creates vectors via (into [] (r/map  )))

Depending of your method of scoring, you could try to do it just with a reducer.
(Without creating a vector with it).

If your code does not spend its time in GC (can be seen in the first
pane), CPU sampling might be a better place to look.

-- 
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: profiler help...

2012-08-24 Thread nicolas.o...@gmail.com
 (defn score-by-count ^long  [b dir]
 (let [ hm (into [] (core/gather-team b dir))
aw (into [] (core/gather-team b (unchecked-negate dir)))]
  (unchecked-subtract (count hm)
  (count aw



(defn counting-accumulator [acc _]
 (inc acc))

(defn score-by-count ^long [b dir]
 (let [ hm (core/gather-team b dir)
aw  (core/gather-team b (unchecked-negate dir))]
   (- (r/reduce counting-accumulator 0 hm) (r/reduce
counting-accumulator 0 aw)))

-- 
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: real-world usage of reducers?

2012-08-23 Thread nicolas.o...@gmail.com
If it is so slow, that's maybe because the branching factor is very high.
Could you have an atom incremented in your evaluation function, or in
next level, to check how many boards are generated for level 2 or 3?
(At least this could give an approximate time for computing each board.
(83 - 8) / num board computed. To check it is in line with what you
mesured of core.logic.)

And why do you need an atom in the move function?
(When is it changed?)

Lastly, if you just need core.logic to compute valid moves from the
logical rules of chess and do not check they actually
apply here, you could precompute that into a big table, which might or
not be faster.

-- 
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: What is the meaning of :while in a for ?

2012-08-23 Thread nicolas.o...@gmail.com
That's amazing.
Thanks.

On Thu, Aug 23, 2012 at 4:22 PM, Andy Fingerhut
andy.finger...@gmail.com wrote:
 I've added some examples of :when and :while, including those given by Herwig 
 and Tassilo in this thread, at ClojureDocs:

 http://clojuredocs.org/clojure_core/clojure.core/for

 Note: Anyone with a free account can add/edit examples on that site.

 Andy

 On Aug 21, 2012, at 8:34 AM, nicolas.o...@gmail.com wrote:

 I understand now.
 The documentation could be clearer on that.
 Your triangular example is very clear.

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



-- 
Sent from an IBM Model M, 15 August 1989.

-- 
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: real-world usage of reducers?

2012-08-22 Thread nicolas.o...@gmail.com
Hi,

3 questions:

1. Are you sure your moves list at the op level is in a vector?
  Looking at the code for reducers, it seems that it is the only
implementation actually doing concurrency.
2. The default block size for spawning a new thread is 512. Meaning
that if you have
  less than 512 first move in your game (quite likely, or else your
tree is too highly branching to do anything
 by min-max anyway), then it is only working on one thread.
This is tuned for large data set with moderate amount of work per datum.
Exactly the opposite of your workload. (Only 20 datums, but a lot of
work per datum).
 You will want to change the size of the block to something like 1, 2 or 3.
 So your last line should look like that:

(defn best-move Start folding here. [dir b d]
  (r/fold 1 best best
   (r/map #(Move-Value. (:move %) (search score-by-count (:tree %) d))
   (:children (game-tree dir b
next-level)
3. I have doubte about your best function. The first branch should
return something that the second branch can read.
I suggest:
(defn best
([] nil)
([best1 best2]
  (cond
(nil? best1) best2
(nil? best2) best1)
t (if (= (:value best1) (:value best2))
 best1 best2


With these modifications, it should run in // and be quite fast.

-- 
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: real-world usage of reducers?

2012-08-22 Thread nicolas.o...@gmail.com
Sorry, I forgot to convert to a vector:

(defn best-move Start folding here. [dir b d]
  (r/fold 1 best best
(r/map #(Move-Value. (:move %) (search score-by-count (:tree %) d))
   (into [] (:children (game-tree
dir b next-level))

-- 
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: Folding a reducer inside of a fold

2012-08-22 Thread nicolas.o...@gmail.com
 In particular, if I attempt to replace the `r/reduce` call on line #23,
 with a call to `r/fold`, I get the following crash:

This calss sems strange.
remaining? should represent a monoid for it to work.

Meaning two functions:
1 - A and (A - A - A)

In your code, the case with no arg returns a boolean, and the function
in the other branch wait
for a boolean and a number.

-- 
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: real-world usage of reducers?

2012-08-22 Thread nicolas.o...@gmail.com
On Wed, Aug 22, 2012 at 1:53 PM, Jim - FooBar(); jimpil1...@gmail.com wrote:
 Ok, so I followed your suggestions and the block size did the trick with
 regards to using all 4 cores of mine...However, even so, I get no
 performance improvements!!! It still needs close to 4 min to go to level 4
 and it still needs 5-6 sec to go to level 2 (a tiny bit faster than the
 sequential equivalent)...
You should see a close to *4 speed up, at least in the level 4.
One thing that could happen is if some of your functions are using
an atom or a reference and the threads keeps bumping into each other
and retrying.
Are you sure that both next-level and core-by-count are pure functions?
(And any other that are used in the search)


 3)I'm not sure I understand what you mean...You're returning nil - I'm 
 returning a very small number,
 they can both be read by the next branch don't they?

The problem is that (:value Integer/MIN_VALUE) is nil, which looks
like a bug and make your code hard to understand.

-- 
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: real-world usage of reducers?

2012-08-22 Thread nicolas.o...@gmail.com
 I'm really sorry but I don't follow...I'm only doing (:value best) or
 (:value next). best or next return a Move-Value (it has :move and :value
 keys) where the :value key could be Integer/MIN_VALUE - I'm not doing
 (:value Integer/MIN_VALUE) anywhere...

Then you want to write:
(defn best
([]   {:value Integer/MIN_VALUE})

because the second branch will be called with the result of the first
branch as a first argument.

-- 
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: real-world usage of reducers?

2012-08-22 Thread nicolas.o...@gmail.com
You should replace your functions that computes the board by function
that does return 30 times the same board.
And evaluation function by something that returns a constant value.
And check : speed and speed-up for folding.

Then you will know for sure whether the slowness comes from the
explore and search or from
the evaluation and computation of moves.

Alternatively, use visualvm (comes with jdk) or any other profiler to
check where are the cost.

-- 
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: What is the meaning of :while in a for ?

2012-08-22 Thread nicolas.o...@gmail.com
=
On Tue, Aug 21, 2012 at 11:50 AM, Arie van Wingerden xapw...@gmail.com wrote:
 Extra restrictions on (range of values of) variables used in the for.
 See here:
 http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/for

The link says nothing about the meaning of the modifiers.
(I agree it should, though.)

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


What is the meaning of :while in a for ?

2012-08-21 Thread nicolas.o...@gmail.com
Dear all,

What is the meaning of :while in a for?
I understand :when, and also that :while jumps more element when the
condition is not met,
but where does it jump to exactly?

Best regards,

Nicolas.

-- 
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: What is the meaning of :while in a for ?

2012-08-21 Thread nicolas.o...@gmail.com
I understand now.
The documentation could be clearer on that.
Your triangular example is very clear.

-- 
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: help needed to use reducers and monoid

2012-08-20 Thread nicolas.o...@gmail.com
(defn generate [board next-boards]
  ;; next-boards return a seq of MoveAndBoard

  (BoardAndChildren. board
 (r/map (fn [m]
  (MoveAndTree.
   (:move m)
(generate (:board m) next-boards)))
  (next-boards board


should work better.

-- 
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: help needed to use reducers and monoid

2012-08-19 Thread nicolas.o...@gmail.com

 How do I construct a combining fn out of 'max-key'  and is there an idiom or
 a pattern for doing so?
You might use the fact that -Infinity is a neutral element for max.
(Or the smallest long if you work with longs).
Alternatively you can represent your value as either a number or nil,
nil being the neutral element.

 Since the docs say that r/fold will only work in parallel for tree-like
 structures like maps and vectors, I've passing the lazy-seq through 'vec'.
 Does that make any sense whatsoever or will the entire thing be realized
 before it ever reaches r/fold?

Yes it will be realised but it does not matter as the children are not realised.
So just the computation of the next moves is done sequentially.

However, as I understand them, reducers will be of any help only if your
trees are highly branching. (They work chunk by chunk and not element
per element. They are tuned
for very simple operations on big data.)
I might be wrong on that though.

Concerning your code altogether, I have multiple remarks:
 - If you use lazyness for generating the tree (which may or not be
the right approach), I would not generate the tree up to a depth, I
would generate the infinite tee and then
  use a depth in the searching function. That way, if your search
function wants to have two level more, it can.
- I would not try to put concurrency in before I understand well the
performance of my sequential code. If you want to use
  eveloutionary algorithm to learn the best evaluation function, you
will have a lot of //ism coming from the evolutionary algorithm
anyway.
- I would profile the code.
- I would try to improve on the algorithm (alpha-beta pruning, a more
selective approach to unfolding nodes, and so on...)

To add concurrency, with the lazyness of the tree generation, I think
it is sufficient to add concurrency in the exploration of the tree.
You should check on the depth before calling a conccurent version.
(Find a depth that gives a reasonable amount of work. For smaller
depth,
run a sequential version of the algorithm.  ).
I am not a concurrency specialist at all, but I would do something like that:
 - realise all the children on one level. (You can also implement a
conccurent version of your valid moves generation, but it is a
different problem. And probably useless, because there is already a
lot of //ism in exploring the tree.)
- create a task per child corresponding to the exploration of said
child. As the operation is CPU bound, you want to have these tasks
executed by a thread pool with a fix number of threads. (There seems
to be Clojure libraries for that. Or you can implement this with
agents.)
- Wait on all the tasks and find the best solution. (best being min or
max depending of level.)
Note that making things concurrent might make it harder to improve the
algorithm.
(For example alpha/beta would need different tasks to communicate in some way.)

Best,

Nicolas.

-- 
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: help needed to use reducers and monoid

2012-08-19 Thread nicolas.o...@gmail.com
Hi Jim,

I tried a bit.
The performance of this is not perfect but seems not horrible.
It can do a level 5 exploration in 11 sec on my computer, with a
branching factor of 30.
(Of course, there is very little computation for the next move.)
The generation is now lazy, but the depth is used in the exploration.
THis will allow a more clever exploration strategy.
(Ideally you should go deeper in branch that are promising but uncertain.)

Apologies for the long code.
-

(ns explore.core
  (:require [clojure.core.reducers :as r])
  )
(set! *warn-on-reflection* true)

(defrecord BoardAndChildren [board children])
(defrecord MoveAndTree [move tree])
(defrecord MoveAndBoard [move board])

(defn generate [board next-boards]
  ;; next-boards return a seq of MoveAndBoard

  (BoardAndChildren. board
 (r/map (fn [m]
(MoveAndTree. (:move m) (generate (:board
board) next-boards)))
  (next-boards board

(defn my-max ([x y] (max x y))
  ([] Double/NEGATIVE_INFINITY))

(defn tree-value ^double [tree evaluate ^long depth]
  (let [children (:children tree)]
  (if (or (zero? depth))
(evaluate (:board tree))
(let [^double res
  (r/reduce my-max
(r/map
 #(- (tree-value (:tree %) evaluate (dec depth)))
children))]
  (if (= res Double/NEGATIVE_INFINITY) (evaluate (:board tree))
  res)

(defn best-move [board next-boards evaluate ^long depth]
  (apply max-key :value
(into []   (r/map (fn [m]
{:move (:move m)
 :value (tree-value (:tree m) evaluate depth)})
  (:children (generate board next-boards))

(defn test-speed [^long depth]
  (best-move nil #(repeat 30  (MoveAndBoard. :a %)) (fn [x]  0.0) (dec depth)))

-

Hope that will help,

Nicolas.

-- 
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: help needed to use reducers and monoid

2012-08-19 Thread nicolas.o...@gmail.com
By the way, I just found an obvious bug in that code, but
that should be easy to correct.

(if (= res Double/NEGATIVE_INFINITY) (evaluate (:board tree))
  res

This is obviously wrong.

-- 
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: help needed to use reducers and monoid

2012-08-19 Thread nicolas.o...@gmail.com

 thanks a lot Nicolas...I'll definitely play around with your code tomorrow
 morning...if you say you can go up to level 5 in 11 sec this is really good
 performance -I can't wait to explore the code...I'll let you know of any
 comments of mine soon!


Of course, don't trust this code. I have written it quite quickly and
might be totally wrong.
(On top of the bug already mentionned).
For example the trick of mapping - on the result of the lower level
tbefore maximising is dubious.
Maybe two functions, one with min, one with max would be clearer.
And I do not construct the best series of moves. Only the best first move.

-- 
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: help needed to use reducers and monoid

2012-08-19 Thread nicolas.o...@gmail.com
A correction for the wrong part:


(defn my-max ([x y] (if (nil? x) y
(if (nil? y) x
(max x y
  ([] nil))

(defn tree-value ^double [tree evaluate ^long depth]
  (let [children (:children tree)]
  (if (or (zero? depth))
(evaluate (:board tree))
(let [^double res
  (r/reduce my-max
(r/map
 #(- (tree-value (:tree %) evaluate (dec depth)))
children))]
  (if (nil? res) (evaluate (:board tree))
  res)

-- 
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: recursion question

2012-08-15 Thread nicolas.o...@gmail.com
First solution:

(defn groupSum [l x]
(or (zero? x) ; we have won!
(and (not ( x 0)) ; we can't win
   (not (empty? l)) ; lost!
   (or (groupSum (rest l) (- x (first l)))
(recur (rest l) x)

The we can't win line assume that all numbers are positive. We use
tail recursion in the only place we can use it.

If all numbers are positive, a more elaborate version would use this fact:
If all numbers are positive, and the sum of a suffix can't reach a
target, you should not try without the first element.
So the function will return :
 - either 0 if we reach the goal
 - a negative number if we went over the goal
 - a positive number if we went under the goal.

If we went under the goal, we don't need to try without the first element.

(defn groupSum0 [l n]
(if (or (empty? l) ( n 0))
n
(let [res (groupSum0 (rest l) (- n (first l)))]
 (if (= res 0) res ;; we are either winning or can't reach 
the goal
(if (zero? (groupSum0 (rest l) n))
  0  ;; we have won
   res)  ;; we repeat we can
reach the goal from here

(defn groupSum [l n] (zero? (groupSum0 l n)))

Next step would be to make groupSum0 not stack overflow on big inputs
and to add memoization to it.

Best regards,

Nicolas.

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


Re: How to measure pieces of Clojure code?

2012-08-11 Thread nicolas.o...@gmail.com
Visualvm is quite nice and simple to use.
On 10 Aug 2012 23:21, Hussein B. hubaghd...@gmail.com wrote:

 Hi,
 I want to measure how much space an algorithm is taking and then trying to
 change some aspects to see how things are going to differ.
 I also want to measure how much time it takes to complete an operation.

 What tools can I use?

 Thanks.

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

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

Re: basic question , clojure io

2012-08-08 Thread nicolas.o...@gmail.com
There is no such thing in Clojure.
Separation of IO and non IO is done by:

- encouraging pure functions
- providing very good pure data structures, and libraries

-- 
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: Attractive examples of function-generating functions

2012-08-08 Thread nicolas.o...@gmail.com
trampolines is a slightly different example.

-- 
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: record constructor

2012-08-07 Thread nicolas.o...@gmail.com
 (defrecord MyRecord [x y z]
   (make-record [arg1 arg2 arg3 ...] ...))

 (make-record MyRecord arg1 arg2 arg3 ...)

This construct is not very good. make-record is not first-class (It
cannot be used as an argument to a function).
Its first argument is not first-class (it has to be statically the
name of a class).

It exposes an implementation detail to client code (the name of a class).

If you really wanted to add constructors, I would think of a
make-MyRecord function or
a multimethod as in your first post, or even both, rather than 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: function calling itself using a generic self reference call?

2012-08-06 Thread nicolas.o...@gmail.com
(defn recurse [f] (fn [ args] (apply f (recurse f) args)))


(def fac
(recurse (fn [self n]
 (if (zero? n)
 1
 (* n (self (dec n)))

There is a performance cost. recursive can be specialised on different
number of arguments, to reduce
this cost.

A solution with macro is possible 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: record constructor

2012-08-06 Thread nicolas.o...@gmail.com
 My answer to this is: everything is an implementation at some level. So do
 you think we need factory functions of factory functions, and factory
 functions of factory functions of factory functions? I am sure that will be
 more flexible than just one level of factory functions.

We already have them. They are just functions.
(And I think thinking in term of factory functions does not make sense.
Every pure function takes something and makes something out of it)

The construction of data from data is best taken care by functions.
That way you don't expose more than you want and you are fully flexible.

If you want to have constructors for your records, define a function:

(defrecord R )

(defn make-R ([] ...) ([x y] ...))

What advantages have your proposal over 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: record constructor

2012-08-05 Thread nicolas.o...@gmail.com
Constructors are not a good idea, because they tie the functionality
to the implementation.


You want to be able to change your record to something else without
changing your client 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:

2012-07-31 Thread nicolas.o...@gmail.com
 The technique, using throw an Exception when succeeded in searching, strikes
 me!

You can make it less ugly with a bit of library:

user (deftype EarlyExit [result])
user.EarlyExit
user (defn early-exit [x] (EarlyExit. x))
user (defn reduce-with-early-exit [f acc coll]
(if (instance? user.EarlyExit acc)  
(. ^EarlyExit acc result)
(if-let [hd (first coll)]
(recur f (f acc hd) (rest coll))
acc)))

Then you can write:

(defn has22 [coll] (= (reduce-with-early-exit #(and (= %2 2) (or (not
%1) (early-exit :found!))) false coll) :found!))

You can write early-exit and reduce-with-early-exit by using a Throwable.
Whichever is best depends on how often you exit early and how long is
your sequence.

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

2012-07-30 Thread nicolas.o...@gmail.com
Another one. (The exception is for early termination)

(def found! (Exception.))

(defn has22 [l]
(try
   (reduce #(and (= 2 %2) (or (not %1) (throw found!))) false l)
   false
   (catch Exception e true)))

-- 
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: Transitioning an App from Java to Clojure (Notes of a Talk)

2012-07-28 Thread nicolas.o...@gmail.com
 There is indeed an infinite number of functions, or relationships between
 natural numbers. I don't think that means that that any one of those
 relationships is not computable because it is within the range of infinite
 functions. The countable parts of a program can still accept an infinite
 amount of input, like Turing's machine. So the best I can say is that all
 functions (relationships between natural numbers) can be computable, but
 humans may or may not have figured out a way to represent all natural
 numbers.

Some of these functions/relations are known to be not computable. For
example a function taking
the source code of a program (in any Turing-complete language) and
returning 1 if the
program stops or 0 if it runs forever. (the halting problem
http://en.wikipedia.org/wiki/Halting_problem )

This functions is mathematically perfectly well defined, but it can be
proved it can not be computed.
(No Turing machine can compute this function. It is important to
understand it is not a complexity
problem. It does not mean such a program would be too slow to be
useful. It really means such a program
can not exist.)

-- 
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: Transitioning an App from Java to Clojure (Notes of a Talk)

2012-07-27 Thread nicolas.o...@gmail.com
Hi,

Great notes. I like a lot.

A few (mostly technical) comments:


 Concept of Computation

 What does it mean to compute? Turns out this is a complicated question. From
 what I can tell, to compute is an actualization (or concrete version) of a
 mathematical function. We are swimming in a universe of functions in math,
 statistics and the natural world. The lights in here are a function of
 certain inputs: ie, the amount of electricity and whether the switch is
 engaged.

In all fairness, this is already an opiniated view of computations.
(It is the view of computations for a functional programmer.)
On top of that, the usual maths functions, do not treat well of partiality.
(non-termination, exceptions...)


 Alan Turing: Ideas of computation can be found in i) his contributions to
 the concept of an algorithm and ii) his description of a turing machine.
 Algorithm: An algorithm is just a step-by-step procedure for calculations.
 Those steps are expressed as a finite list of well-defined instructions for
 calculating a function.
 Turing Machine: This is a theoretical computer, that consumes i) an infinite
 ribbon of tape and ii) can perform read and write operations on the tape and
 iii) alters it's own state. This is a gross simplification. But the concept
 is that a Turing machine with the correct minimal set of operations can
 calculate anything that is computable, no matter the complexity (anything
 for which there is a function).

Anything that is computable is different that anything for which there
is a function, at least in classic mathematics.

2 simple arguments:
 - some functions are not decidable.  (halting problem, for example.)
However, in classic mathematics
 such a function exists. You can even prove its value on some inputs.
 - There is an uncountable number of functions from natural numbers to
natural numbers, and a countable
  number of programs taking a natural number to a natural number. (A
program is a list of character.) So there
 is more functions than computable functions (and, uncountably,
infinitely so.).

There is a branch of mathematics, constructive mathematics, that
exclude things that you can not construct
with a program.


 LISP's approach to computing: Created by John McCarthy, Lisp was originally
 created as a kind of practical mathematical notation. Lists were the major
 data structures and functions were just another value passed into a list.

 Probably one of the defining qualities of Lisp, is that it can be written in
 itself (code is data). This is what makes on-the-fly change of your running
 code (ie macros) possible.
macros are not on the fly change of your running code.

Best,

Nicolas.

-- 
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: reduction to tail recursion

2012-07-24 Thread nicolas.o...@gmail.com
On Mon, Jul 23, 2012 at 3:14 PM, Mimmo Cosenza mimmo.cose...@gmail.com wrote:
 hi Merek and thanks for the link. But it does not answer my question.
 I was looking for a demonstration of the reducibility of (not tail)
 recursion to tail recursion. Or there is a demonstration of that, or nobody
 could say that a (not tail) recursion definition is always reducible to a
 tail recursion definition.

Longer explanation:

Two versions of the proof.
- Every program can be translated to a Turing machine. A turing
machine interpreter can easily be written with a while loop.
  Any while loop is a tail recursion.
- A more interesting proof requires to understand Continuation Passing
Style (CPS) transformation:
 http://en.wikipedia.org/wiki/Continuation-passing_style

In a CPS program, every call is a tail call. You can systematically
transform any program to a CPS one.

In practice, it is often sufficient to mimic the data stack, by adding
an argument containing the stack.

-- 
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: reduction to tail recursion

2012-07-23 Thread nicolas.o...@gmail.com
Yes.

For example, you can have a look at CPS transformation.

If you want tail recursion and not tail calls, you can add
trampolining to the mix.

-- 
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: If a protocol creates a Java interface under the covers...

2012-06-14 Thread nicolas.o...@gmail.com
 (defn move
 The function responsible for moving Pieces. Each piece knows how to move
 itself. If trying? is true, there will be no histiry of the new state of the
 board. Returns the new board.
  ^clojure.lang.PersistentVector
 [game mappings p coords]
 {:pre [(satisfies? Piece p)]}  ;safety comes first

 (if (in? mappings (vector-of-doubles coords)) ;check that position exists on
 the grid
 (let [newPiece (update-position p coords)] ;the piece that results from the
 move
 (reset! (current-items game true) ;replace the appropriate board atom and
 log new state
 (populate-board game   ;replace dead-pieces with nils
 (- (current-items game false) ;deref the appropriate board atom
    (assoc (getListPosition p) nil) ;old position should have nil
    (assoc (getListPosition newPiece) newPiece) ;new pos shoudl have the
 new piece

 (throw (IllegalArgumentException. (str coords  is NOT a valid position
 according to the mappings provided!)

There should not be any atom in this. The function would be more
reusable if it take a board and return
a board without changing any atom.
(You will still be to express the atom change around it but you could
also use to try and build a tree without undoing
anything.)


 (defmacro current-items
 [game atom?]
 `(condp = ~game
       (symbol chess)    (if ~atom? current-chessItems @current-chessItems)
       (symbol checkers) (if ~atom? current-checkers   @current-checkers)
 ))

I don't think this approach is extensible enough. You will want to
implement more games later.
So maybe a good thing is to use protocols or multimethods to represent
game rules.
The atoms should disappear until later. (You are building a library of
moves and rules, there is no notion
of state in that. Only when you use it for playing a game on a GUI you
will need a state)



 populate board is a monster I don't even want to look at it!


 (defn populate-board
 Builds the appropriate board (chess or chekers). Will have nil at vacant
 positions. Really ugly fn but it does everything in 1 pass!
  ^clojure.lang.PersistentVector
 [game board]
 (loop [nb (vec (empty-board game)) ;building a brand new board after each
 move
       p  board]
 (if (empty? p) nb
  (let [fp (first p)]
    (recur
    (if (nil? fp) nb ;if encounter nil just carry on recursing with the
 current board
       (assoc nb  ;else
          (getListPosition fp)    ;the piece's position
        (if (dead-piece? fp)   nil ;if the piece is dead stick nil
                         fp)))  ; else stick the piece in
         (rest p) )  ;carry on recursing

If it is just to remove dead pieces, you could do it during the move.
(When a piece is killed remove it immedialty.)
Then you don't need to copy the board, which will be in turn slightly
less expensive.
(Being able to share and not to copy is one of the benefits of immutability.)

Else something like (into [] (map (fn [x] (and (not (dead-piece? x))
x)) board)) should work.

-- 
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: Is there a reason why 'some' returns nil instead o false?

2012-06-14 Thread nicolas.o...@gmail.com
 (defmacro in?
  Returns true if colle contains elm, false otherwise.
  [colle elm]
 `(if (some #{~elm} ~colle) true false))

Yes. Should not be a macro. (There is no reason for it to be a macro).
On top of that, it is not very often useful to convert nil to false as
clojure understands nil/not-nil as false/true everywhere.
(Someone corrects me if there is a counter example.)

Might be useful for java interop?
Then I would define a
(defn to-bool [x]
   (if x true false))
and use it when necessary.

-- 
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: Is there a reason why 'some' returns nil instead o false?

2012-06-14 Thread nicolas.o...@gmail.com
On Thu, Jun 14, 2012 at 6:19 PM, Jim - FooBar(); jimpil1...@gmail.comwrote:

  I don't see why not if you really really need to return true/false...


Because it can be written as a function. Macro are only for things that
cannot be easily written as functions.
(And then it should be backed by functions that are usable but less
convenient.)
(That is the general theory. There might be exceptional situation where
macro are better. )

-- 
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: Is there a reason why 'some' returns nil instead o false?

2012-06-14 Thread nicolas.o...@gmail.com


 why add the extra overhead of potentially boxing/unboxing x in such a
 simple case? Its not like the macro is getting out of control...Its a one
 liner...

 Because functions are first class and not macros.
Ex:

(map to-bool l)

-- 
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: If a protocol creates a Java interface under the covers...

2012-06-13 Thread nicolas.o...@gmail.com
that mutation inside piece is
 the only non-functional  detail...everything else I am indeed returning new
 boards, new pieces (promotion, death etc)...


If I were you, I would look into a way to make Pieces pure too.
Because their mutability cascades into the whole state and makes the description
of the world non functional.
If everything was functional, undoing and exploring the tree and so on
would be straightforward.

-- 
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: If a protocol creates a Java interface under the covers...

2012-06-13 Thread nicolas.o...@gmail.com
On Wed, Jun 13, 2012 at 10:46 AM, nicolas.o...@gmail.com
nicolas.o...@gmail.com wrote:
 that mutation inside piece is
 the only non-functional  detail...everything else I am indeed returning new
 boards, new pieces (promotion, death etc)...


And from what I understand of your design, I disagree on a point: I
think it is not true a move is a command apply to
a piece. A lot of moves involve multiple pieces.
So I would try to represent a move as something like:

(defprotocol
   Move
   (can-execute [board] check the move can be executed on that board)
   (execute [board] return the board after the move)
... )

-- 
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: If a protocol creates a Java interface under the covers...

2012-06-13 Thread nicolas.o...@gmail.com
 different positions now or some are nil (dead))... if i make the pieces pure
 what comes to mind is resetting or swapping possibly 32 atoms instead..

No, you will have an atom containing a new board with new pieces in
their new position.
(By the way, you can go a long way writing what you want to write even
without an atom.
The game logic should be functional with very few places altering the
game state, possibly in
another namespace.)

-- 
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: If a protocol creates a Java interface under the covers...

2012-06-13 Thread nicolas.o...@gmail.com
 you mean making 32 new pieces after each move regardless of whether they
 moved or not? how can I identify the ones that are different from the ones
 that remain unchanged so i can conj them in a new list? move will eventually
 call 'build-board' which has to look somewhere for the current pieces. If
 moving a piece returns a new piece how do i associate it with the previous
 board to produce the new? remember the piece has to leave its current
 position and go the next one. That is one dissoc and one assoc isn't it?


No. If they are immutable you can reuse all of those that didn't change.
(That also includes part of the board structure itself that do not change).

For example, if your state were a vector [:x :o :x nil  :x]
(for a board of tic-tac-toe), calling (assoc board 3 :x) will return a
new board
with the position 3 set to :x. This board shares all other content,
and even part of
the structure of the board is kept.
This should be enough to represent and operate on the game state.
Performance should be quite good too. A big win is in clarity of the code
and in the fact you can keep different states around: you won need undo
and exploring a tree in // will be easy.

-- 
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: Slow 'quick sort'

2012-06-08 Thread nicolas.o...@gmail.com
Stack-overflows in quicksort can mean that you are hitting the worst
case of this algorithm complexity.
(Meaning that you are sorting an array already sorted in one direction
or the other.
In this situation, the size of the recursive call are n - 1 and 0,
instead of being roughly n/2 for both calls.
Which means that: the stack usage is linear and the complexity is quadratic.
)

Can you try to shuffle your array first?

-- 
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: CRUD application backed only by immutable facts

2012-06-05 Thread nicolas.o...@gmail.com
It is not totally clear in your post how you want to keep the data?
Is it in memory (with a transactional log somewhere)?
If it is the case, you can do better than reducing the whole data set
when executing a query:
you can keep a cache of query results, or indexed data and maintain
it, while still being
purely functional. (For example by attaching those results as meta
data to the data structure, and
defining your own assoc-like functions that maintain a consistency of
the meta-dataed query results)

On Tue, Jun 5, 2012 at 1:59 AM, Kevin Lynagh ke...@keminglabs.com wrote:
 Has anyone seen or implemented a CRUD application in Clojure using a
 database of immutable facts?

 For instance, a traditional database table supporting a todo-list
 application has columns

    user_id, task_id, task_description, is_done

 A new row is created when a user adds a task.
 Then that row is updated so is_done = TRUE when the user checks the
 task off.

 With immutable facts this would instead be a collection of statements:

 User U added task T with description D at time T1
 User U completed task T at time T2

 To get a list of unfinished tasks for a user, you'd need to grab all
 the tasks from this transaction log, put them into a data structure,
 and then remove ones when you learn that they've been completed.
 Whatever is left over is the todo list.

 Nathan Marz talked about this in terms of big data:

    http://nathanmarz.com/blog/how-to-beat-the-cap-theorem.html

 and Datomic's big bet is that your life as a developer gets much
 easier when you just deal with (entity, attribute, value) + time.

 I buy it in theory, but I have no idea what to expect in terms of
 performance (e.g., how long would it take to find the current todo
 list of someone who has added and completed/removed a few thousand
 items?).

 Has anyone implemented this idea on Clojure datastructures using,
 say,  (timestamp, keyseq, value) and reducing a ton of calls to assoc-
 in?
 Aside from speed, what are some other tradeoffs of an immutable
 approach?

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



-- 
Sent from an IBM Model M, 15 August 1989.

-- 
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: Recursive lets

2012-05-30 Thread nicolas.o...@gmail.com
 I agree with the other commenters that letfn is good when you can use
 it, but here you can't use it. Your general approach is really the
 best you can do, though it's nicer to use promise/deliver than atom/
 swap!, since these values are never going to change again.

I was looking for something equivalent to letrec in scheme. (Which
allows slightly more than let or letfn)

But your idea of a promise/deliver is nicer than my atom/reset!: it
expresses the idea of closing the loop better.

Thanks again.

Nicolas.

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


Recursive lets

2012-05-29 Thread nicolas.o...@gmail.com
Dear all,

Is there a way to write something like:

(let [x (foo1 (fn []  (bar y)))
  y  (foo2 x)]   )

where the y on line 1 refers to y in line 2?

I currently use an atom and an affectation to tie the loop...

Best,

Nicolas.

-- 
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: defrecord with inheritance

2012-05-22 Thread nicolas.o...@gmail.com
 Everyone just reiterates the mantra “It's slower! It's slower! It's
 slower!”, but no one talks about the trade-offs. And I bet only a very
 small fraction ever checked what “slower” means in their specific use
 case.

I think the whole thread is about the trade-off: some people complains
that deftype lacks features.
Another problem with extend is that you can't access your instance
variables with
it. And so you end up creating fake Protocols for that, which is even
worse than a big deftype.

-- 
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: defrecord with inheritance

2012-05-22 Thread nicolas.o...@gmail.com
 The only exception is mutable fields in the type where you don't want
uncontrolled access. There you indeed need a protocol to handle the
synchronisation of the field access.


And then you need to include everything accessing the internal state of
your data structures in a big deftype with little possibility of reuse.

For example, the earlier hash example cannot be put as an extension.

Another related problem is the fact that lambda do not close over the
mutable fields within a deftype. (Or at least that is what i understood
from several strange error messages.) FP stops at the doors of deftype...

-- 
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: defrecord with inheritance

2012-05-22 Thread nicolas.o...@gmail.com

 Access internal state?


Like __hash in your code.

 For example, the earlier hash example cannot be put as an extension.

 Why should most extensions manipulate mutable fields?

Most certainly won't. Now none of them can.

-- 
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: defrecord with inheritance

2012-05-21 Thread nicolas.o...@gmail.com

 Have you actually looked at the data structure implementations in
 ClojureScript? The work is done. It's all protocols.

Hi David,

I just have. This is a nice work. There is a lot of repetitions though.
For example:
- IEquiv
  (-equiv [coll other] (equiv-sequential coll other))

-   IHash
  (-hash [coll] (caching-hash coll hash-coll __hash))
 (where caching-hash has to be a macro)

-  ICounted
  (-count [coll] count)

-  ILookup
  (-lookup [coll k] (-nth coll k nil))
  (-lookup [coll k not-found] (-nth coll k not-found))

All these appears multiple times in the file, each time for the same
underlying reason.
Each occurance is a missed opportunity for code reuse.
(There must be other repetitions, that just those I found in a 2 minutes search)
Add 4 more types of Vectors and you will have 4 more copies of those.
And, I am not sure of that, but I think that in Clojurescript, the
extend family has the same performance characteristics than deftype.
Which makes things easier.

Of course, deftype is sufficient for writing any class system, but you
have to repeat yourself.
And that is annoying.
I don't advocate inheritance, which I think is a wrong answer to a
good question, but
someone needs to think of a way to reuse code in deftype.

If you look at the big picture, multimethods are wonderful, protocols
are great, reify is amazing,
the extend family is top notch, but deftype lacks far behind in expressivity.
(It is a very low-level construct, which the other are not.)
And if deftype is in the language is because it is sometimes useful.
And if it is useful, it should be made a pleasure to use as is the
rest of the language.

My first idea would be to add a macro (deftype-something body) that
executes (or reduces) body at compile time
in order to build a data structure containing the fields and the
protocol/interface instances to be included in
the resulting deftype. And then build a small library of functions to
build classes. (extend-protocol, add-field, an so on...). It would
solve one of the main problem of deftype: neither FP nor macros can
help you much to build a type.

Best,

Nicolas.

-- 
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: defrecord with inheritance

2012-05-21 Thread nicolas.o...@gmail.com

 And now any of those implementations can easily change at anytime without
 any external considerations. So what's the problem?

Well if you want to amend all of them at the same time, you have to
modify all of them.

On your advice of using extend-type: maybe I am wrong but I think it
has a performance cost.

I am not sure for the 1%, but the good metric is to look at the
percentage of deftypes, not the whole code base.
I think in a typical program, deftype already amount at less than 10%
of the code.

I wrote some code with a lot of different types implementing the same
interfaces and that are made
by composing different parts.
I ended up splitting aspects in different types and use composition
and fake protocols to implement
cross-cutting aspects. I would have loved to have traits to do that
instead: would have been easier, more performant
and more natural to read.

I could also have copied and pasted a lot, but it is asking for
problem if you modify things later.

-- 
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: defrecord with inheritance

2012-05-21 Thread nicolas.o...@gmail.com
 Same here--I can count on one hand the number of times I've wanted to
 implement polymorphism in three and a half years. Every time
 multimethods have worked great for the task. If you had polymorphism
 in a tight loop they might not suffice, but the decision to abandon
 multimethods should only be made after thorough benchmarking.

I agree multimethods are great.
But when in a tight loop, you don't like them so much.

The point is not whether deftype is useful or not. It is in the
language so it must be useful, even it it is rarely.
The point is whether it is an expressive construct or not.
And it is not expressive enough to my taste.

-- 
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: defrecord with inheritance

2012-05-21 Thread nicolas.o...@gmail.com
 On the other hand, defrecord/deftype encourage you to write your protocol
 implementation in a way that cannot be reused unless you very specifically
 plan for it (factoring the protocol implementation into a separate map) and
 use a coding style that (might?) be less efficient (i.e., adding the
 protocol implementation via extend rather than directly in defrecord).  This
 is not so good and potentially limits the value of protocols for developing
 complex systems.


Inheritance is bad because it ties code reuse to a (mostly)
non-significant hierarchy.
That is not a reason to prevent all code reuse from deftypes.

(It is not because OO gets it wrong that we should not try)

-- 
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: defrecord with inheritance

2012-05-20 Thread nicolas.o...@gmail.com
 (extend Employee
         AProtocol
         (merge default-implementation {:new-function (fn ...)}))


But you lose a bit of performance with 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: defrecord with inheritance

2012-05-20 Thread nicolas.o...@gmail.com
I had wished such a feature all week.
You don't need it often, but when you need it, it is really annoying
to circumvent.
traits would really be useful.

-- 
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: defrecord with inheritance

2012-05-20 Thread nicolas.o...@gmail.com
 So I suggest you take it to heart.  Put deftype, defrecord and defprotocol
 away and don't pull them back out for quite some time.  At the beginning,
 they are just a distraction from Clojure's core philosophy.  Focus on maps,
 vectors, sets, functions, multimethods and macros.

But there are just some algorithms that you need to write in a low-level way.
(Implementing the data-structures built-in in Clojure would be such an example.)

And for this, it you are on the JVM, you want a way to build objects.
And then comes deftype. And after 2 hours, you realise that you would
like to have traits.
(It is quite rare to need them, but very useful when it is the case).

-- 
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: Let over Lambda

2012-05-18 Thread nicolas.o...@gmail.com
LoL is a good book. Very entertaining, even if part of the content is debatable.
(It is a very opiniated book)
Reading it after On Lisp could be a good idea, as there are a few
references from LoL to On Lisp.
http://www.paulgraham.com/onlisp.html

The book is definitely a good read, makes you think a lot, and the
chapter about Forth is very different from any Lisp book. (Because it
is partly about Forth)

-- 
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: Avoid duplicate computation in commute?

2012-05-18 Thread nicolas.o...@gmail.com
I think part of the problem is that commute should not return any result.
You are not sure this is actually the value that will be returned,
this is costly
and misleading.

There should be at least a variant of commute that return 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: Clojure Bee iPhone app updated

2012-05-17 Thread nicolas.o...@gmail.com
Any android port in the pipeline?

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


Iteration or reduction on a transient map

2012-05-16 Thread nicolas.o...@gmail.com
Dear all,

Is there a way to apply a function to all members of a transient map?


Best regards,

Nicolas.

-- 
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: Iteration or reduction on a transient map

2012-05-16 Thread nicolas.o...@gmail.com
So, if I have a transient and want to reduce it and then continue to
use it transiently,
I need to call persistent!, reduce and transient again.

Is there a reason for that?

(The documentation says that read operation are allowed. And it is
actually possible
to write a reduce for a transient vector.)

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

2012-05-11 Thread nicolas.o...@gmail.com
On Fri, May 11, 2012 at 12:47 AM, Rich Hickey richhic...@gmail.com wrote:
 IMO, Nicolas' material is a distraction in understanding reducers, except as 
 historical background.

I perfectly agree.

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

2012-05-10 Thread nicolas.o...@gmail.com
I can describe the background to understand my last email.

From the programming point of view, I have been told since yesterday
that what I explained has already been explained better in Stream
Fusion From Lists to Streams to Nothing at All from Coutts
Leschinskiy and Stewart:

metagraph.org/papers/stream_fusion.pdf

The article is very clear if you can get used to the strange Haskell
syntax and its lack of brackets.

off-topic
From the cultural/theoritical point of view, there is quite well
understood link between data-structures and
some categorical structures.
( I try stay informal and put fancy names and link to definitions
inside brackets )

Types of finite recursive data structures (think of a list) are
defined by being the smallest solution to an
equation like List = 1 + Any x List. Here 1 means the type that
contains only nil, Any means the type of anything, x corresponds to a
pair and + to a choice. So this reads: a list is either nil or a pair
of anything and another list.
Being the smallest solution means that it contains only finite data-structures.
( http://en.wikipedia.org/wiki/Initial_algebra )

An element of such a type is characterised by how they can be reduced/folded.
( http://en.wikipedia.org/wiki/Catamorphism )
fold: forall A, List - ((1 + Any x Acc) - Acc) - Acc
Meaning that there is a one to one mapping between lists and functions of type:
forall Acc, ((1 + Any x Acc) - Acc) - Acc
This is the type of #(reduce _ l): you give it a function that takes
either no arguments and give you
an initial Accumulator or take an element of the list and and the last
Accumulator and returns a new Accumulator, and it returns the last
Accumulators.

This one to one correspondence can be seen as (reduce _ l) in one
direction and  #(_ (fn [p] (and p (apply cons p))) in the other
direction.

This definition of lists (as functions) has been used in programming
languages without data constructors.
( System F for example, http://en.wikipedia.org/wiki/System_F ).

If you look to infinite data structures, like Streams, they are the
biggest solutions of similar equations:
Stream = 1 + Any x Stream (if you accept a Stream can finish early)

They are dual (which means you invert all arrows in all definitions) to Lists.
( see Final Coalgebra in http://en.wikipedia.org/wiki/Initial_algebra )

A stream is characterised as how it is unfolded/generated.
unfold : forall B, (B - 1 + Any x B) - B - Stream
(See how the arrows are reversed with respect to fold)
And so they are in one to one correspondence with :
exists Seed, (Seed x (Seed - 1 + Any x Seed))

Which means any Stream can be defined as a Seed, of a given type Seed
that you can choose freely,
and a way to grow from the seed, a function grow that takes a Seed and
tells you:
- either that the Stream is finished
- or the first element of the Stream and the Seed for the rest of the Stream.

For example the stream of even natural numbers can be seen as the seed
0 together with a function
grow = (fn [ seed ] [ seed (+ seed 2)  ]), saying that first element
is equal to the seed and the rest of the stream
is the one defined by a seed = seed + 2 .

A very good paper showing this style of programming, and more, is :

http://eprints.eemcs.utwente.nl/7281/01/db-utwente-40501F46.pdf
/off-topic

Sorry for the long off-topic.

Best regards,

Nicolas.

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

2012-05-09 Thread nicolas.o...@gmail.com
It looks very good.

Just a few side-notes:
 - this representation is quite well known, as it is the Church
encoding of list, often used in System F, for example.
   It corresponds to stating the definition of sequences as the
initial algebra of F A = 1 + Any x A.
 - you can play a dual trick for Streams and coLists by representing
them as how to generate them, the same way that you can represent list
as how you reduce them.
This gives a representation of a coList as
   [ seed f ] where f is a function from the seed to either nil(if the
coList is finished) or a pair of an element and as seed.
For example, the integers would be
nat =[ 0 (fn [n] (vector n (+ n 1))) ]
Then, you can play the same game and define map, filter (which is not
always productive...), and so on, on this
representation, with the same benefits.

You can then also write converters from this representation to
reducible. This would allow to write
(reduce + (take n nat)) without allocating any sequence...

Best,

Nicolas.

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

2012-05-09 Thread nicolas.o...@gmail.com
On Wed, May 9, 2012 at 1:00 PM, Rich Hickey richhic...@gmail.com wrote:
 This analogy is not quite right.

 (fn [n] (vector n (+ n 1))

 is not a reducing fn. Tt is a cons cell builder, and the Church encoding 
 builds lists.

It is because I did not write it in the right way. Sorry about that.
It can be made nicer with protocols, probably. But the idea is quite simple.
Something is generative (dual to reducible) if it contains a seed, a
function from seed to the first element (called now)
and a function from a seed to the next seed (called later).
Then

(defn from [n]
 [n id inc])

(def nat (from 0))

Then, take converts a generative to a reducible:

(defn take [n [seed now later]]
   (fn [ r ] ; r is the function we reduce with
(loop [m (long n)   seed seed acc (r) ]
(if (zero? m) acc
  (recur (dec m) (later seed) (r acc (now seed)))
) )

So in (reduce + (map square (take n nat))), there is no cell cons
created in any way.
It just beta-reduces to the loop someone would write for the same problem:
(without any kind of deforestation):
(loop [m (long n)   seed 0 acc 0 ]
(if (zero? m) acc
   (recur (dec m) (inc seed) (+ acc (square seed)))

By the way, map has also a definition in the generative setting:

(defn map-generative [f [seed now later] ]
   [seed (comp now f) later])

There might be multiple interesting way to convert from generative to reducible.
take is one, until can be another:

(defn until [p [seed now later]]
   (fn [ r ]
(loop [seed seed acc (r) ]
(let [v (now seed)]
  (if (p v)
  acc
  (recur (later seed) (r acc v)))

It can happen than this never ends if p is never true. (You can add an
optional limit on the number of elements.)

Then to sum all squared number smaller than 100:
   (reduce + (until  #(%  100)  (map square nat))

Then again, no cons cell allocated.

It is straightforward to extend the generative things so that they can
finish early, when now returns nil
for example. Then you can convert easily those finite generative to reducible.

One last point: you can convert any sequence (including infinite
streams) to a generative by using
(fn [s] [ s first next ] )

It is also possible to convert any generative to a stream (for
memoisation for example)
However,the generative representation is independent of the sequence
representation.

 It is only by doing this that you can get the true prize of this library - 
 versions of map/filter etc that can be run in parallel, and that are 
 completely independent of the data structures on which they are run.


It is less clear that generative things are amenable to //-reduction.
However, it should be possible to add a function to jump ahead.( [seed
now later jump] )
This function could default to calling later repeatedly, but can
sometimes be implemented more efficiently.
It might be possible to do better if your reduction function is commutative.

I am not saying it replaces reducible, but that it can be an
interesting complement for a generate/reduce pattern.

I hope it clarifies my last email.

Best,

Nicolas.

-- 
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: code as data vs. code injection vulnerability

2012-05-09 Thread nicolas.o...@gmail.com
On Wed, May 9, 2012 at 5:01 PM, Rostislav Svoboda
rostislav.svob...@gmail.com wrote:
 On 9 May 2012 17:31, Tassilo Horn tass...@member.fsf.org wrote:
 you should bind *read-eval* to false when reading data from unknown sources.

 This is the point! On one hand I need to evaluate data from a client
 on the other hand I'd like to filter out things like rm -rf /, drop
 table users etc.

The best practice is to not evaluate data from your client but to read
it, and process it.
It is a hard problem to decide if a given piece of code in any
language can be safely evaluated or not.
If you really need to evaluate program from hostile clients, design a
small language allowing only safe
programs and write a translater into clojure then eval the 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: question about a macro

2012-04-20 Thread nicolas.o...@gmail.com
Part of the problem is that you confuse compile time and runtime.

Macro are evaluated at compile-time.

So when you write:

(my-macro SomeClass. a b) , my-macro can't access the runtime value of a and b.

So if you want your second example to work, you need flatten to be
called at runtime and not macro-expansion time.

So, if you wanted to apply my-macro to a function, and not a
constructor, something like:

(defn my-macro [fun  args]
  (apply fun (flatten args)))

should work.

However, it probably don't work for SomeClass., which is not a function.

 One way to solve that is to define a function wrapping around
SomeClass. with the  right number of arguments.

Another way is to do a macro which use reflection to look at the
number of arguments of SomeClass. at compile time
and eta-expand it. (ie change (my-macro SomeClass.  args) into (apply
  (fn [ x1  xn ]  (SomeClass. x1 ... xn)) (flatten args)), where
n is computed using reflection).

If SomeClass. takes different possible number of arguments, then the
expansion is a bit more complex because you need to check the number
of arguments at runtime
and call the right constructor.

Best,

Nicolas.

-- 
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: question about a macro

2012-04-20 Thread nicolas.o...@gmail.com
On Fri, Apr 20, 2012 at 11:14 AM, Marc Limotte mslimo...@gmail.com wrote:
 Thomas,

 Try this:

 (defmacro my-macro2 [func  args] `(~func ~@(flatten (eval (vec args)



This won't work for:

(let [a [2 3]] (my-macro2 SomeClass. a))

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


Re: Newbie question about rebinding local variables

2012-04-20 Thread nicolas.o...@gmail.com
This is not the idiomatic way but you can stay quite close from your code by:

(defn game [ board ]
 (fn [n i]
  (cond
 (= n :x) (game (assoc board i 'x))
 ( = n :o) (game (assoc board i 'o))
 (= n :print) (println board

(defn (new-game (game (into [] (repeat 9 nil)

But this is still an encoding of message-passing OO, which is not very
idiomatic.

-- 
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: An efficient persistent, immutable deque for Clojure with amortized O(1) peek and pop at both ends

2011-01-23 Thread nicolas.o...@gmail.com
Did you have a look at:

http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf

After p. 50 there is a description of dequeues. I don't know how they
compare to yours.

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

2011-01-22 Thread nicolas.o...@gmail.com

 Is this also useful for implementing something like Datalog? If yes,
 in what ways?

 Regards,
 Shantanu

I don't know for Datalog but for Prolog.

Imagine you have
parent(a,b).
parent(b,c).

ancestor(X,Y) :- parent(X,Z) , ancestor(Z,Y). (1)
ancestor(X,Y) :- parent(X,Y). (2)

Now you have the goal:
ancestor(a,V).

to apply the rule (1) you must unify ancestor(a,V) with ancestor(X,Y).
It gives you :  {X - a; V -Y}
Then, you must unify parent(X,Z) with either parent(a,b) or parent(b,c).
Only the first one is possible knowing X-a and you get back:
{X-A,V-Y, Z-b}...

and so on.

Prolog alternates branching point with an unification of the goal and
the result of the rules
(and of course backtracking)

Hopes that helps a bit,

Nicolas.

-- 
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: Enhanced Primitive Support Syntax

2011-01-17 Thread nicolas.o...@gmail.com
On Mon, Jan 17, 2011 at 3:10 AM, chris cnuern...@gmail.com wrote:
 Is it insane to suggest that perhaps clojure should work with scala
 such that we can write both languages in the same file?


A lot of reasons for which it is not possible:
- it would mean coordinating two implementations/implementers.
- it would prevent to go to platform for which there is no support in
the other language.
- A type checker would not be really happy to deal with a lot of
Object - Object functions...
- it would be ugly

Having a bit of (optional) type inference for performance and
compile-time safety in Clojure could be interesting though.

-- 
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: Speed of clojure hash map vs java hash map

2010-12-29 Thread nicolas.o...@gmail.com
I never was fully convinced an atom around a functional hash was
perfect for concurrency.

There is no write/write or read/write concurrency possible, even on
independent data.

Someone was working a while ago ob TransactionalHashMap, if I recall well.
Is there something already to benchmark against java?

-- 
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: Public mutable fields in deftype

2010-12-24 Thread nicolas.o...@gmail.com
After a few thoughts, I think this is a mistake not to allow this,
even if it his highly discouraged.

I think indeed, if you consider the data-structure usage of types and
Objects it is a very bad idea to have a mutable private field.

But some type you create are not for holding data on the long-run,
they are to implement an algorithm in a very local, encapsulated way.
Textbooks are full of imperative algorithms that needs some type of
aggregate type with mutations. Some of these algorithms are highly
useful, and difficult to parallellize or write efficiently in a purely
functional way.

In a good program with a nice functional structure, it can happen that
you want to write, inside a module, a function that implements such an
algorithm.
For this, you will need a way to temporary create and manipulate
mutable aggregate types. Copy your data in such ugly data-types, and
execute the imperative algorithm.

What can you currently do?
 -  Use a protocol per object/type, called with the same name with a y
at the end and implement set/get for each mutable part of the
aggregate. This is (very) slightly inefficient and quite ugly: double
the length of the code, hide its meaning, and, worst, it pretends to
have something general (a protocol) where you will only have one
implantation. (The protocol is tailored to mirror the type you
created.)
- Use atoms inside a immutable type. It is a bit less efficient but
slightly less ugly. Anyway, it still makes the code less
straightforward to read.
- Write a java file. It is very annoying for future portability and it
does not seem like a long-term solution.

As an illustration of my point, you can have a look at the n-body
implantation for the shootout:
http://shootout.alioth.debian.org/u32q/program.php?test=nbodylang=clojureid=2
Half the file is full of trivial, non reusable, interface definitions
and implementation.

My idea is that, if we were to write a program with planets, we would
write something nice, using Clojure immutable data-types and
references, and agent, and the like. And the deftype for a Body in the
shootout, wouldn't be very suitable.

But if somewhere in this big-program, we want to write a function that
compute the solution of a n-body problem, we won't have the choice, we
would need to copy the objects in ugly but efficient data-structures
and implement the fast algorithm.

Nobody would advocate that it's not the thing to do for Matrix
computations, and the array family of functions is here for that.
Why favours linear algebra algorithms (first class, can be efficiently
written in straightforward Clojure) with respect to other imperative
algorithm?

I am sure people would use such an option wisely, if it has a
sufficiently worrying name.

Sorry for the long explanation, I hope it made my point clearer.

Best regards,

Nicolas.

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


Public mutable fields in deftype

2010-12-23 Thread nicolas.o...@gmail.com
Dear all,

Is there a way to make some mutable fields public in a deftype?

Best regards,

Nicolas

-- 
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: Public mutable fields in deftype

2010-12-23 Thread nicolas.o...@gmail.com
On Thu, Dec 23, 2010 at 9:28 PM, Meikel Brandmeyer m...@kotka.de wrote:
 Hi,

 Am 23.12.2010 um 15:26 schrieb nicolas.o...@gmail.com:

 Is there a way to make some mutable fields public in a deftype?

 I think it is opinionated, that this is not possible as the documentation 
 states explicitly that the fields will be private when made mutable. You 
 could write a special protocol or interface with getters/setters. However 
 this somehow is ugly and undermines the original intention.


Thanks for your answer.
I think it is a good opinionated choice, because it is the best choice
most of the time.
However, in some specific case, I would like to have a way (even if
you have to jump through a few hoops) to have public mutable fields.
I have currently a file with a protocol per type with getter and
setter, which is quite anti-idiomatic.
There is no real protocol or overloading needed anywhere in this code,
as it is very low-level.

Would that be a lot of work to had a ^:public-unsynchronized-mutable
and ^:public-volatile-mutable?

If I were to write such a patch, would it be accepted?

Best regards,

Nicolas.

-- 
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: Public mutable fields in deftype

2010-12-23 Thread nicolas.o...@gmail.com
On Thu, Dec 23, 2010 at 10:29 PM, Meikel Brandmeyer m...@kotka.de wrote:
 Hi,

 Am 23.12.2010 um 23:15 schrieb nicolas.o...@gmail.com:

 If I were to write such a patch, would it be accepted?

 I lean now quite a bit out the window, but I dare say: „No.“ The reason I 
 think so is that this is opinionated.


And is there a way I missed to do a mutable record?

Best regards,

Nicolas.

-- 
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: Let's see how fast we can make this

2010-12-22 Thread nicolas.o...@gmail.com
Which version of Clojure are you using?
(How to speed that up depends a lot of the version you use)

I would like to see a with a longer run.
Optimised clojure is *asymptotically* nearly as fast as Java.
With under 1000 calls I am not sure the JIT is called.

Best,

Nicolas.


On Wed, Dec 22, 2010 at 5:52 PM, Rayne disciplera...@gmail.com wrote:
 I have a piece of code, and I'd like to see how fast it can be.

 (defn count-num-chars [^String s]
  (loop [s s acc 0]
    (if (seq s)
      (recur (rest s) (if (= (first s) \space) acc (inc acc)))
      acc)))

 This is the fastest I've been able to get it. The function is very
 simple. It takes a string and counts the number of non-space
 characters inside of that string.

 I've been testing this code against a 460 non-space character string.
 Here is the entire source, benchmarking and all:

 (def s (apply str (repeat 20 This is a really long string)))

 (defn count-num-chars [^String s]
  (loop [s s acc 0]
    (if (seq s)
      (recur (rest s) (if (= (first s) \space) acc (inc acc)))
      acc)))

 (println Chars outputted: (count-num-chars s))

 (let [before (System/nanoTime)]
  (dotimes [_ 1000]
    (count-num-chars s))
  (let [after (System/nanoTime)]
    (println Time (in nanoseconds): (/ (- after before) 1000.0

 Running it gives me around 137343.295 nanoseconds. I've seen some Java
 algorithms that could run at just under 3000 nanoseconds.

 Hide your children and hide your women; I want to see the direst,
 nastiest, rawest, fastest possible implementation of this function.

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



-- 
Sent from an IBM Model M, 15 August 1989.

-- 
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: Native Clojure

2010-12-21 Thread nicolas.o...@gmail.com
If you want native with enough reflection to compile clojure,
Objective-C might be a better choice than C++.

-- 
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: Native Clojure

2010-12-21 Thread nicolas.o...@gmail.com

 I am not a Clojure expert. But if I understood Clojure correctly,
 Clojure would not be Clojure if it where natively compiled. Eg. The
 whole lazy seq's are required because of lack of tail call
 optimization in the JVM. Or am I wrong?


I don't think the lazy seq are necessary because of TCO. They are
useful for a lot of things.
They allow to write a nice abstract function, and have it executed in
an efficient manner.
(Without blowing memory, and, with chunky sequences, with good cache locality.)

They can help to prevent some stack overflow problems, but I am not
sure a lot of lazy function would be
TCoptimised. For example, the usual map is not tail recursive:
(defn my-map [f l]
  (when l
(cons (f (first l)) (my-map f (next l)))

You can write a tail recursive version, but it would be equivalent to
accumulating with a loop and reversing the result.
Which you can do in Clojure.

Best regards,

Nicolas.

-- 
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: Native Clojure

2010-12-21 Thread nicolas.o...@gmail.com
 In my experience lazy-seqs are a reasonable replacement for the lack of TCO,
 and from what I've heard that is one of the reasons they exist.
 (defn a [x]
    (lazy-seq
      (cons x (b (inc x)
 (defn b [x]
    (lazy-seq
      (cons x (a (inc x)
 David

I am not sure I get you. COuld you elaborate a bit more this example, please?
Which tail-call functions are you trying to replace by a and b?


Nicolas.

-- 
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: Native Clojure

2010-12-21 Thread nicolas.o...@gmail.com
 Those are mutual recursive functions. Trying to define them as regular
 functions will quickly result in a stack overflow.
 You could use trampoline but in my experience you will take a significant
 performance hit.
 Lazy sequences are a way to efficiently represent mutually recursive
 computations w/o TCO.
 David

I am not sure to understand.

Neither functions are tail-recursive. So in this situation enabling
tail-recursion
would not help.

Best,

Nicolas.

-- 
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: Native Clojure

2010-12-21 Thread nicolas.o...@gmail.com
 With TCO mutually recursive functions do not consume the stack. The same is
 true for well constructed lazy sequences.
 David

With TCO, mutually *tail* recursive functions do not consume the stack.

non-tail call always consume the stack in non CPS compiled languages.
(In which, it consumes the heap).

Nicolas.

-- 
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: Native Clojure

2010-12-21 Thread nicolas.o...@gmail.com
 Yes I know, I thought the way I wrote the code was clear about that :)

I am sorry, I did not understand.

So let me try to explicit your transformation (please correct me if I am wrong):
- start with some mutually recursive functions: a and b, for example
- create a lazy stack for the recursive calls using a lazy-seq
- reduce the seq until you find the result of the computation?

Am I getting the idea or not at all?

-- 
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: Native Clojure

2010-12-21 Thread nicolas.o...@gmail.com
I have an example to clarify what I understood of your idea:

(declare odd)

(defn even [x]
(if (zero? x)
  [true]
  (lazy-seq nil (odd (dec x)

(defn odd [ x]
(if (zero? x)
  [false]
  (lazy-seq nil (even (dec x)

(defn get-value [l]
(if (nil? (first l)) (recur (next l)) (first l)))

(get-value (even 1500))

Nicolas.

-- 
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: Native Clojure

2010-12-21 Thread nicolas.o...@gmail.com
It's a funy and original trick but on this example at least,
it seems slower (and it can use a lot of memory, because it retains a
stack in the heap) than trampoline:

(time (get-value (even 1500)))
Elapsed time: 1899.881769 msecs

And a version with trampoline

(defn odd [^long x]
(if (zero? x)
  false
  #(even (dec x

(defn even [^long x]
(if (zero? x)
  true
  #(odd (dec x

(time (trampoline (even 1500)))
Elapsed time: 366.496137 msecs

-- 
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: Native Clojure

2010-12-20 Thread nicolas.o...@gmail.com
If you wait for clojure in clojure and then use VMkit (LLVM based
thing to do Virtual Machine), it can be an interesting project.
I am not sure if it would be considered as really native, though.

Nicolas.

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


  1   2   >