Core-async transducers with atoms

2017-03-23 Thread Elena Canovi


I have a question about transducers in core.async channels.

As far as I understand, if I define a channel with a transducer, the latter 
cannot depend on any other external argument other than what is put on the 
former.
So the transducer works in a purely functional fashion. 

Here is the question: is it idiomatic to define a transducer which depends 
(without side-effects) on a globally defined atom? 

Consider this example with a chatroom. Suppose we have a set (called 
banned-users) containing the names of users who have been banned from the 
chat. Let us initialize banned-users like this: 

(def banned-users (atom #{}))

Let us further suppose that this set can change in time with users added 
and removed asynchronously.
Every user can send messages to the server containing their name and the 
actual text of the message, in this format:

{:name "John" :text "Hi, friends!"}

Depending on whether the user is banned or not, the server will broadcast 
their message to all the other users or not. To this aim, let us define a 
channel with a transducer:

(def server (chan 1 (filter #(not (contains? @banned-users (:name  %) ) )))

As you can see, the effect of the transducer on the input message depends 
on the current value of banned-users. In other words, the channel does not 
work in a purely functional way, because given an input message, the result 
of applying the transducer will depend on the global context.

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


Re: Controlling how maps/records/atoms etc. are printed out

2016-11-12 Thread Colin Yates
Thanks Timothy

On Saturday, 12 November 2016, Timothy Baldridge 
wrote:

> clojure.core/print-method is a multi method that handles the printing of
> objects. You can override or implement the print method by:
>
> (defmethod print-method my.class.Foo
>   [^my.class.Foo instance ^Writer w]
>   (.write w ...))
>
> I do that to provide custom printing for deftypes, but you can easily
> override how records are printed as well.
>
> Timothy
>
> On Sat, Nov 12, 2016 at 2:35 AM, Colin Yates  > wrote:
>
>> Hi all,
>>
>> I cache quite a bit of stuff on the server, so when I return or print
>> out the 'system' I get the unhelpful recursive stack trace of Java
>> running out of heap.
>>
>> Is there some protocol I can implement on large data structures such
>> that whenever they are serialised they just dump some of their
>> contents?
>>
>> These objects will only ever be printed out either at the REPL,
>> (println) or clojure.tools.logging/log etc. I never expect them to be
>> serialised and then later deserialised from the serialised form.
>>
>> Any suggestions?
>>
>> Thanks all,
>>
>> Colin
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clojure@googlegroups.com
>> 
>> Note that posts from new members are moderated - please be patient with
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+unsubscr...@googlegroups.com
>> 
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to clojure+unsubscr...@googlegroups.com
>> .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
>
> --
> “One of the main causes of the fall of the Roman Empire was that–lacking
> zero–they had no way to indicate successful termination of their C
> programs.”
> (Robert Firth)
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> 
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> 
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com
> .
> For more options, visit https://groups.google.com/d/optout.
>

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


Re: Controlling how maps/records/atoms etc. are printed out

2016-11-12 Thread Timothy Baldridge
clojure.core/print-method is a multi method that handles the printing of
objects. You can override or implement the print method by:

(defmethod print-method my.class.Foo
  [^my.class.Foo instance ^Writer w]
  (.write w ...))

I do that to provide custom printing for deftypes, but you can easily
override how records are printed as well.

Timothy

On Sat, Nov 12, 2016 at 2:35 AM, Colin Yates  wrote:

> Hi all,
>
> I cache quite a bit of stuff on the server, so when I return or print
> out the 'system' I get the unhelpful recursive stack trace of Java
> running out of heap.
>
> Is there some protocol I can implement on large data structures such
> that whenever they are serialised they just dump some of their
> contents?
>
> These objects will only ever be printed out either at the REPL,
> (println) or clojure.tools.logging/log etc. I never expect them to be
> serialised and then later deserialised from the serialised form.
>
> Any suggestions?
>
> Thanks all,
>
> Colin
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>



-- 
“One of the main causes of the fall of the Roman Empire was that–lacking
zero–they had no way to indicate successful termination of their C
programs.”
(Robert Firth)

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


Controlling how maps/records/atoms etc. are printed out

2016-11-12 Thread Colin Yates
Hi all,

I cache quite a bit of stuff on the server, so when I return or print
out the 'system' I get the unhelpful recursive stack trace of Java
running out of heap.

Is there some protocol I can implement on large data structures such
that whenever they are serialised they just dump some of their
contents?

These objects will only ever be printed out either at the REPL,
(println) or clojure.tools.logging/log etc. I never expect them to be
serialised and then later deserialised from the serialised form.

Any suggestions?

Thanks all,

Colin

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


Re: atoms not working same in cljs as in clj?

2016-05-20 Thread Kenneth Tilton
On Fri, May 20, 2016 at 12:50 PM, Kevin Downey  wrote:

> This is a difference in the type function. The clojurescript type
> function ignores metadata.


Thanks! That was my second guess, but I looked and did not see that
documented on the differences page.

I already had an ia-type? function encapsulating the type check so I
modified that to check the meta under cljs.

-- 
Kenneth Tilton
54 Isle of Venice Dr, Apt 5
Fort Lauderdale, FL 33301

kentil...@gmail.com
646-269-1077

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


Re: atoms not working same in cljs as in clj?

2016-05-20 Thread Kevin Downey
This is a difference in the type function. The clojurescript type
function ignores metadata. So the clojurescript type function is like
the clojure class function, and clojurescript doesn't have a class function.

On 05/20/2016 09:22 AM, hiskennyness wrote:
> I see here
> https://github.com/clojure/clojurescript/wiki/Differences-from-Clojure
> that "Atoms work as in Clojure.", but I think I see a difference:
> 
> 1. I am using a custom type hierarchy in a namespace
> tiltontec.modeller.cell_types:
> 
> |
> (defonce ia-types (-> (make-hierarchy)
>   (derive ::model ::object)
>   (derive ::cell ::object)
>   (derive ::c-formula ::cell)))
> 
> |
> 
> 2. At the repl I switch to the cell types namespace and create an atom:
> 
> |
> (def my-formula (atom 42 :meta {:type ::c-formula}))
> |
> 
> 3. In Clojure:
> 
> |
> (type my-formula) => :tiltontec.modeller.cell-types/c-formula
> |
> 
> 4. In cljs:
> 
> |
> (type my-formula) => cljs.core.Atom
> |
> 
> Sanity check:
> 
> |
> (meta my-formula) => {:type :tiltontec.modeller.cell-types/c-formula}
> |
> 
> Am I missing something?
> 
> -- 
> 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
> <mailto:clojure+unsubscr...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout.


-- 
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?

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


atoms not working same in cljs as in clj?

2016-05-20 Thread hiskennyness
I see here 
https://github.com/clojure/clojurescript/wiki/Differences-from-Clojure that 
"Atoms work as in Clojure.", but I think I see a difference:

1. I am using a custom type hierarchy in a namespace 
tiltontec.modeller.cell_types:

(defonce ia-types (-> (make-hierarchy)
  (derive ::model ::object)
  (derive ::cell ::object)
  (derive ::c-formula ::cell)))


2. At the repl I switch to the cell types namespace and create an atom:

(def my-formula (atom 42 :meta {:type ::c-formula}))

3. In Clojure:

(type my-formula) => :tiltontec.modeller.cell-types/c-formula

4. In cljs:

(type my-formula) => cljs.core.Atom

Sanity check:

(meta my-formula) => {:type :tiltontec.modeller.cell-types/c-formula}

Am I missing something?

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


Re: Naming convention for atoms, refs, etc.?

2015-12-10 Thread Mars0i


On Thursday, December 10, 2015 at 4:40:49 AM UTC-6, Dan Kersten wrote:
>
> I write such code like this:
>
> (defn sdescriptive-name [] )
> (def my-atom (atom (descriptive-name)))
>
> Where descriptive-name would describe the data shape or purpose.
> This way the atom is not obscured behind many lines of code and the 
> data-generation is factored into a testable function with a hopefully 
> self-documenting name.
>
> On Thu, 10 Dec 2015 at 10:27 Colin Yates > 
> wrote:
>
>> I know it is dangerous to make sweeping statements, but any solution to 
>> “a lot of code obscures meaning therefore do X” is often solving the wrong 
>> thing - the real problem is "a lot of code that obscures meaning” :-).
>>
>> I hope that doesn’t come across as condescending as I fear...
>>
>
How dare you. :-)

No, feedback is always good.

As a rule of thumb, I tend to agree, but there are tradeoffs.  In this case 
the long string of let bindings are all similar, and are used to create an 
initial data structure that plays a central role in a simulation.   
Different simulations vary only by what's in this data structure.  It's 
clearest to keep the bindings together in one place, and there's no reason 
to pollute the top level.

Daniel's solution is a good one.  I had the code set up that way at one 
point, and may go back to it.

(Normally I store the data structure directly in a top-level variable, 
which is referenced only once at the beginning of simulation runs, and 
update the structure in a purely functional way.   Because of interaction 
with another program in my current project, I now have to maintain the 
structure in a state variable that changes, so I've added the atom 
wrapper.  Same kind of data structure as in the purely functional versions, 
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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Naming convention for atoms, refs, etc.?

2015-12-10 Thread Daniel Kersten
I write such code like this:

(defn sdescriptive-name [] )
(def my-atom (atom (descriptive-name)))

Where descriptive-name would describe the data shape or purpose.
This way the atom is not obscured behind many lines of code and the
data-generation is factored into a testable function with a hopefully
self-documenting name.

On Thu, 10 Dec 2015 at 10:27 Colin Yates  wrote:

> I know it is dangerous to make sweeping statements, but any solution to “a
> lot of code obscures meaning therefore do X” is often solving the wrong
> thing - the real problem is "a lot of code that obscures meaning” :-).
>
> I hope that doesn’t come across as condescending as I fear...
>
>
> On 10 Dec 2015, at 06:02, Mars0i  wrote:
>
> Another use case, fwiw:
>
> (def my-atom
>   (let [...
>  
>  ...]
> (atom ...)))
>
> A special naming convention for (e.g.) atoms makes it clear that what's
> below the many lines of let bindings (and maybe comment lines, too) is
> going to produce an atom; you don't have to read down and find the one line
> that contains '(atom'.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

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


Re: Naming convention for atoms, refs, etc.?

2015-12-10 Thread Colin Yates
I know it is dangerous to make sweeping statements, but any solution to “a lot 
of code obscures meaning therefore do X” is often solving the wrong thing - the 
real problem is "a lot of code that obscures meaning” :-).

I hope that doesn’t come across as condescending as I fear...

> On 10 Dec 2015, at 06:02, Mars0i  wrote:
> 
> Another use case, fwiw:
> 
> (def my-atom
>   (let [...
>  
>  ...]
> (atom ...)))
> 
> A special naming convention for (e.g.) atoms makes it clear that what's below 
> the many lines of let bindings (and maybe comment lines, too) is going to 
> produce an atom; you don't have to read down and find the one line that 
> contains '(atom'.
> 
> -- 
> 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 
> <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 
> <mailto:clojure+unsubscr...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout 
> <https://groups.google.com/d/optout>.

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


Re: Naming convention for atoms, refs, etc.?

2015-12-09 Thread Mars0i
Another use case, fwiw:

(def my-atom
  (let [...
 
 ...]
(atom ...)))

A special naming convention for (e.g.) atoms makes it clear that what's 
below the many lines of let bindings (and maybe comment lines, too) is 
going to produce an atom; you don't have to read down and find the one line 
that contains '(atom'.

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


Re: Naming convention for atoms, refs, etc.?

2015-12-07 Thread Colin Yates
Sure - but if I saw a reference (no pun intended) to ‘shopping-cart’ I would 
expect that to be stateful. Fns which take something and return something else 
I tend to name `something->something-else`. In other words, I am unlikely to 
have a var whose name is a lower-case noun that isn’t state. 

It is interesting to me, now I think about it that I have seen a few 
syntactical style guides but no semantic style guides for Clojure. This 
question suggests we need one….


> On 7 Dec 2015, at 09:41, Mark Engelberg  wrote:
> 
> On the contrary, I find that when I have something in my app like a 
> shopping-cart, there are usually two flavors of functions.  On the one hand, 
> there will be helper functions that take an immutable shopping-cart and 
> return a new immutable shopping-cart.  But on the other hand, there will also 
> be a few functions that manipulate the actual stateful atom/ref containing 
> the immutable shopping-cart.
> 
> I can see how some sort of convention might be handy to distinguish, at a 
> glance, whether a function takes the immutable or stateful version of 
> shopping-cart by some symbol in the name of the input.
> 
> 
> On Mon, Dec 7, 2015 at 12:37 AM, Colin Yates  <mailto:colin.ya...@gmail.com>> wrote:
> +1.
> 
> I haven’t done an extensive study, but I am sure all of my atoms’s stand out 
> from other fns/vars because the name makes it obvious. For example, 
> ‘shopping-cart’ can _only_ sensibly be state which can only be an atom. 
> 
> Having said that, if I had mixed refs and atoms then I might consider 
> splitting those, but in general I find it obvious and intuitive when looking 
> through past code which are atoms and which are fns/vars.
> 
> Might just be me though :-). 
> 
>> On 7 Dec 2015, at 08:26, Daniel Kersten > <mailto:dkers...@gmail.com>> wrote:
>> 
>> I personally don't like this.
>> 
>> An atom won't suddenly change value without your knowledge because to get 
>> its value, you must use @ or deref (which should be a big warning that, yes, 
>> this value might change between calls to deref).
>> 
>> Adding sigils, in my opinion, adds to the noise and makes it harder to read. 
>> I personally find sigils to be a noisy mistake in other languages (perl, php 
>> etc) and in my opinion you can get more benefit through a suitable naming 
>> convention such as a -state prefix, eg: foo-state
>> 
>> I think, mainly my dislike for sigils is on variables and not so much on 
>> functions as I'm ok with foo? being a predicate and foo! being unsafe in 
>> STM. I think that's because they tell you useful meta information about what 
>> the function does, but to use a variable, I already have to know what data 
>> it's representing in order to call the correct functions on it and 
>> annotating it with sigils doesn't help much (unless perhaps you go full 
>> blown Hungarian notation, but even that isn't rich enough to adequately 
>> describe the nested data structures we use in Clojure - good descriptive 
>> variable names are much better at conveying content and purpose).
>> 
>> I guess it may largely just be personal taste, although I would also take 
>> the wider community into account: there's a lot of code out there not using 
>> this convention - will that become confusing if you rely on symbols to tell 
>> you that a variable is an atom?
>> On Mon 7 Dec 2015 at 00:27 Mars0i > <mailto:marsh...@logical.net>> wrote:
>> On Sunday, December 6, 2015 at 5:52:02 PM UTC-6, Glen Mailer wrote:
>> I saw some sample code that prefixed the atom name with a ! recently, seemed 
>> to look sensible to me.
>> (swap! !state conj :whatever)
>> 
>> And so on.
>> 
>> 
>> This idea is conceptually elegant, since the marker, !, is the same as the 
>> related function suffix.  
>> 
>> I worry that having two bangs with a space between them, as in the swap! 
>> example above, is a little bit visually confusing.   Also, I wonder whether 
>> placing @ next two another non-alphanumeric character is visually confusing 
>> or messy.  
>> 
>> As an experiment, I just started using & as a suffix for variables whose 
>> values are atoms.:
>> (def state& (atom 1))
>> (swap! state& inc)
>> @state&
>> 
>> Using only a suffix character means that you don't have a punctuation 
>> character next to @, which I prefer.  
>> 
>> (I wouldn't want to use ! as the suffix for variables that are not 
>> functions, though.  (swap! state! inc) potentially very confusing.  It's not 
>> that someone reading

Re: Naming convention for atoms, refs, etc.?

2015-12-07 Thread Mark Engelberg
On the contrary, I find that when I have something in my app like a
shopping-cart, there are usually two flavors of functions.  On the one
hand, there will be helper functions that take an immutable shopping-cart
and return a new immutable shopping-cart.  But on the other hand, there
will also be a few functions that manipulate the actual stateful atom/ref
containing the immutable shopping-cart.

I can see how some sort of convention might be handy to distinguish, at a
glance, whether a function takes the immutable or stateful version of
shopping-cart by some symbol in the name of the input.


On Mon, Dec 7, 2015 at 12:37 AM, Colin Yates  wrote:

> +1.
>
> I haven’t done an extensive study, but I am sure all of my atoms’s stand
> out from other fns/vars because the name makes it obvious. For example,
> ‘shopping-cart’ can _only_ sensibly be state which can only be an atom.
>
> Having said that, if I had mixed refs and atoms then I might consider
> splitting those, but in general I find it obvious and intuitive when
> looking through past code which are atoms and which are fns/vars.
>
> Might just be me though :-).
>
> On 7 Dec 2015, at 08:26, Daniel Kersten  wrote:
>
> I personally don't like this.
>
> An atom won't suddenly change value without your knowledge because to get
> its value, you must use @ or deref (which should be a big warning that,
> yes, this value might change between calls to deref).
>
> Adding sigils, in my opinion, adds to the noise and makes it harder to
> read. I personally find sigils to be a noisy mistake in other languages
> (perl, php etc) and in my opinion you can get more benefit through a
> suitable naming convention such as a -state prefix, eg: foo-state
>
> I think, mainly my dislike for sigils is on variables and not so much on
> functions as I'm ok with foo? being a predicate and foo! being unsafe in
> STM. I think that's because they tell you useful meta information about
> what the function does, but to use a variable, I already have to know what
> data it's representing in order to call the correct functions on it and
> annotating it with sigils doesn't help much (unless perhaps you go full
> blown Hungarian notation, but even that isn't rich enough to adequately
> describe the nested data structures we use in Clojure - good descriptive
> variable names are much better at conveying content and purpose).
>
> I guess it may largely just be personal taste, although I would also take
> the wider community into account: there's a lot of code out there not using
> this convention - will that become confusing if you rely on symbols to tell
> you that a variable is an atom?
> On Mon 7 Dec 2015 at 00:27 Mars0i  wrote:
>
>> On Sunday, December 6, 2015 at 5:52:02 PM UTC-6, Glen Mailer wrote:
>>>
>>> I saw some sample code that prefixed the atom name with a ! recently,
>>> seemed to look sensible to me.
>>>
>>> (swap! !state conj :whatever)
>>>
>>> And so on.
>>>
>>
>> This idea is conceptually elegant, since the marker, !, is the same as
>> the related function suffix.
>>
>> I worry that having two bangs with a space between them, as in the swap!
>> example above, is a little bit visually confusing.   Also, I wonder whether
>> placing @ next two another non-alphanumeric character is visually confusing
>> or messy.
>>
>> As an experiment, I just started using & as a suffix for variables whose
>> values are atoms.:
>> (def state& (atom 1))
>> (swap! state& inc)
>> @state&
>>
>> Using only a suffix character means that you don't have a punctuation
>> character next to @, which I prefer.
>>
>> (I wouldn't want to use ! as the suffix for variables that are not
>> functions, though.  (swap! state! inc) potentially very confusing.  It's
>> not that someone reading it couldn't figure it out, but if I saw that, I'd
>> have to think for a second, and then keep remembering that state! is not a
>> function.)
>>
>> It occurred to me that I've seen both & and $ used in some languages to
>> suggest pointer dereferencing, so there's some vague harmony to using one
>> of them as indicators as markers of statefulness.  "Ampersand" sounds
>> vaguely like "atom".  If one wanted to have separate marker characters for
>> atoms, refs, and agents, maybe & is a good choice for atoms.  Not sure it's
>> necessary to have different conventions for these three distinct uses,
>> though.
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clo

Re: Naming convention for atoms, refs, etc.?

2015-12-07 Thread Daniel Kersten
Good point, Colin, about mixed refs and atoms. That might change things a
little (although in my years of Clojure, I have never needed to mix them to
the point of needing to clarify).
I would still prefer a textually descriptive name over a symbolic prefix or
suffix in this case though. At the very least, something like foo-atom or
foo-ref would be clear to people not used to the convention, while foo&
could mean anything. I think usually one can come up with better
descriptions than -atom too.

But... Maybe I'm just a little bit too symbol averse 🤔😏
On Mon 7 Dec 2015 at 08:37 Colin Yates  wrote:

> +1.
>
> I haven’t done an extensive study, but I am sure all of my atoms’s stand
> out from other fns/vars because the name makes it obvious. For example,
> ‘shopping-cart’ can _only_ sensibly be state which can only be an atom.
>
> Having said that, if I had mixed refs and atoms then I might consider
> splitting those, but in general I find it obvious and intuitive when
> looking through past code which are atoms and which are fns/vars.
>
> Might just be me though :-).
>
> On 7 Dec 2015, at 08:26, Daniel Kersten  wrote:
>
> I personally don't like this.
>
> An atom won't suddenly change value without your knowledge because to get
> its value, you must use @ or deref (which should be a big warning that,
> yes, this value might change between calls to deref).
>
> Adding sigils, in my opinion, adds to the noise and makes it harder to
> read. I personally find sigils to be a noisy mistake in other languages
> (perl, php etc) and in my opinion you can get more benefit through a
> suitable naming convention such as a -state prefix, eg: foo-state
>
> I think, mainly my dislike for sigils is on variables and not so much on
> functions as I'm ok with foo? being a predicate and foo! being unsafe in
> STM. I think that's because they tell you useful meta information about
> what the function does, but to use a variable, I already have to know what
> data it's representing in order to call the correct functions on it and
> annotating it with sigils doesn't help much (unless perhaps you go full
> blown Hungarian notation, but even that isn't rich enough to adequately
> describe the nested data structures we use in Clojure - good descriptive
> variable names are much better at conveying content and purpose).
>
> I guess it may largely just be personal taste, although I would also take
> the wider community into account: there's a lot of code out there not using
> this convention - will that become confusing if you rely on symbols to tell
> you that a variable is an atom?
> On Mon 7 Dec 2015 at 00:27 Mars0i  wrote:
>
>> On Sunday, December 6, 2015 at 5:52:02 PM UTC-6, Glen Mailer wrote:
>>>
>>> I saw some sample code that prefixed the atom name with a ! recently,
>>> seemed to look sensible to me.
>>>
>>> (swap! !state conj :whatever)
>>>
>>> And so on.
>>>
>>
>> This idea is conceptually elegant, since the marker, !, is the same as
>> the related function suffix.
>>
>> I worry that having two bangs with a space between them, as in the swap!
>> example above, is a little bit visually confusing.   Also, I wonder whether
>> placing @ next two another non-alphanumeric character is visually confusing
>> or messy.
>>
>> As an experiment, I just started using & as a suffix for variables whose
>> values are atoms.:
>> (def state& (atom 1))
>> (swap! state& inc)
>> @state&
>>
>> Using only a suffix character means that you don't have a punctuation
>> character next to @, which I prefer.
>>
>> (I wouldn't want to use ! as the suffix for variables that are not
>> functions, though.  (swap! state! inc) potentially very confusing.  It's
>> not that someone reading it couldn't figure it out, but if I saw that, I'd
>> have to think for a second, and then keep remembering that state! is not a
>> function.)
>>
>> It occurred to me that I've seen both & and $ used in some languages to
>> suggest pointer dereferencing, so there's some vague harmony to using one
>> of them as indicators as markers of statefulness.  "Ampersand" sounds
>> vaguely like "atom".  If one wanted to have separate marker characters for
>> atoms, refs, and agents, maybe & is a good choice for atoms.  Not sure it's
>> necessary to have different conventions for these three distinct uses,
>> though.
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to t

