Re: Some basic guidance to designing functional vs. state parts of app

2010-03-03 Thread eyeris
One aspect of your question that makes it difficult to answer is that
you don't explain what the repercussions should be (in terms of
synchronization) when a new applicant or job enters the pool or a new
skill is attributed to an applicant. Should the job<->applicant
matching function be restarted? Are you simply trying to isolate the
matching algorithm from updates to the data structures?



On Mar 2, 10:34 pm, Sophie  wrote:
> As a bit of a newbie to the functional + identity/state design space,
> I'm struggling a bit with where to use identity constructs (refs) and
> where to stay with pure functions, and could use some guidance. Pardon
> me if some of my terms are a bit off. Here is a simple hypothetical
> app for matching Applicants to Jobs.
>
> I have several Applicants, each with some set of Skills. There are
> several Jobs, each with some Requirements. There is some Match
> relation between Skills and the Jobs they can match. The set of
> Applicants, each of their skills, and the set of Jobs can change with
> time. There is a set of Jobs that each Applicant can fill,
> functionally computed from applicant skills & job requirements &
> Match.
>
> Ok, so jobs_that_an_applicant_can_fill is a pure function, I get
> that.
>
> Do I design a single "World" ref whose state changes with time to
> different worlds, so adding a new Applicant or even adding a new Skill
> to an existing Applicant results in a new World value? Or is it better
> to have an "Applicants" ref and a "Jobs" ref that refer to different
> sets of those er.. things?
>
> Can each Applicant have a "skills" ref, whose state changes to
> different sets of Skills? Should I design it this way?
>
> How do I choose? What are the trade-offs?
>
> Any and all guidance, insights, advice etc. welcome!
>
> 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


Re: Some basic guidance to designing functional vs. state parts of app

2010-03-03 Thread Armando Blancas


On Mar 2, 8:34 pm, Sophie  wrote:
> Do I design a single "World" ref whose state changes with time to
> different worlds, so adding a new Applicant or even adding a new Skill
> to an existing Applicant results in a new World value? Or is it better
> to have an "Applicants" ref and a "Jobs" ref that refer to different
> sets of those er.. things?
>

It's simpler to use refs close to the object that will change; that
makes
the code to mutate the value simpler; if the world is the only mutable
object,
then the code to change something in there will increase with the
depth
of the mutation.

> Can each Applicant have a "skills" ref, whose state changes to
> different sets of Skills? Should I design it this way?

Yes; and if the kills set in independent of other state it may be an
atom and you
avoid a dosync if the program is single-threaded.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from 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: Some basic guidance to designing functional vs. state parts of app

2010-03-03 Thread Mike Meyer
On Wed, 3 Mar 2010 14:20:56 -0800 (PST)
Armando Blancas  wrote:

> 
> 
> On Mar 2, 8:34 pm, Sophie  wrote:
> > Do I design a single "World" ref whose state changes with time to
> > different worlds, so adding a new Applicant or even adding a new Skill
> > to an existing Applicant results in a new World value? Or is it better
> > to have an "Applicants" ref and a "Jobs" ref that refer to different
> > sets of those er.. things?
> >
> 
> It's simpler to use refs close to the object that will change; that
> makes
> the code to mutate the value simpler; if the world is the only mutable
> object,
> then the code to change something in there will increase with the
> depth
> of the mutation.

I'm not sure it's simpler: update-in makes reaching deep into a
structure to create a new structure with that one change in it easy,
and is probably more efficient than trying to do the same thing by
hand.

More importantly, if you break your refs up into smaller objects, you
should get better concurrency, as you can change two such refs in two
different threads without a problem. If you put the two in a structure
in the same ref, then you can't update one while the other is being
worked on.

 http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.

O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from 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: Some basic guidance to designing functional vs. state parts of app

