The key to writing an algorithm functionally is to break it up into simple
components.

You're performing three calculations:

    (def x (myfunc x))

    (def buffer (in_buffer buffer x))

    (+ (nth buffer 1) (nth buffer 3))

Let's tackle each in turn.

The first is a continually changing value of x, with the new value
calculated from the previous. We can represent this as a sequence, e.g.

    (x, (f x), (f (f x)), (f (f (f x))), ...)

We could write a function to do this for us:

    (defn iterate [f x]
      (cons x (lazy-seq (iterate f (f x)))))

But fortunately the iterate function already exists in the clojure.core
namespace. So this solves your first calculation:

    (def x (myfunc x))   ==>  (iterate myfunc 0)

Next, we want a sliding buffer of 5 values. Again, we could represent this
as a sequence, e.g.

    ([a b c d e], [b c d e f], [c d e f g], ...)

We could write our own function for this

    (defn sliding-buffer [n xs]
      (cons (take n xs) (lazy-seq (sliding-buffer n (rest xs)))))

But it turns out there's already a function to do this in clojure.core,
called partition:

    (def buffer (in_buffer buffer x))   ==>   (partition 5 1 (iterate
myfunc 0))

Okay, we're nearly there. Now we just need to add the second and fourth
numbers (indexes 1 and 3) together for each value in the sequence.

We can do this with a map:

    (map
      (fn [b] (+ (nth b 1) (nth b 2)))
      (partition 5 1 (iterate myfunc 0)))

Or, with a bit of syntax sugar:

    (->> (iterate myfunc 0)
         (partition 5 1)
         (map #(+ (nth % 1) (nth % 3))))

In my opinion, one of the key difficulties with programming in a functional
style is to realise that a single loop in an imperative program may hide
multiple pieces of functionality. The functional style favours splitting
this out into sequence operations that do one thing each.

- James

On 6 October 2013 20:02, vMac <vanmac...@gmail.com> wrote:

> Hello,
>
> I'm new to closure and functional programming and need some adviec/help
> with
> my oldschool programming style.
> I've written the following little program and hope someone could help me
> to improve it.
>
> The programm computes numbers through an iterative function , put the
> numbers in a 'shift buffer' and computes some value from the entries
> in that buffer.
>
> I'm sure it's not optimal at all and could be improved a lot.
> I've used a vector (and not a list) as buffer because I have to address
> and use the elements using nth. Hope thats ok, but not sure of that.
> I wish I could enter the new values at the start (left side) but found noe
> efficient way to do it. With vector one should use conj to add new values
> and
> that could only be done from the right side of the buffer , right?
> I'm sure there is a much better way to build such a 'shift buffer', any
> ideas?
>
> Another concern I have is the used of  def's in the iteration loop.
>  Overwriting the x and the buffer may not be optimal, but I have no idea of
> another (more functional) approch to that.
>
>
> ; defines my function
> (defn myfunc [x]
>   (mod (+ (inc x) (rand-int 10) ) 10))
>
> ; creates buffer and sets initial values
> (def buffer (vec (take 5 (repeat 0))) )
>
> ; creating a 'shift buffer': removes oldest entry and adds a new value at
> the end
>
> (defn in_buffer [buff x]
>   (conj (subvec buff 1) x))
>
> ; sets start value
> (def x 0)
>
> ; iteration loop
> (dorun(for [i (range 20)]
>
>       (do
>           (def x (myfunc x))  ; computes new value using myfunc and sets
> new x value
>           (def buffer (in_buffer buffer x)); writes value into buffer and
> sets new buffer
>           (println buffer) ;print buffer
>           (println (+ (nth buffer 1) (nth buffer 3)) )))) ; ;compute with
> values from bufffer
>
>
>
>
> Thank you or your help.
>
>
>  --
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>

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

Reply via email to