Re: Naming convention for atoms, refs, etc.?

2015-12-07 Thread Colin Yates
+1.

I haven’t done an extensive study, but I am sure all of my atoms’s stand out 
from other fns/vars because the name makes it obvious. For example, 
‘shopping-cart’ can _only_ sensibly be state which can only be an atom. 

Having said that, if I had mixed refs and atoms then I might consider splitting 
those, but in general I find it obvious and intuitive when looking through past 
code which are atoms and which are fns/vars.

Might just be me though :-). 

> On 7 Dec 2015, at 08:26, Daniel Kersten  wrote:
> 
> I personally don't like this.
> 
> An atom won't suddenly change value without your knowledge because to get its 
> value, you must use @ or deref (which should be a big warning that, yes, this 
> value might change between calls to deref).
> 
> Adding sigils, in my opinion, adds to the noise and makes it harder to read. 
> I personally find sigils to be a noisy mistake in other languages (perl, php 
> etc) and in my opinion you can get more benefit through a suitable naming 
> convention such as a -state prefix, eg: foo-state
> 
> I think, mainly my dislike for sigils is on variables and not so much on 
> functions as I'm ok with foo? being a predicate and foo! being unsafe in STM. 
> I think that's because they tell you useful meta information about what the 
> function does, but to use a variable, I already have to know what data it's 
> representing in order to call the correct functions on it and annotating it 
> with sigils doesn't help much (unless perhaps you go full blown Hungarian 
> notation, but even that isn't rich enough to adequately describe the nested 
> data structures we use in Clojure - good descriptive variable names are much 
> better at conveying content and purpose).
> 
> I guess it may largely just be personal taste, although I would also take the 
> wider community into account: there's a lot of code out there not using this 
> convention - will that become confusing if you rely on symbols to tell you 
> that a variable is an atom?
> On Mon 7 Dec 2015 at 00:27 Mars0i  <mailto:marsh...@logical.net>> wrote:
> On Sunday, December 6, 2015 at 5:52:02 PM UTC-6, Glen Mailer wrote:
> I saw some sample code that prefixed the atom name with a ! recently, seemed 
> to look sensible to me.
> (swap! !state conj :whatever)
> 
> And so on.
> 
> 
> This idea is conceptually elegant, since the marker, !, is the same as the 
> related function suffix.  
> 
> I worry that having two bangs with a space between them, as in the swap! 
> example above, is a little bit visually confusing.   Also, I wonder whether 
> placing @ next two another non-alphanumeric character is visually confusing 
> or messy.  
> 
> As an experiment, I just started using & as a suffix for variables whose 
> values are atoms.:
> (def state& (atom 1))
> (swap! state& inc)
> @state&
> 
> Using only a suffix character means that you don't have a punctuation 
> character next to @, which I prefer.  
> 
> (I wouldn't want to use ! as the suffix for variables that are not functions, 
> though.  (swap! state! inc) potentially very confusing.  It's not that 
> someone reading it couldn't figure it out, but if I saw that, I'd have to 
> think for a second, and then keep remembering that state! is not a function.)
> 
> It occurred to me that I've seen both & and $ used in some languages to 
> suggest pointer dereferencing, so there's some vague harmony to using one of 
> them as indicators as markers of statefulness.  "Ampersand" sounds vaguely 
> like "atom".  If one wanted to have separate marker characters for atoms, 
> refs, and agents, maybe & is a good choice for atoms.  Not sure it's 
> necessary to have different conventions for these three distinct uses, 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 
> <mailto: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 
> <mailto:clojure%2bunsubscr...@googlegroups.com>
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en 
> <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 
> <mailto:clojure+unsubscr...@googlegroups.c

Re: Naming convention for atoms, refs, etc.?

2015-12-07 Thread Daniel Kersten
I personally don't like this.

An atom won't suddenly change value without your knowledge because to get
its value, you must use @ or deref (which should be a big warning that,
yes, this value might change between calls to deref).

Adding sigils, in my opinion, adds to the noise and makes it harder to
read. I personally find sigils to be a noisy mistake in other languages
(perl, php etc) and in my opinion you can get more benefit through a
suitable naming convention such as a -state prefix, eg: foo-state

I think, mainly my dislike for sigils is on variables and not so much on
functions as I'm ok with foo? being a predicate and foo! being unsafe in
STM. I think that's because they tell you useful meta information about
what the function does, but to use a variable, I already have to know what
data it's representing in order to call the correct functions on it and
annotating it with sigils doesn't help much (unless perhaps you go full
blown Hungarian notation, but even that isn't rich enough to adequately
describe the nested data structures we use in Clojure - good descriptive
variable names are much better at conveying content and purpose).

I guess it may largely just be personal taste, although I would also take
the wider community into account: there's a lot of code out there not using
this convention - will that become confusing if you rely on symbols to tell
you that a variable is an atom?
On Mon 7 Dec 2015 at 00:27 Mars0i  wrote:

> On Sunday, December 6, 2015 at 5:52:02 PM UTC-6, Glen Mailer wrote:
>>
>> I saw some sample code that prefixed the atom name with a ! recently,
>> seemed to look sensible to me.
>>
>> (swap! !state conj :whatever)
>>
>> And so on.
>>
>
> This idea is conceptually elegant, since the marker, !, is the same as the
> related function suffix.
>
> I worry that having two bangs with a space between them, as in the swap!
> example above, is a little bit visually confusing.   Also, I wonder whether
> placing @ next two another non-alphanumeric character is visually confusing
> or messy.
>
> As an experiment, I just started using & as a suffix for variables whose
> values are atoms.:
> (def state& (atom 1))
> (swap! state& inc)
> @state&
>
> Using only a suffix character means that you don't have a punctuation
> character next to @, which I prefer.
>
> (I wouldn't want to use ! as the suffix for variables that are not
> functions, though.  (swap! state! inc) potentially very confusing.  It's
> not that someone reading it couldn't figure it out, but if I saw that, I'd
> have to think for a second, and then keep remembering that state! is not a
> function.)
>
> It occurred to me that I've seen both & and $ used in some languages to
> suggest pointer dereferencing, so there's some vague harmony to using one
> of them as indicators as markers of statefulness.  "Ampersand" sounds
> vaguely like "atom".  If one wanted to have separate marker characters for
> atoms, refs, and agents, maybe & is a good choice for atoms.  Not sure it's
> necessary to have different conventions for these three distinct uses,
> 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
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

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


Re: Naming convention for atoms, refs, etc.?

2015-12-06 Thread Mars0i
On Sunday, December 6, 2015 at 5:52:02 PM UTC-6, Glen Mailer wrote:
>
> I saw some sample code that prefixed the atom name with a ! recently, 
> seemed to look sensible to me.
>
> (swap! !state conj :whatever)
>
> And so on.
>

This idea is conceptually elegant, since the marker, !, is the same as the 
related function suffix.  

I worry that having two bangs with a space between them, as in the swap! 
example above, is a little bit visually confusing.   Also, I wonder whether 
placing @ next two another non-alphanumeric character is visually confusing 
or messy.  

As an experiment, I just started using & as a suffix for variables whose 
values are atoms.:
(def state& (atom 1))
(swap! state& inc)
@state&

Using only a suffix character means that you don't have a punctuation 
character next to @, which I prefer.  

(I wouldn't want to use ! as the suffix for variables that are not 
functions, though.  (swap! state! inc) potentially very confusing.  It's 
not that someone reading it couldn't figure it out, but if I saw that, I'd 
have to think for a second, and then keep remembering that state! is not a 
function.)

It occurred to me that I've seen both & and $ used in some languages to 
suggest pointer dereferencing, so there's some vague harmony to using one 
of them as indicators as markers of statefulness.  "Ampersand" sounds 
vaguely like "atom".  If one wanted to have separate marker characters for 
atoms, refs, and agents, maybe & is a good choice for atoms.  Not sure it's 
necessary to have different conventions for these three distinct uses, 
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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Naming convention for atoms, refs, etc.?

2015-12-06 Thread Glen Mailer
I saw some sample code that prefixed the atom name with a ! recently, seemed to 
look sensible to me.

(swap! !state conj :whatever)

And so on.

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


Re: Naming convention for atoms, refs, etc.?

2015-12-06 Thread Nicola Mometto
I seriously doubt that's ever going to happen. There's no good reason to do 
that.

> On 6 Dec 2015, at 21:00, Gregg Reynolds  wrote:
> 
> 
> On Dec 6, 2015 2:45 PM, "Nicola Mometto"  wrote:
> >
> > 'foo@ is not a valid symbol name
> 
> Oops.  Maybe now is the time to make good on "other characters may be allowed 
> eventually" (from the Reader doc.)  I can't think of a good reason not to 
> allow @ in symbols.  Would it mess anything up?
> 
> > > On 6 Dec 2015, at 20:44, Gregg Reynolds  wrote:
> > >
> > > Ps.  Note the nice symmetry between *foo* and @foo@.
> > >
> > > On Dec 6, 2015 2:42 PM, "Gregg Reynolds"  wrote:
> > > Postfix @?  Haven't pondered this before but I like the idea.  Why should 
> > > perl have all the fun?
> > >
> > > On Dec 5, 2015 3:47 PM, "Mars0i"  wrote:
> > > &, $, and ! might be good to use as special naming characters for 
> > > atoms/refs/agents, either as an initial char, a final char, or both, but 
> > > I'm wondering whether anyone already has a naming convention that they 
> > > use.
> > >
> > > --
> > > You received this message because you are subscribed to the Google
> > > Groups "Clojure" group.
> > > To post to this group, send email to clojure@googlegroups.com
> > > Note that posts from new members are moderated - please be patient with 
> > > your first post.
> > > To unsubscribe from this group, send email to
> > > clojure+unsubscr...@googlegroups.com
> > > For more options, visit this group at
> > > http://groups.google.com/group/clojure?hl=en
> > > ---
> > > You received this message because you are subscribed to the Google Groups 
> > > "Clojure" group.
> > > To unsubscribe from this group and stop receiving emails from it, send an 
> > > email to clojure+unsubscr...@googlegroups.com.
> > > For more options, visit https://groups.google.com/d/optout.
> > >
> > > --
> > > You received this message because you are subscribed to the Google
> > > Groups "Clojure" group.
> > > To post to this group, send email to clojure@googlegroups.com
> > > Note that posts from new members are moderated - please be patient with 
> > > your first post.
> > > To unsubscribe from this group, send email to
> > > clojure+unsubscr...@googlegroups.com
> > > For more options, visit this group at
> > > http://groups.google.com/group/clojure?hl=en
> > > ---
> > > You received this message because you are subscribed to the Google Groups 
> > > "Clojure" group.
> > > To unsubscribe from this group and stop receiving emails from it, send an 
> > > email to clojure+unsubscr...@googlegroups.com.
> > > For more options, visit https://groups.google.com/d/optout.
> >
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clojure@googlegroups.com
> > Note that posts from new members are moderated - please be patient with 
> > your first post.
> > To unsubscribe from this group, send email to
> > clojure+unsubscr...@googlegroups.com
> > For more options, visit this group at
> > http://groups.google.com/group/clojure?hl=en
> > ---
> > You received this message because you are subscribed to the Google Groups 
> > "Clojure" group.
> > To unsubscribe from this group and stop receiving emails from it, send an 
> > email to clojure+unsubscr...@googlegroups.com.
> > For more options, visit https://groups.google.com/d/optout.
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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


Re: Naming convention for atoms, refs, etc.?

2015-12-06 Thread Gregg Reynolds
On Dec 6, 2015 2:45 PM, "Nicola Mometto"  wrote:
>
> 'foo@ is not a valid symbol name

Oops.  Maybe now is the time to make good on "other characters may be
allowed eventually" (from the Reader doc.)  I can't think of a good reason
not to allow @ in symbols.  Would it mess anything up?

> > On 6 Dec 2015, at 20:44, Gregg Reynolds  wrote:
> >
> > Ps.  Note the nice symmetry between *foo* and @foo@.
> >
> > On Dec 6, 2015 2:42 PM, "Gregg Reynolds"  wrote:
> > Postfix @?  Haven't pondered this before but I like the idea.  Why
should perl have all the fun?
> >
> > On Dec 5, 2015 3:47 PM, "Mars0i"  wrote:
> > &, $, and ! might be good to use as special naming characters for
atoms/refs/agents, either as an initial char, a final char, or both, but
I'm wondering whether anyone already has a naming convention that they use.
> >
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clojure@googlegroups.com
> > Note that posts from new members are moderated - please be patient with
your first post.
> > To unsubscribe from this group, send email to
> > clojure+unsubscr...@googlegroups.com
> > For more options, visit this group at
> > http://groups.google.com/group/clojure?hl=en
> > ---
> > You received this message because you are subscribed to the Google
Groups "Clojure" group.
> > To unsubscribe from this group and stop receiving emails from it, send
an email to clojure+unsubscr...@googlegroups.com.
> > For more options, visit https://groups.google.com/d/optout.
> >
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clojure@googlegroups.com
> > Note that posts from new members are moderated - please be patient with
your first post.
> > To unsubscribe from this group, send email to
> > clojure+unsubscr...@googlegroups.com
> > For more options, visit this group at
> > http://groups.google.com/group/clojure?hl=en
> > ---
> > You received this message because you are subscribed to the Google
Groups "Clojure" group.
> > To unsubscribe from this group and stop receiving emails from it, send
an email to clojure+unsubscr...@googlegroups.com.
> > For more options, visit https://groups.google.com/d/optout.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
"Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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


Re: Naming convention for atoms, refs, etc.?

2015-12-06 Thread Nicola Mometto
'foo@ is not a valid symbol name

> On 6 Dec 2015, at 20:44, Gregg Reynolds  wrote:
> 
> Ps.  Note the nice symmetry between *foo* and @foo@.
> 
> On Dec 6, 2015 2:42 PM, "Gregg Reynolds"  wrote:
> Postfix @?  Haven't pondered this before but I like the idea.  Why should 
> perl have all the fun?
> 
> On Dec 5, 2015 3:47 PM, "Mars0i"  wrote:
> &, $, and ! might be good to use as special naming characters for 
> atoms/refs/agents, either as an initial char, a final char, or both, but I'm 
> wondering whether anyone already has a naming convention that they use.
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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


Re: Naming convention for atoms, refs, etc.?

2015-12-06 Thread Gregg Reynolds
Ps.  Note the nice symmetry between *foo* and @foo@.
On Dec 6, 2015 2:42 PM, "Gregg Reynolds"  wrote:

> Postfix @?  Haven't pondered this before but I like the idea.  Why should
> perl have all the fun?
> On Dec 5, 2015 3:47 PM, "Mars0i"  wrote:
>
>> &, $, and ! might be good to use as special naming characters for
>> atoms/refs/agents, either as an initial char, a final char, or both, but
>> I'm wondering whether anyone already has a naming convention that they use.
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clojure@googlegroups.com
>> Note that posts from new members are moderated - please be patient with
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+unsubscr...@googlegroups.com
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to clojure+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>>
>

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


Re: Naming convention for atoms, refs, etc.?

2015-12-06 Thread Gregg Reynolds
Postfix @?  Haven't pondered this before but I like the idea.  Why should
perl have all the fun?
On Dec 5, 2015 3:47 PM, "Mars0i"  wrote:

> &, $, and ! might be good to use as special naming characters for
> atoms/refs/agents, either as an initial char, a final char, or both, but
> I'm wondering whether anyone already has a naming convention that they use.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

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


Re: Naming convention for atoms, refs, etc.?

2015-12-05 Thread Mars0i
On Saturday, December 5, 2015 at 8:04:34 PM UTC-6, tbc++ wrote:
>
> Also, if you have so many atoms in your program that it becomes hard to 
> remember where they are, that would be another source of concern ;-)
>

Yeah   I'm worried that I'll come back to the code a year later and not 
remember that the variable contains an atom, and wonder why I'm getting 
different things out of it.  Though I suppose the at-sign might be a 
tip-off.

Or suppose I have a recurrent role in several functions or several 
namespaces or several programs, for which I always use the same name.  
Using the same name in different contexts makes the meaning of the 
variables clear.  Then it turns out that I have to make a new special 
version of this kind of program, in which I need to store the same kind of 
data in an atom rather than simply passing it from function to function.  I 
want to give the variable containing the data the same name ... but I 
don't, because this variable is different--it contains an atom containing 
the usual data, rather than the data itself.  (This is actually the 
situation that prompted the question.  I don't like having to store the 
data in an atom, but )

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


Re: Naming convention for atoms, refs, etc.?

2015-12-05 Thread Mars0i
On Saturday, December 5, 2015 at 5:45:22 PM UTC-6, James Reeves wrote:
>
> Why should they have any sort of naming scheme? Dynamic vars are unusual 
> because their values can change. Atoms and refs remain the same, and even 
> though inside their values mutate, they don't affect the outer var.
>

Good point, James.  They're just regular variables.  Still, their role is 
very different from that of normal Clojure variables.  I prefer to give 
them a different kind of name.  But I can understand why others wouldn't. 

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


Re: Naming convention for atoms, refs, etc.?

2015-12-05 Thread Timothy Baldridge
Also, if you have so many atoms in your program that it becomes hard to
remember where they are, that would be another source of concern ;-)

On Sat, Dec 5, 2015 at 4:44 PM, James Reeves  wrote:

> Why should they have any sort of naming scheme? Dynamic vars are unusual
> because their values can change. Atoms and refs remain the same, and even
> though inside their values mutate, they don't affect the outer var.
>
> - James
>
> On 5 December 2015 at 21:39, Mars0i  wrote:
>
>> Does anyone want to suggest or promote a naming convention for atoms,
>> refs, and agents, i.e. some of things that you can dereference with @ i.e.
>> deref?
>>
>> (Also, what about futures, delays, and promises?  I think of these as
>> playing a different sort of role, even though deref works with them, too.)
>>
>> The Clojure style guide
>> <https://github.com/bbatsov/clojure-style-guide#naming> says:
>>
>> Use *earmuffs* for things intended for rebinding (ie. are dynamic).
>>
>> ;; good
>> (def ^:dynamic *a* 10)
>>
>>
>> It could be reasonable to use earmuffs for atoms, etc., too, but I think
>> that "@*my-atom*" is ugly because of the juxtaposed @-sign and asterisk,
>> and in any event I think of rebinding as a different kind of thing from
>> what happens with atoms/refs/agents.
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clojure@googlegroups.com
>> Note that posts from new members are moderated - please be patient with
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+unsubscr...@googlegroups.com
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to clojure+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>



-- 
“One of the main causes of the fall of the Roman Empire was that–lacking
zero–they had no way to indicate successful termination of their C
programs.”
(Robert Firth)

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


Re: Naming convention for atoms, refs, etc.?

2015-12-05 Thread James Reeves
Why should they have any sort of naming scheme? Dynamic vars are unusual
because their values can change. Atoms and refs remain the same, and even
though inside their values mutate, they don't affect the outer var.

- James

On 5 December 2015 at 21:39, Mars0i  wrote:

> Does anyone want to suggest or promote a naming convention for atoms,
> refs, and agents, i.e. some of things that you can dereference with @ i.e.
> deref?
>
> (Also, what about futures, delays, and promises?  I think of these as
> playing a different sort of role, even though deref works with them, too.)
>
> The Clojure style guide
> <https://github.com/bbatsov/clojure-style-guide#naming> says:
>
> Use *earmuffs* for things intended for rebinding (ie. are dynamic).
>
> ;; good
> (def ^:dynamic *a* 10)
>
>
> It could be reasonable to use earmuffs for atoms, etc., too, but I think
> that "@*my-atom*" is ugly because of the juxtaposed @-sign and asterisk,
> and in any event I think of rebinding as a different kind of thing from
> what happens with atoms/refs/agents.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

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


Re: Naming convention for atoms, refs, etc.?

2015-12-05 Thread Mars0i
&, $, and ! might be good to use as special naming characters for 
atoms/refs/agents, either as an initial char, a final char, or both, but 
I'm wondering whether anyone already has a naming convention that they use.

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


Naming convention for atoms, refs, etc.?

2015-12-05 Thread Mars0i
Does anyone want to suggest or promote a naming convention for atoms, refs, 
and agents, i.e. some of things that you can dereference with @ i.e. deref?

(Also, what about futures, delays, and promises?  I think of these as 
playing a different sort of role, even though deref works with them, too.)

The Clojure style guide 
<https://github.com/bbatsov/clojure-style-guide#naming> says:

Use *earmuffs* for things intended for rebinding (ie. are dynamic). 

;; good
(def ^:dynamic *a* 10)


It could be reasonable to use earmuffs for atoms, etc., too, but I think 
that "@*my-atom*" is ugly because of the juxtaposed @-sign and asterisk, 
and in any event I think of rebinding as a different kind of thing from 
what happens with atoms/refs/agents.

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


Re: Atoms, reference to itself cause StackOverflowError

2015-08-07 Thread Simone Mosciatti
Thank you :)

Extremely clear !

On Friday, August 7, 2015 at 3:48:14 PM UTC+2, Stuart Sierra wrote:
>
> Hi Simone,
>
> The stack overflow here is caused by the REPL trying to print a circular 
> reference. `swap!` always returns the new value of the Atom, and the REPL 
> tries to print it.
>
> If you don't print the Atom, this self-reference can still work:
>
> user=> (def a (atom {}))
> #'user/a
> user=> (do (swap! a assoc :self a) nil)
> nil
> user=> (= a (:self @a))
> true
>
> –S
>
>
> On Friday, August 7, 2015 at 9:42:05 AM UTC-4, Simone Mosciatti wrote:
>>
>> Hi all,
>>
>> I noticed this behaviour that I was not expecting:
>>
>> simo@simo:~$ lein repl
>> nREPL server started on port 42010 on host 127.0.0.1 - nrepl://
>> 127.0.0.1:42010
>> REPL-y 0.3.5, nREPL 0.2.6
>> Clojure 1.6.0
>> OpenJDK 64-Bit Server VM 1.7.0_79-b14
>> Docs: (doc function-name-here)
>>   (find-doc "part-of-name-here")
>>   Source: (source function-name-here)
>>  Javadoc: (javadoc java-object-or-class-here)
>> Exit: Control+D or (exit) or (quit)
>>  Results: Stored in vars *1, *2, *3, an exception in *e
>>
>> user=> (def a (atom {}))
>> #'user/a
>> user=> (swap! a assoc :self a)
>>
>> StackOverflowError   java.util.regex.Pattern$GroupHead.match 
>> (Pattern.java:4556)
>> user=> (swap! a assoc :test :ok)
>>
>> StackOverflowError   java.lang.Character.codePointAt (Character.java:4668)
>> user=> a
>>
>> StackOverflowError   java.util.regex.Pattern$Curly.match0 
>> (Pattern.java:4148)
>> user=> (def b (atom {}))
>> #'user/b
>> user=> (swap! b assoc :test :ok)
>> {:test :ok}
>>
>> It is something expected or I should open a bug report ?
>>
>> Greets
>>
>> Simone
>>
>

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


Re: Atoms, reference to itself cause StackOverflowError

2015-08-07 Thread Stuart Sierra
Hi Simone,

The stack overflow here is caused by the REPL trying to print a circular 
reference. `swap!` always returns the new value of the Atom, and the REPL 
tries to print it.

If you don't print the Atom, this self-reference can still work:

user=> (def a (atom {}))
#'user/a
user=> (do (swap! a assoc :self a) nil)
nil
user=> (= a (:self @a))
true

–S


On Friday, August 7, 2015 at 9:42:05 AM UTC-4, Simone Mosciatti wrote:
>
> Hi all,
>
> I noticed this behaviour that I was not expecting:
>
> simo@simo:~$ lein repl
> nREPL server started on port 42010 on host 127.0.0.1 - nrepl://
> 127.0.0.1:42010
> REPL-y 0.3.5, nREPL 0.2.6
> Clojure 1.6.0
> OpenJDK 64-Bit Server VM 1.7.0_79-b14
> Docs: (doc function-name-here)
>   (find-doc "part-of-name-here")
>   Source: (source function-name-here)
>  Javadoc: (javadoc java-object-or-class-here)
> Exit: Control+D or (exit) or (quit)
>  Results: Stored in vars *1, *2, *3, an exception in *e
>
> user=> (def a (atom {}))
> #'user/a
> user=> (swap! a assoc :self a)
>
> StackOverflowError   java.util.regex.Pattern$GroupHead.match 
> (Pattern.java:4556)
> user=> (swap! a assoc :test :ok)
>
> StackOverflowError   java.lang.Character.codePointAt (Character.java:4668)
> user=> a
>
> StackOverflowError   java.util.regex.Pattern$Curly.match0 
> (Pattern.java:4148)
> user=> (def b (atom {}))
> #'user/b
> user=> (swap! b assoc :test :ok)
> {:test :ok}
>
> It is something expected or I should open a bug report ?
>
> Greets
>
> Simone
>

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


Atoms, reference to itself cause StackOverflowError

2015-08-07 Thread Simone Mosciatti
Hi all,

I noticed this behaviour that I was not expecting:

simo@simo:~$ lein repl
nREPL server started on port 42010 on host 127.0.0.1 - 
nrepl://127.0.0.1:42010
REPL-y 0.3.5, nREPL 0.2.6
Clojure 1.6.0
OpenJDK 64-Bit Server VM 1.7.0_79-b14
Docs: (doc function-name-here)
  (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=> (def a (atom {}))
#'user/a
user=> (swap! a assoc :self a)

StackOverflowError   java.util.regex.Pattern$GroupHead.match 
(Pattern.java:4556)
user=> (swap! a assoc :test :ok)

StackOverflowError   java.lang.Character.codePointAt (Character.java:4668)
user=> a

StackOverflowError   java.util.regex.Pattern$Curly.match0 
(Pattern.java:4148)
user=> (def b (atom {}))
#'user/b
user=> (swap! b assoc :test :ok)
{:test :ok}

It is something expected or I should open a bug report ?

Greets

Simone

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


Re: atoms, memoize, future-s and CAS

2014-12-20 Thread Andy L
Hi,

Thanks for all suggestions. It all encouraged me to deep dive into atom-s
code which turns out to be a simple wrapper over Java
java.util.concurrent.atomic.AtomicReference which essentially is a
spinlock. Knowing how it works under the hood makes so easier
to use it ...

Below piece (hopefully correct) let me update map atomically:
(defn cond-assoc!
  [atomic-map key val]
  (loop []
(let [candidate (if (contains? @atomic-map key) @atomic-map (assoc
@atomic-map key val))]
  (if (compare-and-set! atomic-map @atomic-map candidate)
candidate
(recur)


I also learned that using future (or essentially Java threads) is so poor
approach to scalability. derefing memoized delay of my function wrapped
with future worked well to some point. After pushing it a bit with more
concurrent tasks, my JVM started freezing under pressure of to many
threads. I ended up with my custom hybrid of a queued future-s. I have also
a version done in core.async - I will try to write it up in a separate
piece at some point ..

Best regards,
Andy

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


Re: atoms, memoize, future-s and CAS

2014-12-08 Thread Michał Marczyk
On 8 December 2014 at 21:46, Fluid Dynamics  wrote:
> [...]
> Which means it's locking or bust. You just get to either do the locking
> yourself or delegate :)

Sure, but isn't it nice when somebody else does your locking for you? :-)

Incidentally, there is a trade-off here between lockless reads and
cache-locking writes in the version with (locking …) and synchronized
reads (of delays) and somewhat concurrency-friendly writes in the
version with CHM.putIfAbsent and delays. So actually explicit (locking
…) might be preferable for certain workloads. Benchmarking required.

Michał

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

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


Re: atoms, memoize, future-s and CAS

2014-12-08 Thread Michał Marczyk
Oh, and as for how to use it here, you could for example say

  (.putIfAbsent concurrent-hash-map :foo (delay (foo)))

Then the first thread to @(get concurrent-hash-map :foo (delay
:not-found)) (or similar) would actually compute the value.

With a map in an atom, you could swap! using a function like

  (fn [old-state]
(if (contains? old-state :foo)
  (assoc old-state :foo (delay (foo)))
  old-state))

I'd probably prefer a CHM for this purpose, though.

Michał


On 8 December 2014 at 21:33, Michał Marczyk  wrote:
> On 8 December 2014 at 17:54, Andy L  wrote:
>>> But I'd personally just use a delay rather than "locking" for this
>>> purpose.
>>
>>
>> It is not that I like locking at all. However I still fail to see, how in a
>> multithreaded context memoize/cache prevents executing a given function more
>> than once (which I want to avoid at any cost here) since cache lookup and
>> swap! does not seem to be atomic :
>> https://github.com/clojure/core.cache/blob/master/src/main/clojure/clojure/core/cache.clj#L52
>
> When you say
>
>   (delay (foo)),
>
> foo will be called at most once, regardless of how many times you
> deref (@) / force the delay. (If you never force the delay, it will
> not be called at all.) The way this is enforced is through making
> deref a synchronized method on delays.
>
> Cheers,
> Michał

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


Re: atoms, memoize, future-s and CAS

2014-12-08 Thread Fluid Dynamics
On Monday, December 8, 2014 3:34:05 PM UTC-5, Michał Marczyk wrote:
>
> On 8 December 2014 at 17:54, Andy L > 
> wrote: 
> >> But I'd personally just use a delay rather than "locking" for this 
> >> purpose. 
> > 
> > 
> > It is not that I like locking at all. However I still fail to see, how 
> in a 
> > multithreaded context memoize/cache prevents executing a given function 
> more 
> > than once (which I want to avoid at any cost here) since cache lookup 
> and 
> > swap! does not seem to be atomic : 
> > 
> https://github.com/clojure/core.cache/blob/master/src/main/clojure/clojure/core/cache.clj#L52
>  
>
> When you say 
>
>   (delay (foo)), 
>
> foo will be called at most once, regardless of how many times you 
> deref (@) / force the delay. (If you never force the delay, it will 
> not be called at all.) The way this is enforced is through making 
> deref a synchronized method on delays. 
>

Which means it's locking or bust. You just get to either do the locking 
yourself or delegate :) 

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


Re: atoms, memoize, future-s and CAS

2014-12-08 Thread Michał Marczyk
On 8 December 2014 at 17:54, Andy L  wrote:
>> But I'd personally just use a delay rather than "locking" for this
>> purpose.
>
>
> It is not that I like locking at all. However I still fail to see, how in a
> multithreaded context memoize/cache prevents executing a given function more
> than once (which I want to avoid at any cost here) since cache lookup and
> swap! does not seem to be atomic :
> https://github.com/clojure/core.cache/blob/master/src/main/clojure/clojure/core/cache.clj#L52

When you say

  (delay (foo)),

foo will be called at most once, regardless of how many times you
deref (@) / force the delay. (If you never force the delay, it will
not be called at all.) The way this is enforced is through making
deref a synchronized method on delays.

Cheers,
Michał

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


Re: atoms, memoize, future-s and CAS

2014-12-08 Thread Andy L
>
>
> Most of the cache implementations in core.cache have no side-effects. They
> simply return a new cache rather than overwriting the old one. The memoize
> library places the cache in an atom, so it's guaranteed to change
> atomically.
>


I tried to read the cache code (btw an excellent exercise) , and I think I
understand how persistent data structure/atom is employed here in case we
deal with side effects free functions.


> You could write this as a function. There's nothing in there that requires
> a macro.
>
> (defn when-map-future-swap! [a k f]
>   (locking a
> (when-not (contains? @a k)
>   (swap! a assoc k nil)
>   (future (swap! a assoc k (f k))
>

I realized that later too ...

But I'd personally just use a delay rather than "locking" for this purpose.
>

It is not that I like locking at all. However I still fail to see, how in a
multithreaded context memoize/cache prevents executing a given function
more than once (which I want to avoid at any cost here) since cache lookup
and swap! does not seem to be atomic :
https://github.com/clojure/core.cache/blob/master/src/main/clojure/clojure/core/cache.clj#L52
.

Best regards,
Andy

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


Re: atoms, memoize, future-s and CAS

2014-12-07 Thread James Reeves
On 7 December 2014 at 05:13, Andy L  wrote:

>
>
>
>> The SoftCache uses a ConcurrentHashMap, but that caching option isn't
>> used in core.memoize. Are you building a custom memoizer?
>>
>>
> WRT ConcurrentHashMap, it was an incorrect conclusion on my part. In any
> case, I fail to see "thread safety" in the cache implementation, but again
> I could be wrong. Or it might not be needed for 99.99% cache use cases.
> Also, at that point I would like to avoid to "defcache" my own version.
>

Most of the cache implementations in core.cache have no side-effects. They
simply return a new cache rather than overwriting the old one. The memoize
library places the cache in an atom, so it's guaranteed to change
atomically.


> So I ended up with this (this is my first LISP macro ever, so please be
> gentle :-) :
>
> (defmacro when-map-future-swap! [a k f]
>   `(locking ~a
>  (when (not (contains? @~a ~k))
>(swap! ~a assoc ~k nil)
>(future (swap! ~a assoc  ~k (~f ~k)))
>)
>  )
>   )
>

You could write this as a function. There's nothing in there that requires
a macro.

(defn when-map-future-swap! [a k f]
  (locking a
(when-not (contains? @a k)
  (swap! a assoc k nil)
  (future (swap! a assoc k (f k))

But I'd personally just use a delay rather than "locking" for this purpose.

- James

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


Re: atoms, memoize, future-s and CAS

2014-12-06 Thread Andy L
or even better (using future themselves as a "marker" in the atom):

(defmacro map-future-swap! [a k f]
  `(locking ~a
 (when (not (contains? @~a ~k))
   (swap! ~a assoc ~k (future (swap! ~a assoc  ~k (~f ~k
   )
 )
  )

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


Re: atoms, memoize, future-s and CAS

2014-12-06 Thread Andy L
> The SoftCache uses a ConcurrentHashMap, but that caching option isn't used
> in core.memoize. Are you building a custom memoizer?
>
>
WRT ConcurrentHashMap, it was an incorrect conclusion on my part. In any
case, I fail to see "thread safety" in the cache implementation, but again
I could be wrong. Or it might not be needed for 99.99% cache use cases.
Also, at that point I would like to avoid to "defcache" my own version.


So I ended up with this (this is my first LISP macro ever, so please be
gentle :-) :

(defmacro when-map-future-swap! [a k f]
  `(locking ~a
 (when (not (contains? @~a ~k))
   (swap! ~a assoc ~k nil)
   (future (swap! ~a assoc  ~k (~f ~k)))
   )
 )
  )

Which seems to do what I need:

user=> (defn f[k] (Thread/sleep 3000) k)
#'user/f
user=> (when-map-future-swap! a "arg" f)
#
user=> a
#
user=> (Thread/sleep 4000)
nil
user=> a
#


Andy

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


Re: atoms, memoize, future-s and CAS

2014-12-06 Thread James Reeves
On 7 December 2014 at 01:13, Andy L  wrote:
>
> Thanks for looking into that. This indeed would solve a "semantics"
> problem of memoize, as it returns a value now. However, it seems that 
> clojure.core.memoize,
> or rather  clojure.core.cache memoize is based of, is not thread safe.
>
> It uses ConcurrentHashMap's "put" under the hood, instead of atomic
> "putIfAbsent". I might be completely wrong here though.
>

The SoftCache uses a ConcurrentHashMap, but that caching option isn't used
in core.memoize. Are you building a custom memoizer?

- James

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


Re: atoms, memoize, future-s and CAS

2014-12-06 Thread Andy L
> (defn memoized [f]
>   (comp deref (memoize (fn [& args] (delay (apply f args)
>
>
Thanks for looking into that. This indeed would solve a "semantics" problem
of memoize, as it returns a value now. However, it seems that
clojure.core.memoize,
or rather  clojure.core.cache memoize is based of, is not thread safe.

It uses ConcurrentHashMap's "put" under the hood, instead of atomic
"putIfAbsent". I might be completely wrong here though.

Cheers,
Andy

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


Re: atoms, memoize, future-s and CAS

2014-12-06 Thread James Reeves
It sounds like you want a delay. Delays are guaranteed to execute their
body only once, so we can combine a delay with an atom:

(defn memoized [f]
  (comp deref (memoize (fn [& args] (delay (apply f args)

In theory that should produce a memoize that executes the function only
once for each set of arguments.

- James

On 6 December 2014 at 21:32, Andy L  wrote:

> Hi,
>
> Here is the situation. There is a function "f" retrieving some data from
> various sources (including reading files, a lot of io, e.g. map-reduce)
> expected by design to return the same result for given input. Results of
> "f" invocation from parallely running futures are stored in an atom wrapped
> map and everything works just fine.
>
> With a small exception when "f" invocations with the same arguments
> overlap  - the same expensive "io" is kicked off 2 or more time s. Not a
> tragedy, but still very unpleasant and wasteful. The expectation would be
> that a subsequent "f" call would just bail without doing anything while
> initial invocation assoc new data into an atom,
>
> The first intuition was to use memoize, however I do not think its
> semantics fit well into this case, since the result is a "side-effect" on
> an atom as opposed to return value.
>
> The easiest solution, is to create another atom with a map of the
> arguments into a "state". If some other "future" is already there working
> hard on the problem, we simply bail. However, that leads to another problem.
>
> "compare-and-set!" just operates on atoms as wholes, which is fine for
> unstructured data, but  falls short for things somewhat more complex,
> like here.
>
> While updating an atom in this context is trivial:
>
> user=> (def a (atom {}))
> user=> (swap! a assoc ["arg1" "arg2"] :PENDING)
> {["arg1" "arg2"] "resultA"}
>
> I would like to link the condition and future together somehow like that:
>
> user=> (when ((complement contains?) @a ["arg1" "arg3"]) (swap! a assoc
> ["arg1" "arg3"] :PENDING ))
>
> That obviously will not work, unless I wrap it with "locking", which is
> not necessarily a nice thing to do. I also tried to use refs here, however
> they do not fit well here either and the solution is not as nice as it
> could be.
>
> After that long introduction, I would like ask for some insight 
> Thanks in advance ...
>
>
> Best,
> Andy
>
>
>
>
>
>
>
>
>
>
>
>  --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

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


atoms, memoize, future-s and CAS

2014-12-06 Thread Andy L
Hi,

Here is the situation. There is a function "f" retrieving some data from
various sources (including reading files, a lot of io, e.g. map-reduce)
expected by design to return the same result for given input. Results of
"f" invocation from parallely running futures are stored in an atom wrapped
map and everything works just fine.

With a small exception when "f" invocations with the same arguments
overlap  - the same expensive "io" is kicked off 2 or more time s. Not a
tragedy, but still very unpleasant and wasteful. The expectation would be
that a subsequent "f" call would just bail without doing anything while
initial invocation assoc new data into an atom,

The first intuition was to use memoize, however I do not think its
semantics fit well into this case, since the result is a "side-effect" on
an atom as opposed to return value.

The easiest solution, is to create another atom with a map of the arguments
into a "state". If some other "future" is already there working hard on the
problem, we simply bail. However, that leads to another problem.

"compare-and-set!" just operates on atoms as wholes, which is fine for
unstructured data, but  falls short for things somewhat more complex,
like here.

While updating an atom in this context is trivial:

user=> (def a (atom {}))
user=> (swap! a assoc ["arg1" "arg2"] :PENDING)
{["arg1" "arg2"] "resultA"}

I would like to link the condition and future together somehow like that:

user=> (when ((complement contains?) @a ["arg1" "arg3"]) (swap! a assoc
["arg1" "arg3"] :PENDING ))

That obviously will not work, unless I wrap it with "locking", which is not
necessarily a nice thing to do. I also tried to use refs here, however they
do not fit well here either and the solution is not as nice as it could be.

After that long introduction, I would like ask for some insight  Thanks
in advance ...


Best,
Andy

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


Re: Expanding The Use Of Transducers To Atoms?

2014-10-27 Thread László Török
IMHO, for what you describe, i.e. "I'd like to view an atom's changes in
state as a lazy sequence." there is no need to change the IAtom or
add-watch function.

Watchers are called for their side-effects, so if you want to consume their
output as a "lazy sequence", you have to do that transformation step in the
watcher function that you attach to the atom/ref/agent.

Having said that, as changes to an atom happen asynchronously, I don't
think that exposing it as lazy-seq is very efficient way of consuming the
values.

However, with the advent of core.async, there is now a very elegant way of
consuming them via a channel and that channel can have a transducer stack
attached (clojure 1.7+), so something along the lines of

(def atom-to-watch (atom 0))

(defn make-watcher [out-ch-with-transducer]
  (fn [x]
(async/put! out-ch-with-transducer x

(def ch (async/chan 100 your-transducer-stack))

(add-watch atom-to-watch (make-watcher ch))

;; somewhere else in your code you can consume the values
(go
  (loop [v (async/:

>
> I've been reading about transducers with interest.
>
> The official docs at http://clojure.org/transducers  say "*Because
> transducers are decoupled from input or output sources, they can be used in
> many different processes - collections, streams, channels, observables,
> etc.* "
>
> At this stage, there is direct support for collections and core.async.  But,
> given the comment above about "observables",  this got me to wondering
> about another scenario ...
>
> I'd like to view an atom's changes in state as a lazy sequence.  The first
> state of the atom is like the first item in the seq, the next time the atom
> changes state, its new state is the second item in the seq is generated,
> etc.  An infinite seq of new states.   (I want to do this in the context of
> clojurescript and a GUI library called reagent.  Think FRP).
>
> Now imagine that I could attach a transducer to this seq of state changes,
> so that I end up with a modified seq of state changes.
>
> Now, I can figure out how to do this by gluing together an atom watcher
> with a core.sync channel.  All doable with a small bit of work, I guess.
>
> But I wondered.  Given the claim above about transducers and how they can
> be used in the case of observables, should this atom-as-seq-with-transducer
> be easier?  Should the IAtom interface or the add-watcher function be
> changed to make this process easier?
>
> Just a thought.
>
> --
> Mike
>
>
>  --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>



-- 
László Török
Checkout justonemorepoint.com - Know your true value

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


Expanding The Use Of Transducers To Atoms?

2014-10-26 Thread Mike Thompson

I've been reading about transducers with interest.

The official docs at http://clojure.org/transducers  say "*Because 
transducers are decoupled from input or output sources, they can be used in 
many different processes - collections, streams, channels, observables, 
etc.* " 

At this stage, there is direct support for collections and core.async.  But, 
given the comment above about "observables",  this got me to wondering 
about another scenario ... 

I'd like to view an atom's changes in state as a lazy sequence.  The first 
state of the atom is like the first item in the seq, the next time the atom 
changes state, its new state is the second item in the seq is generated, 
etc.  An infinite seq of new states.   (I want to do this in the context of 
clojurescript and a GUI library called reagent.  Think FRP).

Now imagine that I could attach a transducer to this seq of state changes, 
so that I end up with a modified seq of state changes. 

Now, I can figure out how to do this by gluing together an atom watcher 
with a core.sync channel.  All doable with a small bit of work, I guess. 

But I wondered.  Given the claim above about transducers and how they can 
be used in the case of observables, should this atom-as-seq-with-transducer 
be easier?  Should the IAtom interface or the add-watcher function be 
changed to make this process easier?

Just a thought. 

--
Mike


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


Re: futures and atoms and bears, oh my!

2014-07-15 Thread Jeremy Heiler
On Tue, Jul 15, 2014 at 9:44 AM, Stefan Kamphausen 
wrote:
>
> Note, that it may be a reasonable fix to your situation to change bar
> instead of foo.  This is possible by evaluating the new definition of bar
> /later/; bar could also be a dynamically bindable Var, so that when
> compiling foo, we do not know how to call bar correctly.  That's the way
> the compiler works.  A linter like eastwood[1] might report this, though.
>

I was going to say the same thing about dynamic vars. Here's an example:

user=> (defn ^:dynamic foo [x] (inc x))
#'user/foo
user=> (foo 1)
2
user=> (binding [foo (fn [x y] (+ x y))] (foo 1 2))
3

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


Re: futures and atoms and bears, oh my!

2014-07-15 Thread Stefan Kamphausen


>
> (defn foo
>   "I don't do a whole lot."
>   [a b]
>   ((let [y (bar(a b))]
> (println a b "Hello, World!"
>
>
Now, *there* are some very suspicious parens around...

1. You're trying to call a as a function
2. Yes, you're calling bar with too few parameters, but how many? One.
3. Finally, after fixing that, you'd try to call nil as a function.  Can 
you see, why?  The '(('.


... just to be nitpicking and slightly off-topic, I know.  Sorry.

Note, that it may be a reasonable fix to your situation to change bar 
instead of foo.  This is possible by evaluating the new definition of bar 
/later/; bar could also be a dynamically bindable Var, so that when 
compiling foo, we do not know how to call bar correctly.  That's the way 
the compiler works.  A linter like eastwood[1] might report this, though.


Kind regards,
stefan

[1] https://github.com/jonase/eastwood

>  

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


Re: futures and atoms and bears, oh my!

2014-07-15 Thread edward
You're right and ouch! That's horrible. It's an error that should be known 
at eval time.

On Tuesday, July 15, 2014 1:20:04 PM UTC+1, Jony Hudson wrote:
>
> I think that's what you'd expect. This will also evaluate just fine:
>
> (defn foo
>   [x y]
>   (bar x y))
>
> but will fail at run-time too.
>
>
> Jony
>
> On Tuesday, 15 July 2014 13:07:43 UTC+1, edw...@kenworthy.info wrote:
>>
>> Creating a new project in Lein then opening it in Light Table and with 
>> minimal edits:
>>
>> (ns test.core)
>>
>> (defn bar [a b c])
>>
>> (defn foo
>>   "I don't do a whole lot."
>>   [a b]
>>   ((let [y (bar(a b))]
>> (println a b "Hello, World!"
>>
>> foo evaluates without error despite calling bar with too few parameters.
>>
>>  

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


Re: futures and atoms and bears, oh my!

2014-07-15 Thread Jony Hudson
I think that's what you'd expect. This will also evaluate just fine:

(defn foo
  [x y]
  (bar x y))

but will fail at run-time too.


Jony

On Tuesday, 15 July 2014 13:07:43 UTC+1, edw...@kenworthy.info wrote:
>
> Creating a new project in Lein then opening it in Light Table and with 
> minimal edits:
>
> (ns test.core)
>
> (defn bar [a b c])
>
> (defn foo
>   "I don't do a whole lot."
>   [a b]
>   ((let [y (bar(a b))]
> (println a b "Hello, World!"
>
> foo evaluates without error despite calling bar with too few parameters.
>
>  

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


Re: futures and atoms and bears, oh my!

2014-07-15 Thread edward


On Tuesday, July 15, 2014 12:38:53 PM UTC+1, Jeremy Heiler wrote:
>
> On Tue, Jul 15, 2014 at 3:15 AM, > 
> wrote:
>
>> Curiouser and curiouser.
>>
>> I turns out the problem was *not* with my next-to-play function but 
>> rather with the fact that it takes three arguments but I was only passing 
>> it two.
>>
>> The curious part is that whilst the compiler complained about the wrong 
>> arity if I evaluated the call directly, it didn't when it was part of a let!
>>
>
> Are you able to reproduce this problem with a fresh environment?
>  
>

Yes.

Creating a new project in Lein then opening it in Light Table and with 
minimal edits:

(ns test.core)

(defn bar [a b c])

(defn foo
  "I don't do a whole lot."
  [a b]
  ((let [y (bar(a b))]
(println a b "Hello, World!"

foo evaluates without error despite calling bar with too few parameters.

I suspect in my code next-to-play is messing up the stack because it pulls 
3 parameters off the stack when only 2 have been placed on it.


>> (let [next-player (next-to-play @current-board player)]...
>>
>> should be:
>>
>> (let [next-player (next-to-play @current-board player false)]...
>>
>> But the compiler doesn't complain!
>>
>  

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


Re: futures and atoms and bears, oh my!

2014-07-15 Thread Jeremy Heiler
On Tue, Jul 15, 2014 at 3:15 AM,  wrote:

> Curiouser and curiouser.
>
> I turns out the problem was *not* with my next-to-play function but rather
> with the fact that it takes three arguments but I was only passing it two.
>
> The curious part is that whilst the compiler complained about the wrong
> arity if I evaluated the call directly, it didn't when it was part of a let!
>

Are you able to reproduce this problem with a fresh environment?


>
> (let [next-player (next-to-play @current-board player)]...
>
> should be:
>
> (let [next-player (next-to-play @current-board player false)]...
>
> But the compiler doesn't complain!
>

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


Re: futures and atoms and bears, oh my!

2014-07-15 Thread edward
Curiouser and curiouser.

I turns out the problem was *not* with my next-to-play function but rather 
with the fact that it takes three arguments but I was only passing it two.

The curious part is that whilst the compiler complained about the wrong 
arity if I evaluated the call directly, it didn't when it was part of a let!

(let [next-player (next-to-play @current-board player)]...

should be:

(let [next-player (next-to-play @current-board player false)]...

But the compiler doesn't complain!


On Tuesday, July 15, 2014 7:06:36 AM UTC+1, edw...@kenworthy.info wrote:
>
> Quick follow up, replacing get-and-make-move with
>
> (defn get-and-make-move
>   [board strategy player]
>   board)
>
> Still have the same problem: so the issue is not with that function nor 
> any of the functions it calls (nor the strategies).
>
> Beginning to think it's my next-to-play function, which would be weird as, 
> again, it works in the single threaded command line version.
>
>
>
>
> On Tuesday, July 15, 2014 6:41:05 AM UTC+1, edw...@kenworthy.info wrote:
>>
>> Pretty sure the strategy isn't a problem (random-strategy picks a random 
>> move from all legal moves) and it works in the single-threaded command line 
>> version of the app.
>>
>> ditto all-directions which is constant:
>>
>> (def ^:constant all-directions
>>   "Defines the array of all possible directions from a square."
>>   [[-1 -1][0 -1][+1 -1]
>>[-1  0]  [+1  0]
>>[-1 +1][0 +1][+1 +1]])
>>
>> Reasonable suggestions though.
>>
>> I think I'll have to create a version of get-and-make-move that just 
>> returns a random board (i.e. is as simple as possible) and see what happens.
>>
>> Is there a way to trace into a thread created by (future) ?
>>
>> On Tuesday, July 15, 2014 12:57:33 AM UTC+1, Gary Johnson wrote:
>>>
>>> Looking at this code without further knowledge of the strategy function, 
>>> my first guess is simply that your strategy function may not be returning a 
>>> result which satisfies the valid-move? and legal-move? predicates thus 
>>> throwing you into an infinite loop. Possibly the printf is being suppressed 
>>> within the swap! operation, but some testing would be required to see if 
>>> this is the case generally. The other obvious potential for a hiccup would 
>>> be if all-directions is somehow growing with each iteration of make-move, 
>>> thus preventing idx from ever exceeding its length. Not knowing what is 
>>> going on inside all these functions makes this a rather tricky bit of guess 
>>> work at best. Anyway, I'd try running get-move from the repl to see how 
>>> likely it is to get stuck in an infinite loop.
>>>
>>>   Good luck,
>>> ~Gary
>>>
>>

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


Re: futures and atoms and bears, oh my!

2014-07-14 Thread edward
Quick follow up, replacing get-and-make-move with

(defn get-and-make-move
  [board strategy player]
  board)

Still have the same problem: so the issue is not with that function nor any 
of the functions it calls (nor the strategies).

Beginning to think it's my next-to-play function, which would be weird as, 
again, it works in the single threaded command line version.




On Tuesday, July 15, 2014 6:41:05 AM UTC+1, edw...@kenworthy.info wrote:
>
> Pretty sure the strategy isn't a problem (random-strategy picks a random 
> move from all legal moves) and it works in the single-threaded command line 
> version of the app.
>
> ditto all-directions which is constant:
>
> (def ^:constant all-directions
>   "Defines the array of all possible directions from a square."
>   [[-1 -1][0 -1][+1 -1]
>[-1  0]  [+1  0]
>[-1 +1][0 +1][+1 +1]])
>
> Reasonable suggestions though.
>
> I think I'll have to create a version of get-and-make-move that just 
> returns a random board (i.e. is as simple as possible) and see what happens.
>
> Is there a way to trace into a thread created by (future) ?
>
> On Tuesday, July 15, 2014 12:57:33 AM UTC+1, Gary Johnson wrote:
>>
>> Looking at this code without further knowledge of the strategy function, 
>> my first guess is simply that your strategy function may not be returning a 
>> result which satisfies the valid-move? and legal-move? predicates thus 
>> throwing you into an infinite loop. Possibly the printf is being suppressed 
>> within the swap! operation, but some testing would be required to see if 
>> this is the case generally. The other obvious potential for a hiccup would 
>> be if all-directions is somehow growing with each iteration of make-move, 
>> thus preventing idx from ever exceeding its length. Not knowing what is 
>> going on inside all these functions makes this a rather tricky bit of guess 
>> work at best. Anyway, I'd try running get-move from the repl to see how 
>> likely it is to get stuck in an infinite loop.
>>
>>   Good luck,
>> ~Gary
>>
>

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


Re: futures and atoms and bears, oh my!

2014-07-14 Thread edward
Pretty sure the strategy isn't a problem (random-strategy picks a random 
move from all legal moves) and it works in the single-threaded command line 
version of the app.

ditto all-directions which is constant:

(def ^:constant all-directions
  "Defines the array of all possible directions from a square."
  [[-1 -1][0 -1][+1 -1]
   [-1  0]  [+1  0]
   [-1 +1][0 +1][+1 +1]])

Reasonable suggestions though.

I think I'll have to create a version of get-and-make-move that just 
returns a random board (i.e. is as simple as possible) and see what happens.

Is there a way to trace into a thread created by (future) ?

On Tuesday, July 15, 2014 12:57:33 AM UTC+1, Gary Johnson wrote:
>
> Looking at this code without further knowledge of the strategy function, 
> my first guess is simply that your strategy function may not be returning a 
> result which satisfies the valid-move? and legal-move? predicates thus 
> throwing you into an infinite loop. Possibly the printf is being suppressed 
> within the swap! operation, but some testing would be required to see if 
> this is the case generally. The other obvious potential for a hiccup would 
> be if all-directions is somehow growing with each iteration of make-move, 
> thus preventing idx from ever exceeding its length. Not knowing what is 
> going on inside all these functions makes this a rather tricky bit of guess 
> work at best. Anyway, I'd try running get-move from the repl to see how 
> likely it is to get stuck in an infinite loop.
>
>   Good luck,
> ~Gary
>

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


Re: futures and atoms and bears, oh my!

2014-07-14 Thread Gary Johnson
Looking at this code without further knowledge of the strategy function, my 
first guess is simply that your strategy function may not be returning a 
result which satisfies the valid-move? and legal-move? predicates thus 
throwing you into an infinite loop. Possibly the printf is being suppressed 
within the swap! operation, but some testing would be required to see if 
this is the case generally. The other obvious potential for a hiccup would 
be if all-directions is somehow growing with each iteration of make-move, 
thus preventing idx from ever exceeding its length. Not knowing what is 
going on inside all these functions makes this a rather tricky bit of guess 
work at best. Anyway, I'd try running get-move from the repl to see how 
likely it is to get stuck in an infinite loop.

  Good luck,
~Gary

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


Re: futures and atoms and bears, oh my!

2014-07-14 Thread edward

(defn get-move
  "Call the player's strategy function to get a move.
  Keep calling until a valid and legal move is returned
  and pass that back.
  There is no way to escape without the strategy returning
  a valid and legal move."
  [board strategy player]
  (let [[x y :as move] (strategy board player)]
(if (and (valid-move? board move) (legal-move? board player move))
  move ; return the move
  (do
(printf "!Attempted illegal move [%d %d] by %s.\n" x y player)
(recur board strategy player)

(defn make-move
  "Update board to reflect move by a player"
  [board move player]
  ;; First make the move, then make any flips
  (loop [brd (place-piece board move player)
 idx 0]
(if (>= idx (count all-directions))
brd
(recur (make-flips brd move player (all-directions idx)) (inc 
idx)

(defn- get-and-make-move
  "Gets a valid and legal move from the strategy
  and then makes it, returning the new board.
  This does what the PAIP 'get-move' function did."
  [board strategy player]
  (let [[x y :as move] (get-move board strategy player)]
(make-move board move player)))

On Monday, July 14, 2014 12:35:47 PM UTC+1, James Reeves wrote:
>
> Could you post more of your code? If you suspect your code is stopping at 
> the first swap!, it might be an idea to post the contents of 
> get-and-make-move 
> as well.
>
> - James
>
>
> On 14 July 2014 11:25, > wrote:
>
>> So I've got something strange happening.
>>
>> I have a function (play, see below) which I spin off in a separate thread:
>>
>>   (future (play {:black black-strategy :white white-strategy} :black))
>>
>> The weird thing is whilst the first (println) in play is printed to the 
>> console, and so is a similar print from the watch I have on current-board, 
>> the play thread seems to stall at that point: I never see "done swap" or 
>> any other prints from play and my UI doesn't update past the initial change 
>> to current-board.
>>
>> It's almost as if swap! does it's job but then never returns.
>>
>> Any pointers for me?
>>
>>
>> (defn play [player-strategies player]
>>   (println "play called (next is waiting 5 seconds before doing 
>> anything.")
>>   (Thread/sleep 5000)
>>   (swap! current-board #(get-and-make-move %1 (player-strategies player) 
>> player))
>>   (println "done swap!")
>>   (let [next-player (next-to-play @current-board player)]
>> (if-not next-player
>>   (let [result (count-difference :black)]
>> (printf "GAME OVER");; should 
>> return the result
>> (print-board @current-board)
>>  ;   (print (result-string result))
>> (newline)   ;)
>> result)
>>   (recur player-strategies next-player)
>>
>>  -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

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


Re: futures and atoms and bears, oh my!

2014-07-14 Thread James Reeves
Could you post more of your code? If you suspect your code is stopping at
the first swap!, it might be an idea to post the contents of get-and-make-move
as well.

- James


On 14 July 2014 11:25,  wrote:

> So I've got something strange happening.
>
> I have a function (play, see below) which I spin off in a separate thread:
>
>   (future (play {:black black-strategy :white white-strategy} :black))
>
> The weird thing is whilst the first (println) in play is printed to the
> console, and so is a similar print from the watch I have on current-board,
> the play thread seems to stall at that point: I never see "done swap" or
> any other prints from play and my UI doesn't update past the initial change
> to current-board.
>
> It's almost as if swap! does it's job but then never returns.
>
> Any pointers for me?
>
>
> (defn play [player-strategies player]
>   (println "play called (next is waiting 5 seconds before doing anything.")
>   (Thread/sleep 5000)
>   (swap! current-board #(get-and-make-move %1 (player-strategies player)
> player))
>   (println "done swap!")
>   (let [next-player (next-to-play @current-board player)]
> (if-not next-player
>   (let [result (count-difference :black)]
> (printf "GAME OVER");; should
> return the result
> (print-board @current-board)
>  ;   (print (result-string result))
> (newline)   ;)
> result)
>   (recur player-strategies next-player)
>
>  --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

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


futures and atoms and bears, oh my!

2014-07-14 Thread edward
So I've got something strange happening.

I have a function (play, see below) which I spin off in a separate thread:

  (future (play {:black black-strategy :white white-strategy} :black))

The weird thing is whilst the first (println) in play is printed to the 
console, and so is a similar print from the watch I have on current-board, 
the play thread seems to stall at that point: I never see "done swap" or 
any other prints from play and my UI doesn't update past the initial change 
to current-board.

It's almost as if swap! does it's job but then never returns.

Any pointers for me?


(defn play [player-strategies player]
  (println "play called (next is waiting 5 seconds before doing anything.")
  (Thread/sleep 5000)
  (swap! current-board #(get-and-make-move %1 (player-strategies player) 
player))
  (println "done swap!")
  (let [next-player (next-to-play @current-board player)]
(if-not next-player
  (let [result (count-difference :black)]
(printf "GAME OVER");; should 
return the result
(print-board @current-board)
 ;   (print (result-string result))
(newline)   ;)
result)
  (recur player-strategies next-player)

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


Re: using atoms as logs for channels in core.async

2014-05-14 Thread Gary Verhaegen
The function map> takes a channel and a function, and returns a new
channel; every time an element is sent through that new channel, it
first goes through the given function (and it is the result of that
function that is actually sent through the original channel).

The function map< is similar, except it applies the given function to
each element that exits the channel.

So in my function, (as/map< (fn [x] (swap! at pop) x) chan) creates a
new channel that will remove an element from the sequence referenced
by the atom at every time a value is sent through it.

The result of the function is thus a new channel that conjes all of
its input to the atom, and pops an element from the atom every time
someone takes from it. But from an external point of view, thanks to
both functions returning the element unchanged, it acts exactly like a
normal channel.

Note that it essentially wraps the original channel within two other
channels, so the original channel is unchanged and should therefore
not be used anymore.

I have to leave now; if you still have any question after playing with
the following code, I'll be glad to answer them when I come back (in
~10 hours or so)

;; project.clj

(defproject async "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME";
  :license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.6.0"]
 [org.clojure/core.async "0.1.303.0-886421-alpha"]]
  :main ^:skip-aot async.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all}})

;; src/async/core.clj

(ns async.core
  (:require [clojure.core.async :as as :refer [go ! chan]]))

(defn decorate-channel
  [chan at]
  (as/map> (fn [x] (swap! at conj x) x)
   (as/map< (fn [x] (swap! at pop) x)
chan)))

(defn some-fn-using-a-channel
  [ch]
  (go (dotimes [_ 10] (! ch 1)))
  (go (dotimes [_ 10] ( wrote:
> Hi Gary,
>
> Your function looks interesting and succinct, but I am still new to this
> subject so am not sure how it would be used. Could you give some examples?
>
> Jesse
>
>
> On Wednesday, May 14, 2014 3:34:17 AM UTC+9, Gary Verhaegen wrote:
>>
>> What about the following? (as is bound to clojure.core.async ns)
>>
>> (defn decorate-channel
>>   [chan at]
>>   (as/map> (fn [x] (swap! at conj x) x)
>>(as/map< (fn [x] (swap! at pop) x)
>>chan)))
>>
>> As far as I can tell, it should do what you want, without introducing
>> global vars. It also returns a "normal" async channel that can be used
>> anywhere a channel is expected, without special handling. This could
>> be very handy for debugging.
>>
>>
>> On 13 May 2014 06:02, gamma235  wrote:
>> >
>> > Hey guys, I took your suggestions and just wanna deliver the finished
>> > product. I included the macro in there for practice, but agree it is
>> > probably not necessary. Thanks for all your help.
>> >
>> > p is for pretty :)
>> >
>> >>
>> >> (defn pchan [ch]
>> >>
>> >>   {:channel ch, :buffer (atom [])})
>> >
>> >
>> >>
>> >> (defn pbuff [{:keys [ch buffer]}]
>> >>(println @buffer))
>> >
>> >
>> >>
>> >> (defn pput [{:keys [channel buffer]} v]
>> >>   (do
>> >> (go
>> >>  (>! channel v))
>> >> (swap! buffer conj v)
>> >> (println "put " v)))
>> >
>> >
>> >>
>> >> (defn ptake [{:keys [channel buffer]}]
>> >> (go
>> >>  (let [v (> >>(if-not (empty? @buffer)
>> >> (do
>> >>(swap! buffer pop)
>> >>(println "took " v)
>> >> (println "take pending ..."))
>> >
>> >
>> >>
>> >> (defmacro def-pchan
>> >>   ([name]
>> >>`(def ~name (pchan (chan
>> >>   ([name buff]
>> >>`(def ~name (pchan (chan ~buff)
>> >
>> >
>> >>
>> >> (defn clear-buffer [{:keys [buffer]}]
>> >>   (reset! buffer []))
>> >>
>> > it works!
>> >>
>> >> (def-pchan pc)
>> >> (:buffer pc)
>> >> (pbuff pc)
>> >> (ptake pc)
>> >> (pput pc 42)
>> >> (clear-buffer pc)
>> >
>> > --
>> > You received this message because you are subscribed to the Google
>> > Groups "Clojure" group.
>> > To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com.
>> > For more options, visit https://groups.google.com/d/optout.
>
> --
> 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 patien

Re: using atoms as logs for channels in core.async

2014-05-13 Thread gamma235
Hi Gary, 

Your function looks interesting and succinct, but I am still new to this 
subject so am not sure how it would be used. Could you give some examples?

Jesse

On Wednesday, May 14, 2014 3:34:17 AM UTC+9, Gary Verhaegen wrote:
>
> What about the following? (as is bound to clojure.core.async ns) 
>
> (defn decorate-channel 
>   [chan at] 
>   (as/map> (fn [x] (swap! at conj x) x) 
>(as/map< (fn [x] (swap! at pop) x) 
>chan))) 
>
> As far as I can tell, it should do what you want, without introducing 
> global vars. It also returns a "normal" async channel that can be used 
> anywhere a channel is expected, without special handling. This could 
> be very handy for debugging. 
>
>
> On 13 May 2014 06:02, gamma235 > 
> wrote: 
> > 
> > Hey guys, I took your suggestions and just wanna deliver the finished 
> > product. I included the macro in there for practice, but agree it is 
> > probably not necessary. Thanks for all your help. 
> > 
> > p is for pretty :) 
> > 
> >> 
> >> (defn pchan [ch] 
> >> 
> >>   {:channel ch, :buffer (atom [])}) 
> > 
> > 
> >> 
> >> (defn pbuff [{:keys [ch buffer]}] 
> >>(println @buffer)) 
> > 
> > 
> >> 
> >> (defn pput [{:keys [channel buffer]} v] 
> >>   (do 
> >> (go 
> >>  (>! channel v)) 
> >> (swap! buffer conj v) 
> >> (println "put " v))) 
> > 
> > 
> >> 
> >> (defn ptake [{:keys [channel buffer]}] 
> >> (go 
> >>  (let [v ( >>(if-not (empty? @buffer) 
> >> (do 
> >>(swap! buffer pop) 
> >>(println "took " v) 
> >> (println "take pending ...")) 
> > 
> > 
> >> 
> >> (defmacro def-pchan 
> >>   ([name] 
> >>`(def ~name (pchan (chan 
> >>   ([name buff] 
> >>`(def ~name (pchan (chan ~buff) 
> > 
> > 
> >> 
> >> (defn clear-buffer [{:keys [buffer]}] 
> >>   (reset! buffer [])) 
> >> 
> > it works! 
> >> 
> >> (def-pchan pc) 
> >> (:buffer pc) 
> >> (pbuff pc) 
> >> (ptake pc) 
> >> (pput pc 42) 
> >> (clear-buffer pc) 
> > 
> > -- 
> > You received this message because you are subscribed to the Google 
> > Groups "Clojure" group. 
> > To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com . 
> > For more options, visit https://groups.google.com/d/optout. 
>

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


Re: using atoms as logs for channels in core.async

2014-05-13 Thread Gary Verhaegen
What about the following? (as is bound to clojure.core.async ns)

(defn decorate-channel
  [chan at]
  (as/map> (fn [x] (swap! at conj x) x)
   (as/map< (fn [x] (swap! at pop) x)
   chan)))

As far as I can tell, it should do what you want, without introducing
global vars. It also returns a "normal" async channel that can be used
anywhere a channel is expected, without special handling. This could
be very handy for debugging.


On 13 May 2014 06:02, gamma235  wrote:
>
> Hey guys, I took your suggestions and just wanna deliver the finished
> product. I included the macro in there for practice, but agree it is
> probably not necessary. Thanks for all your help.
>
> p is for pretty :)
>
>>
>> (defn pchan [ch]
>>
>>   {:channel ch, :buffer (atom [])})
>
>
>>
>> (defn pbuff [{:keys [ch buffer]}]
>>(println @buffer))
>
>
>>
>> (defn pput [{:keys [channel buffer]} v]
>>   (do
>> (go
>>  (>! channel v))
>> (swap! buffer conj v)
>> (println "put " v)))
>
>
>>
>> (defn ptake [{:keys [channel buffer]}]
>> (go
>>  (let [v (>(if-not (empty? @buffer)
>> (do
>>(swap! buffer pop)
>>(println "took " v)
>> (println "take pending ..."))
>
>
>>
>> (defmacro def-pchan
>>   ([name]
>>`(def ~name (pchan (chan
>>   ([name buff]
>>`(def ~name (pchan (chan ~buff)
>
>
>>
>> (defn clear-buffer [{:keys [buffer]}]
>>   (reset! buffer []))
>>
> it works!
>>
>> (def-pchan pc)
>> (:buffer pc)
>> (pbuff pc)
>> (ptake pc)
>> (pput pc 42)
>> (clear-buffer pc)
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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


Re: using atoms as logs for channels in core.async

2014-05-12 Thread gamma235

Hey guys, I took your suggestions and just wanna deliver the finished 
product. I included the macro in there for practice, but agree it is 
probably not necessary. Thanks for all your help. 

p is for pretty :)
 

> (defn pchan [ch]
>   {:channel ch, :buffer (atom [])})
>
 

> (defn pbuff [{:keys [ch buffer]}]
>(println @buffer))
>
 

> (defn pput [{:keys [channel buffer]} v]
>   (do 
> (go 
>  (>! channel v))
> (swap! buffer conj v)
> (println "put " v)))
>
 

> (defn ptake [{:keys [channel buffer]}]
> (go 
>  (let [v ((if-not (empty? @buffer)
> (do 
>(swap! buffer pop)
>(println "took " v)
> (println "take pending ..."))
>
 

> (defmacro def-pchan
>   ([name]
>`(def ~name (pchan (chan
>   ([name buff]
>`(def ~name (pchan (chan ~buff)
>
 

> (defn clear-buffer [{:keys [buffer]}]
>   (reset! buffer []))
>
> it works!  

> (def-pchan pc)
> (:buffer pc)
> (pbuff pc)
> (ptake pc)
> (pput pc 42)
> (clear-buffer pc)

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


Re: using atoms as logs for channels in core.async

2014-05-12 Thread gamma235
Ok the destructuring is clear to me now. And yes Jay Field article was great :)

So the only thing that remains now is to get the symbol being passed into my 
original transparent-put function to stop evaluating to either ch-log or 
clojure.core.async.impl.channels.ManyToManyChannel@5096B86b-log

I'm using your macro David but it still won't put with an update to the atom.


Jesse

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


Re: using atoms as logs for channels in core.async

2014-05-12 Thread James Reeves
On 12 May 2014 10:48, gamma235  wrote:

> When I try this using your code above I get a stack-trace that I can't
> understand. Am I using it wrong?
>
> (transparent-chan c)
>> (transparent-put c 42)
>> (transparent-take c)
>>
>
Yep, try this instead:

  (def tc (transparent-chan c))
  (transparent-put tc 42)
  (transparent-take tc)

I'm creating a new data structure that contains both a channel and an atom,
and I'm returning it from transparent-ch. I'm not modifying the original
channel in any fashion.

The destructuring is just a shortcut. This code:

  (defn transparent-put [{:keys [channel buffer]} x]
(go
  (>! channel x)
  (swap! buffer conj x)))

Is equivalent to:

  (defn transparent-put [tc x]
(let [{:keys [channel buffer]} tc]
  (go
(>! channel x)
(swap! buffer conj x)))

Which is equivalent to:

  (defn transparent-put [tc x]
(let [channel (:channel tc)
  buffer (:buffer tc)]
  (go
(>! channel x)
(swap! buffer conj x)))

- James

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


Re: using atoms as logs for channels in core.async

2014-05-12 Thread Dave Della Costa
>>
>> >> On Monday, May 12, 2014 1:26:57 PM UTC+9, David Della Costa wrote:
>> >>
>> >> I apologize, apparently you can't use go-loop how I did below,
>> >>
>> >> => (def my-go-loop (async/go-loop [msg (async/> "got
>> >> msg "
>> >> msg " from channel " 'c)))
>> >>
>> >> ...try this instead:
>> >>
>> >> (def my-go-loop (async/go-loop [] (let [msg (async/> (println "got
>> >> msg " msg " from channel " 'c
>> >>
>> >> Sorry about that!
>> >>
>> >> DD
>> >>
>> >> (2014/05/12 13:21), Dave Della Costa wrote:
>> >> >
>> >> >> 1) I feel like it is a redundant to define bindings multiple
>> >> times in
>> >> >> my go's let exprs when the params have already been passed
>> in as
>> >> >> arguments. Is there a more idiomatic way to do this?
>> >> >
>> >> > I think the fact that you are re-binding in a let should
>> show you
>> >> that
>> >> > these variables are already in scope: that let is wholly
>> >> redundant, just
>> >> > remove it.
>> >> >
>> >> >
>> >> >> 2) Whenever I try to create a generic process to
>> automatically
>> >> >> generate a log-name for each channel and then call update,
>> I get a
>>     >> >> 'symbol cannot be cast to atom' error. How can I get
>> around this? It
>> >> >> seems to happen even if I don't use the log-name function.
>> >> >
>> >> > It's simple: a symbol is not an atom.  It's telling you
>> exactly
>> >> what you
>> >> > need to know: you cannot call swap! on a symbol.  Make sure
>> your
>> >> atom is
>> >> > the first argument to swap! wherever you use it.
>> >> >
>> >> >
>> >> >> 3) Is there a better way to keep track of what's on a
>> channel that
>> >> >> doesn't use macros?
>> >> >
>> >> > You cannot look inside of a channel, but to do what you
>> want and
>> >> get a
>> >> > sense of how core.async works, I think you are on the right
>> track by
>> >> > logging as you put stuff in and take it out.
>> >> >
>> >> > That said, I would start by getting rid of the log and the
>> >> macro--these
>> >> > are unnecessary complications--and do things very simply:
>> >> >
>> >> > => (require '[clojure.core.async :as async])
>> >> > nil
>> >> > => (def c (async/chan))
>> >> > #'user/c
>> >> > => (def my-go-loop (async/go-loop [msg (async/> (println "got
>> >> msg "
>> >> > msg " from channel " 'c)))
>> >> > #'user/my-go-loop
>> >> > => (defn put-and-print! [c msg] (println "putting msg " msg
>> " onto
>> >> > channel " 'c) (async/put! c msg))
>> >> > #'user/put-and-print!
>> >> > => (put-and-print! c "I am a message!")
>> >> > putting msg  I am a message!  onto channel  c
>> >> > got msg  I am a message!  from channel  c
>> >> > nil
>> >> > =>
>> >> >
>> >> > Printing out "channel c" is kind of silly since there is
>> only one,
>> >> but
>> >> > it sounds like you may want to do this with multiple
>> channels so
>> >> this is
>> >> > one way to print out the variable name--simply quote it.
>> >> >
>> >> > DD
>> >>  

Re: using atoms as logs for channels in core.async

2014-05-12 Thread Dave Della Costa
> in as
> >> >> arguments. Is there a more idiomatic way to do this?
> >> >
> >> > I think the fact that you are re-binding in a let should
> show you
> >> that
> >> > these variables are already in scope: that let is wholly
> >> redundant, just
> >> > remove it.
> >> >
> >> >
> >> >> 2) Whenever I try to create a generic process to
> automatically
> >> >> generate a log-name for each channel and then call update,
> I get a
> >> >> 'symbol cannot be cast to atom' error. How can I get
> around this? It
> >> >> seems to happen even if I don't use the log-name function.
> >> >
> >> > It's simple: a symbol is not an atom.  It's telling you
> exactly
> >> what you
> >> > need to know: you cannot call swap! on a symbol.  Make sure
> your
> >> atom is
> >> > the first argument to swap! wherever you use it.
> >> >
> >> >
> >> >> 3) Is there a better way to keep track of what's on a
> channel that
> >> >> doesn't use macros?
> >> >
> >> > You cannot look inside of a channel, but to do what you
> want and
> >> get a
> >> > sense of how core.async works, I think you are on the right
> track by
> >> > logging as you put stuff in and take it out.
> >> >
> >> > That said, I would start by getting rid of the log and the
> >> macro--these
> >> > are unnecessary complications--and do things very simply:
> >> >
> >> > => (require '[clojure.core.async :as async])
> >> > nil
> >> > => (def c (async/chan))
> >> > #'user/c
> >> > => (def my-go-loop (async/go-loop [msg (async/ (println "got
> >> msg "
> >> > msg " from channel " 'c)))
> >> > #'user/my-go-loop
> >> > => (defn put-and-print! [c msg] (println "putting msg " msg
> " onto
> >> > channel " 'c) (async/put! c msg))
> >> > #'user/put-and-print!
> >> > => (put-and-print! c "I am a message!")
> >> > putting msg  I am a message!  onto channel  c
> >> > got msg  I am a message!  from channel  c
> >> > nil
> >> > =>
> >> >
> >> > Printing out "channel c" is kind of silly since there is
> only one,
> >> but
> >> > it sounds like you may want to do this with multiple
> channels so
> >> this is
> >> > one way to print out the variable name--simply quote it.
> >> >
> >> > DD
> >> >
> >> > (2014/05/12 11:41), gamma235 wrote:
> >> >> Hi everyone,
> >> >>
> >> >> I am getting my feet wet with core.async and am trying to
> attach
> >> atoms
> >> >> to channels that update automatically and print out to the
> >> console as
> >> >> you take and put. This is not for anything serious, just a
> way to
> >> get
> >> >> familiar with the behavior and functionality of the
> library and
> >> practice
> >> >> my Clojure skills. Thanks in advaan
> >> >>
> >> >> Here is my code:
> >> >>
> >> >> (defn log-name [ch] (symbol (str ch '-log)))
> >> >>  
> >> >>  ;; Is this efficiently written?
> >> >> (defmacro transparent-chan [ch]  
> >> >>   (do
> >> >> `(def ~ch (chan))
> >> >> `(def (log-name ~ch) (atom []))
> >> >> `(println "new transparent channel created!")))
> >> >>  
> >> >> (defn- update [log

Re: using atoms as logs for channels in core.async

2014-05-12 Thread gamma235
m like this. 
> > 
> >> Later I was thinking about incorporating it into a gui to see 
> >> if it's possible to design an asynchronous message passing system 
> >> using drag and drop icons that represent pubs and subs, channels with 
> >> a drop-down contents tab, and running listening processes. 
> >> I know this is probably out of my league, but I was just asking 
> >> myself how something like that might be implemented. 
> > 
> > I think it's totally possible and there's no reason it would be out of 
> > your league. Just keep trying and asking questions here (and on IRC too 
> > if you want to jump on, plenty of folks there willing to help out). 
> > 
> > DD 
> > 
> > (2014/05/12 17:26), gamma235 wrote: 
> >> Thank you for your answer David. 
> >> 
> >> I think I am confused about how to distinguish between a symbol and a 
> >> variable, as I thought that the symbol being derefed pointed to the 
> atom 
> >> that it was made to define when transparent-chan was called. 
> >> 
> >> Also, I am trying to specifically solve the logging problem  to 
> >> understand how I might use stored values or state outside the scope of 
> >> the channel as a means of creating the illusion of referencing its 
> >> contents. Later I was thinking about incorporating it into a gui to see 
> >> if it's possible to design an asynchronous message passing system using 
> >> drag and drop icons that represent pubs and subs, channels with a 
> >> drop-down contents tab, and running listening processes. I know this is 
> >> probably out of my league, but I was just asking myself how something 
> >> like that might be implemented. I will of course continue to learn and 
> >> reinforce the basics though on my own. 
> >> 
> >> Jesse 
> >> 
> >> On Monday, May 12, 2014 1:26:57 PM UTC+9, David Della Costa wrote: 
> >> 
> >> I apologize, apparently you can't use go-loop how I did below, 
> >> 
> >> => (def my-go-loop (async/go-loop [msg (async/ >> msg " 
> >> msg " from channel " 'c))) 
> >> 
> >> ...try this instead: 
> >> 
> >> (def my-go-loop (async/go-loop [] (let [msg (async/ "got 
> >> msg " msg " from channel " 'c 
> >> 
> >> Sorry about that! 
> >> 
> >> DD 
> >> 
> >> (2014/05/12 13:21), Dave Della Costa wrote: 
> >> > 
> >> >> 1) I feel like it is a redundant to define bindings multiple 
> >> times in 
> >> >> my go's let exprs when the params have already been passed in as 
> >> >> arguments. Is there a more idiomatic way to do this? 
> >> > 
> >> > I think the fact that you are re-binding in a let should show you 
> >> that 
> >> > these variables are already in scope: that let is wholly 
> >> redundant, just 
> >> > remove it. 
> >> > 
> >> > 
> >> >> 2) Whenever I try to create a generic process to automatically 
> >> >> generate a log-name for each channel and then call update, I get 
> a 
> >> >> 'symbol cannot be cast to atom' error. How can I get around 
> this? It 
> >> >> seems to happen even if I don't use the log-name function. 
> >> > 
> >> > It's simple: a symbol is not an atom.  It's telling you exactly 
> >> what you 
> >> > need to know: you cannot call swap! on a symbol.  Make sure your 
> >> atom is 
> >> > the first argument to swap! wherever you use it. 
> >> > 
> >> > 
> >> >> 3) Is there a better way to keep track of what's on a channel 
> that 
> >> >> doesn't use macros? 
> >> > 
> >> > You cannot look inside of a channel, but to do what you want and 
> >> get a 
> >> > sense of how core.async works, I think you are on the right track 
> by 
> >> > logging as you put stuff in and take it out. 
> >> > 
> >> > That said, I would start by getting rid of the log and the 
> >> macro--these 
> >> > are unnecessary complications--and do things very simply: 
> >> > 
> >> > => (require '[clojure.core.async :

Re: using atoms as logs for channels in core.async

2014-05-12 Thread Dave Della Costa
now this is
>> probably out of my league, but I was just asking myself how something
>> like that might be implemented. I will of course continue to learn and
>> reinforce the basics though on my own. 
>>
>> Jesse
>>
>> On Monday, May 12, 2014 1:26:57 PM UTC+9, David Della Costa wrote:
>>
>> I apologize, apparently you can't use go-loop how I did below,
>>
>> => (def my-go-loop (async/go-loop [msg (async/> msg "
>> msg " from channel " 'c)))
>>
>> ...try this instead:
>>
>> (def my-go-loop (async/go-loop [] (let [msg (async/> msg " msg " from channel " 'c
>>
>> Sorry about that!
>>
>> DD
>>
>> (2014/05/12 13:21), Dave Della Costa wrote:
>> >
>> >> 1) I feel like it is a redundant to define bindings multiple
>> times in
>> >> my go's let exprs when the params have already been passed in as
>> >> arguments. Is there a more idiomatic way to do this?
>> >
>> > I think the fact that you are re-binding in a let should show you
>> that
>> > these variables are already in scope: that let is wholly
>> redundant, just
>> > remove it.
>> >
>> >
>> >> 2) Whenever I try to create a generic process to automatically
>> >> generate a log-name for each channel and then call update, I get a
>> >> 'symbol cannot be cast to atom' error. How can I get around this? It
>> >> seems to happen even if I don't use the log-name function.
>> >
>> > It's simple: a symbol is not an atom.  It's telling you exactly
>> what you
>> > need to know: you cannot call swap! on a symbol.  Make sure your
>> atom is
>> > the first argument to swap! wherever you use it.
>> >
>> >
>> >> 3) Is there a better way to keep track of what's on a channel that
>> >> doesn't use macros?
>> >
>> > You cannot look inside of a channel, but to do what you want and
>> get a
>> > sense of how core.async works, I think you are on the right track by
>> > logging as you put stuff in and take it out.
>> >
>> > That said, I would start by getting rid of the log and the
>> macro--these
>> > are unnecessary complications--and do things very simply:
>> >
>> > => (require '[clojure.core.async :as async])
>> > nil
>> > => (def c (async/chan))
>> > #'user/c
>> > => (def my-go-loop (async/go-loop [msg (async/> msg "
>> > msg " from channel " 'c)))
>> > #'user/my-go-loop
>> > => (defn put-and-print! [c msg] (println "putting msg " msg " onto
>> > channel " 'c) (async/put! c msg))
>> > #'user/put-and-print!
>> > => (put-and-print! c "I am a message!")
>> > putting msg  I am a message!  onto channel  c
>> > got msg  I am a message!  from channel  c
>> > nil
>> > =>
>> >
>> > Printing out "channel c" is kind of silly since there is only one,
>> but
>> > it sounds like you may want to do this with multiple channels so
>> this is
>> > one way to print out the variable name--simply quote it.
>> >
>> > DD
>> >
>> > (2014/05/12 11:41), gamma235 wrote:
>> >> Hi everyone,
>> >>
>> >> I am getting my feet wet with core.async and am trying to attach
>> atoms
>> >> to channels that update automatically and print out to the
>> console as
>> >> you take and put. This is not for anything serious, just a way to
>> get
>> >> familiar with the behavior and functionality of the library and
>> practice
>> >> my Clojure skills. Thanks in advaan
>> >>
>> >> Here is my code:
>> >>
>> >> (defn log-name [ch] (symbol (str ch '-log)))
>> >>  
>> >>  ;; Is this efficiently written?
>> >> (defmacro transparent-chan [ch]  
>> >>   (do
>> >> `(def ~ch (chan))
>> >> `(def (log-name ~ch) (atom []))
>

Re: using atoms as logs for channels in core.async

2014-05-12 Thread Dave Della Costa
> > I think the fact that you are re-binding in a let should show you
> that
> > these variables are already in scope: that let is wholly
> redundant, just
> > remove it.
> >
> >
> >> 2) Whenever I try to create a generic process to automatically
> >> generate a log-name for each channel and then call update, I get a
> >> 'symbol cannot be cast to atom' error. How can I get around this? It
> >> seems to happen even if I don't use the log-name function.
> >
> > It's simple: a symbol is not an atom.  It's telling you exactly
> what you
> > need to know: you cannot call swap! on a symbol.  Make sure your
> atom is
> > the first argument to swap! wherever you use it.
> >
> >
> >> 3) Is there a better way to keep track of what's on a channel that
> >> doesn't use macros?
> >
> > You cannot look inside of a channel, but to do what you want and
> get a
> > sense of how core.async works, I think you are on the right track by
> > logging as you put stuff in and take it out.
> >
> > That said, I would start by getting rid of the log and the
> macro--these
> > are unnecessary complications--and do things very simply:
> >
> > => (require '[clojure.core.async :as async])
> > nil
> > => (def c (async/chan))
> > #'user/c
> > => (def my-go-loop (async/go-loop [msg (async/ msg "
> > msg " from channel " 'c)))
> > #'user/my-go-loop
> > => (defn put-and-print! [c msg] (println "putting msg " msg " onto
> > channel " 'c) (async/put! c msg))
> > #'user/put-and-print!
> > => (put-and-print! c "I am a message!")
> > putting msg  I am a message!  onto channel  c
> > got msg  I am a message!  from channel  c
> > nil
> > =>
> >
> > Printing out "channel c" is kind of silly since there is only one,
> but
> > it sounds like you may want to do this with multiple channels so
> this is
> > one way to print out the variable name--simply quote it.
> >
> > DD
> >
> > (2014/05/12 11:41), gamma235 wrote:
> >> Hi everyone,
> >>
> >> I am getting my feet wet with core.async and am trying to attach
> atoms
> >> to channels that update automatically and print out to the
> console as
> >> you take and put. This is not for anything serious, just a way to
> get
> >> familiar with the behavior and functionality of the library and
> practice
> >> my Clojure skills. Thanks in advaan
> >>
> >> Here is my code:
> >>
> >> (defn log-name [ch] (symbol (str ch '-log)))
> >>  
> >>  ;; Is this efficiently written?
> >> (defmacro transparent-chan [ch]  
> >>   (do
> >> `(def ~ch (chan))
> >> `(def (log-name ~ch) (atom []))
> >> `(println "new transparent channel created!")))
> >>  
> >> (defn- update [log v]
> >>   (do
> >> (swap! log conj v)
> >> (println "log test passed: " v " has been logged")
> >> (println "channel contents: " @log)))
> >>  
> >>  (defn transparent-put [ch v]
> >>(let [log (log-name ch)]
> >>  (go
> >>   (let [ch ch
> >> v v]
> >> (>! ch v)
> >> (println v " has been successfully moved through the
> channel")))
> >>  (update log v)
> >>  (println "put test passed: " v " has been put on the
> channel")
> >>  (println " rechecking channel contents: " @log)))
> >>  
> >> (defn transparent-take [ch]
> >>   (go
> >>(let [v ( >>  log-name (symbol (str ch '-log))]
> >>  (swap! log-name #(remove #{v} %))
> >>(println v "has been removed from channel")))
> >>   (println " removal pending"))
> >>
> >>  
> >>
&

Re: using atoms as logs for channels in core.async

2014-05-12 Thread gamma235
When I try this using your code above I get a stack-trace that I can't 
understand. Am I using it wrong?

(transparent-chan c)
> (transparent-put c 42)
> (transparent-take c)



   - 
>
>"Exception in thread \"async-dispatch-64\" "
>"java.lang.IllegalArgumentException: No implementation of method: 
>:take! of protocol: #'clojure.core.async.impl.protocols/ReadPort found for 
>class: nil"
>"\tat clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:541)"
   
   





On Monday, May 12, 2014 1:16:19 PM UTC+9, James Reeves wrote:
>
> On 12 May 2014 03:41, gamma235 > wrote:
>
>>
>> (defn log-name [ch] (symbol (str ch '-log)))
>>>  
>>>  ;; Is this efficiently written?
>>> (defmacro transparent-chan [ch]   
>>>   (do
>>> `(def ~ch (chan))
>>> `(def (log-name ~ch) (atom []))
>>> `(println "new transparent channel created!")))
>>>
>>
> This looks like you're replicating the functionality of maps using defs. 
> Instead, consider something like:
>
> (defn transparent-chan [ch]
>   {:channel ch, :buffer (atom [])})
>
> Another improvement you may wish to consider is to use a queue, rather 
> than a vector. Immutable queues exist in Clojure, but are something of a 
> hidden feature.
>
> (defn transparent-chan [ch]
>   {:channel ch, :buffer (atom clojure.lang.PersistentQueue/EMPTY)})
>
> Queues act more like channels, in that popping a queue strips off the 
> oldest item, whereas popping a vector strips off the newest.
>
> With this in mind, you could write functions like:
>
> (defn transparent-put [{:keys [channel buffer]} x]
>   (go
> (>! channel x)
> (swap! buffer conj x)))
>
> (defn transparent-take [{:keys [channel buffer]} x]
>   (go
> (let [x (   (swap! buffer pop)
>   x)))
>
> (defn transparent-buffer [{keys [buffer]}]
>   (vec @buffer))
>
> - James
>

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


Re: using atoms as logs for channels in core.async

2014-05-12 Thread gamma235
Thanks James,

I played around with the persistent queues before I started this exercise, 
but opted for atoms, after seeing this behavior (a la JOC): 

<https://lh6.googleusercontent.com/-4u0XBfNvbv4/U3CMpigLRoI/BjE/HDjKbcvSgAM/s1600/Screen+Shot+2014-05-12+at+5.55.27+PM.png>


I never considered sticking the persistent queue in the atom and your code 
above made me realize that maps are a way better way to do this. 

Rock on, 

Jesse

On Monday, May 12, 2014 1:16:19 PM UTC+9, James Reeves wrote:
>
> On 12 May 2014 03:41, gamma235 > wrote:
>
>>
>> (defn log-name [ch] (symbol (str ch '-log)))
>>>  
>>>  ;; Is this efficiently written?
>>> (defmacro transparent-chan [ch]   
>>>   (do
>>> `(def ~ch (chan))
>>> `(def (log-name ~ch) (atom []))
>>> `(println "new transparent channel created!")))
>>>
>>
> This looks like you're replicating the functionality of maps using defs. 
> Instead, consider something like:
>
> (defn transparent-chan [ch]
>   {:channel ch, :buffer (atom [])})
>
> Another improvement you may wish to consider is to use a queue, rather 
> than a vector. Immutable queues exist in Clojure, but are something of a 
> hidden feature.
>
> (defn transparent-chan [ch]
>   {:channel ch, :buffer (atom clojure.lang.PersistentQueue/EMPTY)})
>
> Queues act more like channels, in that popping a queue strips off the 
> oldest item, whereas popping a vector strips off the newest.
>
> With this in mind, you could write functions like:
>
> (defn transparent-put [{:keys [channel buffer]} x]
>   (go
> (>! channel x)
> (swap! buffer conj x)))
>
> (defn transparent-take [{:keys [channel buffer]} x]
>   (go
> (let [x (   (swap! buffer pop)
>   x)))
>
> (defn transparent-buffer [{keys [buffer]}]
>   (vec @buffer))
>
> - James
>

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


Re: using atoms as logs for channels in core.async

2014-05-12 Thread gamma235
Thank you for your answer David. 

I think I am confused about how to distinguish between a symbol and a 
variable, as I thought that the symbol being derefed pointed to the atom 
that it was made to define when transparent-chan was called. 

Also, I am trying to specifically solve the logging problem  to understand 
how I might use stored values or state outside the scope of the channel as 
a means of creating the illusion of referencing its contents. Later I was 
thinking about incorporating it into a gui to see if it's possible to 
design an asynchronous message passing system using drag and drop icons 
that represent pubs and subs, channels with a drop-down contents tab, and 
running listening processes. I know this is probably out of my league, but 
I was just asking myself how something like that might be implemented. I 
will of course continue to learn and reinforce the basics though on my own. 

Jesse

On Monday, May 12, 2014 1:26:57 PM UTC+9, David Della Costa wrote:
>
> I apologize, apparently you can't use go-loop how I did below, 
>
> => (def my-go-loop (async/go-loop [msg (async/ msg " from channel " 'c))) 
>
> ...try this instead: 
>
> (def my-go-loop (async/go-loop [] (let [msg (async/ msg " msg " from channel " 'c 
>
> Sorry about that! 
>
> DD 
>
> (2014/05/12 13:21), Dave Della Costa wrote: 
> > 
> >> 1) I feel like it is a redundant to define bindings multiple times in 
> >> my go's let exprs when the params have already been passed in as 
> >> arguments. Is there a more idiomatic way to do this? 
> > 
> > I think the fact that you are re-binding in a let should show you that 
> > these variables are already in scope: that let is wholly redundant, just 
> > remove it. 
> > 
> > 
> >> 2) Whenever I try to create a generic process to automatically 
> >> generate a log-name for each channel and then call update, I get a 
> >> 'symbol cannot be cast to atom' error. How can I get around this? It 
> >> seems to happen even if I don't use the log-name function. 
> > 
> > It's simple: a symbol is not an atom.  It's telling you exactly what you 
> > need to know: you cannot call swap! on a symbol.  Make sure your atom is 
> > the first argument to swap! wherever you use it. 
> > 
> > 
> >> 3) Is there a better way to keep track of what's on a channel that 
> >> doesn't use macros? 
> > 
> > You cannot look inside of a channel, but to do what you want and get a 
> > sense of how core.async works, I think you are on the right track by 
> > logging as you put stuff in and take it out. 
> > 
> > That said, I would start by getting rid of the log and the macro--these 
> > are unnecessary complications--and do things very simply: 
> > 
> > => (require '[clojure.core.async :as async]) 
> > nil 
> > => (def c (async/chan)) 
> > #'user/c 
> > => (def my-go-loop (async/go-loop [msg (async/ > msg " from channel " 'c))) 
> > #'user/my-go-loop 
> > => (defn put-and-print! [c msg] (println "putting msg " msg " onto 
> > channel " 'c) (async/put! c msg)) 
> > #'user/put-and-print! 
> > => (put-and-print! c "I am a message!") 
> > putting msg  I am a message!  onto channel  c 
> > got msg  I am a message!  from channel  c 
> > nil 
> > => 
> > 
> > Printing out "channel c" is kind of silly since there is only one, but 
> > it sounds like you may want to do this with multiple channels so this is 
> > one way to print out the variable name--simply quote it. 
> > 
> > DD 
> > 
> > (2014/05/12 11:41), gamma235 wrote: 
> >> Hi everyone, 
> >> 
> >> I am getting my feet wet with core.async and am trying to attach atoms 
> >> to channels that update automatically and print out to the console as 
> >> you take and put. This is not for anything serious, just a way to get 
> >> familiar with the behavior and functionality of the library and 
> practice 
> >> my Clojure skills. Thanks in advaan 
> >> 
> >> Here is my code: 
> >> 
> >> (defn log-name [ch] (symbol (str ch '-log))) 
> >>   
> >>  ;; Is this efficiently written? 
> >> (defmacro transparent-chan [ch]   
> >>   (do 
> >> `(def ~ch (chan)) 
> >> `(def (log-name ~ch) (atom [])) 
> >> `(println "new transparent channel created!"))) 
> >>   
> >> (defn-

Re: using atoms as logs for channels in core.async

2014-05-11 Thread Dave Della Costa
I apologize, apparently you can't use go-loop how I did below,

=> (def my-go-loop (async/go-loop [msg (async/ 
>> 1) I feel like it is a redundant to define bindings multiple times in
>> my go's let exprs when the params have already been passed in as
>> arguments. Is there a more idiomatic way to do this?
> 
> I think the fact that you are re-binding in a let should show you that
> these variables are already in scope: that let is wholly redundant, just
> remove it.
> 
> 
>> 2) Whenever I try to create a generic process to automatically
>> generate a log-name for each channel and then call update, I get a
>> 'symbol cannot be cast to atom' error. How can I get around this? It
>> seems to happen even if I don't use the log-name function.
> 
> It's simple: a symbol is not an atom.  It's telling you exactly what you
> need to know: you cannot call swap! on a symbol.  Make sure your atom is
> the first argument to swap! wherever you use it.
> 
> 
>> 3) Is there a better way to keep track of what's on a channel that
>> doesn't use macros?
> 
> You cannot look inside of a channel, but to do what you want and get a
> sense of how core.async works, I think you are on the right track by
> logging as you put stuff in and take it out.
> 
> That said, I would start by getting rid of the log and the macro--these
> are unnecessary complications--and do things very simply:
> 
> => (require '[clojure.core.async :as async])
> nil
> => (def c (async/chan))
> #'user/c
> => (def my-go-loop (async/go-loop [msg (async/ msg " from channel " 'c)))
> #'user/my-go-loop
> => (defn put-and-print! [c msg] (println "putting msg " msg " onto
> channel " 'c) (async/put! c msg))
> #'user/put-and-print!
> => (put-and-print! c "I am a message!")
> putting msg  I am a message!  onto channel  c
> got msg  I am a message!  from channel  c
> nil
> =>
> 
> Printing out "channel c" is kind of silly since there is only one, but
> it sounds like you may want to do this with multiple channels so this is
> one way to print out the variable name--simply quote it.
> 
> DD
> 
> (2014/05/12 11:41), gamma235 wrote:
>> Hi everyone,
>>
>> I am getting my feet wet with core.async and am trying to attach atoms
>> to channels that update automatically and print out to the console as
>> you take and put. This is not for anything serious, just a way to get
>> familiar with the behavior and functionality of the library and practice
>> my Clojure skills. Thanks in advaan
>>
>> Here is my code: 
>>
>> (defn log-name [ch] (symbol (str ch '-log)))
>>  
>>  ;; Is this efficiently written?
>> (defmacro transparent-chan [ch]   
>>   (do
>> `(def ~ch (chan))
>> `(def (log-name ~ch) (atom []))
>> `(println "new transparent channel created!")))
>>  
>> (defn- update [log v]
>>   (do
>> (swap! log conj v)
>> (println "log test passed: " v " has been logged")
>> (println "channel contents: " @log)))
>>  
>>  (defn transparent-put [ch v]
>>(let [log (log-name ch)]
>>  (go
>>   (let [ch ch
>> v v]
>> (>! ch v)
>> (println v " has been successfully moved through the channel")))
>>  (update log v)
>>  (println "put test passed: " v " has been put on the channel")
>>  (println " rechecking channel contents: " @log)))
>>  
>> (defn transparent-take [ch]
>>   (go
>>(let [v (>  log-name (symbol (str ch '-log))]
>>  (swap! log-name #(remove #{v} %))
>>(println v "has been removed from channel")))
>>   (println " removal pending"))
>>
>>  
>>
>> ;; tests
>> (transparent-chan c)
>> c
>> c-log
>> @c-log
>> (transparent-put c 42)
>> (transparent-take c)
>>
>>
>>
>> My main questions are regarding variable scope: 
>> 1) I feel like it is a redundant to define bindings multiple times in my
>> go's let exprs when the params have already been passed in as arguments.
>> Is there a more idiomatic way to do this?
>>
>> 2) Whenever I try to create a generic process to automatically generate
>> a log-name for each channel and then call upd

Re: using atoms as logs for channels in core.async

2014-05-11 Thread Dave Della Costa

> 1) I feel like it is a redundant to define bindings multiple times in
> my go's let exprs when the params have already been passed in as
> arguments. Is there a more idiomatic way to do this?

I think the fact that you are re-binding in a let should show you that
these variables are already in scope: that let is wholly redundant, just
remove it.


> 2) Whenever I try to create a generic process to automatically
> generate a log-name for each channel and then call update, I get a
> 'symbol cannot be cast to atom' error. How can I get around this? It
> seems to happen even if I don't use the log-name function.

It's simple: a symbol is not an atom.  It's telling you exactly what you
need to know: you cannot call swap! on a symbol.  Make sure your atom is
the first argument to swap! wherever you use it.


> 3) Is there a better way to keep track of what's on a channel that
> doesn't use macros?

You cannot look inside of a channel, but to do what you want and get a
sense of how core.async works, I think you are on the right track by
logging as you put stuff in and take it out.

That said, I would start by getting rid of the log and the macro--these
are unnecessary complications--and do things very simply:

=> (require '[clojure.core.async :as async])
nil
=> (def c (async/chan))
#'user/c
=> (def my-go-loop (async/go-loop [msg (async/ (defn put-and-print! [c msg] (println "putting msg " msg " onto
channel " 'c) (async/put! c msg))
#'user/put-and-print!
=> (put-and-print! c "I am a message!")
putting msg  I am a message!  onto channel  c
got msg  I am a message!  from channel  c
nil
=>

Printing out "channel c" is kind of silly since there is only one, but
it sounds like you may want to do this with multiple channels so this is
one way to print out the variable name--simply quote it.

DD

(2014/05/12 11:41), gamma235 wrote:
> Hi everyone,
> 
> I am getting my feet wet with core.async and am trying to attach atoms
> to channels that update automatically and print out to the console as
> you take and put. This is not for anything serious, just a way to get
> familiar with the behavior and functionality of the library and practice
> my Clojure skills. Thanks in advaan
> 
> Here is my code: 
> 
> (defn log-name [ch] (symbol (str ch '-log)))
>  
>  ;; Is this efficiently written?
> (defmacro transparent-chan [ch]   
>   (do
> `(def ~ch (chan))
> `(def (log-name ~ch) (atom []))
> `(println "new transparent channel created!")))
>  
> (defn- update [log v]
>   (do
> (swap! log conj v)
> (println "log test passed: " v " has been logged")
> (println "channel contents: " @log)))
>  
>  (defn transparent-put [ch v]
>(let [log (log-name ch)]
>  (go
>   (let [ch ch
> v v]
> (>! ch v)
> (println v " has been successfully moved through the channel")))
>  (update log v)
>  (println "put test passed: " v " has been put on the channel")
>  (println " rechecking channel contents: " @log)))
>  
> (defn transparent-take [ch]
>   (go
>(let [v (  log-name (symbol (str ch '-log))]
>  (swap! log-name #(remove #{v} %))
>(println v "has been removed from channel")))
>   (println " removal pending"))
> 
>  
> 
> ;; tests
> (transparent-chan c)
> c
> c-log
> @c-log
> (transparent-put c 42)
> (transparent-take c)
> 
> 
> 
> My main questions are regarding variable scope: 
> 1) I feel like it is a redundant to define bindings multiple times in my
> go's let exprs when the params have already been passed in as arguments.
> Is there a more idiomatic way to do this?
> 
> 2) Whenever I try to create a generic process to automatically generate
> a log-name for each channel and then call update, I get a 'symbol cannot
> be cast to atom' error. How can I get around this? It seems to happen
> even if I don't use the log-name function.
> 
> 3) Is there a better way to keep track of what's on a channel that
> doesn't use macros?
> 
> -- 
> 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 mo

Re: using atoms as logs for channels in core.async

2014-05-11 Thread James Reeves
On 12 May 2014 03:41, gamma235  wrote:

>
> (defn log-name [ch] (symbol (str ch '-log)))
>>
>>  ;; Is this efficiently written?
>> (defmacro transparent-chan [ch]
>>   (do
>> `(def ~ch (chan))
>> `(def (log-name ~ch) (atom []))
>> `(println "new transparent channel created!")))
>>
>
This looks like you're replicating the functionality of maps using defs.
Instead, consider something like:

(defn transparent-chan [ch]
  {:channel ch, :buffer (atom [])})

Another improvement you may wish to consider is to use a queue, rather than
a vector. Immutable queues exist in Clojure, but are something of a hidden
feature.

(defn transparent-chan [ch]
  {:channel ch, :buffer (atom clojure.lang.PersistentQueue/EMPTY)})

Queues act more like channels, in that popping a queue strips off the
oldest item, whereas popping a vector strips off the newest.

With this in mind, you could write functions like:

(defn transparent-put [{:keys [channel buffer]} x]
  (go
(>! channel x)
(swap! buffer conj x)))

(defn transparent-take [{:keys [channel buffer]} x]
  (go
(let [x (http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


using atoms as logs for channels in core.async

2014-05-11 Thread gamma235
Hi everyone,

I am getting my feet wet with core.async and am trying to attach atoms to 
channels that update automatically and print out to the console as you take 
and put. This is not for anything serious, just a way to get familiar with 
the behavior and functionality of the library and practice my Clojure 
skills. Thanks in advaan

Here is my code: 

(defn log-name [ch] (symbol (str ch '-log)))
>  
>  ;; Is this efficiently written?
> (defmacro transparent-chan [ch]   
>   (do
> `(def ~ch (chan))
> `(def (log-name ~ch) (atom []))
> `(println "new transparent channel created!")))
>  
> (defn- update [log v]
>   (do
> (swap! log conj v)
> (println "log test passed: " v " has been logged")
> (println "channel contents: " @log)))
>  
>  (defn transparent-put [ch v]
>(let [log (log-name ch)]
>  (go
>   (let [ch ch
> v v]
> (>! ch v)
> (println v " has been successfully moved through the channel")))
>  (update log v)
>  (println "put test passed: " v " has been put on the channel")
>  (println " rechecking channel contents: " @log)))
>  
> (defn transparent-take [ch]
>   (go
>(let [v (  log-name (symbol (str ch '-log))]
>  (swap! log-name #(remove #{v} %))
>(println v "has been removed from channel")))
>   (println " removal pending"))
>
 

> ;; tests
> (transparent-chan c)
> c
> c-log
> @c-log
> (transparent-put c 42)
> (transparent-take c)



My main questions are regarding variable scope: 
1) I feel like it is a redundant to define bindings multiple times in my 
go's let exprs when the params have already been passed in as arguments. Is 
there a more idiomatic way to do this?

2) Whenever I try to create a generic process to automatically generate a 
log-name for each channel and then call update, I get a 'symbol cannot be 
cast to atom' error. How can I get around this? It seems to happen even if 
I don't use the log-name function.

3) Is there a better way to keep track of what's on a channel that doesn't 
use macros?

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


Re: Reactive Patterns with Atoms - am I using too much state?

2013-12-01 Thread Sam Ritchie
Okay, got it. It looks like you're using agents where I'd been using 
atoms. Not sure if there's much of a difference for these use cases... 
the one-directional flow of source -> state -> watcher update 
notification -> ui change seems to work well with both agents and atoms.


Brian Marick wrote:

On Nov 30, 2013, at 10:39 AM, Sam Ritchie  wrote:


Brian, I like that too. It looks like you're providing the state when you do 
the def-action?


If I understand the question right, yes. A test of a state function would look 
like:

(fact
   (incrementer {:value 1} 3) =>  {:value 4}))


Is the "self" variable "state", captured through the closure?


`self` is the agent, whose dereference is passed in as the symbol named `state`.

That part I'm uncomfortable with. I've put each agent in a namespace with its 
action functions. The convention is that the agent is named `self`, and 
`def-action` knows that convention. It works, but it reminds me too much of 
singletons and all those cases where you start out thinking a single instance 
is all you'll ever need and then discover you were wrong.


Latest book: /Functional Programming for the Object-Oriented Programmer/
https://leanpub.com/fp-oo



--
Sam Ritchie (@sritchie)
Paddleguru Co-Founder
703.863.8561
www.paddleguru.com <http://www.paddleguru.com/>
Twitter <http://twitter.com/paddleguru>// Facebook 
<http://facebook.com/paddleguru>


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

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: Reactive Patterns with Atoms - am I using too much state?

2013-11-30 Thread Brian Marick

On Nov 30, 2013, at 10:39 AM, Sam Ritchie  wrote:

> Brian, I like that too. It looks like you're providing the state when you do 
> the def-action?

If I understand the question right, yes. A test of a state function would look 
like:

(fact 
  (incrementer {:value 1} 3) => {:value 4}))

> Is the "self" variable "state", captured through the closure?

`self` is the agent, whose dereference is passed in as the symbol named `state`.

That part I'm uncomfortable with. I've put each agent in a namespace with its 
action functions. The convention is that the agent is named `self`, and 
`def-action` knows that convention. It works, but it reminds me too much of 
singletons and all those cases where you start out thinking a single instance 
is all you'll ever need and then discover you were wrong. 


Latest book: /Functional Programming for the Object-Oriented Programmer/
https://leanpub.com/fp-oo

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


Re: Reactive Patterns with Atoms - am I using too much state?

2013-11-30 Thread Sam Ritchie
Interesting; I had started playing with the core.async approach, and 
it's good to see that Pedestal's on that same path.


Brian, I like that too. It looks like you're providing the state when 
you do the def-action? Is the "self" variable "state", captured through 
the closure?


Walter van der Laan wrote:
An alternative that I'm looking at is pedestal 0.3.0. It sort of works 
like this...


;; Create a transform-channel and transform-function to handle all 
changes to 'state'

(defn init []
  (let [c (chan)]
(go (while true
  (when-let [[path v] (! transform-chan [path v]))

;; Change the state by calling transform
(transform [athlete-number :active?] true)
(transform [athlete-number :timestamp] ms)

;; Create an inform-channel where functions can subscribe to changes 
in 'state'

(def inform-channel-subscriptions
  [[update-timestamp [:* :timestamp]]
   [update-active [:* :active?]]])

This approach is described in:
https://github.com/pedestal/pedestal/blob/master/app/examples/walkthrough.clj

On Friday, November 29, 2013 6:58:32 PM UTC+1, Sam Ritchie wrote:

Hey guys,

As I start to work on more Clojurescript UI code, I've been
running into a pattern with atoms and watches that I THINK I can
abstract away... but the solution feels wrong, and I'd love to
hear a better way.

Say I'm building a stopwatch for timing runners in a race. I've
got a clojure record like this:

(defrecord StopwatchState [
  active? ;; timer running?
  timestamp ;; UTC time of this particular state
  stopwatch-time ;; the time on the stopwatch as of "timestamp"
  results ;; pairs of [athlete number, time]])

and a bunch of functions that toggle the timer, mark an athlete
crossing the line, update the timer, etc.

My view holds the current state in an atom:

(def state (atom ,,some-stopwatch-state))

and I update my views by adding watches to the atom and refreshing
the various UI components to match the new state.

Now! Here's the annoying pattern. In the cljs UI world, to poke
these atoms, I end up wrapping all of my model functions like this:

(defn toggle! []
  (swap! state toggle))
(defn mark! [athlete-number]
  (swap! state mark athlete-number))

I can think of two ways to break the pattern.

1) A deep-code-walking macro that transforms code like (mark state
athlete-number) into (swap! state mark athlete-number) if the
first argument is an atom;
2) a defstatefn macro that defines the "mark" and "mark!" versions
at the same time.

Both feel wrong. My goal is to program in a more declarative way.
Is there a better way to structure UI code?

-- 
Sam Ritchie (@sritchie)

Paddleguru Co-Founder
703.863.8561
www.paddleguru.com <http://www.paddleguru.com/>
Twitter <http://twitter.com/paddleguru>// Facebook
<http://facebook.com/paddleguru>

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


--
Sam Ritchie (@sritchie)
Paddleguru Co-Founder
703.863.8561
www.paddleguru.com <http://www.paddleguru.com/>
Twitter <http://twitter.com/paddleguru>// Facebook 
<http://facebook.com/paddleguru>


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

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: Reactive Patterns with Atoms - am I using too much state?

2013-11-30 Thread Walter van der Laan
An alternative that I'm looking at is pedestal 0.3.0. It sort of works like 
this...

;; Create a transform-channel and transform-function to handle all changes 
to 'state'
(defn init []
  (let [c (chan)]
(go (while true
  (when-let [[path v] (! transform-chan [path v]))

;; Change the state by calling transform
(transform [athlete-number :active?] true)
(transform [athlete-number :timestamp] ms)

;; Create an inform-channel where functions can subscribe to changes in 
'state'
(def inform-channel-subscriptions
  [[update-timestamp [:* :timestamp]]
   [update-active [:* :active?]]])

This approach is described in:
https://github.com/pedestal/pedestal/blob/master/app/examples/walkthrough.clj

On Friday, November 29, 2013 6:58:32 PM UTC+1, Sam Ritchie wrote:
>
>  Hey guys,
>
> As I start to work on more Clojurescript UI code, I've been running into a 
> pattern with atoms and watches that I THINK I can abstract away... but the 
> solution feels wrong, and I'd love to hear a better way.
>
> Say I'm building a stopwatch for timing runners in a race. I've got a 
> clojure record like this:
>
> (defrecord StopwatchState [
>   active? ;; timer running?
>   timestamp ;; UTC time of this particular state
>   stopwatch-time ;; the time on the stopwatch as of "timestamp"
>   results ;; pairs of [athlete number, time]])
>
> and a bunch of functions that toggle the timer, mark an athlete crossing 
> the line, update the timer, etc.
>
> My view holds the current state in an atom:
>
> (def state (atom ,,some-stopwatch-state))
>
> and I update my views by adding watches to the atom and refreshing the 
> various UI components to match the new state.
>
> Now! Here's the annoying pattern. In the cljs UI world, to poke these 
> atoms, I end up wrapping all of my model functions like this:
>
> (defn toggle! []
>   (swap! state toggle))
> (defn mark! [athlete-number]
>   (swap! state mark athlete-number))
>
> I can think of two ways to break the pattern.
>
> 1) A deep-code-walking macro that transforms code like (mark state 
> athlete-number) into (swap! state mark athlete-number) if the first 
> argument is an atom;
> 2) a defstatefn macro that defines the "mark" and "mark!" versions at the 
> same time.
>
> Both feel wrong. My goal is to program in a more declarative way. Is there 
> a better way to structure UI code?
>
> -- 
> Sam Ritchie (@sritchie)
> Paddleguru Co-Founder
> 703.863.8561
> www.paddleguru.com
> Twitter <http://twitter.com/paddleguru> // 
> Facebook<http://facebook.com/paddleguru>
>  

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


Re: Reactive Patterns with Atoms - am I using too much state?

2013-11-29 Thread Brian Marick

On Nov 29, 2013, at 11:58 AM, Sam Ritchie  wrote:

> 2) a defstatefn macro that defines the "mark" and "mark!" versions at the 
> same time.

I do that with agents:

(def-action text :send [state number message])

… creates a `text*` and a `text>!`, where `test>!` is

(defn text>! [number message] (send self text* number message))

A nice bit about this is that `text*` is pure, so easily testable. Since 
`text>!` is constructed, I'm happy not testing it. Since I use Midje 
prerequisites to test that the `>!`-style functions are called when 
appropriate, I get nicely decoupled unit tests that don't have to know they're 
working with agents (except that the `>!` functions always return irrelevant 
values.)

I haven't been using this style for long, but it feels right so far.


Latest book: /Functional Programming for the Object-Oriented Programmer/
https://leanpub.com/fp-oo

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


Reactive Patterns with Atoms - am I using too much state?

2013-11-29 Thread Sam Ritchie

Hey guys,

As I start to work on more Clojurescript UI code, I've been running into 
a pattern with atoms and watches that I THINK I can abstract away... but 
the solution feels wrong, and I'd love to hear a better way.


Say I'm building a stopwatch for timing runners in a race. I've got a 
clojure record like this:


(defrecord StopwatchState [
  active? ;; timer running?
  timestamp ;; UTC time of this particular state
  stopwatch-time ;; the time on the stopwatch as of "timestamp"
  results ;; pairs of [athlete number, time]])

and a bunch of functions that toggle the timer, mark an athlete crossing 
the line, update the timer, etc.


My view holds the current state in an atom:

(def state (atom ,,some-stopwatch-state))

and I update my views by adding watches to the atom and refreshing the 
various UI components to match the new state.


Now! Here's the annoying pattern. In the cljs UI world, to poke these 
atoms, I end up wrapping all of my model functions like this:


(defn toggle! []
  (swap! state toggle))
(defn mark! [athlete-number]
  (swap! state mark athlete-number))

I can think of two ways to break the pattern.

1) A deep-code-walking macro that transforms code like (mark state 
athlete-number) into (swap! state mark athlete-number) if the first 
argument is an atom;
2) a defstatefn macro that defines the "mark" and "mark!" versions at 
the same time.


Both feel wrong. My goal is to program in a more declarative way. Is 
there a better way to structure UI code?


--
Sam Ritchie (@sritchie)
Paddleguru Co-Founder
703.863.8561
www.paddleguru.com <http://www.paddleguru.com/>
Twitter <http://twitter.com/paddleguru>// Facebook 
<http://facebook.com/paddleguru>


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

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Re: big atoms (was Re: STM - a request for "war stories")

2012-12-14 Thread Marko Topolnik


> In the epic thread about the STM between Rich and Cliff Click[1] the 
> main argument against the STM was that it didn't help solve the problem 
> of where to place guards around the data. From one of Cliff's arguments: 
>
> In a trivial example I can say �go up one call level and atomic 
> there�, 
> but in the Real Program � I can�t do that. 
> Go up how many layers and add atomic? 1 layer? 10 layers? 100 layers? 
> Yes, I see unique call-stacks 
> with >100 layers. I can�t put atomic around main because that makes my 
> program single-threaded. 
>
>
> I believe Cliff is arguing here that when a program pushes all of the 
> state into a single atom where a lot of writes occur that app 
> effectively is single-threaded. (Please correct me if I am 
> misunderstanding!) Thoughts? 
>

Actually, this is one of Cliff's weaker points. Note that when he says 
"atomic", he really means "dosync". He speaks from experience with HotSpot 
where this was a constant source of bugs. It doesn't translate directly 
into the same ptifalls with Clojure's STM because 1) Clojure has strict 
control on what needs a transaction to mutate and 2) the points of mutation 
are much more focused when you are dealing with immutable structures.

Cliff's strongest argument comes from experience with MPI, where he raises 
very valid points against any implementation of a high-performance 
concurrent library:

This is exactly the trap MPI fell into; and *you* have to do it anyways.  
>  Double-unsmiley.   :-(   :-( 
>
> Here’s the deal:
>
> I write a Large Complex Program, one that Really Needs STM to get it 
>right.   
>- But performance sucks.   
>- So I do a deep dive into the STM runtime, and discover it has 
>warts.   
>- So I hack my code to work around the warts in the STM.   
>- Crap like: at an average of 5 cpus in this atomic block the STM 
>‘works’, but at an average of 7 cpus in the same atomic block I get a 
>continous fail/retry rate that’s so bad I might as well not bother.  So I 
>guard the STM area with a “5-at-a-time” lock and a queue of threads 
> waiting 
>to enter.  Bleah (been there; done that – for a DB not an STM but 
>same-in-priniciple situation).  A thousand thousand variations of the same 
>crap happens, each requiring a different hack to my code to make it 
>performant.   
>- Meanwhile the STM author (You: Rich) hacks out some warts & hands me 
>a beta version.   
>- I hack my code to match the STM’s new behavior, and discover some 
>new warts.
>
> Back & Forth we go – and suddenly: my app’s “performance correctness” is 
> intimately tied to the exact STM implementation.  Any change to the STM’s 
> behavior kills my performance – and you, Rich, have learned a lot about the 
> building of a robust good STM.  You (now) know the mistakes you made and *
> know*it’s time to restart the STM implementation from scratch.
>
 
On the other hand, this is a problem occuring only at the most demanding 
level of load on the code. People may still benefit from the STM to write 
simple, correct concurrent programs. As I already explained, in my 
experience atoms cover 98% of that need and locks are still unavoidable. If 
I wrote a whole system from scratch and based everything on the STM, *then* it 
could replace locks. This will never happen in a JDK-based 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

big atoms (was Re: STM - a request for "war stories")

2012-12-13 Thread Ben Mabey


Datomic stores the entire database in an atom (not an STM ref), and 
updates it with a call to swap! It is literally no more complex than a 
trivial hackneyed book example. :-)




A lot of my systems have evolved into something similar and I've 
wondered what the implications of this approach are. As more and more 
state is added to this single atom and with multiple threads performing 
swap!s (CASs) how will performance be effected? i.e. How will write 
contention play out in a system designed like this? I'm sure the answer 
to this depends on the details of the system but at what point does this 
become a problem?


In the epic thread about the STM between Rich and Cliff Click[1] the 
main argument against the STM was that it didn't help solve the problem 
of where to place guards around the data. From one of Cliff's arguments:


In a trivial example I can say “go up one call level and atomic there”, 
but in the Real Program – I can’t do that.
Go up how many layers and add atomic? 1 layer? 10 layers? 100 layers? 
Yes, I see unique call-stacks
with >100 layers. I can’t put atomic around main because that makes my 
program single-threaded.



I believe Cliff is arguing here that when a program pushes all of the 
state into a single atom where a lot of writes occur that app 
effectively is single-threaded. (Please correct me if I am 
misunderstanding!) Thoughts?


-Ben


1. http://www.azulsystems.com/blog/cliff/2008-05-27-clojure-stms-vs-locks

--
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: On using atoms together with side effect functions

2012-01-06 Thread Cedric Greevey
On Fri, Jan 6, 2012 at 11:28 PM, Alan Malloy  wrote:
> but if you look at the post

There is no call for taking a rude tone. I correctly answered the
question as originally posed.

-- 
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: On using atoms together with side effect functions

2012-01-06 Thread Alan Malloy
On Jan 6, 7:32 pm, Cedric Greevey  wrote:
> On Fri, Jan 6, 2012 at 10:22 PM, Alan Malloy  wrote:
> > On Jan 6, 6:16 pm, Cedric Greevey  wrote:
> >> On Fri, Jan 6, 2012 at 4:34 PM, Alan Malloy  wrote:
> >> > On Jan 6, 12:56 pm, Jozef Wagner  wrote:
> >> >> Thank you,
>
> >> >> But the things are more complicated. In my case, I need to update the 
> >> >> atom
> >> >> with the result of a (native) function which unfortunately also performs
> >> >> some side effects and cannot be split in two.
>
> >> >> Updated example:
>
> >> >> (def state {:result nil :input [1 2 3]})
>
> >> >> (defn update-item!
> >> >>   [item]
> >> >>   (if (:result item) ; if already processed, do nothing
> >> >>     item
> >> >>     (let [result (side-effect-fn! (:input item))]
> >> >>       (assoc item :result result
>
> >> >> (swap! state update-item!) ;; same problem
>
> >> > Not doable with atoms if you have a side-effecty thing that you can't
> >> > separate out. You'll have to use something lower-level like Java
> >> > synchronization or locks.
>
> >> Or something higher level like transactions. Use a ref and have
> >> update! alter the ref, then (send-off some-agent #(spit ...)), inside
> >> a dosync. The agent send only goes if the transaction commits.
>
> > This works exactly as well as with atoms: it works fine if you have a
> > pure function and an I/O function, but doesn't work if you have a
> > single function that does both pure computation and I/O side effects.
> > Jozef has some Java magic that does I/O as a side effect of a
> > computation, and he cannot untangle the two.
>
> Wrong. Jozef has this:
>
> (def aval (atom {:dumped false :contents "hello world"}))
>
> (defn update!
>   [item]
>   (when-not (:dumped item)
>     (spit "a.out" (:contents item) :append true)
>     (assoc item :dumped true)))
>
> (swap! aval update!)
>
> Which can be transformed to this:
>
> (def aval (ref {:dumped false :contents "hello world"}))
>
> (def aagent (agent nil))
>
> (defn update
>   [item]
>   (dosync
>     (if (:dumped @item)
>       (ref-set item nil)
>       (do
>         (alter item assoc :dumped true)
>         (send-off aagent (fn [_] (do (spit "a.out" (:contents @item)
> :append true) nil)))
>
> (update aval)
>
> which should have the same semantics, except that the spit cannot be
> done twice (or more) for one call to update.

That's the simplification he made in his first post, but if you look
at the post I was actually replying to he's confessed he actually has
a different situation.

-- 
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: On using atoms together with side effect functions

2012-01-06 Thread Cedric Greevey
On Fri, Jan 6, 2012 at 10:22 PM, Alan Malloy  wrote:
> On Jan 6, 6:16 pm, Cedric Greevey  wrote:
>> On Fri, Jan 6, 2012 at 4:34 PM, Alan Malloy  wrote:
>> > On Jan 6, 12:56 pm, Jozef Wagner  wrote:
>> >> Thank you,
>>
>> >> But the things are more complicated. In my case, I need to update the atom
>> >> with the result of a (native) function which unfortunately also performs
>> >> some side effects and cannot be split in two.
>>
>> >> Updated example:
>>
>> >> (def state {:result nil :input [1 2 3]})
>>
>> >> (defn update-item!
>> >>   [item]
>> >>   (if (:result item) ; if already processed, do nothing
>> >>     item
>> >>     (let [result (side-effect-fn! (:input item))]
>> >>       (assoc item :result result
>>
>> >> (swap! state update-item!) ;; same problem
>>
>> > Not doable with atoms if you have a side-effecty thing that you can't
>> > separate out. You'll have to use something lower-level like Java
>> > synchronization or locks.
>>
>> Or something higher level like transactions. Use a ref and have
>> update! alter the ref, then (send-off some-agent #(spit ...)), inside
>> a dosync. The agent send only goes if the transaction commits.
>
> This works exactly as well as with atoms: it works fine if you have a
> pure function and an I/O function, but doesn't work if you have a
> single function that does both pure computation and I/O side effects.
> Jozef has some Java magic that does I/O as a side effect of a
> computation, and he cannot untangle the two.

Wrong. Jozef has this:

(def aval (atom {:dumped false :contents "hello world"}))

(defn update!
  [item]
  (when-not (:dumped item)
(spit "a.out" (:contents item) :append true)
(assoc item :dumped true)))

(swap! aval update!)

Which can be transformed to this:

(def aval (ref {:dumped false :contents "hello world"}))

(def aagent (agent nil))

(defn update
  [item]
  (dosync
(if (:dumped @item)
  (ref-set item nil)
  (do
(alter item assoc :dumped true)
(send-off aagent (fn [_] (do (spit "a.out" (:contents @item)
:append true) nil)))

(update aval)

which should have the same semantics, except that the spit cannot be
done twice (or more) for one call to update.

-- 
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: On using atoms together with side effect functions

2012-01-06 Thread Alan Malloy
On Jan 6, 6:16 pm, Cedric Greevey  wrote:
> On Fri, Jan 6, 2012 at 4:34 PM, Alan Malloy  wrote:
> > On Jan 6, 12:56 pm, Jozef Wagner  wrote:
> >> Thank you,
>
> >> But the things are more complicated. In my case, I need to update the atom
> >> with the result of a (native) function which unfortunately also performs
> >> some side effects and cannot be split in two.
>
> >> Updated example:
>
> >> (def state {:result nil :input [1 2 3]})
>
> >> (defn update-item!
> >>   [item]
> >>   (if (:result item) ; if already processed, do nothing
> >>     item
> >>     (let [result (side-effect-fn! (:input item))]
> >>       (assoc item :result result
>
> >> (swap! state update-item!) ;; same problem
>
> > Not doable with atoms if you have a side-effecty thing that you can't
> > separate out. You'll have to use something lower-level like Java
> > synchronization or locks.
>
> Or something higher level like transactions. Use a ref and have
> update! alter the ref, then (send-off some-agent #(spit ...)), inside
> a dosync. The agent send only goes if the transaction commits.

This works exactly as well as with atoms: it works fine if you have a
pure function and an I/O function, but doesn't work if you have a
single function that does both pure computation and I/O side effects.
Jozef has some Java magic that does I/O as a side effect of a
computation, and he cannot untangle the two.

-- 
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: On using atoms together with side effect functions

2012-01-06 Thread Cedric Greevey
On Fri, Jan 6, 2012 at 4:34 PM, Alan Malloy  wrote:
> On Jan 6, 12:56 pm, Jozef Wagner  wrote:
>> Thank you,
>>
>> But the things are more complicated. In my case, I need to update the atom
>> with the result of a (native) function which unfortunately also performs
>> some side effects and cannot be split in two.
>>
>> Updated example:
>>
>> (def state {:result nil :input [1 2 3]})
>>
>> (defn update-item!
>>   [item]
>>   (if (:result item) ; if already processed, do nothing
>>     item
>>     (let [result (side-effect-fn! (:input item))]
>>       (assoc item :result result
>>
>> (swap! state update-item!) ;; same problem
>
> Not doable with atoms if you have a side-effecty thing that you can't
> separate out. You'll have to use something lower-level like Java
> synchronization or locks.

Or something higher level like transactions. Use a ref and have
update! alter the ref, then (send-off some-agent #(spit ...)), inside
a dosync. The agent send only goes if the transaction commits.

-- 
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: On using atoms together with side effect functions

2012-01-06 Thread Alan Malloy
On Jan 6, 12:56 pm, Jozef Wagner  wrote:
> Thank you,
>
> But the things are more complicated. In my case, I need to update the atom
> with the result of a (native) function which unfortunately also performs
> some side effects and cannot be split in two.
>
> Updated example:
>
> (def state {:result nil :input [1 2 3]})
>
> (defn update-item!
>   [item]
>   (if (:result item) ; if already processed, do nothing
>     item
>     (let [result (side-effect-fn! (:input item))]
>       (assoc item :result result
>
> (swap! state update-item!) ;; same problem

Not doable with atoms if you have a side-effecty thing that you can't
separate out. You'll have to use something lower-level like Java
synchronization or locks.

-- 
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: On using atoms together with side effect functions

2012-01-06 Thread Jozef Wagner
Thank you,

But the things are more complicated. In my case, I need to update the atom 
with the result of a (native) function which unfortunately also performs 
some side effects and cannot be split in two.

Updated example:

(def state {:result nil :input [1 2 3]})

(defn update-item!
  [item]
  (if (:result item) ; if already processed, do nothing
item
(let [result (side-effect-fn! (:input item))]
  (assoc item :result result

(swap! state update-item!) ;; same problem

Jozef

-- 
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: On using atoms together with side effect functions

2012-01-06 Thread Dave Ray
On Fri, Jan 6, 2012 at 3:02 PM, Jozef Wagner  wrote:
> Consider this contrived piece of code:
>
> (def aval (atom {:dumped false :contents "hello world"}))
>
> (defn update!
>   [item]
>   (when-not (:dumped item)
>     (spit "a.out" (:contents item) :append true)
>     (assoc item :dumped true)))
>
> How should I correctly call update! ? Each of following two calls have
> drawbacks.
>
> (swap! aval update!) ;; update! can be called more than once
>
> (let [new-val (update! aval)]
>   ;; aval can be changed in between from other thread
>   (reset! aval new-val))
>
> Best,
> Jozef
>

Jozef,

I think you can solve this by adding a little more info and keeping
the update function and side effects separate:

(def aval (atom { :contents "hello world" }))

(defn update-item [{:keys [dumped] :as item}]
  (assoc item :dumped true :needs-dump (not dumped)))

(let [{:keys [needs-dump contents]} (swap! aval update-item)]
  (if needs-dump
(spit "a.out" contents :append true)))

Whoever gets to aval first while it hasn't been dumped will see
needs-dump as true and write the file. Depending on your requirements,
if the file write fails, you'll might need to do some extra work to
put aval back in a state consistent with reality.

Hope this helps,

Dave

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


On using atoms together with side effect functions

2012-01-06 Thread Jozef Wagner
Consider this contrived piece of code:

(def aval (atom {:dumped false :contents "hello world"}))

(defn update!
  [item]
  (when-not (:dumped item)
(spit "a.out" (:contents item) :append true)
(assoc item :dumped true)))

How should I correctly call update! ? Each of following two calls have 
drawbacks.

(swap! aval update!) ;; update! can be called more than once

(let [new-val (update! aval)]
  ;; aval can be changed in between from other thread
  (reset! aval new-val))

Best,
Jozef

-- 
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: working with agents and atoms - a beginner question

2010-06-17 Thread Ryan Waters
After reading your posts and thinking "wouldn't it be nice to just
kick off a thread and not care about the return value" I recall Rich
using/liking [1] the Java Executor framework [2].   I looked at
clojure.lang.Agent and saw it used there, too.  It's tricky because I
wouldn't want to lean on Java too much for something this fundamental
or go too far without expecting to have to code something as
complicated as what's found in core.clj (with possible java mechanics
as found in RT.java).

I picture wanting a system that can kick off workers (Executor
framework) that only needs start() and join() semantics.  I haven't
gone through all the Executor and related stuff yet so I still need to
read about everything that's available.

- - -

[1] http://clojure.org/concurrent_programming
[2] http://www.ibm.com/developerworks/java/library/j-jtp1126.html




On Wed, Jun 16, 2010 at 3:51 PM, Meikel Brandmeyer  wrote:
> Hi,
>
> Am 16.06.2010 um 22:34 schrieb Christophe Grand:
>
>> I agree, it still feels a little dirty to use a future without caring
>> about the return value but on the positive said you get an easy way to
>> block and wait for the tread to finish (deref) and you also get
>> future-done?, future-cancel and future-cancelled which can prove
>> useful.
>
> True. This infrastructure is an incentive to use future. Maybe one can wash 
> away the dirty feeling by believing, that deref'ing is actually a 
> syncronisation point of sorts and the return value just a "side-effect".
>
> Sincerely
> Meikel
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
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: working with agents and atoms - a beginner question

2010-06-16 Thread Meikel Brandmeyer
Hi,

Am 16.06.2010 um 22:34 schrieb Christophe Grand:

> I agree, it still feels a little dirty to use a future without caring
> about the return value but on the positive said you get an easy way to
> block and wait for the tread to finish (deref) and you also get
> future-done?, future-cancel and future-cancelled which can prove
> useful.

True. This infrastructure is an incentive to use future. Maybe one can wash 
away the dirty feeling by believing, that deref'ing is actually a 
syncronisation point of sorts and the return value just a "side-effect".

Sincerely
Meikel

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


Re: working with agents and atoms - a beginner question

2010-06-16 Thread Christophe Grand
On Wed, Jun 16, 2010 at 10:20 PM, Meikel Brandmeyer  wrote:
> The typical solution for your problem would probably be:
>
> (->> long-running-function-with-recur Thread. .start)
>
> This starts you function in a dedicated thread and you can save the overhead 
> of send-off and use recur directly. I'm unsure about using future here. For 
> me future is a thing, which returns something. Using it for a process which 
> does return something useful seems "dirty" to me.

I agree, it still feels a little dirty to use a future without caring
about the return value but on the positive said you get an easy way to
block and wait for the tread to finish (deref) and you also get
future-done?, future-cancel and future-cancelled which can prove
useful.

Christophe


-- 
European Clojure Training Session: Brussels, 23-25/6 http://conj-labs.eu/
Professional: http://cgrand.net/ (fr)
On Clojure: http://clj-me.cgrand.net/ (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: working with agents and atoms - a beginner question

2010-06-16 Thread Meikel Brandmeyer
Hi,

Am 15.06.2010 um 23:27 schrieb Ryan Waters:

> Thank you for pointing that out.  I notice your style is similar to
> Rich's in his ant.clj [1] which seems like the kind of solution that
> might be used in other functional and/or lisp languages.  Do you know
> if that's the case with self-calling functions and agents?  However,
> isn't there more overhead with calls to send-off instead of recur?

Yes, there is additional overhead. However hijacking a thread from agent thread 
pool (even if send-off) is misusing agents as Christophe said. Agents is about 
updating states. Not about (long running) threads.

The typical solution for your problem would probably be:

(->> long-running-function-with-recur Thread. .start)

This starts you function in a dedicated thread and you can save the overhead of 
send-off and use recur directly. I'm unsure about using future here. For me 
future is a thing, which returns something. Using it for a process which does 
return something useful seems "dirty" to me.

> I understand functions sent to an agent will only run one at a time,
> fifo-style, but was under the impression *agent* was for the current
> "main" thread of the program.  Does *agent* instead refer to whatever
> is the current thread in the function's runtime context?  Hope that
> question makes sense.

*agent* is bound to the agent whose action we are currently running in this 
thread. So concurrently running actions see different *agent*s.

Hope this helps.

Sincerely
Meikel

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


Re: working with agents and atoms - a beginner question

2010-06-16 Thread Ryan Waters
On Wed, Jun 16, 2010 at 12:17 AM, Christophe Grand
 wrote:
> Hi Ryan,
>
> On Tue, Jun 15, 2010 at 6:01 PM, Ryan Waters  wrote:
>> I'm working with the code at the following gist and also pasted below:
>>
>> http://gist.github.com/421550
>>
>> I'd like to have execution of a separate thread (agent) continue
>> running until it sees the atom 'running' change to false.
>>
>> Unfortunately, the program doesn't return from the send-off but
>> to my understanding it should.  Why won't it return?  I'm using
>> clojure 1.1.
>
> It does return from send-off -- in your gist's version at last thanks
> to Shawn but there are still other errors.
>
>> (ns nmanage)
>>
>> (def running (atom true))
>>
>> (defn process
>>  []
>
> A fn sent as an action to an agent must accept at least one arg: the
> agent's current value (if additional args are passed to args, the
> action fn must accept them too). So the above line should be [_] (_ to
> signify that you don't care about the value) instead of []
>

Thank you - I was unaware that a function sent to an agent had to
accept at least one arg.

>>  (when @running
>>    (prn "hi")
>>    (Thread/sleep 1000))
>>  (recur))
>
> Here your recur is misplaced, you want to recur when @running is true
> so the (recur) should be at the end of the when form and it should
> have an extra argument since we changed process to take one arg.
> However this when/recur pattern is what the while macro expands to.
>
> (defn process [_]
>  (while @running
>   (prn "hi")
>   (Thread/sleep 1000)))
>

Very true - in this example, I totally agree.  The example I put
together is a simplified version of the program I'm working on which
uses some file I/O.  I'm wanting to tail a file and process its
contents over time so I had a loop that would read the file until it
started reading 'nil', then sleep, then try again, creating a loop
within a loop (and polling the file for new contents).  In trying to
keep the example program faithful to the other, I ended up with some
nonsensical clojure  ; )

>
>> ;;;
>> (send-off (agent nil) (process))
>
> Here it should be (send-off (agent nil) process) but Shawn already
> pointed this out.
>
> I think that using an agent and not caring about its value is kind of
> an abuse, better use a future.
>
> (def running (atom true))
>
> (future
>  (while @running
>    (prn "hi")
>    (Thread/sleep 1000)))
>

Here my near total ignorance of futures comes into play.  Thank you
very much for pointing this out as a better way.  I've been so eager
to write a first program in clojure that I haven't gotten through all
the 1.1 (and 1.0) language features yet. :D


> ;;;
> (do
>  (prn "this prints now - fixed thanks to Shawn Hoover")
>  (Thread/sleep 2000)
>  (reset! running false))
>
> hth,
>
> Christophe
>
> --
> European Clojure Training Session: Brussels, 23-25/6 http://conj-labs.eu/
> Professional: http://cgrand.net/ (fr)
> On Clojure: http://clj-me.cgrand.net/ (en)
>

I appreciate yours and everyone's valuable time!

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