2010-03-03 Thread Rick Moynihan
On 3 March 2010 04:34, Sophie  wrote:
> As a bit of a newbie to the functional + identity/state design space,
> I'm struggling a bit with where to use identity constructs (refs) and
> where to stay with pure functions, and could use some guidance. Pardon
> me if some of my terms are a bit off. Here is a simple hypothetical
> app for matching Applicants to Jobs.
>
> I have several Applicants, each with some set of Skills. There are
> several Jobs, each with some Requirements. There is some Match
> relation between Skills and the Jobs they can match. The set of
> Applicants, each of their skills, and the set of Jobs can change with
> time. There is a set of Jobs that each Applicant can fill,
> functionally computed from applicant skills & job requirements &
> Match.
>
> Ok, so jobs_that_an_applicant_can_fill is a pure function, I get
> that.
>
> Do I design a single "World" ref whose state changes with time to
> different worlds, so adding a new Applicant or even adding a new Skill
> to an existing Applicant results in a new World value? Or is it better
> to have an "Applicants" ref and a "Jobs" ref that refer to different
> sets of those er.. things?
>
> Can each Applicant have a "skills" ref, whose state changes to
> different sets of Skills? Should I design it this way?
>
> How do I choose? What are the trade-offs?

If you have a single value representing the whole world, then it seems
that protecting it with an atom would be the simplest and most
idiomatic solution.  Refs are for co-ordinated change, i.e. where you
want to update multiple values at the same time.  For a single value
there seems to be little reason to adopt refs, though I've often
wondered why Stuart Halloway's book gives an example updating a single
ref of messages for a chat application.

If you partition your data more, into several values, then you should
use refs to co-ordinate the change.  The more granular you make the
refs, the more you trade complexity of design for potential throughput
under concurrent load, as finer grained refs are likely to mean less
collisions during transactions (unless of course you update every ref
in every transaction - which sounds like it'd be the worst case
scenario).

R.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from 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: Some basic guidance to designing functional vs. state parts of app

2010-03-03 Thread Richard Newman

For a single value
there seems to be little reason to adopt refs, though I've often
wondered why Stuart Halloway's book gives an example updating a single
ref of messages for a chat application.


I seem to recall atoms being the last reference type to be introduced.  
They might not have existed when Stuart was writing.


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from 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: Some basic guidance to designing functional vs. state parts of app

2010-03-03 Thread rzeze...@gmail.com


On Mar 2, 11:34 pm, Sophie  wrote:
>
> How do I choose? What are the trade-offs?
>
> Any and all guidance, insights, advice etc. welcome!
>
> Thanks!

To me, it seems like you have two orthogonal pieces of data, and a
function that builds a report from that data.  You have a set of job
listings, and a set of applicants.  I see no reason why these need to
be coordinated (ref).  The addition of a job listing is totally
independent of an applicant updating her resume.  So it's
uncoordinated (atom).  That is, the job listings are always in a
consistent state no matter what I do to the applicant data.  Said
another way, there's nothing I can do to the applicant data that can
put the job listings in an inconsistent state.

As for the match function.  Well it needs to get a snapshot of both
pieces of data, and then determine what applicants match up with each
job listing.  While this function is running a job could be added, an
applicant could update her resume, or maybe an applicant will remove
her resume but your function won't see any of that, but who cares?  It
will see a consistent snapshot of both pieces of data, and from those
it will build the result.  As of time T1, here is your latest and
greatest match report.

Now, say you want the match report built every time a job listing or
applicant data is changed.  This way the 'latest' report is always in
memory and ready to go.  Well, in this case, you now need to
coordinate the update of job listings or applicant data with the
generation of the report.  You never want your program to enter a
state where the job listings are in state L101 and applicants are in
state A54 and your report is based on the combination of (L101, A53).
That's an inconsistent state because your report is not based on the
latest data.  In this case, you'd probably want to use refs to make
sure the your job/applicant data is coordinated with your report
data.  However, if your data is constantly changing, and the match
function takes a while to run then this may be very slow.

Take what I say with a grain of salt as I'm also fairly new to this
stuff.  At the end of the day, experience is probably the best
teacher.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from 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: Some basic guidance to designing functional vs. state parts of app

2010-03-04 Thread Sophie
Thank you all, the replies so far and the questions have already
deepened my understanding considerably!

Looking forward to more. I think a bit more discussion like this (not
necessarily my quite skimpy example) would be quite valuable to many
like me.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from 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: Some basic guidance to designing functional vs. state parts of app

2010-03-05 Thread Stuart Halloway
Someone could (and hopefully will) write a multi-hundred-page book  
exclusively on Clojure's approach to state. I simply didn't have  
enough space while overviewing the whole language.


If you want an identity that is isolated from whatever else is (or  
might in the future) happen in your app, prefer atoms. However, if it  
does (or will) coordinate with other identities, use refs.


I guess switching between these should be a feature of the Clojure  
Refactoring IDE. :-)


Stu


For a single value
there seems to be little reason to adopt refs, though I've often
wondered why Stuart Halloway's book gives an example updating a  
single

ref of messages for a chat application.


I seem to recall atoms being the last reference type to be  
introduced. They might not have existed when Stuart was writing.


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient  
with your first post.

To unsubscribe from 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: Some basic guidance to designing functional vs. state parts of app

2010-03-05 Thread Mark Engelberg
On Wed, Mar 3, 2010 at 5:20 PM, Rick Moynihan wrote:

>
> If you have a single value representing the whole world, then it seems
> that protecting it with an atom would be the simplest and most
> idiomatic solution.

...

> For a single value
> there seems to be little reason to adopt refs, ...


I disagree.  The problem with atoms is that updating an atom is a
side-effect that cannot (typically) participate safely in a transaction.  It
might be retried, so if for example, you want to increment the contents of
an atom, it might get incremented multiple times which is generally not okay
(if you're storing something in a cache, then a retry might be okay).

If you make a design decision to use an atom, you are effectively committing
to never, ever being able to update that atom within a transaction.

In my opinion, this has major implications and is a decision that should not
be taken lightly.  In a language like Clojure, we should strive to write
things that are as side-effect free as possible, so they can participate in
transactions.  Using atoms runs the risk of creating headaches later, so
unless you're 100% sure the semantics of your program won't change if they
are retried, or if you're 100% sure you'll never want to change the contents
of the atom as part of a sequence of logic involving setting other refs,
don't use atoms.

refs can do everything atoms can do and more.  They are slightly slower,
perhaps, but much safer.  So unless you have an explicit performance reason
to use atoms and have thought through the implications, the simplest design
choice is to prefer refs.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from 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: Some basic guidance to designing functional vs. state parts of app

2010-03-05 Thread eyeris
I don't follow your logic. Modifications of refs within a transaction
retry too.


On Mar 5, 11:56 am, Mark Engelberg  wrote:
> On Wed, Mar 3, 2010 at 5:20 PM, Rick Moynihan wrote:
>
>
>
> > If you have a single value representing the whole world, then it seems
> > that protecting it with an atom would be the simplest and most
> > idiomatic solution.
>
> ...
>
> > For a single value
> > there seems to be little reason to adopt refs, ...
>
> I disagree.  The problem with atoms is that updating an atom is a
> side-effect that cannot (typically) participate safely in a transaction.  It
> might be retried, so if for example, you want to increment the contents of
> an atom, it might get incremented multiple times which is generally not okay
> (if you're storing something in a cache, then a retry might be okay).
>
> If you make a design decision to use an atom, you are effectively committing
> to never, ever being able to update that atom within a transaction.
>
> In my opinion, this has major implications and is a decision that should not
> be taken lightly.  In a language like Clojure, we should strive to write
> things that are as side-effect free as possible, so they can participate in
> transactions.  Using atoms runs the risk of creating headaches later, so
> unless you're 100% sure the semantics of your program won't change if they
> are retried, or if you're 100% sure you'll never want to change the contents
> of the atom as part of a sequence of logic involving setting other refs,
> don't use atoms.
>
> refs can do everything atoms can do and more.  They are slightly slower,
> perhaps, but much safer.  So unless you have an explicit performance reason
> to use atoms and have thought through the implications, the simplest design
> choice is to prefer refs.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from 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: Some basic guidance to designing functional vs. state parts of app

2010-03-05 Thread David Nolen
On Fri, Mar 5, 2010 at 4:08 PM, eyeris  wrote:

> I don't follow your logic. Modifications of refs within a transaction
> retry too.
>

He's saying that atoms don't participate in the STM. If an atom depends on
the value of some refs, your program might be put into an inconsistent state
if the transaction is retried and you're changing the value of the atom in
the transaction.

In general using an atom means you're sure that you'll never want to perform
an atomic change of both it and some other mutable reference in your
program.

That's my understanding of it anyway.

David

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

Re: Some basic guidance to designing functional vs. state parts of app

2010-03-05 Thread Mark Engelberg
When you increment the contents of an atom, for example, it happens
immediately.  If it is inside a transaction, and the transaction retries,
the contents will be incremented multiple times.  Refs, on the other hand,
retry from the initial state at the beginning of the transaction, so as long
as there are no external side effects, you get the illusion that it only
happened once.  Essentially, changing an atom is like other side effects
(e.g., display or file output), and therefore cannot be safely used inside a
transaction.

On Fri, Mar 5, 2010 at 1:08 PM, eyeris  wrote:

> I don't follow your logic. Modifications of refs within a transaction
> retry too.
>
>

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

Re: Some basic guidance to designing functional vs. state parts of app

2010-03-05 Thread Rick Moynihan
On 5 March 2010 17:56, Mark Engelberg  wrote:
>
> On Wed, Mar 3, 2010 at 5:20 PM, Rick Moynihan 
> wrote:
>>
>> If you have a single value representing the whole world, then it seems
>> that protecting it with an atom would be the simplest and most
>> idiomatic solution.
>
>> For a single value there seems to be little reason to adopt refs, ...
>
> I disagree.  The problem with atoms is that updating an atom is a
> side-effect that cannot (typically) participate safely in a transaction.  It
> might be retried, so if for example, you want to increment the contents of
> an atom, it might get incremented multiple times which is generally not okay
> (if you're storing something in a cache, then a retry might be okay).
>
> If you make a design decision to use an atom, you are effectively committing
> to never, ever being able to update that atom within a transaction.

This is a good point, one that I hadn't considered and arguably also
non-obvious!  Though all is not necessarily lost when state you don't
control is held in an atom, as you can wrap it inside an agent which
will be co-ordinated with the STM, ensuring safe modification in the
event of retries.

> refs can do everything atoms can do and more.  They are slightly slower, 
> perhaps, but much safer.  So
> unless you have an explicit performance reason to use atoms and have thought 
> through the
> implications, the simplest design choice is to prefer refs.

My simple (uncontended) tests seem to indicate that atoms are about 4x
faster than refs (though I'd love to see a more comprehensive
benchmark).  Regardless I'll certainly be more cautious about using
atoms in the future, as refs are without doubt more composable.

R.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from 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: Some basic guidance to designing functional vs. state parts of app

2010-03-06 Thread Jeff Rose
> > If you make a design decision to use an atom, you are effectively committing
> > to never, ever being able to update that atom within a transaction.

> > refs can do everything atoms can do and more.  They are slightly slower, 
> > perhaps, but much safer.  So
> > unless you have an explicit performance reason to use atoms and have 
> > thought through the
> > implications, the simplest design choice is to prefer refs.

I agree.  At first I was always mixing and matching atoms and refs,
but it seems like a case of premature optimization.  If I understand
correctly atoms don't give you any benefit over refs besides
performance.  As you grow a program it's virtually impossible to
predict which variables will end up needing coordinated updates, so
why not just use refs and count on the STM for everything by default?
Once you get to the performance optimization phase you can start
converting refs to atoms, add type hints where appropriate, and make
use of transients in your inner loops.

The ref->atom refactoring would be very cool, and if you start by
using refs for everything it would be easy as a first pass to turn any
ref that is always modified alone into an atom.

-Jeff

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