<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=7r3ad</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=7r3ad"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/7r3ad"/>
	<updated>2026-09-11T17:15:17Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki3_9_rp&amp;diff=28289</id>
		<title>CSC/ECE 517 Fall 2009/wiki3 9 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki3_9_rp&amp;diff=28289"/>
		<updated>2009-11-18T08:17:34Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= The Non-Redundancy Principle =&lt;br /&gt;
&lt;br /&gt;
In [http://se.ethz.ch/~meyer/ Bertrand Meyer's] [http://en.wikipedia.org/wiki/Object-Oriented_Software_Construction ''Object Oriented Software Construction''], he outlines many principles to increase reusability by managing complexity in software design.  Some of these apply primarily to object oriented programming, primarily the principles dedicated to abstract data types.  Most of the principles, however, apply to programming generally.  The first five discussed in the book are often discussed in articles (the &amp;quot;Open-Close Principle&amp;quot; perhaps being the most popular), but equally important principles are discussed later in the book as well.  One such principle, presented in the section on ''Contracting For Software Reliability'', is called The Non-Redundancy Principle.&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
&lt;br /&gt;
As with all principles presented in ''Object Oriented Software Construction'', the principle itself is quite terse:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt; Under no circumstances shall the body of a routine ever test for the routine's precondition.  &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As simple as this may seem on first blush, it has extensive implications.&lt;br /&gt;
&lt;br /&gt;
Before we discuss the implications, it is proper to provide a bit of context regarding preconditions, postconditions and programming by contract.&lt;br /&gt;
&lt;br /&gt;
== Context ==&lt;br /&gt;
&lt;br /&gt;
Meyer outlined the notion of ''programming by contract'', which boils down to a methodology to enforce software modularity by clearly defining the relationships between various components, much in the same way relationships between individuals and/or companies are formalized in contracts.&lt;br /&gt;
&lt;br /&gt;
In Chapter 11, Meyer indicates that for each party in the contract, the aspects of the contract include:&lt;br /&gt;
&lt;br /&gt;
* Rights&lt;br /&gt;
* Obligations&lt;br /&gt;
* Preconditions&lt;br /&gt;
* Postconditions&lt;br /&gt;
&lt;br /&gt;
In short, these indicate what is expected of the ''supplier'' and the ''client'' (terms describing the roles of objects that are party to the contract).  Specifically, a ''precondition'' is a minimum criteria that must be satisfied on the part of the client for the contract to be valid.  The heart of the Non-Redundancy Principle is ''who'' checks that the preconditions are satisfied, and ''when'' are those checks made.&lt;br /&gt;
&lt;br /&gt;
It must be decided whether the client or the supplier of a service should enforce the preconditions.  Once that is made clear, the software designer must decide when the precondition will be enforced, and once it is enforced, it should never be checked.&lt;br /&gt;
&lt;br /&gt;
Meyer goes to some length to justify this position, which flies in the face of the defensive programming mantra, which generally encourages as much checking as possible, ostensibly to help eliminate errors &amp;quot;just in case&amp;quot;.  As we will see in the following sections, and as Meyer describes, it is difficult to justify this approach, purly on the grounds that such redundant checking inordinately increases the complexity of the software.&lt;br /&gt;
&lt;br /&gt;
== Implications ==&lt;br /&gt;
&lt;br /&gt;
There are a variety of implications that emerge from the Non-Redundancy Principle.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
&lt;br /&gt;
A common mantra in programming is &amp;quot;Don't Repeat Yourself&amp;quot; or simply &amp;quot;DRY&amp;quot; for short.  In it's simplest form, the Non-Redundancy Principle is a specialization of DRY, in that it prohibits developers from repeating themselves.&lt;br /&gt;
&lt;br /&gt;
Consider the example that Meyer uses of a function responsible for returning a real positive square root of a number.  In Java, such a function might look like:&lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * Returns the postive real square root of the input, d.&lt;br /&gt;
  */&lt;br /&gt;
 public double sqrt(double d) {&lt;br /&gt;
   return Math.sqrt(d);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
What happens if the number passed in is negative?  Will the method return a real square root?  We have specified in the supplier (in this case, the method called &amp;quot;sqrt&amp;quot;) is obligated to return a positive real square root.  By specifying a precondition that the input must be greater than or equal to zero, we now also qualify that obligation by imposing it only if the precondition is satisfied.  &lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * Returns the postive real square root of the input, d.&lt;br /&gt;
  * Precondition: input d &amp;gt;= 0&lt;br /&gt;
  */&lt;br /&gt;
 public double sqrt(double d) {&lt;br /&gt;
   return Math.sqrt(d);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now we have a precondition.  But what does all this have to do with the Non-Redundancy Principle?&lt;br /&gt;
&lt;br /&gt;
It might be tempting to then write this:&lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * Returns the postive real square root of the input, d.&lt;br /&gt;
  * Precondition: input d &amp;gt;= 0&lt;br /&gt;
  */&lt;br /&gt;
 public double sqrt(double d) {&lt;br /&gt;
   if (d &amp;lt; 0) throw new IllegalArgumentException(&amp;quot;Input must be greater than or equal to zero.&amp;quot;);&lt;br /&gt;
   return Math.sqrt(d);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
But, according to the Non-Redundancy Principle, this is prohibited! Why?  Well, what does Math.sqrt do?  Does it also check for a value less than zero?  It turns out that it does.  But the point here is that if we use the code directly above this paragraph, our system now checkes for numbers less than zero ''twice''.  Not only have we repeated ourselves, but we have increased the complexity of the code, which brings us to how the Non-Redundancy Principle reduces code complexity.&lt;br /&gt;
&lt;br /&gt;
=== Code Complexity === &lt;br /&gt;
&lt;br /&gt;
One way to measure code complexity is through [http://www.mccabe.com/iq_research_iqgloss.htm#cyclomatic cyclomatic complexity] (sometimes called the ''McCabe Number'').  Simply put, cyclomatic complexity measures the number of different paths through a piece of code.  It is often cited as a good measure of how maintainable a piece of code is, and certainly has an impact on how burdensome testing will be.  In the example above:&lt;br /&gt;
&lt;br /&gt;
 public double sqrt(double d) {&lt;br /&gt;
   if (d &amp;lt; 0) throw new IllegalArgumentException(&amp;quot;Input must be greater than or equal to zero.&amp;quot;);&lt;br /&gt;
   return Math.sqrt(d);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
We can immediately see that adding the check for the precondition to the method added an additional exit from the method, namely, the method can now throw an IllegalArgumentExecetion.  Taken singly, this may not seem like a big deal, but imagine methods with two or more preconditions, and imagine every method in the system starts checking for each.  On a systemic scale, redundant checking vastly increases the code bulk, complexity, and testing burden of the system.&lt;br /&gt;
&lt;br /&gt;
=== Run-time versus Compile-time Errors ===&lt;br /&gt;
&lt;br /&gt;
It may be tempting to look at systems that ''enforce'' preconditions to be in violation of the Non-Redundancy Principle.  After all, in the way that Meyer describes design by contract, if the precondition for a method is violated, its behavior is undefined.  But since ''Object Oriented Software Construction'' was written, new techniques have emerged to ensure that such preconditions are not violated, but they do so without ''checking'' for the precondition.  Rather, they are codified statements of the precondition.&lt;br /&gt;
&lt;br /&gt;
One such example can be seen in [http://jcp.org/en/jsr/detail?id=308 JSR 308] for Java.  It specifies that Java annotations could be applied to types (in addition to classes and methods).  Indeed, the code to support this has ben written, and is available in the form of the [http://types.cs.washington.edu/jsr308/ Checker Framework].&lt;br /&gt;
&lt;br /&gt;
This type of annotation allows a developer to specify, using type annotations, that a certain precondition must be met.  For example, we might want to specify that a particular reference should never be null, perhaps because we want to call a method on it:&lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * Precondition: ref must be non-null.&lt;br /&gt;
  */&lt;br /&gt;
 public Class(Object ref) {&lt;br /&gt;
   ref.getClass();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In this case, if the precondition is violated, we get a RunTimeError (NullPointerException).  If we instead using the checker framework, we can say the same thing, but in a way the compiler (and developers!) can understand:&lt;br /&gt;
&lt;br /&gt;
 public Class(@NonNull Object ref) {&lt;br /&gt;
   ref.getClass();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
In this case, if a value that might be null is passed in, the ''compiler'' will produce an error.  Thus, this approach moves runtime errors to compile time.  At first blush it may appear that the checker framework is &amp;quot;checking&amp;quot; for the precondition, but note that it doesn't carry any of the hallmarks Meyer discusses: it does not impact performance, it does not increase cyclomatic complexity, and it does not make the code any bulkier.&lt;br /&gt;
&lt;br /&gt;
More and more modern languages this support of framework.  For example, [http://www.scala-lang.org/ Scala] supports it through a [http://www.scala-lang.org/node/140 pluggable compiler architecture]. It is worth noting that such systems, rather than violating the Non-Redundancy Principle, in fact not only comply, but go one step further by, in many cases, eliminating the need for checks at all!&lt;br /&gt;
&lt;br /&gt;
== Glossary ==&lt;br /&gt;
&lt;br /&gt;
;Client&lt;br /&gt;
: A class that uses the features of another, its supplier, on the basis of the supplier's interface specification (contract)&lt;br /&gt;
;Contract&lt;br /&gt;
: The set of precies conditions that govern the relations between a supplier class and its clients.  The contract for a class includes the individual contracts for the exported routines of the class, represented by preconditions and postconditions, and the global class properties, represented by the class invariant.&lt;br /&gt;
;Design By Contract&lt;br /&gt;
: A method of software construction that designs the components of the system so that they will cooperate on the basis of precisely defined contracts.&lt;br /&gt;
;Postcondition&lt;br /&gt;
: An assertion attached to a routine, which must be guaranteed by the routine's body on a return from any call to the routine if the precondition was satisfied on entry.  Part of the contract governing the routine.&lt;br /&gt;
;Precondition&lt;br /&gt;
: An assertion attached to a routine, which must be guaranteed by every client prior to any call to the routine. Part of the contract governing the routine.&lt;br /&gt;
;Supplier&lt;br /&gt;
: A class that provides another, its client, with features to be used through an interface specification (contract).&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki3_9_rp&amp;diff=28277</id>
		<title>CSC/ECE 517 Fall 2009/wiki3 9 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki3_9_rp&amp;diff=28277"/>
		<updated>2009-11-18T07:38:40Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= The Non-Redundancy Principle =&lt;br /&gt;
&lt;br /&gt;
In Bertrand Meyer's ''Object Oriented Software Construction'', he outlines many principles to increase reusability by managing complexity in software design.  Some of these apply primarily to object oriented programming, primarily the principles dedicated to abstract data types.  Most of the principles, however, apply to programming generally.  The first five discussed in the book are often discussed in articles (the &amp;quot;Open-Close Principle&amp;quot; perhaps being the most popular), but equally important principles are discussed later in the book as well.  One such principle, presented in the section on ''Contracting For Software Reliability'', is called The Non-Redundancy Principle.&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
&lt;br /&gt;
As with all principles presented in ''Object Oriented Software Construction'', the principle itself is quite terse:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt; Under no circumstances shall the body of a routine ever test for the routine's precondition.  &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As simple as this may seem on first blush, it has extensive implications.&lt;br /&gt;
&lt;br /&gt;
Before we discuss the implications, it is proper to provide a bit of context regarding preconditions, postconditions and programming by contract.&lt;br /&gt;
&lt;br /&gt;
== Context ==&lt;br /&gt;
&lt;br /&gt;
Meyer outlined the notion of ''programming by contract'', which boils down to a methodology to enforce software modularity by clearly defining the relationships between various components, much in the same way relationships between individuals and/or companies are formalized in contracts.&lt;br /&gt;
&lt;br /&gt;
In Chapter 11, Meyer indicates that for each party in the contract, the aspects of the contract include:&lt;br /&gt;
&lt;br /&gt;
* Rights&lt;br /&gt;
* Obligations&lt;br /&gt;
* Preconditions&lt;br /&gt;
* Postconditions&lt;br /&gt;
&lt;br /&gt;
In short, these indicate what is expected of the ''supplier'' and the ''client'' (terms describing the roles of objects that are party to the contract).  Specifically, a ''precondition'' is a minimum criteria that must be satisfied on the part of the client for the contract to be valid.  The heart of the Non-Redundancy Principle is ''who'' checks that the preconditions are satisfied, and ''when'' are those checks made.&lt;br /&gt;
&lt;br /&gt;
It must be decided whether the client or the supplier of a service should enforce the preconditions.  Once that is made clear, the software designer must decide when the precondition will be enforced, and once it is enforced, it should never be checked.&lt;br /&gt;
&lt;br /&gt;
Meyer goes to some length to justify this position, which flies in the face of the defensive programming mantra, which generally encourages as much checking as possible, ostensibly to help eliminate errors &amp;quot;just in case&amp;quot;.  As we will see in the following sections, and as Meyer describes, it is difficult to justify this approach, purly on the grounds that such redundant checking inordinately increases the complexity of the software.&lt;br /&gt;
&lt;br /&gt;
== Implications ==&lt;br /&gt;
&lt;br /&gt;
There are a variety of implications that emerge from the Non-Redundancy Principle.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
&lt;br /&gt;
A common mantra in programming is &amp;quot;Don't Repeat Yourself&amp;quot; or simply &amp;quot;DRY&amp;quot; for short.  In it's simplest form, the Non-Redundancy Principle is a specialization of DRY, in that it prohibits developers from repeating themselves.&lt;br /&gt;
&lt;br /&gt;
Consider the example that Meyer uses of a function responsible for returning a real positive square root of a number.  In Java, such a function might look like:&lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * Returns the postive real square root of the input, d.&lt;br /&gt;
  */&lt;br /&gt;
 public double sqrt(double d) {&lt;br /&gt;
   return Math.sqrt(d);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
What happens if the number passed in is negative?  Will the method return a real square root?  We have specified in the supplier (in this case, the method called &amp;quot;sqrt&amp;quot;) is obligated to return a positive real square root.  By specifying a precondition that the input must be greater than or equal to zero, we now also qualify that obligation by imposing it only if the precondition is satisfied.  &lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * Returns the postive real square root of the input, d.&lt;br /&gt;
  * Precondition: input d &amp;gt;= 0&lt;br /&gt;
  */&lt;br /&gt;
 public double sqrt(double d) {&lt;br /&gt;
   return Math.sqrt(d);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now we have a precondition.  But what does all this have to do with the Non-Redundancy Principle?&lt;br /&gt;
&lt;br /&gt;
It might be tempting to then write this:&lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * Returns the postive real square root of the input, d.&lt;br /&gt;
  * Precondition: input d &amp;gt;= 0&lt;br /&gt;
  */&lt;br /&gt;
 public double sqrt(double d) {&lt;br /&gt;
   if (d &amp;lt; 0) throw new IllegalArgumentException(&amp;quot;Input must be greater than or equal to zero.&amp;quot;);&lt;br /&gt;
   return Math.sqrt(d);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
But, according to the Non-Redundancy Principle, this is prohibited! Why?  Well, what does Math.sqrt do?  Does it also check for a value less than zero?  It turns out that it does.  But the point here is that if we use the code directly above this paragraph, our system now checkes for numbers less than zero ''twice''.  Not only have we repeated ourselves, but we have increased the complexity of the code, which brings us to how the Non-Redundancy Principle reduces code complexity.&lt;br /&gt;
&lt;br /&gt;
=== Code Complexity === &lt;br /&gt;
&lt;br /&gt;
One way to measure code complexity is through [http://www.mccabe.com/iq_research_iqgloss.htm#cyclomatic cyclomatic complexity] (sometimes called the ''McCabe Number'').  Simply put, cyclomatic complexity measures the number of different paths through a piece of code.  It is often cited as a good measure of how maintainable a piece of code is, and certainly has an impact on how burdensome testing will be.  In the example above:&lt;br /&gt;
&lt;br /&gt;
 public double sqrt(double d) {&lt;br /&gt;
   if (d &amp;lt; 0) throw new IllegalArgumentException(&amp;quot;Input must be greater than or equal to zero.&amp;quot;);&lt;br /&gt;
   return Math.sqrt(d);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
We can immediately see that adding the check for the precondition to the method added an additional exit from the method, namely, the method can now throw an IllegalArgumentExecetion.  Taken singly, this may not seem like a big deal, but imagine methods with two or more preconditions, and imagine every method in the system starts checking for each.  On a systemic scale, redundant checking vastly increases the code bulk, complexity, and testing burden of the system.&lt;br /&gt;
&lt;br /&gt;
=== Run-time versus Compile-time Errors ===&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki3_9_rp&amp;diff=28274</id>
		<title>CSC/ECE 517 Fall 2009/wiki3 9 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki3_9_rp&amp;diff=28274"/>
		<updated>2009-11-18T07:27:57Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= The Non-Redundancy Principle =&lt;br /&gt;
&lt;br /&gt;
In Bertrand Meyer's ''Object Oriented Software Construction'', he&lt;br /&gt;
outlines many principles to increase reusability by managing&lt;br /&gt;
complexity in software design.  Some of these apply primarily to&lt;br /&gt;
object oriented programming, primarily the principles dedicated to&lt;br /&gt;
abstract data types.  Most of the principles, however, apply to&lt;br /&gt;
programming generally.  The first five discussed in the book are often&lt;br /&gt;
discussed in articles (the &amp;quot;Open-Close Principle&amp;quot; perhaps being the&lt;br /&gt;
most popular), but equally important principles are discussed later in&lt;br /&gt;
the book as well.  One such principle, presented in the section on&lt;br /&gt;
''Contracting For Software Reliability'', is called The Non-Redundancy&lt;br /&gt;
Principle.&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
&lt;br /&gt;
As with all principles presented in ''Object Oriented Software&lt;br /&gt;
Construction'', the principle itself is quite terse:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt; Under no circumstances shall the body of a routine ever&lt;br /&gt;
test for the routine's precondition.  &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As simple as this may seem on first blush, it has extensive&lt;br /&gt;
implications.&lt;br /&gt;
&lt;br /&gt;
Before we discuss the implications, it is proper to provide a bit of&lt;br /&gt;
context regarding preconditions, postconditions and programming by&lt;br /&gt;
contract.&lt;br /&gt;
&lt;br /&gt;
== Context ==&lt;br /&gt;
&lt;br /&gt;
Meyer outlined the notion of ''programming by contract'', which boils&lt;br /&gt;
down to a methodology to enforce software modularity by clearly&lt;br /&gt;
defining the relationships between various components, much in the&lt;br /&gt;
same way relationships between individuals and/or companies are&lt;br /&gt;
formalized in contracts.&lt;br /&gt;
&lt;br /&gt;
In Chapter 11, Meyer indicates that for each party in the contract,&lt;br /&gt;
the aspects of the contract include:&lt;br /&gt;
&lt;br /&gt;
* Rights&lt;br /&gt;
* Obligations&lt;br /&gt;
* Preconditions&lt;br /&gt;
* Postconditions&lt;br /&gt;
&lt;br /&gt;
In short, these indicate what is expected of the ''supplier'' and the&lt;br /&gt;
''client'' (terms describing the roles of objects that are party to&lt;br /&gt;
the contract).  Specifically, a ''precondition'' is a minimum criteria&lt;br /&gt;
that must be satisfied on the part of the client for the contract to&lt;br /&gt;
be valid.  The heart of the Non-Redundancy Principle is ''who'' checks&lt;br /&gt;
that the preconditions are satisfied, and ''when'' are those checks&lt;br /&gt;
made.&lt;br /&gt;
&lt;br /&gt;
It must be decided whether the client or the supplier of a service&lt;br /&gt;
should enforce the preconditions.  Once that is made clear, the&lt;br /&gt;
software designer must decide when the precondition will be enforced,&lt;br /&gt;
and once it is enforced, it should never be checked.&lt;br /&gt;
&lt;br /&gt;
Meyer goes to some length to justify this position, which flies in the&lt;br /&gt;
face of the defensive programming mantra, which generally encourages&lt;br /&gt;
as much checking as possible, ostensibly to help eliminate errors&lt;br /&gt;
&amp;quot;just in case&amp;quot;.  As we will see in the following sections, and as&lt;br /&gt;
Meyer describes, it is difficult to justify this approach, purly on&lt;br /&gt;
the grounds that such redundant checking inordinately increases the&lt;br /&gt;
complexity of the software.&lt;br /&gt;
&lt;br /&gt;
== Implications ==&lt;br /&gt;
&lt;br /&gt;
There are a variety of implications that emerge from the&lt;br /&gt;
Non-Redundancy Principle.&lt;br /&gt;
&lt;br /&gt;
=== DRY Principle ===&lt;br /&gt;
&lt;br /&gt;
A common mantra in programming is &amp;quot;Don't Repeat Yourself&amp;quot; or simply&lt;br /&gt;
&amp;quot;DRY&amp;quot; for short.  In it's simplest form, the Non-Redundancy Principle&lt;br /&gt;
is a specialization of DRY, in that it prohibits developers from&lt;br /&gt;
repeating themselves.&lt;br /&gt;
&lt;br /&gt;
Consider the example that Meyer uses of a function responsible for&lt;br /&gt;
returning a real positive square root of a number.  In Java, such a function&lt;br /&gt;
might look like:&lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * Returns the postive real square root of the input, d.&lt;br /&gt;
  */&lt;br /&gt;
 public double sqrt(double d) {&lt;br /&gt;
   return Math.sqrt(d);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
What happens if the number passed in is negative?  Will the method&lt;br /&gt;
return a real square root?  We have specified in the supplier (in this&lt;br /&gt;
case, the method called &amp;quot;sqrt&amp;quot;) is obligated to return a positive real&lt;br /&gt;
square root.  By specifying a precondition that the input must be&lt;br /&gt;
greater than or equal to zero, we now also qualify that obligation by&lt;br /&gt;
imposing it only if the precondition is satisfied.  &lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * Returns the postive real square root of the input, d.&lt;br /&gt;
  * Precondition: input d &amp;gt;= 0&lt;br /&gt;
  */&lt;br /&gt;
 public double sqrt(double d) {&lt;br /&gt;
   return Math.sqrt(d);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Now we have a precondition.  But what does all this have to do with&lt;br /&gt;
the Non-Redundancy Principle?&lt;br /&gt;
&lt;br /&gt;
It might be tempting to then write this:&lt;br /&gt;
&lt;br /&gt;
 /**&lt;br /&gt;
  * Returns the postive real square root of the input, d.&lt;br /&gt;
  * Precondition: input d &amp;gt;= 0&lt;br /&gt;
  */&lt;br /&gt;
 public double sqrt(double d) {&lt;br /&gt;
   if (d &amp;lt; 0) throw new IllegalArgumentException(&amp;quot;Input must be greater than or equal to zero.&amp;quot;);&lt;br /&gt;
   return Math.sqrt(d);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
But, according to the Non-Redundancy Principle, this is prohibited!&lt;br /&gt;
Why?  Well, what does Math.sqrt do?  Does it also check for a value&lt;br /&gt;
less than zero?  It turns out that it does.  But the point here is&lt;br /&gt;
that if we use the code directly above this paragraph, our system now&lt;br /&gt;
checkes for numbers less than zero ''twice''.  Not only have we&lt;br /&gt;
repeated ourselves, but we have increased the complexity of the code,&lt;br /&gt;
which brings us to how the Non-Redundancy Principle reduces code&lt;br /&gt;
complexity.&lt;br /&gt;
&lt;br /&gt;
=== Code Complexity ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run-time versus Compile-time Errors ===&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25966</id>
		<title>CSC/ECE 517 Fall 2009/wiki2 6 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25966"/>
		<updated>2009-10-14T05:50:09Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: /* List Comprehension */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Topic=&lt;br /&gt;
&lt;br /&gt;
While Smalltalk and Java were instrumental in bringing object-oriented programming into the mainstream, the 1990s also saw the development of hybrid languages that supported multiple programming paradigms, often combining procedural, object-oriented and functional approaches. Discuss the development and design considerations that went into languages like OCaml, Scala, F# and Fan, and how they build upon an object-oriented foundation to offer languages that offer type safety while maintaining brevity and expressive power.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &lt;br /&gt;
&lt;br /&gt;
There are many ways to classify programming languages: on the basis of static or dynamic typing, type safety, high or low levels of abstraction, and by programming paradigm.&lt;br /&gt;
&lt;br /&gt;
In this article, the focus is on programming paradigms, which can loosely be thought of as defining the atomic units a language offers as building block with which to build programs.  There are three primary paradigms in use today:&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Procedural_programming Procedural]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Object-oriented_programming Object-Oriented]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Declarative_programming Declarative]&lt;br /&gt;
&lt;br /&gt;
Declarative languages span a wide array of programming styles.  For simplicity in this article, we will focus on [http://en.wikipedia.org/wiki/Functional_programming functional] languages, which are an important subset of declarative languages.&lt;br /&gt;
&lt;br /&gt;
Many languages provide only one of the paradigms to their users.  [http://www.engin.umd.umich.edu/CIS/course.des/cis400/fortran/fortran.html FORTRAN], [http://www.engin.umd.umich.edu/CIS/course.des/cis400/cobol/cobol.html COBOL], [http://en.wikipedia.org/wiki/Pascal_%28programming_language%29 Pascal], [http://cm.bell-labs.com/cm/cs/who/dmr/chist.html C] and [http://en.wikipedia.org/wiki/BASIC BASIC] are all procedural, [http://www.engin.umd.umich.edu/CIS/course.des/cis400/simula/simula.html Simula], [http://www.smalltalk.org/main/ Smalltalk]] and [http://www.eiffel.com/developers/design_by_contract.html Eiffel] are object-oriented and [http://haskell.org/ Haskell] and [http://en.wikipedia.org/wiki/ML_%28programming_language%29 ML] are functional.  These languages provide a single paradigm for programming, which limits programmers to the particular set of constructs available in that model.&lt;br /&gt;
&lt;br /&gt;
The three paradigms evolved somewhat independently and offer unique constructs with which to solve programming problems.  Some languages are multi-paradigm, however, and allow a programmer to use the tools  most fitting for the problem at hand, sometimes mixing and matching freely within a single program.  The original language of this type is Lisp, which dates back to the mid-1950s.  In the last 20 years, many other hybrid languages have emerged, often derivatives of existing languages.  C++ is derived from C, and offers both procedural and object-oriented approaches.  [http://java.sun.com Java], one of the most widely used languages today, offers both procedural and object-oriented paradigms as well.  [http://caml.inria.fr/ OCaml] is derived from ML, and offers functional and object-oriented styles.  There are many others that have become popular in recent years, like [http://python.org Python] and [http://www.ruby-lang.org/en/ Ruby].&lt;br /&gt;
&lt;br /&gt;
In this article, our goal is to examine what these hybrid languages offer above and beyond strictly object-oriented languages.  In particular, we will examine the features of object-oriented languages and functional languages, and how they have been blended in a modern hybrid language called [http://scala-lang.org Scala].&lt;br /&gt;
&lt;br /&gt;
=Features of Object Oriented Languages=&lt;br /&gt;
The key construct provided by object-oriented languages is the ''object'', which bundles the data and behavior together into a cohesive unit.&lt;br /&gt;
&lt;br /&gt;
==Encapsulation==&lt;br /&gt;
Encapsulation is the technique of rolling behavior and data into an object that exhibits (and is handled in terms of) a particular behavior, rather than a particular composition.  This technique allows the internals of an object to remain hidden from external entities, which in turn enables the object to modify its implementation over time while providing the same external behaviors.&lt;br /&gt;
&lt;br /&gt;
For example, encapsulation would allow a class to add logging functionality without affecting other classes' collaboration with it.  Any feature that is solely an implementation concern (speeding up a sorting algorithm, checking inputs for invalid data, changing the way resource errors are handled, etc.) can be evolved and modified over time within the object without breaking functionality elsewhere in the program that relies on the object in question.&lt;br /&gt;
&lt;br /&gt;
==Dependency Inversion==&lt;br /&gt;
&lt;br /&gt;
One of the major benefits of focusing on the ''behavior'' of objects rather than their ''implementation'' is that the behavior aspects can be well defined and captured in an interface.  This allows code that once would rely on an unstable implementation to instead shift its dependency onto a stable interface, and have the implementation then implement the interface.  This process is known as ''dependency inversion'', because of the way in which it alter the dependency structure of the code.&lt;br /&gt;
&lt;br /&gt;
For example, let us say we have a web server that makes use of a logging facility to log information to disk.  In this case, the web server depends on the logging facility:&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger.png]]&lt;br /&gt;
&lt;br /&gt;
Later, it becomes apparent that the web server also want to be able to log to other destinations.  To facilitate this, we introduce a ''Logger'' interface, and make have the web server depend on that, so as to insulate it from new types of loggers that may be introduced.  This allows us to modify both the server and the loggers in isolation, having them both depend on the interface rather than each other, essentially reversing, or ''inverting'' the dependency diagram.&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger-invert.png]]&lt;br /&gt;
&lt;br /&gt;
In this diagram, the behavior of the logger is well-defined and stable, and is captured in the interface represented by the yellow box.  The blue boxes are classes that are implementations, and are insulated from one another by the interface, allowing them to vary independently without breaking the program as a whole.  This is an example of the robustness that the object-oriented approach lends to a program through use of encapsulation.&lt;br /&gt;
&lt;br /&gt;
==Polymorphism and Dynamic Dispatch==&lt;br /&gt;
                                 &lt;br /&gt;
The object-oriented approach of thinking in terms of behavior lends itself to have multiple implementations of a single behavior. This allows the behavior (or contract) to have &amp;quot;many forms&amp;quot;, and is the source of the term &amp;quot;polymorphism&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
As an example, we can see this is the case of the logger above. To the web server, a logger is simply an object with which logs can be stored.  There are many possible implementations; we could use the file logger or the network logger as seen above, but we could also implement a console logger or a database logger.  Essentially, this means that the web server could call a method to log information without any knowledge of exactly what kind of object it was calling.  The raises the question of how (and when) a programming language decides which log method to call.  Is it compiled in, or is it determined at runtime?&lt;br /&gt;
&lt;br /&gt;
The answer is that it is determined at runtime.  This type of late binding, called ''dynamic dispatch'', allows a program to remain flexible even after it is deployed, permitting end-users to determine what kind of logging functionality they want be passing in various implementations of the logger interface when the web server is run, even implementations that were written ''after'' the web server was written and deployed!&lt;br /&gt;
&lt;br /&gt;
The major theme here is that the object-oriented approach of favoring encapsulation has many effects that ripple throughout the design process, almost all of which allow programmers to reduce the brittleness of their software by delaying commitment to particular implementations.&lt;br /&gt;
&lt;br /&gt;
=Features of Functional Languages=&lt;br /&gt;
&lt;br /&gt;
Much like object-oriented languages, functional languages offer a dominant paradigm that has far-reaching consequences in software design.  For object-oriented languages, that element is encapsulation, and for functional languages, it is that functions are first-class entities, which simply means that functions are treated just like any other value in the language.  This allows them to be passed as parameters, delayed, composed, invoked, and returned from other functions.  But what is a function?&lt;br /&gt;
&lt;br /&gt;
A function's most notable trait is that it is free of ''side-effects'', or state changes to the program that occur as a result of its execution.  We could say a lot about side effects, but the general rule is that a function will always return the same value given the same input.  This means that functions are ''stateless''.  Therefore, entities like random number generators and loggers are not functional, because they either store state or have some effect that is not related to the value they return.  Another way to think of functions is that they are completely defined in terms of their input and output.&lt;br /&gt;
&lt;br /&gt;
From this simple feature flows many characteristic language features.  We will discuss them in turn.&lt;br /&gt;
&lt;br /&gt;
==Immutability==&lt;br /&gt;
Maybe the most noticeable feature (or restriction) to programmers of languages that are not functional, [http://en.wikipedia.org/wiki/Immutable_object immutability] is one of the hallmarks of a functional language.  Most non-functional languages allow ''assignment'', or the ability to assign new values to variables as the program runs.  In functional programming, a value is declared only once and then never changes.  This feature of of the language flows out of the notion that functions have no side-effects, and is often viewed as more of a restriction than a feature.&lt;br /&gt;
&lt;br /&gt;
The power of immutability comes from the fact that programs that fully utilize immutability are much simpler than those that do not, making them amenable to automated analysis by a computer.  Computers can then prove various properties about function programs, like concurrent behavior (presence or absence of deadlock/livelock), memory usage, and what within what bounds various values in the program will lie.&lt;br /&gt;
&lt;br /&gt;
==Higher Order Functions==&lt;br /&gt;
&lt;br /&gt;
Higher order functions are simply functions that accept or return other functions as values.  This is made possible because functions are treated as first-class entities, and allows very expressive implementations of many algorithms to be written.&lt;br /&gt;
&lt;br /&gt;
There are several hallmark higher order functions: map, reduce, fold left/right and filter are a few examples.  Going into the intricacies of each is beyond the scope of this article, but Abelson and Sussman's seminal [http://mitpress.mit.edu/sicp/ Structure and Interpretation of Computer Programs] has an [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.1 excellent treatment] of the subject.&lt;br /&gt;
&lt;br /&gt;
==Recursion==&lt;br /&gt;
&lt;br /&gt;
Programmers that are new to functional programming often balk at the notion that values cannot change over time (as variables do in imperative languages).  If values cannot change, how can we execute loops?&lt;br /&gt;
&lt;br /&gt;
Let us examine the example of [http://en.wikipedia.org/wiki/Peano_axioms#Arithmetic Peano Arithmetic], which is a simple technique of adding two numbers together by successively decrementing one number while incrementing the other, until the number being decremented is zero.  The procedural approach would simply use a loop:&lt;br /&gt;
&lt;br /&gt;
  public int add(int a, int b) {&lt;br /&gt;
    while (a &amp;gt; 0) {&lt;br /&gt;
      a--;&lt;br /&gt;
      b++;&lt;br /&gt;
    }&lt;br /&gt;
    return b;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
This is a straight-forward implementation of Peano Arthmetic, but you'll notice that both a and b change over time.  How can implement Peano Arthimetic in a functional language?&lt;br /&gt;
&lt;br /&gt;
The answer lies in recursion, where values are immutable, and loops are implemented as successive calls to the current function with new arguments.  The avoids the complexity of having values change over time while offering all the power of the loops we often see in imperative languages (for...each, do...while, etc.)  Going back to our example, this is what the same function would look like using recursion:&lt;br /&gt;
&lt;br /&gt;
  public int add(int a, int b) {&lt;br /&gt;
    if (a==0) { return b; }&lt;br /&gt;
    return add(a-1, b+1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In this case, the values for a and b do not change over time, but rather new versions of a and b a created in each stack frame as the method successively calls itself.  This has several advantages, perhaps the most important of which is that the recursive version of the add method does not modify the values passed into it, but rather allocates new values for use in each successive call.&lt;br /&gt;
&lt;br /&gt;
A deep treatment of these language features is beyond the scope of this article, but again, Abelson and Sussman have [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.1 addressed] the topic at some length in their book.&lt;br /&gt;
&lt;br /&gt;
==Delayed (Lazy) Evaluation==&lt;br /&gt;
An extremely powerful feature of functional programming that is enabled by immutability is ''lazy evaluation''.  This simply means that expressions can be defined, even recursively, and are not computed until the values that would result from that computation are needed.  This is possible because values in functional programs don't change over time, which means expressions can be evaluated at any point in time as needed.&lt;br /&gt;
&lt;br /&gt;
Take an imperative expression like this (in Java):&lt;br /&gt;
&lt;br /&gt;
  int i = 4;&lt;br /&gt;
  int j = i + 3;&lt;br /&gt;
  i++;&lt;br /&gt;
&lt;br /&gt;
If you evaluate these expressions in order, j will be equal to 7, but if you were to delay the evaluation of j until after the third line, j would be equal to 8.  This is a very simple example of how variables that change over time require expressions be evaluated in a particular order to maintain the correctness of the program.  Functional programming explicitly disallows the third line, and therefore enables the value of j to be calculated only when it is needed.  The implications of this are significant, as we'll see in the next section.&lt;br /&gt;
&lt;br /&gt;
=Hybrid Object-Oriented/Functional Languages=&lt;br /&gt;
&lt;br /&gt;
To programmers of languages like SmallTalk, Simula and Java, many of the features provided in functional languages will seem foreign or strange.  But, as discussed, there are significant advantages to the functional approach for certain types of programs.  While the object-oriented paradigm has proven itself to be very useful, many modern languages have sought to integrate functional features as well to increase the expressiveness and power of the language.  One such language is Scala, which, like Java, runs on the Java Virtual Machine (JVM), and is thus shares Java's libraries and portability while offering many [http://www.ibm.com/developerworks/java/library/j-scala01228.html functional features] that are not available in object-oriented languages like Java.  In the [http://www.scala-lang.org/node/25 overview] of Scala available on its homepage, Scala is briefly described:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
[Scala] smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application.&amp;quot;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
How does Scala allow code sizes to be reduced so much?  It uses sophisticated type inferencing to reduce type signature redundancy, allows for functional programming constructs to be used, and provides syntax for oft-used programming idioms.  Essentially, it takes the lessons learned from decades of functional and object-oriented programming experience and rolls them into a modern hybrid language that can make full use legacy Java code.&lt;br /&gt;
&lt;br /&gt;
Scala is representative of an entire class of hybrid object/functional languages like OCaml, F# and Fan, and therefore makes a good language for use in the examples in this article.  The intent is not to present highly technical examples, but rather to give readers an impression of how hybrid languages increase expressive power over their single-paradigm counterparts.&lt;br /&gt;
&lt;br /&gt;
==Case Classes==&lt;br /&gt;
Idiomatic object-oriented programming involves encapsulation of data, as previously discussed.  In older object-oriented languages, this required defining internal data values, and then providing necessary get and set methods to access and/or modify those values. Here is an example a class in Java that provides only get methods for some (immutable) values it holds.  It includes all the methods that ''should'' be included in such a class, including a toString, equals and hashCode method.  Note that is an error if such methods are ''not'' included in structural Java classes, which is why I include them here.&lt;br /&gt;
&lt;br /&gt;
  public class UserData {&lt;br /&gt;
      private final String firstName;&lt;br /&gt;
      private final String lastName;&lt;br /&gt;
      private final Integer age;&lt;br /&gt;
      public UserData(String firstName, String lastName, Integer age) {&lt;br /&gt;
          this.firstName = firstName;&lt;br /&gt;
          this.lastName = lastName;&lt;br /&gt;
          this.age = age;&lt;br /&gt;
      }&lt;br /&gt;
      public String getFirstName() {&lt;br /&gt;
          return this.firstName;&lt;br /&gt;
      }&lt;br /&gt;
      public String getLastName() {&lt;br /&gt;
          return this.lastName;&lt;br /&gt;
      }&lt;br /&gt;
      public Integer getAge() {&lt;br /&gt;
          return this.age;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public boolean equals(Object obj) {&lt;br /&gt;
          if (obj == null) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (getClass() != obj.getClass()) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          final UserData other = (UserData) obj;&lt;br /&gt;
          if ((this.firstName == null) ? (other.firstName != null) : !this.firstName.equals(other.firstName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if ((this.lastName == null) ? (other.lastName != null) : !this.lastName.equals(other.lastName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.age != other.age &amp;amp;&amp;amp; (this.age == null || !this.age.equals(other.age))) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          return true;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public int hashCode() {&lt;br /&gt;
          int hash = 7;&lt;br /&gt;
          hash = 19 * hash + (this.firstName != null ? this.firstName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.lastName != null ? this.lastName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.age != null ? this.age.hashCode() : 0);&lt;br /&gt;
          return hash;&lt;br /&gt;
      }&lt;br /&gt;
      public String toString() {&lt;br /&gt;
          StringBuilder sb = new StringBuilder();&lt;br /&gt;
          sb.append(&amp;quot;UserData[firstName: &amp;quot;);&lt;br /&gt;
          sb.append(this.firstName);&lt;br /&gt;
          sb.append(&amp;quot; lastName: &amp;quot;);&lt;br /&gt;
          sb.append(this.lastName);&lt;br /&gt;
          sb.append(&amp;quot; age: &amp;quot;);&lt;br /&gt;
          sb.append(this.age);&lt;br /&gt;
          sb.append(&amp;quot;]&amp;quot;);&lt;br /&gt;
          return sb.toString();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, ''all'' the functionality of the above class can be expressed with:&lt;br /&gt;
&lt;br /&gt;
  case class UserData(val firstName: String, val lastName: String, val age: Int)&lt;br /&gt;
&lt;br /&gt;
To reiterate, the version in Scala actually does include a constructor, accessor methods, three fields that can only be set once, equals and hashCode  methods (comparing the structural equality of the two instances of the class), as well a meaningful toString method which prints the fields.&lt;br /&gt;
&lt;br /&gt;
There are numerous other benefits in using case classes, including automatic destructuring in pattern matching.  We will discuss these features in the next section.&lt;br /&gt;
&lt;br /&gt;
This feature by itself vastly reduces both development and maintenance burden for developers.  Classes in Scala are defined in lines, rather than entire files.  All the potential errors that could creep into that code are removed, and the ''intent'' of the developer is very clear.&lt;br /&gt;
&lt;br /&gt;
==Destructuring Binds and Pattern Matching==&lt;br /&gt;
Lisp, one of the earliest hybrid languages, offered primarily functional features with object-orientation built on top (in a system called CLOS).  One piece of functionality written with Common Lisp's metaprogramming facility was the ability to execute [http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_destructuring-bind.html destructuring binds], which are a powerful way of checking for a particular type ([http://en.wikipedia.org/wiki/Pattern_matching pattern matching]) and simultaneously extracting values from the inside of that type to use them in some computation. In the spirit of Common Lisp, Scala also offers destructuring binds and pattern matching.  Let's take a look at what they can do for us.&lt;br /&gt;
&lt;br /&gt;
Let us suppose we want to make use of our UserData class, defined above.  We want to find all users with ages over 18 and store their names in a database.  If we were to write a method that would simply do the database store for a single user, it might look like this:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      Integer age = user.getAge();&lt;br /&gt;
      if (age &amp;gt; 18) {&lt;br /&gt;
          recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, this would be a trivial pattern match, with a destructuring bind to capture the fields inside the UserData (in this case, we bind them to f, l and a):&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In this case, we don't get an enourmous savings in terms of the number of lines of code used, but we gain tremendously in expressive power.  Let's say we wanted to do the same thing, but not include users named &amp;quot;Bob&amp;quot;.  In Java:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      String firstName = user.getFirstName();&lt;br /&gt;
      if (firstName != &amp;quot;Bob&amp;quot;) {&lt;br /&gt;
          Integer age = user.getAge();&lt;br /&gt;
          if (age &amp;gt; 18) {&lt;br /&gt;
              recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
And now in Scala:&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 &amp;amp;&amp;amp; f != &amp;quot;Bob&amp;quot; =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Hopefully this provides a little bit of insight into how destructuring can improve the expressiveness of your code.  A more in depth discussion on pattern matching and binding can be be found in [http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-4 Part 4] of Code Commit's series &amp;quot;Scala For Java Refugees&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==List Comprehension==&lt;br /&gt;
In imperative languages (including both procedural and object-oriented languages), it is common to loop very often, either with a for loop or a while loop.  Hybrid languages allow for this, and also incorporate more abstract operations on structures seen in functional programming.&lt;br /&gt;
&lt;br /&gt;
For example, suppose we wanted to take in a structure containing a bunch of UserData objects, and return a list of strings, containing the last name, a comma, and then the first name of each user.&lt;br /&gt;
&lt;br /&gt;
In Java, this might look like this:&lt;br /&gt;
&lt;br /&gt;
  public ArrayList&amp;lt;String&amp;gt; toStrings(ArrayList&amp;lt;UserData&amp;gt; users) {&lt;br /&gt;
      ArrayList&amp;lt;String&amp;gt; returnedList = new ArrayList&amp;lt;String&amp;gt;();&lt;br /&gt;
      for (UserData u : users) {&lt;br /&gt;
          returnedList.add(u.getLastName() + &amp;quot;, &amp;quot; + u.firstName);&lt;br /&gt;
      }&lt;br /&gt;
      return returnedList;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In the seven lines of code, only the method declaration and the add to the new list really have anything to do with the business logic.  In Scala, that boiler plate can be avoided:&lt;br /&gt;
&lt;br /&gt;
  def toStrings(users: List[UserData]) = users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This method definition is so short that it is arguable we shouldn't even define the method, and should simply use the map operation inline:&lt;br /&gt;
&lt;br /&gt;
  users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
Why is the definition here so short?  Because the hybrid language gives us two new constructs that are useful in a great variety of situations: first-class functions, and the map operation.  &lt;br /&gt;
&lt;br /&gt;
# First, we define a function that takes in an instance of UserData and returns a String that is simply the concatenation of the user's last name, a comma, and the user's first name.&lt;br /&gt;
# Next, we pass that function to the map function, which then:&lt;br /&gt;
#* Takes an instance of UserData from the list called users&lt;br /&gt;
#* Passes that instance into the function, getting back a String&lt;br /&gt;
#* Appends the resultant String to a list that will be returned to the caller&lt;br /&gt;
&lt;br /&gt;
The map operation goes through the entire list (users) and applies the function to each element, collects the results, and returns them. In essence, the map operation handles all the looping, and the code in conceptually a lot simpler.&lt;br /&gt;
&lt;br /&gt;
This is a small demonstration of how functional languages and object-oriented languages an combine their strengths.  We retain all the encapsulation of the object-oriented approach (although u.lastName and u.firstName appear to be fields, they are in fact accessor methods), but we also have the power of higher abstraction levels from the functional world (in this case, the map operation).&lt;br /&gt;
&lt;br /&gt;
==Lazy Evaluation==&lt;br /&gt;
The final feature I'd like to touch upon is lazy evaluation.  One of the many implications of lazy evaluation is that we can now program using infinite data structures; we define a way in which deeper parts of the data structure are calculated from the existing parts, and only lazily evaluate parts of the structure as they are accessed.  This allows us to express algorithms quite concisely.  This can be used in a variety of cases like random number generation, methods of successive approximation (like Newton's Method), fractal calculations, and generation of infinite series, as seen in the numerical methods or, more simply, the Fibonacci sequence.  Because it is so well known, I will use the Fibonacci sequence as an example here.  First, in Java:&lt;br /&gt;
&lt;br /&gt;
   public long fib(int k) {&lt;br /&gt;
       if (k &amp;lt;= 2) {&lt;br /&gt;
           return 1;&lt;br /&gt;
       } else {&lt;br /&gt;
           return fib(k-1) + fib(k-2);&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This is a short, inefficient, recursive solution.  It doesn't cache answers, either in a single call or across calls, which means it performs a huge amount of redundant computation.  So it has a number of problems, but it is concise.&lt;br /&gt;
&lt;br /&gt;
In Scala, we can remedy all those problems and remain concise using a [http://www.scala-lang.org/docu/files/api/scala/Stream.html Stream], a lazily evaluated form of a List:&lt;br /&gt;
&lt;br /&gt;
  val fibs: Stream[Int] = Stream(0,1) append fibs.zip(fibs.drop(1)).map(x =&amp;gt; x._1 + x._2)&lt;br /&gt;
&lt;br /&gt;
This definition is concise, offers automatic memoization and is thread-safe.  To add those features to the Java code would require 20 lines of additional code at a minimum.  It returns a Stream that can be queried for the kth Fibonacci number in the same way as the fib method defined in Java could, but calculates the 92rd Fibonacci in a fraction of a second.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
Unfortunately, this article barely scratches the surface of the topic.  There are decades of research and experience that have gone into modern programming languages, and the way in which they blend various programming paradigms blurs what were once quite distinct borders in the landscape of programming languages.  But, that blurring has allowed these modern languages to offer programmers a bigger set of tools that aren't merely an amalgamation of features from every language, but a carefully crafted blend of features that enhance the expressiveness of these languages while not substantially increasing the syntax or API surface area.&lt;br /&gt;
&lt;br /&gt;
=Glossary=&lt;br /&gt;
&lt;br /&gt;
; Dynamic Dispatch&lt;br /&gt;
: The ability of a language to determine at runtime which implementation of a method should be executed.  In object-oriented languages, this is usually on the basis of the object's class.&lt;br /&gt;
&lt;br /&gt;
; Encapsulation&lt;br /&gt;
: The technique of enclosing the data and behavior of an object that are artifacts of its implementation, exposing only behaviors (and data) needed to satisfy its external contract.&lt;br /&gt;
&lt;br /&gt;
; Immutability&lt;br /&gt;
: The property of an object that disallows the object from being changed after it is constructed.  Immutability is often desireable in applications where the object will be used in highly parallel environments (e.g. many threads, over a network, etc.)&lt;br /&gt;
&lt;br /&gt;
; Polymorphism&lt;br /&gt;
: Literally, &amp;quot;many forms&amp;quot;; the technique of using multiple implementations of the same contract (or interface) to enable compenents of a piece of software to be interchanged easily.&lt;br /&gt;
&lt;br /&gt;
; Recursion&lt;br /&gt;
: A methodology for defining an algorithm or data structure in terms of itself.  Often involves a direct self-referential call with a regressing value that is checked before the recursive call is performed, thus terminating the recursion.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
If you want to know more about hybrid languages, its best to choose one (or a few!) and read about what they offer.  If you're familiar with Java, or C#, take a look at the [http://www.scala-lang.org/node/104 tour of Scala] or perhaps some of the [http://www.fandev.org/doc/docIntro/StartHere.html features of Fan].  &lt;br /&gt;
&lt;br /&gt;
There are also a few major dynamically typed hybrid languages.  Chief among these is [http://python.org Python], which has several implementations in [http://python.org C], [http://jython.org/ Java] and [http://codespeak.net/pypy/dist/pypy/doc/ Python](!).  [http://ruby-lang.org Ruby] is also a newer hybrid language, originating in Japan, but was made famous worldwide because of its [http://rubyonrails.org/ Rails] web programming framework that was possible in large part due to its hybrid nature.  It also has a [http://jruby.org/ Java implementation].  Finally, if you're working on the JVM an want a hybrid, dynamically-typed language with syntax that is close to Java's, [http://groovy.codehaus.org/ Groovy] is your best bet.&lt;br /&gt;
&lt;br /&gt;
If you're very interested in performance, Common Lisp may have something to offer you, and there are [http://www.sbcl.org/ several] [http://www.cons.org/cmucl/ performant] [http://clisp.cons.org/ implementations].  If you want to learn more about why hybrid languages are so powerful, Paul Graham's book [http://www.paulgraham.com/onlisp.html On Lisp] explains why.  If you really care about using the power of the JVM and are doing concurrent programming, a very modern lisp called [http://clojure.org Clojure] will be very interesting.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25965</id>
		<title>CSC/ECE 517 Fall 2009/wiki2 6 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25965"/>
		<updated>2009-10-14T05:41:33Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: /* Recursion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Topic=&lt;br /&gt;
&lt;br /&gt;
While Smalltalk and Java were instrumental in bringing object-oriented programming into the mainstream, the 1990s also saw the development of hybrid languages that supported multiple programming paradigms, often combining procedural, object-oriented and functional approaches. Discuss the development and design considerations that went into languages like OCaml, Scala, F# and Fan, and how they build upon an object-oriented foundation to offer languages that offer type safety while maintaining brevity and expressive power.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &lt;br /&gt;
&lt;br /&gt;
There are many ways to classify programming languages: on the basis of static or dynamic typing, type safety, high or low levels of abstraction, and by programming paradigm.&lt;br /&gt;
&lt;br /&gt;
In this article, the focus is on programming paradigms, which can loosely be thought of as defining the atomic units a language offers as building block with which to build programs.  There are three primary paradigms in use today:&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Procedural_programming Procedural]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Object-oriented_programming Object-Oriented]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Declarative_programming Declarative]&lt;br /&gt;
&lt;br /&gt;
Declarative languages span a wide array of programming styles.  For simplicity in this article, we will focus on [http://en.wikipedia.org/wiki/Functional_programming functional] languages, which are an important subset of declarative languages.&lt;br /&gt;
&lt;br /&gt;
Many languages provide only one of the paradigms to their users.  [http://www.engin.umd.umich.edu/CIS/course.des/cis400/fortran/fortran.html FORTRAN], [http://www.engin.umd.umich.edu/CIS/course.des/cis400/cobol/cobol.html COBOL], [http://en.wikipedia.org/wiki/Pascal_%28programming_language%29 Pascal], [http://cm.bell-labs.com/cm/cs/who/dmr/chist.html C] and [http://en.wikipedia.org/wiki/BASIC BASIC] are all procedural, [http://www.engin.umd.umich.edu/CIS/course.des/cis400/simula/simula.html Simula], [http://www.smalltalk.org/main/ Smalltalk]] and [http://www.eiffel.com/developers/design_by_contract.html Eiffel] are object-oriented and [http://haskell.org/ Haskell] and [http://en.wikipedia.org/wiki/ML_%28programming_language%29 ML] are functional.  These languages provide a single paradigm for programming, which limits programmers to the particular set of constructs available in that model.&lt;br /&gt;
&lt;br /&gt;
The three paradigms evolved somewhat independently and offer unique constructs with which to solve programming problems.  Some languages are multi-paradigm, however, and allow a programmer to use the tools  most fitting for the problem at hand, sometimes mixing and matching freely within a single program.  The original language of this type is Lisp, which dates back to the mid-1950s.  In the last 20 years, many other hybrid languages have emerged, often derivatives of existing languages.  C++ is derived from C, and offers both procedural and object-oriented approaches.  [http://java.sun.com Java], one of the most widely used languages today, offers both procedural and object-oriented paradigms as well.  [http://caml.inria.fr/ OCaml] is derived from ML, and offers functional and object-oriented styles.  There are many others that have become popular in recent years, like [http://python.org Python] and [http://www.ruby-lang.org/en/ Ruby].&lt;br /&gt;
&lt;br /&gt;
In this article, our goal is to examine what these hybrid languages offer above and beyond strictly object-oriented languages.  In particular, we will examine the features of object-oriented languages and functional languages, and how they have been blended in a modern hybrid language called [http://scala-lang.org Scala].&lt;br /&gt;
&lt;br /&gt;
=Features of Object Oriented Languages=&lt;br /&gt;
The key construct provided by object-oriented languages is the ''object'', which bundles the data and behavior together into a cohesive unit.&lt;br /&gt;
&lt;br /&gt;
==Encapsulation==&lt;br /&gt;
Encapsulation is the technique of rolling behavior and data into an object that exhibits (and is handled in terms of) a particular behavior, rather than a particular composition.  This technique allows the internals of an object to remain hidden from external entities, which in turn enables the object to modify its implementation over time while providing the same external behaviors.&lt;br /&gt;
&lt;br /&gt;
For example, encapsulation would allow a class to add logging functionality without affecting other classes' collaboration with it.  Any feature that is solely an implementation concern (speeding up a sorting algorithm, checking inputs for invalid data, changing the way resource errors are handled, etc.) can be evolved and modified over time within the object without breaking functionality elsewhere in the program that relies on the object in question.&lt;br /&gt;
&lt;br /&gt;
==Dependency Inversion==&lt;br /&gt;
&lt;br /&gt;
One of the major benefits of focusing on the ''behavior'' of objects rather than their ''implementation'' is that the behavior aspects can be well defined and captured in an interface.  This allows code that once would rely on an unstable implementation to instead shift its dependency onto a stable interface, and have the implementation then implement the interface.  This process is known as ''dependency inversion'', because of the way in which it alter the dependency structure of the code.&lt;br /&gt;
&lt;br /&gt;
For example, let us say we have a web server that makes use of a logging facility to log information to disk.  In this case, the web server depends on the logging facility:&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger.png]]&lt;br /&gt;
&lt;br /&gt;
Later, it becomes apparent that the web server also want to be able to log to other destinations.  To facilitate this, we introduce a ''Logger'' interface, and make have the web server depend on that, so as to insulate it from new types of loggers that may be introduced.  This allows us to modify both the server and the loggers in isolation, having them both depend on the interface rather than each other, essentially reversing, or ''inverting'' the dependency diagram.&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger-invert.png]]&lt;br /&gt;
&lt;br /&gt;
In this diagram, the behavior of the logger is well-defined and stable, and is captured in the interface represented by the yellow box.  The blue boxes are classes that are implementations, and are insulated from one another by the interface, allowing them to vary independently without breaking the program as a whole.  This is an example of the robustness that the object-oriented approach lends to a program through use of encapsulation.&lt;br /&gt;
&lt;br /&gt;
==Polymorphism and Dynamic Dispatch==&lt;br /&gt;
                                 &lt;br /&gt;
The object-oriented approach of thinking in terms of behavior lends itself to have multiple implementations of a single behavior. This allows the behavior (or contract) to have &amp;quot;many forms&amp;quot;, and is the source of the term &amp;quot;polymorphism&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
As an example, we can see this is the case of the logger above. To the web server, a logger is simply an object with which logs can be stored.  There are many possible implementations; we could use the file logger or the network logger as seen above, but we could also implement a console logger or a database logger.  Essentially, this means that the web server could call a method to log information without any knowledge of exactly what kind of object it was calling.  The raises the question of how (and when) a programming language decides which log method to call.  Is it compiled in, or is it determined at runtime?&lt;br /&gt;
&lt;br /&gt;
The answer is that it is determined at runtime.  This type of late binding, called ''dynamic dispatch'', allows a program to remain flexible even after it is deployed, permitting end-users to determine what kind of logging functionality they want be passing in various implementations of the logger interface when the web server is run, even implementations that were written ''after'' the web server was written and deployed!&lt;br /&gt;
&lt;br /&gt;
The major theme here is that the object-oriented approach of favoring encapsulation has many effects that ripple throughout the design process, almost all of which allow programmers to reduce the brittleness of their software by delaying commitment to particular implementations.&lt;br /&gt;
&lt;br /&gt;
=Features of Functional Languages=&lt;br /&gt;
&lt;br /&gt;
Much like object-oriented languages, functional languages offer a dominant paradigm that has far-reaching consequences in software design.  For object-oriented languages, that element is encapsulation, and for functional languages, it is that functions are first-class entities, which simply means that functions are treated just like any other value in the language.  This allows them to be passed as parameters, delayed, composed, invoked, and returned from other functions.  But what is a function?&lt;br /&gt;
&lt;br /&gt;
A function's most notable trait is that it is free of ''side-effects'', or state changes to the program that occur as a result of its execution.  We could say a lot about side effects, but the general rule is that a function will always return the same value given the same input.  This means that functions are ''stateless''.  Therefore, entities like random number generators and loggers are not functional, because they either store state or have some effect that is not related to the value they return.  Another way to think of functions is that they are completely defined in terms of their input and output.&lt;br /&gt;
&lt;br /&gt;
From this simple feature flows many characteristic language features.  We will discuss them in turn.&lt;br /&gt;
&lt;br /&gt;
==Immutability==&lt;br /&gt;
Maybe the most noticeable feature (or restriction) to programmers of languages that are not functional, [http://en.wikipedia.org/wiki/Immutable_object immutability] is one of the hallmarks of a functional language.  Most non-functional languages allow ''assignment'', or the ability to assign new values to variables as the program runs.  In functional programming, a value is declared only once and then never changes.  This feature of of the language flows out of the notion that functions have no side-effects, and is often viewed as more of a restriction than a feature.&lt;br /&gt;
&lt;br /&gt;
The power of immutability comes from the fact that programs that fully utilize immutability are much simpler than those that do not, making them amenable to automated analysis by a computer.  Computers can then prove various properties about function programs, like concurrent behavior (presence or absence of deadlock/livelock), memory usage, and what within what bounds various values in the program will lie.&lt;br /&gt;
&lt;br /&gt;
==Higher Order Functions==&lt;br /&gt;
&lt;br /&gt;
Higher order functions are simply functions that accept or return other functions as values.  This is made possible because functions are treated as first-class entities, and allows very expressive implementations of many algorithms to be written.&lt;br /&gt;
&lt;br /&gt;
There are several hallmark higher order functions: map, reduce, fold left/right and filter are a few examples.  Going into the intricacies of each is beyond the scope of this article, but Abelson and Sussman's seminal [http://mitpress.mit.edu/sicp/ Structure and Interpretation of Computer Programs] has an [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.1 excellent treatment] of the subject.&lt;br /&gt;
&lt;br /&gt;
==Recursion==&lt;br /&gt;
&lt;br /&gt;
Programmers that are new to functional programming often balk at the notion that values cannot change over time (as variables do in imperative languages).  If values cannot change, how can we execute loops?&lt;br /&gt;
&lt;br /&gt;
Let us examine the example of [http://en.wikipedia.org/wiki/Peano_axioms#Arithmetic Peano Arithmetic], which is a simple technique of adding two numbers together by successively decrementing one number while incrementing the other, until the number being decremented is zero.  The procedural approach would simply use a loop:&lt;br /&gt;
&lt;br /&gt;
  public int add(int a, int b) {&lt;br /&gt;
    while (a &amp;gt; 0) {&lt;br /&gt;
      a--;&lt;br /&gt;
      b++;&lt;br /&gt;
    }&lt;br /&gt;
    return b;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
This is a straight-forward implementation of Peano Arthmetic, but you'll notice that both a and b change over time.  How can implement Peano Arthimetic in a functional language?&lt;br /&gt;
&lt;br /&gt;
The answer lies in recursion, where values are immutable, and loops are implemented as successive calls to the current function with new arguments.  The avoids the complexity of having values change over time while offering all the power of the loops we often see in imperative languages (for...each, do...while, etc.)  Going back to our example, this is what the same function would look like using recursion:&lt;br /&gt;
&lt;br /&gt;
  public int add(int a, int b) {&lt;br /&gt;
    if (a==0) { return b; }&lt;br /&gt;
    return add(a-1, b+1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In this case, the values for a and b do not change over time, but rather new versions of a and b a created in each stack frame as the method successively calls itself.  This has several advantages, perhaps the most important of which is that the recursive version of the add method does not modify the values passed into it, but rather allocates new values for use in each successive call.&lt;br /&gt;
&lt;br /&gt;
A deep treatment of these language features is beyond the scope of this article, but again, Abelson and Sussman have [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.1 addressed] the topic at some length in their book.&lt;br /&gt;
&lt;br /&gt;
==Delayed (Lazy) Evaluation==&lt;br /&gt;
An extremely powerful feature of functional programming that is enabled by immutability is ''lazy evaluation''.  This simply means that expressions can be defined, even recursively, and are not computed until the values that would result from that computation are needed.  This is possible because values in functional programs don't change over time, which means expressions can be evaluated at any point in time as needed.&lt;br /&gt;
&lt;br /&gt;
Take an imperative expression like this (in Java):&lt;br /&gt;
&lt;br /&gt;
  int i = 4;&lt;br /&gt;
  int j = i + 3;&lt;br /&gt;
  i++;&lt;br /&gt;
&lt;br /&gt;
If you evaluate these expressions in order, j will be equal to 7, but if you were to delay the evaluation of j until after the third line, j would be equal to 8.  This is a very simple example of how variables that change over time require expressions be evaluated in a particular order to maintain the correctness of the program.  Functional programming explicitly disallows the third line, and therefore enables the value of j to be calculated only when it is needed.  The implications of this are significant, as we'll see in the next section.&lt;br /&gt;
&lt;br /&gt;
=Hybrid Object-Oriented/Functional Languages=&lt;br /&gt;
&lt;br /&gt;
To programmers of languages like SmallTalk, Simula and Java, many of the features provided in functional languages will seem foreign or strange.  But, as discussed, there are significant advantages to the functional approach for certain types of programs.  While the object-oriented paradigm has proven itself to be very useful, many modern languages have sought to integrate functional features as well to increase the expressiveness and power of the language.  One such language is Scala, which, like Java, runs on the Java Virtual Machine (JVM), and is thus shares Java's libraries and portability while offering many [http://www.ibm.com/developerworks/java/library/j-scala01228.html functional features] that are not available in object-oriented languages like Java.  In the [http://www.scala-lang.org/node/25 overview] of Scala available on its homepage, Scala is briefly described:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
[Scala] smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application.&amp;quot;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
How does Scala allow code sizes to be reduced so much?  It uses sophisticated type inferencing to reduce type signature redundancy, allows for functional programming constructs to be used, and provides syntax for oft-used programming idioms.  Essentially, it takes the lessons learned from decades of functional and object-oriented programming experience and rolls them into a modern hybrid language that can make full use legacy Java code.&lt;br /&gt;
&lt;br /&gt;
Scala is representative of an entire class of hybrid object/functional languages like OCaml, F# and Fan, and therefore makes a good language for use in the examples in this article.  The intent is not to present highly technical examples, but rather to give readers an impression of how hybrid languages increase expressive power over their single-paradigm counterparts.&lt;br /&gt;
&lt;br /&gt;
==Case Classes==&lt;br /&gt;
Idiomatic object-oriented programming involves encapsulation of data, as previously discussed.  In older object-oriented languages, this required defining internal data values, and then providing necessary get and set methods to access and/or modify those values. Here is an example a class in Java that provides only get methods for some (immutable) values it holds.  It includes all the methods that ''should'' be included in such a class, including a toString, equals and hashCode method.  Note that is an error if such methods are ''not'' included in structural Java classes, which is why I include them here.&lt;br /&gt;
&lt;br /&gt;
  public class UserData {&lt;br /&gt;
      private final String firstName;&lt;br /&gt;
      private final String lastName;&lt;br /&gt;
      private final Integer age;&lt;br /&gt;
      public UserData(String firstName, String lastName, Integer age) {&lt;br /&gt;
          this.firstName = firstName;&lt;br /&gt;
          this.lastName = lastName;&lt;br /&gt;
          this.age = age;&lt;br /&gt;
      }&lt;br /&gt;
      public String getFirstName() {&lt;br /&gt;
          return this.firstName;&lt;br /&gt;
      }&lt;br /&gt;
      public String getLastName() {&lt;br /&gt;
          return this.lastName;&lt;br /&gt;
      }&lt;br /&gt;
      public Integer getAge() {&lt;br /&gt;
          return this.age;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public boolean equals(Object obj) {&lt;br /&gt;
          if (obj == null) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (getClass() != obj.getClass()) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          final UserData other = (UserData) obj;&lt;br /&gt;
          if ((this.firstName == null) ? (other.firstName != null) : !this.firstName.equals(other.firstName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if ((this.lastName == null) ? (other.lastName != null) : !this.lastName.equals(other.lastName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.age != other.age &amp;amp;&amp;amp; (this.age == null || !this.age.equals(other.age))) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          return true;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public int hashCode() {&lt;br /&gt;
          int hash = 7;&lt;br /&gt;
          hash = 19 * hash + (this.firstName != null ? this.firstName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.lastName != null ? this.lastName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.age != null ? this.age.hashCode() : 0);&lt;br /&gt;
          return hash;&lt;br /&gt;
      }&lt;br /&gt;
      public String toString() {&lt;br /&gt;
          StringBuilder sb = new StringBuilder();&lt;br /&gt;
          sb.append(&amp;quot;UserData[firstName: &amp;quot;);&lt;br /&gt;
          sb.append(this.firstName);&lt;br /&gt;
          sb.append(&amp;quot; lastName: &amp;quot;);&lt;br /&gt;
          sb.append(this.lastName);&lt;br /&gt;
          sb.append(&amp;quot; age: &amp;quot;);&lt;br /&gt;
          sb.append(this.age);&lt;br /&gt;
          sb.append(&amp;quot;]&amp;quot;);&lt;br /&gt;
          return sb.toString();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, ''all'' the functionality of the above class can be expressed with:&lt;br /&gt;
&lt;br /&gt;
  case class UserData(val firstName: String, val lastName: String, val age: Int)&lt;br /&gt;
&lt;br /&gt;
To reiterate, the version in Scala actually does include a constructor, accessor methods, three fields that can only be set once, equals and hashCode  methods (comparing the structural equality of the two instances of the class), as well a meaningful toString method which prints the fields.&lt;br /&gt;
&lt;br /&gt;
There are numerous other benefits in using case classes, including automatic destructuring in pattern matching.  We will discuss these features in the next section.&lt;br /&gt;
&lt;br /&gt;
This feature by itself vastly reduces both development and maintenance burden for developers.  Classes in Scala are defined in lines, rather than entire files.  All the potential errors that could creep into that code are removed, and the ''intent'' of the developer is very clear.&lt;br /&gt;
&lt;br /&gt;
==Destructuring Binds and Pattern Matching==&lt;br /&gt;
Lisp, one of the earliest hybrid languages, offered primarily functional features with object-orientation built on top (in a system called CLOS).  One piece of functionality written with Common Lisp's metaprogramming facility was the ability to execute [http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_destructuring-bind.html destructuring binds], which are a powerful way of checking for a particular type ([http://en.wikipedia.org/wiki/Pattern_matching pattern matching]) and simultaneously extracting values from the inside of that type to use them in some computation. In the spirit of Common Lisp, Scala also offers destructuring binds and pattern matching.  Let's take a look at what they can do for us.&lt;br /&gt;
&lt;br /&gt;
Let us suppose we want to make use of our UserData class, defined above.  We want to find all users with ages over 18 and store their names in a database.  If we were to write a method that would simply do the database store for a single user, it might look like this:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      Integer age = user.getAge();&lt;br /&gt;
      if (age &amp;gt; 18) {&lt;br /&gt;
          recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, this would be a trivial pattern match, with a destructuring bind to capture the fields inside the UserData (in this case, we bind them to f, l and a):&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In this case, we don't get an enourmous savings in terms of the number of lines of code used, but we gain tremendously in expressive power.  Let's say we wanted to do the same thing, but not include users named &amp;quot;Bob&amp;quot;.  In Java:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      String firstName = user.getFirstName();&lt;br /&gt;
      if (firstName != &amp;quot;Bob&amp;quot;) {&lt;br /&gt;
          Integer age = user.getAge();&lt;br /&gt;
          if (age &amp;gt; 18) {&lt;br /&gt;
              recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
And now in Scala:&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 &amp;amp;&amp;amp; f != &amp;quot;Bob&amp;quot; =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Hopefully this provides a little bit of insight into how destructuring can improve the expressiveness of your code.  A more in depth discussion on pattern matching and binding can be be found in [http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-4 Part 4] of Code Commit's series &amp;quot;Scala For Java Refugees&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==List Comprehension==&lt;br /&gt;
In imperative languages (including both procedural and object-oriented languages), it is common to loop very often, either with a for loop or a while loop.  Hybrid languages allow for this, and also incorporate more abstract operations on structures seen in functional programming.&lt;br /&gt;
&lt;br /&gt;
For example, suppose we wanted to take in a structure containing a bunch of UserData objects, and return a list of strings, containing the last name, a comma, and then the first name of each user.&lt;br /&gt;
&lt;br /&gt;
In Java, this might look like this:&lt;br /&gt;
&lt;br /&gt;
  public ArrayList&amp;lt;String&amp;gt; toStrings(ArrayList&amp;lt;UserData&amp;gt; users) {&lt;br /&gt;
      ArrayList&amp;lt;String&amp;gt; returnedList = new ArrayList&amp;lt;String&amp;gt;();&lt;br /&gt;
      for (UserData u : users) {&lt;br /&gt;
          returnedList.add(u.getLastName() + &amp;quot;, &amp;quot; + u.firstName);&lt;br /&gt;
      }&lt;br /&gt;
      return returnedList;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In the seven lines of code, only the method declaration and the add to the new list really have anything to do with the business logic.  In Scala, that boiler plate can be avoided:&lt;br /&gt;
&lt;br /&gt;
  def toStrings(users: List[UserData]) = users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This method definition is so short that it is arguable we shouldn't even define the method, and should simply use the map operation inline:&lt;br /&gt;
&lt;br /&gt;
  users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This is a small demonstration of how functional languages and object-oriented languages an combine their strengths.  We retain all the encapsulation of the object-oriented approach (although u.lastName and u.firstName appear to be fields, they are in fact accessor methods), but we also have the power of higher abstraction levels from the functional world (in this case, the map operation).&lt;br /&gt;
&lt;br /&gt;
==Lazy Evaluation==&lt;br /&gt;
The final feature I'd like to touch upon is lazy evaluation.  One of the many implications of lazy evaluation is that we can now program using infinite data structures; we define a way in which deeper parts of the data structure are calculated from the existing parts, and only lazily evaluate parts of the structure as they are accessed.  This allows us to express algorithms quite concisely.  This can be used in a variety of cases like random number generation, methods of successive approximation (like Newton's Method), fractal calculations, and generation of infinite series, as seen in the numerical methods or, more simply, the Fibonacci sequence.  Because it is so well known, I will use the Fibonacci sequence as an example here.  First, in Java:&lt;br /&gt;
&lt;br /&gt;
   public long fib(int k) {&lt;br /&gt;
       if (k &amp;lt;= 2) {&lt;br /&gt;
           return 1;&lt;br /&gt;
       } else {&lt;br /&gt;
           return fib(k-1) + fib(k-2);&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This is a short, inefficient, recursive solution.  It doesn't cache answers, either in a single call or across calls, which means it performs a huge amount of redundant computation.  So it has a number of problems, but it is concise.&lt;br /&gt;
&lt;br /&gt;
In Scala, we can remedy all those problems and remain concise using a [http://www.scala-lang.org/docu/files/api/scala/Stream.html Stream], a lazily evaluated form of a List:&lt;br /&gt;
&lt;br /&gt;
  val fibs: Stream[Int] = Stream(0,1) append fibs.zip(fibs.drop(1)).map(x =&amp;gt; x._1 + x._2)&lt;br /&gt;
&lt;br /&gt;
This definition is concise, offers automatic memoization and is thread-safe.  To add those features to the Java code would require 20 lines of additional code at a minimum.  It returns a Stream that can be queried for the kth Fibonacci number in the same way as the fib method defined in Java could, but calculates the 92rd Fibonacci in a fraction of a second.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
Unfortunately, this article barely scratches the surface of the topic.  There are decades of research and experience that have gone into modern programming languages, and the way in which they blend various programming paradigms blurs what were once quite distinct borders in the landscape of programming languages.  But, that blurring has allowed these modern languages to offer programmers a bigger set of tools that aren't merely an amalgamation of features from every language, but a carefully crafted blend of features that enhance the expressiveness of these languages while not substantially increasing the syntax or API surface area.&lt;br /&gt;
&lt;br /&gt;
=Glossary=&lt;br /&gt;
&lt;br /&gt;
; Dynamic Dispatch&lt;br /&gt;
: The ability of a language to determine at runtime which implementation of a method should be executed.  In object-oriented languages, this is usually on the basis of the object's class.&lt;br /&gt;
&lt;br /&gt;
; Encapsulation&lt;br /&gt;
: The technique of enclosing the data and behavior of an object that are artifacts of its implementation, exposing only behaviors (and data) needed to satisfy its external contract.&lt;br /&gt;
&lt;br /&gt;
; Immutability&lt;br /&gt;
: The property of an object that disallows the object from being changed after it is constructed.  Immutability is often desireable in applications where the object will be used in highly parallel environments (e.g. many threads, over a network, etc.)&lt;br /&gt;
&lt;br /&gt;
; Polymorphism&lt;br /&gt;
: Literally, &amp;quot;many forms&amp;quot;; the technique of using multiple implementations of the same contract (or interface) to enable compenents of a piece of software to be interchanged easily.&lt;br /&gt;
&lt;br /&gt;
; Recursion&lt;br /&gt;
: A methodology for defining an algorithm or data structure in terms of itself.  Often involves a direct self-referential call with a regressing value that is checked before the recursive call is performed, thus terminating the recursion.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
If you want to know more about hybrid languages, its best to choose one (or a few!) and read about what they offer.  If you're familiar with Java, or C#, take a look at the [http://www.scala-lang.org/node/104 tour of Scala] or perhaps some of the [http://www.fandev.org/doc/docIntro/StartHere.html features of Fan].  &lt;br /&gt;
&lt;br /&gt;
There are also a few major dynamically typed hybrid languages.  Chief among these is [http://python.org Python], which has several implementations in [http://python.org C], [http://jython.org/ Java] and [http://codespeak.net/pypy/dist/pypy/doc/ Python](!).  [http://ruby-lang.org Ruby] is also a newer hybrid language, originating in Japan, but was made famous worldwide because of its [http://rubyonrails.org/ Rails] web programming framework that was possible in large part due to its hybrid nature.  It also has a [http://jruby.org/ Java implementation].  Finally, if you're working on the JVM an want a hybrid, dynamically-typed language with syntax that is close to Java's, [http://groovy.codehaus.org/ Groovy] is your best bet.&lt;br /&gt;
&lt;br /&gt;
If you're very interested in performance, Common Lisp may have something to offer you, and there are [http://www.sbcl.org/ several] [http://www.cons.org/cmucl/ performant] [http://clisp.cons.org/ implementations].  If you want to learn more about why hybrid languages are so powerful, Paul Graham's book [http://www.paulgraham.com/onlisp.html On Lisp] explains why.  If you really care about using the power of the JVM and are doing concurrent programming, a very modern lisp called [http://clojure.org Clojure] will be very interesting.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25964</id>
		<title>CSC/ECE 517 Fall 2009/wiki2 6 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25964"/>
		<updated>2009-10-14T05:29:47Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: /* Polymorphism and Dynamic Dispatch */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Topic=&lt;br /&gt;
&lt;br /&gt;
While Smalltalk and Java were instrumental in bringing object-oriented programming into the mainstream, the 1990s also saw the development of hybrid languages that supported multiple programming paradigms, often combining procedural, object-oriented and functional approaches. Discuss the development and design considerations that went into languages like OCaml, Scala, F# and Fan, and how they build upon an object-oriented foundation to offer languages that offer type safety while maintaining brevity and expressive power.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &lt;br /&gt;
&lt;br /&gt;
There are many ways to classify programming languages: on the basis of static or dynamic typing, type safety, high or low levels of abstraction, and by programming paradigm.&lt;br /&gt;
&lt;br /&gt;
In this article, the focus is on programming paradigms, which can loosely be thought of as defining the atomic units a language offers as building block with which to build programs.  There are three primary paradigms in use today:&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Procedural_programming Procedural]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Object-oriented_programming Object-Oriented]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Declarative_programming Declarative]&lt;br /&gt;
&lt;br /&gt;
Declarative languages span a wide array of programming styles.  For simplicity in this article, we will focus on [http://en.wikipedia.org/wiki/Functional_programming functional] languages, which are an important subset of declarative languages.&lt;br /&gt;
&lt;br /&gt;
Many languages provide only one of the paradigms to their users.  [http://www.engin.umd.umich.edu/CIS/course.des/cis400/fortran/fortran.html FORTRAN], [http://www.engin.umd.umich.edu/CIS/course.des/cis400/cobol/cobol.html COBOL], [http://en.wikipedia.org/wiki/Pascal_%28programming_language%29 Pascal], [http://cm.bell-labs.com/cm/cs/who/dmr/chist.html C] and [http://en.wikipedia.org/wiki/BASIC BASIC] are all procedural, [http://www.engin.umd.umich.edu/CIS/course.des/cis400/simula/simula.html Simula], [http://www.smalltalk.org/main/ Smalltalk]] and [http://www.eiffel.com/developers/design_by_contract.html Eiffel] are object-oriented and [http://haskell.org/ Haskell] and [http://en.wikipedia.org/wiki/ML_%28programming_language%29 ML] are functional.  These languages provide a single paradigm for programming, which limits programmers to the particular set of constructs available in that model.&lt;br /&gt;
&lt;br /&gt;
The three paradigms evolved somewhat independently and offer unique constructs with which to solve programming problems.  Some languages are multi-paradigm, however, and allow a programmer to use the tools  most fitting for the problem at hand, sometimes mixing and matching freely within a single program.  The original language of this type is Lisp, which dates back to the mid-1950s.  In the last 20 years, many other hybrid languages have emerged, often derivatives of existing languages.  C++ is derived from C, and offers both procedural and object-oriented approaches.  [http://java.sun.com Java], one of the most widely used languages today, offers both procedural and object-oriented paradigms as well.  [http://caml.inria.fr/ OCaml] is derived from ML, and offers functional and object-oriented styles.  There are many others that have become popular in recent years, like [http://python.org Python] and [http://www.ruby-lang.org/en/ Ruby].&lt;br /&gt;
&lt;br /&gt;
In this article, our goal is to examine what these hybrid languages offer above and beyond strictly object-oriented languages.  In particular, we will examine the features of object-oriented languages and functional languages, and how they have been blended in a modern hybrid language called [http://scala-lang.org Scala].&lt;br /&gt;
&lt;br /&gt;
=Features of Object Oriented Languages=&lt;br /&gt;
The key construct provided by object-oriented languages is the ''object'', which bundles the data and behavior together into a cohesive unit.&lt;br /&gt;
&lt;br /&gt;
==Encapsulation==&lt;br /&gt;
Encapsulation is the technique of rolling behavior and data into an object that exhibits (and is handled in terms of) a particular behavior, rather than a particular composition.  This technique allows the internals of an object to remain hidden from external entities, which in turn enables the object to modify its implementation over time while providing the same external behaviors.&lt;br /&gt;
&lt;br /&gt;
For example, encapsulation would allow a class to add logging functionality without affecting other classes' collaboration with it.  Any feature that is solely an implementation concern (speeding up a sorting algorithm, checking inputs for invalid data, changing the way resource errors are handled, etc.) can be evolved and modified over time within the object without breaking functionality elsewhere in the program that relies on the object in question.&lt;br /&gt;
&lt;br /&gt;
==Dependency Inversion==&lt;br /&gt;
&lt;br /&gt;
One of the major benefits of focusing on the ''behavior'' of objects rather than their ''implementation'' is that the behavior aspects can be well defined and captured in an interface.  This allows code that once would rely on an unstable implementation to instead shift its dependency onto a stable interface, and have the implementation then implement the interface.  This process is known as ''dependency inversion'', because of the way in which it alter the dependency structure of the code.&lt;br /&gt;
&lt;br /&gt;
For example, let us say we have a web server that makes use of a logging facility to log information to disk.  In this case, the web server depends on the logging facility:&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger.png]]&lt;br /&gt;
&lt;br /&gt;
Later, it becomes apparent that the web server also want to be able to log to other destinations.  To facilitate this, we introduce a ''Logger'' interface, and make have the web server depend on that, so as to insulate it from new types of loggers that may be introduced.  This allows us to modify both the server and the loggers in isolation, having them both depend on the interface rather than each other, essentially reversing, or ''inverting'' the dependency diagram.&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger-invert.png]]&lt;br /&gt;
&lt;br /&gt;
In this diagram, the behavior of the logger is well-defined and stable, and is captured in the interface represented by the yellow box.  The blue boxes are classes that are implementations, and are insulated from one another by the interface, allowing them to vary independently without breaking the program as a whole.  This is an example of the robustness that the object-oriented approach lends to a program through use of encapsulation.&lt;br /&gt;
&lt;br /&gt;
==Polymorphism and Dynamic Dispatch==&lt;br /&gt;
                                 &lt;br /&gt;
The object-oriented approach of thinking in terms of behavior lends itself to have multiple implementations of a single behavior. This allows the behavior (or contract) to have &amp;quot;many forms&amp;quot;, and is the source of the term &amp;quot;polymorphism&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
As an example, we can see this is the case of the logger above. To the web server, a logger is simply an object with which logs can be stored.  There are many possible implementations; we could use the file logger or the network logger as seen above, but we could also implement a console logger or a database logger.  Essentially, this means that the web server could call a method to log information without any knowledge of exactly what kind of object it was calling.  The raises the question of how (and when) a programming language decides which log method to call.  Is it compiled in, or is it determined at runtime?&lt;br /&gt;
&lt;br /&gt;
The answer is that it is determined at runtime.  This type of late binding, called ''dynamic dispatch'', allows a program to remain flexible even after it is deployed, permitting end-users to determine what kind of logging functionality they want be passing in various implementations of the logger interface when the web server is run, even implementations that were written ''after'' the web server was written and deployed!&lt;br /&gt;
&lt;br /&gt;
The major theme here is that the object-oriented approach of favoring encapsulation has many effects that ripple throughout the design process, almost all of which allow programmers to reduce the brittleness of their software by delaying commitment to particular implementations.&lt;br /&gt;
&lt;br /&gt;
=Features of Functional Languages=&lt;br /&gt;
&lt;br /&gt;
Much like object-oriented languages, functional languages offer a dominant paradigm that has far-reaching consequences in software design.  For object-oriented languages, that element is encapsulation, and for functional languages, it is that functions are first-class entities, which simply means that functions are treated just like any other value in the language.  This allows them to be passed as parameters, delayed, composed, invoked, and returned from other functions.  But what is a function?&lt;br /&gt;
&lt;br /&gt;
A function's most notable trait is that it is free of ''side-effects'', or state changes to the program that occur as a result of its execution.  We could say a lot about side effects, but the general rule is that a function will always return the same value given the same input.  This means that functions are ''stateless''.  Therefore, entities like random number generators and loggers are not functional, because they either store state or have some effect that is not related to the value they return.  Another way to think of functions is that they are completely defined in terms of their input and output.&lt;br /&gt;
&lt;br /&gt;
From this simple feature flows many characteristic language features.  We will discuss them in turn.&lt;br /&gt;
&lt;br /&gt;
==Immutability==&lt;br /&gt;
Maybe the most noticeable feature (or restriction) to programmers of languages that are not functional, [http://en.wikipedia.org/wiki/Immutable_object immutability] is one of the hallmarks of a functional language.  Most non-functional languages allow ''assignment'', or the ability to assign new values to variables as the program runs.  In functional programming, a value is declared only once and then never changes.  This feature of of the language flows out of the notion that functions have no side-effects, and is often viewed as more of a restriction than a feature.&lt;br /&gt;
&lt;br /&gt;
The power of immutability comes from the fact that programs that fully utilize immutability are much simpler than those that do not, making them amenable to automated analysis by a computer.  Computers can then prove various properties about function programs, like concurrent behavior (presence or absence of deadlock/livelock), memory usage, and what within what bounds various values in the program will lie.&lt;br /&gt;
&lt;br /&gt;
==Higher Order Functions==&lt;br /&gt;
&lt;br /&gt;
Higher order functions are simply functions that accept or return other functions as values.  This is made possible because functions are treated as first-class entities, and allows very expressive implementations of many algorithms to be written.&lt;br /&gt;
&lt;br /&gt;
There are several hallmark higher order functions: map, reduce, fold left/right and filter are a few examples.  Going into the intricacies of each is beyond the scope of this article, but Abelson and Sussman's seminal [http://mitpress.mit.edu/sicp/ Structure and Interpretation of Computer Programs] has an [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.1 excellent treatment] of the subject.&lt;br /&gt;
&lt;br /&gt;
==Recursion==&lt;br /&gt;
&lt;br /&gt;
Programmers that are new to functional programming often balk at the notion that values cannot change over time (as variables do in imperative languages).  If values cannot change, how can we execute loops?&lt;br /&gt;
&lt;br /&gt;
The answer lies in recursion, where values are immutable, and loops are implemented as successive calls to the current function with new arguments.  The avoids the complexity of having values change over time while offering all the power of the loops we often see in imperative languages (for...each, do...while, etc.)  Again, a deep treatment of these language features is beyond the scope of this article, but again, Abelson and Sussman have [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.1 addressed] the topic at some length in their book.&lt;br /&gt;
&lt;br /&gt;
==Delayed (Lazy) Evaluation==&lt;br /&gt;
An extremely powerful feature of functional programming that is enabled by immutability is ''lazy evaluation''.  This simply means that expressions can be defined, even recursively, and are not computed until the values that would result from that computation are needed.  This is possible because values in functional programs don't change over time, which means expressions can be evaluated at any point in time as needed.&lt;br /&gt;
&lt;br /&gt;
Take an imperative expression like this (in Java):&lt;br /&gt;
&lt;br /&gt;
  int i = 4;&lt;br /&gt;
  int j = i + 3;&lt;br /&gt;
  i++;&lt;br /&gt;
&lt;br /&gt;
If you evaluate these expressions in order, j will be equal to 7, but if you were to delay the evaluation of j until after the third line, j would be equal to 8.  This is a very simple example of how variables that change over time require expressions be evaluated in a particular order to maintain the correctness of the program.  Functional programming explicitly disallows the third line, and therefore enables the value of j to be calculated only when it is needed.  The implications of this are significant, as we'll see in the next section.&lt;br /&gt;
&lt;br /&gt;
=Hybrid Object-Oriented/Functional Languages=&lt;br /&gt;
&lt;br /&gt;
To programmers of languages like SmallTalk, Simula and Java, many of the features provided in functional languages will seem foreign or strange.  But, as discussed, there are significant advantages to the functional approach for certain types of programs.  While the object-oriented paradigm has proven itself to be very useful, many modern languages have sought to integrate functional features as well to increase the expressiveness and power of the language.  One such language is Scala, which, like Java, runs on the Java Virtual Machine (JVM), and is thus shares Java's libraries and portability while offering many [http://www.ibm.com/developerworks/java/library/j-scala01228.html functional features] that are not available in object-oriented languages like Java.  In the [http://www.scala-lang.org/node/25 overview] of Scala available on its homepage, Scala is briefly described:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
[Scala] smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application.&amp;quot;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
How does Scala allow code sizes to be reduced so much?  It uses sophisticated type inferencing to reduce type signature redundancy, allows for functional programming constructs to be used, and provides syntax for oft-used programming idioms.  Essentially, it takes the lessons learned from decades of functional and object-oriented programming experience and rolls them into a modern hybrid language that can make full use legacy Java code.&lt;br /&gt;
&lt;br /&gt;
Scala is representative of an entire class of hybrid object/functional languages like OCaml, F# and Fan, and therefore makes a good language for use in the examples in this article.  The intent is not to present highly technical examples, but rather to give readers an impression of how hybrid languages increase expressive power over their single-paradigm counterparts.&lt;br /&gt;
&lt;br /&gt;
==Case Classes==&lt;br /&gt;
Idiomatic object-oriented programming involves encapsulation of data, as previously discussed.  In older object-oriented languages, this required defining internal data values, and then providing necessary get and set methods to access and/or modify those values. Here is an example a class in Java that provides only get methods for some (immutable) values it holds.  It includes all the methods that ''should'' be included in such a class, including a toString, equals and hashCode method.  Note that is an error if such methods are ''not'' included in structural Java classes, which is why I include them here.&lt;br /&gt;
&lt;br /&gt;
  public class UserData {&lt;br /&gt;
      private final String firstName;&lt;br /&gt;
      private final String lastName;&lt;br /&gt;
      private final Integer age;&lt;br /&gt;
      public UserData(String firstName, String lastName, Integer age) {&lt;br /&gt;
          this.firstName = firstName;&lt;br /&gt;
          this.lastName = lastName;&lt;br /&gt;
          this.age = age;&lt;br /&gt;
      }&lt;br /&gt;
      public String getFirstName() {&lt;br /&gt;
          return this.firstName;&lt;br /&gt;
      }&lt;br /&gt;
      public String getLastName() {&lt;br /&gt;
          return this.lastName;&lt;br /&gt;
      }&lt;br /&gt;
      public Integer getAge() {&lt;br /&gt;
          return this.age;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public boolean equals(Object obj) {&lt;br /&gt;
          if (obj == null) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (getClass() != obj.getClass()) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          final UserData other = (UserData) obj;&lt;br /&gt;
          if ((this.firstName == null) ? (other.firstName != null) : !this.firstName.equals(other.firstName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if ((this.lastName == null) ? (other.lastName != null) : !this.lastName.equals(other.lastName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.age != other.age &amp;amp;&amp;amp; (this.age == null || !this.age.equals(other.age))) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          return true;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public int hashCode() {&lt;br /&gt;
          int hash = 7;&lt;br /&gt;
          hash = 19 * hash + (this.firstName != null ? this.firstName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.lastName != null ? this.lastName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.age != null ? this.age.hashCode() : 0);&lt;br /&gt;
          return hash;&lt;br /&gt;
      }&lt;br /&gt;
      public String toString() {&lt;br /&gt;
          StringBuilder sb = new StringBuilder();&lt;br /&gt;
          sb.append(&amp;quot;UserData[firstName: &amp;quot;);&lt;br /&gt;
          sb.append(this.firstName);&lt;br /&gt;
          sb.append(&amp;quot; lastName: &amp;quot;);&lt;br /&gt;
          sb.append(this.lastName);&lt;br /&gt;
          sb.append(&amp;quot; age: &amp;quot;);&lt;br /&gt;
          sb.append(this.age);&lt;br /&gt;
          sb.append(&amp;quot;]&amp;quot;);&lt;br /&gt;
          return sb.toString();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, ''all'' the functionality of the above class can be expressed with:&lt;br /&gt;
&lt;br /&gt;
  case class UserData(val firstName: String, val lastName: String, val age: Int)&lt;br /&gt;
&lt;br /&gt;
To reiterate, the version in Scala actually does include a constructor, accessor methods, three fields that can only be set once, equals and hashCode  methods (comparing the structural equality of the two instances of the class), as well a meaningful toString method which prints the fields.&lt;br /&gt;
&lt;br /&gt;
There are numerous other benefits in using case classes, including automatic destructuring in pattern matching.  We will discuss these features in the next section.&lt;br /&gt;
&lt;br /&gt;
This feature by itself vastly reduces both development and maintenance burden for developers.  Classes in Scala are defined in lines, rather than entire files.  All the potential errors that could creep into that code are removed, and the ''intent'' of the developer is very clear.&lt;br /&gt;
&lt;br /&gt;
==Destructuring Binds and Pattern Matching==&lt;br /&gt;
Lisp, one of the earliest hybrid languages, offered primarily functional features with object-orientation built on top (in a system called CLOS).  One piece of functionality written with Common Lisp's metaprogramming facility was the ability to execute [http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_destructuring-bind.html destructuring binds], which are a powerful way of checking for a particular type ([http://en.wikipedia.org/wiki/Pattern_matching pattern matching]) and simultaneously extracting values from the inside of that type to use them in some computation. In the spirit of Common Lisp, Scala also offers destructuring binds and pattern matching.  Let's take a look at what they can do for us.&lt;br /&gt;
&lt;br /&gt;
Let us suppose we want to make use of our UserData class, defined above.  We want to find all users with ages over 18 and store their names in a database.  If we were to write a method that would simply do the database store for a single user, it might look like this:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      Integer age = user.getAge();&lt;br /&gt;
      if (age &amp;gt; 18) {&lt;br /&gt;
          recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, this would be a trivial pattern match, with a destructuring bind to capture the fields inside the UserData (in this case, we bind them to f, l and a):&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In this case, we don't get an enourmous savings in terms of the number of lines of code used, but we gain tremendously in expressive power.  Let's say we wanted to do the same thing, but not include users named &amp;quot;Bob&amp;quot;.  In Java:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      String firstName = user.getFirstName();&lt;br /&gt;
      if (firstName != &amp;quot;Bob&amp;quot;) {&lt;br /&gt;
          Integer age = user.getAge();&lt;br /&gt;
          if (age &amp;gt; 18) {&lt;br /&gt;
              recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
And now in Scala:&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 &amp;amp;&amp;amp; f != &amp;quot;Bob&amp;quot; =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Hopefully this provides a little bit of insight into how destructuring can improve the expressiveness of your code.  A more in depth discussion on pattern matching and binding can be be found in [http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-4 Part 4] of Code Commit's series &amp;quot;Scala For Java Refugees&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==List Comprehension==&lt;br /&gt;
In imperative languages (including both procedural and object-oriented languages), it is common to loop very often, either with a for loop or a while loop.  Hybrid languages allow for this, and also incorporate more abstract operations on structures seen in functional programming.&lt;br /&gt;
&lt;br /&gt;
For example, suppose we wanted to take in a structure containing a bunch of UserData objects, and return a list of strings, containing the last name, a comma, and then the first name of each user.&lt;br /&gt;
&lt;br /&gt;
In Java, this might look like this:&lt;br /&gt;
&lt;br /&gt;
  public ArrayList&amp;lt;String&amp;gt; toStrings(ArrayList&amp;lt;UserData&amp;gt; users) {&lt;br /&gt;
      ArrayList&amp;lt;String&amp;gt; returnedList = new ArrayList&amp;lt;String&amp;gt;();&lt;br /&gt;
      for (UserData u : users) {&lt;br /&gt;
          returnedList.add(u.getLastName() + &amp;quot;, &amp;quot; + u.firstName);&lt;br /&gt;
      }&lt;br /&gt;
      return returnedList;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In the seven lines of code, only the method declaration and the add to the new list really have anything to do with the business logic.  In Scala, that boiler plate can be avoided:&lt;br /&gt;
&lt;br /&gt;
  def toStrings(users: List[UserData]) = users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This method definition is so short that it is arguable we shouldn't even define the method, and should simply use the map operation inline:&lt;br /&gt;
&lt;br /&gt;
  users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This is a small demonstration of how functional languages and object-oriented languages an combine their strengths.  We retain all the encapsulation of the object-oriented approach (although u.lastName and u.firstName appear to be fields, they are in fact accessor methods), but we also have the power of higher abstraction levels from the functional world (in this case, the map operation).&lt;br /&gt;
&lt;br /&gt;
==Lazy Evaluation==&lt;br /&gt;
The final feature I'd like to touch upon is lazy evaluation.  One of the many implications of lazy evaluation is that we can now program using infinite data structures; we define a way in which deeper parts of the data structure are calculated from the existing parts, and only lazily evaluate parts of the structure as they are accessed.  This allows us to express algorithms quite concisely.  This can be used in a variety of cases like random number generation, methods of successive approximation (like Newton's Method), fractal calculations, and generation of infinite series, as seen in the numerical methods or, more simply, the Fibonacci sequence.  Because it is so well known, I will use the Fibonacci sequence as an example here.  First, in Java:&lt;br /&gt;
&lt;br /&gt;
   public long fib(int k) {&lt;br /&gt;
       if (k &amp;lt;= 2) {&lt;br /&gt;
           return 1;&lt;br /&gt;
       } else {&lt;br /&gt;
           return fib(k-1) + fib(k-2);&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This is a short, inefficient, recursive solution.  It doesn't cache answers, either in a single call or across calls, which means it performs a huge amount of redundant computation.  So it has a number of problems, but it is concise.&lt;br /&gt;
&lt;br /&gt;
In Scala, we can remedy all those problems and remain concise using a [http://www.scala-lang.org/docu/files/api/scala/Stream.html Stream], a lazily evaluated form of a List:&lt;br /&gt;
&lt;br /&gt;
  val fibs: Stream[Int] = Stream(0,1) append fibs.zip(fibs.drop(1)).map(x =&amp;gt; x._1 + x._2)&lt;br /&gt;
&lt;br /&gt;
This definition is concise, offers automatic memoization and is thread-safe.  To add those features to the Java code would require 20 lines of additional code at a minimum.  It returns a Stream that can be queried for the kth Fibonacci number in the same way as the fib method defined in Java could, but calculates the 92rd Fibonacci in a fraction of a second.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
Unfortunately, this article barely scratches the surface of the topic.  There are decades of research and experience that have gone into modern programming languages, and the way in which they blend various programming paradigms blurs what were once quite distinct borders in the landscape of programming languages.  But, that blurring has allowed these modern languages to offer programmers a bigger set of tools that aren't merely an amalgamation of features from every language, but a carefully crafted blend of features that enhance the expressiveness of these languages while not substantially increasing the syntax or API surface area.&lt;br /&gt;
&lt;br /&gt;
=Glossary=&lt;br /&gt;
&lt;br /&gt;
; Dynamic Dispatch&lt;br /&gt;
: The ability of a language to determine at runtime which implementation of a method should be executed.  In object-oriented languages, this is usually on the basis of the object's class.&lt;br /&gt;
&lt;br /&gt;
; Encapsulation&lt;br /&gt;
: The technique of enclosing the data and behavior of an object that are artifacts of its implementation, exposing only behaviors (and data) needed to satisfy its external contract.&lt;br /&gt;
&lt;br /&gt;
; Immutability&lt;br /&gt;
: The property of an object that disallows the object from being changed after it is constructed.  Immutability is often desireable in applications where the object will be used in highly parallel environments (e.g. many threads, over a network, etc.)&lt;br /&gt;
&lt;br /&gt;
; Polymorphism&lt;br /&gt;
: Literally, &amp;quot;many forms&amp;quot;; the technique of using multiple implementations of the same contract (or interface) to enable compenents of a piece of software to be interchanged easily.&lt;br /&gt;
&lt;br /&gt;
; Recursion&lt;br /&gt;
: A methodology for defining an algorithm or data structure in terms of itself.  Often involves a direct self-referential call with a regressing value that is checked before the recursive call is performed, thus terminating the recursion.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
If you want to know more about hybrid languages, its best to choose one (or a few!) and read about what they offer.  If you're familiar with Java, or C#, take a look at the [http://www.scala-lang.org/node/104 tour of Scala] or perhaps some of the [http://www.fandev.org/doc/docIntro/StartHere.html features of Fan].  &lt;br /&gt;
&lt;br /&gt;
There are also a few major dynamically typed hybrid languages.  Chief among these is [http://python.org Python], which has several implementations in [http://python.org C], [http://jython.org/ Java] and [http://codespeak.net/pypy/dist/pypy/doc/ Python](!).  [http://ruby-lang.org Ruby] is also a newer hybrid language, originating in Japan, but was made famous worldwide because of its [http://rubyonrails.org/ Rails] web programming framework that was possible in large part due to its hybrid nature.  It also has a [http://jruby.org/ Java implementation].  Finally, if you're working on the JVM an want a hybrid, dynamically-typed language with syntax that is close to Java's, [http://groovy.codehaus.org/ Groovy] is your best bet.&lt;br /&gt;
&lt;br /&gt;
If you're very interested in performance, Common Lisp may have something to offer you, and there are [http://www.sbcl.org/ several] [http://www.cons.org/cmucl/ performant] [http://clisp.cons.org/ implementations].  If you want to learn more about why hybrid languages are so powerful, Paul Graham's book [http://www.paulgraham.com/onlisp.html On Lisp] explains why.  If you really care about using the power of the JVM and are doing concurrent programming, a very modern lisp called [http://clojure.org Clojure] will be very interesting.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25963</id>
		<title>CSC/ECE 517 Fall 2009/wiki2 6 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25963"/>
		<updated>2009-10-14T05:25:09Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: Added glossary.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Topic=&lt;br /&gt;
&lt;br /&gt;
While Smalltalk and Java were instrumental in bringing object-oriented programming into the mainstream, the 1990s also saw the development of hybrid languages that supported multiple programming paradigms, often combining procedural, object-oriented and functional approaches. Discuss the development and design considerations that went into languages like OCaml, Scala, F# and Fan, and how they build upon an object-oriented foundation to offer languages that offer type safety while maintaining brevity and expressive power.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &lt;br /&gt;
&lt;br /&gt;
There are many ways to classify programming languages: on the basis of static or dynamic typing, type safety, high or low levels of abstraction, and by programming paradigm.&lt;br /&gt;
&lt;br /&gt;
In this article, the focus is on programming paradigms, which can loosely be thought of as defining the atomic units a language offers as building block with which to build programs.  There are three primary paradigms in use today:&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Procedural_programming Procedural]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Object-oriented_programming Object-Oriented]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Declarative_programming Declarative]&lt;br /&gt;
&lt;br /&gt;
Declarative languages span a wide array of programming styles.  For simplicity in this article, we will focus on [http://en.wikipedia.org/wiki/Functional_programming functional] languages, which are an important subset of declarative languages.&lt;br /&gt;
&lt;br /&gt;
Many languages provide only one of the paradigms to their users.  [http://www.engin.umd.umich.edu/CIS/course.des/cis400/fortran/fortran.html FORTRAN], [http://www.engin.umd.umich.edu/CIS/course.des/cis400/cobol/cobol.html COBOL], [http://en.wikipedia.org/wiki/Pascal_%28programming_language%29 Pascal], [http://cm.bell-labs.com/cm/cs/who/dmr/chist.html C] and [http://en.wikipedia.org/wiki/BASIC BASIC] are all procedural, [http://www.engin.umd.umich.edu/CIS/course.des/cis400/simula/simula.html Simula], [http://www.smalltalk.org/main/ Smalltalk]] and [http://www.eiffel.com/developers/design_by_contract.html Eiffel] are object-oriented and [http://haskell.org/ Haskell] and [http://en.wikipedia.org/wiki/ML_%28programming_language%29 ML] are functional.  These languages provide a single paradigm for programming, which limits programmers to the particular set of constructs available in that model.&lt;br /&gt;
&lt;br /&gt;
The three paradigms evolved somewhat independently and offer unique constructs with which to solve programming problems.  Some languages are multi-paradigm, however, and allow a programmer to use the tools  most fitting for the problem at hand, sometimes mixing and matching freely within a single program.  The original language of this type is Lisp, which dates back to the mid-1950s.  In the last 20 years, many other hybrid languages have emerged, often derivatives of existing languages.  C++ is derived from C, and offers both procedural and object-oriented approaches.  [http://java.sun.com Java], one of the most widely used languages today, offers both procedural and object-oriented paradigms as well.  [http://caml.inria.fr/ OCaml] is derived from ML, and offers functional and object-oriented styles.  There are many others that have become popular in recent years, like [http://python.org Python] and [http://www.ruby-lang.org/en/ Ruby].&lt;br /&gt;
&lt;br /&gt;
In this article, our goal is to examine what these hybrid languages offer above and beyond strictly object-oriented languages.  In particular, we will examine the features of object-oriented languages and functional languages, and how they have been blended in a modern hybrid language called [http://scala-lang.org Scala].&lt;br /&gt;
&lt;br /&gt;
=Features of Object Oriented Languages=&lt;br /&gt;
The key construct provided by object-oriented languages is the ''object'', which bundles the data and behavior together into a cohesive unit.&lt;br /&gt;
&lt;br /&gt;
==Encapsulation==&lt;br /&gt;
Encapsulation is the technique of rolling behavior and data into an object that exhibits (and is handled in terms of) a particular behavior, rather than a particular composition.  This technique allows the internals of an object to remain hidden from external entities, which in turn enables the object to modify its implementation over time while providing the same external behaviors.&lt;br /&gt;
&lt;br /&gt;
For example, encapsulation would allow a class to add logging functionality without affecting other classes' collaboration with it.  Any feature that is solely an implementation concern (speeding up a sorting algorithm, checking inputs for invalid data, changing the way resource errors are handled, etc.) can be evolved and modified over time within the object without breaking functionality elsewhere in the program that relies on the object in question.&lt;br /&gt;
&lt;br /&gt;
==Dependency Inversion==&lt;br /&gt;
&lt;br /&gt;
One of the major benefits of focusing on the ''behavior'' of objects rather than their ''implementation'' is that the behavior aspects can be well defined and captured in an interface.  This allows code that once would rely on an unstable implementation to instead shift its dependency onto a stable interface, and have the implementation then implement the interface.  This process is known as ''dependency inversion'', because of the way in which it alter the dependency structure of the code.&lt;br /&gt;
&lt;br /&gt;
For example, let us say we have a web server that makes use of a logging facility to log information to disk.  In this case, the web server depends on the logging facility:&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger.png]]&lt;br /&gt;
&lt;br /&gt;
Later, it becomes apparent that the web server also want to be able to log to other destinations.  To facilitate this, we introduce a ''Logger'' interface, and make have the web server depend on that, so as to insulate it from new types of loggers that may be introduced.  This allows us to modify both the server and the loggers in isolation, having them both depend on the interface rather than each other, essentially reversing, or ''inverting'' the dependency diagram.&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger-invert.png]]&lt;br /&gt;
&lt;br /&gt;
In this diagram, the behavior of the logger is well-defined and stable, and is captured in the interface represented by the yellow box.  The blue boxes are classes that are implementations, and are insulated from one another by the interface, allowing them to vary independently without breaking the program as a whole.  This is an example of the robustness that the object-oriented approach lends to a program through use of encapsulation.&lt;br /&gt;
&lt;br /&gt;
==Polymorphism and Dynamic Dispatch==&lt;br /&gt;
                                 &lt;br /&gt;
The object-oriented approach of thinking in terms of behavior lends itself to have multiple implementations of a single behavior.  We can see this is the case of the logger above. To the web server, a logger is simply an object with which logs can be stored.  There are many possible implementations; we could use the file logger or the network logger as seen above, but we could also implement a console logger or a database logger.  Essentially, this means that the web server could call a method to log information without any knowledge of exactly what kind of object it was calling.  The raises the question of how (and when) a programming language decides which log method to call.  Is it compiled in, or is it determined at runtime?&lt;br /&gt;
&lt;br /&gt;
The answer is that it is determined at runtime.  This type of ''late binding'' allows a program to remain flexible even after it is deployed, permitting end-users to determine what kind of logging functionality they want be passing in various implementations of the logger interface when the web server is run, even implementations that were written ''after'' the web server was written and deployed!  This kind of flexibility is a result of ''polymorphism'', which simply means that the an interface (like the logger interface in our example) can have ''many forms'', or implementations.  The way the language determines which one to invoke is through ''dynamic dispatch'', which is essentially a lookup table maintained as the program runs that maps calls to methods like logging to the implementations specified.&lt;br /&gt;
&lt;br /&gt;
The major theme here is that the object-oriented approach of favoring encapsulation has many effects that ripple throughout the design process, almost all of which allow programmers to reduce the brittleness of their software by delaying commitment to particular implementations.&lt;br /&gt;
&lt;br /&gt;
=Features of Functional Languages=&lt;br /&gt;
&lt;br /&gt;
Much like object-oriented languages, functional languages offer a dominant paradigm that has far-reaching consequences in software design.  For object-oriented languages, that element is encapsulation, and for functional languages, it is that functions are first-class entities, which simply means that functions are treated just like any other value in the language.  This allows them to be passed as parameters, delayed, composed, invoked, and returned from other functions.  But what is a function?&lt;br /&gt;
&lt;br /&gt;
A function's most notable trait is that it is free of ''side-effects'', or state changes to the program that occur as a result of its execution.  We could say a lot about side effects, but the general rule is that a function will always return the same value given the same input.  This means that functions are ''stateless''.  Therefore, entities like random number generators and loggers are not functional, because they either store state or have some effect that is not related to the value they return.  Another way to think of functions is that they are completely defined in terms of their input and output.&lt;br /&gt;
&lt;br /&gt;
From this simple feature flows many characteristic language features.  We will discuss them in turn.&lt;br /&gt;
&lt;br /&gt;
==Immutability==&lt;br /&gt;
Maybe the most noticeable feature (or restriction) to programmers of languages that are not functional, [http://en.wikipedia.org/wiki/Immutable_object immutability] is one of the hallmarks of a functional language.  Most non-functional languages allow ''assignment'', or the ability to assign new values to variables as the program runs.  In functional programming, a value is declared only once and then never changes.  This feature of of the language flows out of the notion that functions have no side-effects, and is often viewed as more of a restriction than a feature.&lt;br /&gt;
&lt;br /&gt;
The power of immutability comes from the fact that programs that fully utilize immutability are much simpler than those that do not, making them amenable to automated analysis by a computer.  Computers can then prove various properties about function programs, like concurrent behavior (presence or absence of deadlock/livelock), memory usage, and what within what bounds various values in the program will lie.&lt;br /&gt;
&lt;br /&gt;
==Higher Order Functions==&lt;br /&gt;
&lt;br /&gt;
Higher order functions are simply functions that accept or return other functions as values.  This is made possible because functions are treated as first-class entities, and allows very expressive implementations of many algorithms to be written.&lt;br /&gt;
&lt;br /&gt;
There are several hallmark higher order functions: map, reduce, fold left/right and filter are a few examples.  Going into the intricacies of each is beyond the scope of this article, but Abelson and Sussman's seminal [http://mitpress.mit.edu/sicp/ Structure and Interpretation of Computer Programs] has an [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.1 excellent treatment] of the subject.&lt;br /&gt;
&lt;br /&gt;
==Recursion==&lt;br /&gt;
&lt;br /&gt;
Programmers that are new to functional programming often balk at the notion that values cannot change over time (as variables do in imperative languages).  If values cannot change, how can we execute loops?&lt;br /&gt;
&lt;br /&gt;
The answer lies in recursion, where values are immutable, and loops are implemented as successive calls to the current function with new arguments.  The avoids the complexity of having values change over time while offering all the power of the loops we often see in imperative languages (for...each, do...while, etc.)  Again, a deep treatment of these language features is beyond the scope of this article, but again, Abelson and Sussman have [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.1 addressed] the topic at some length in their book.&lt;br /&gt;
&lt;br /&gt;
==Delayed (Lazy) Evaluation==&lt;br /&gt;
An extremely powerful feature of functional programming that is enabled by immutability is ''lazy evaluation''.  This simply means that expressions can be defined, even recursively, and are not computed until the values that would result from that computation are needed.  This is possible because values in functional programs don't change over time, which means expressions can be evaluated at any point in time as needed.&lt;br /&gt;
&lt;br /&gt;
Take an imperative expression like this (in Java):&lt;br /&gt;
&lt;br /&gt;
  int i = 4;&lt;br /&gt;
  int j = i + 3;&lt;br /&gt;
  i++;&lt;br /&gt;
&lt;br /&gt;
If you evaluate these expressions in order, j will be equal to 7, but if you were to delay the evaluation of j until after the third line, j would be equal to 8.  This is a very simple example of how variables that change over time require expressions be evaluated in a particular order to maintain the correctness of the program.  Functional programming explicitly disallows the third line, and therefore enables the value of j to be calculated only when it is needed.  The implications of this are significant, as we'll see in the next section.&lt;br /&gt;
&lt;br /&gt;
=Hybrid Object-Oriented/Functional Languages=&lt;br /&gt;
&lt;br /&gt;
To programmers of languages like SmallTalk, Simula and Java, many of the features provided in functional languages will seem foreign or strange.  But, as discussed, there are significant advantages to the functional approach for certain types of programs.  While the object-oriented paradigm has proven itself to be very useful, many modern languages have sought to integrate functional features as well to increase the expressiveness and power of the language.  One such language is Scala, which, like Java, runs on the Java Virtual Machine (JVM), and is thus shares Java's libraries and portability while offering many [http://www.ibm.com/developerworks/java/library/j-scala01228.html functional features] that are not available in object-oriented languages like Java.  In the [http://www.scala-lang.org/node/25 overview] of Scala available on its homepage, Scala is briefly described:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
[Scala] smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application.&amp;quot;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
How does Scala allow code sizes to be reduced so much?  It uses sophisticated type inferencing to reduce type signature redundancy, allows for functional programming constructs to be used, and provides syntax for oft-used programming idioms.  Essentially, it takes the lessons learned from decades of functional and object-oriented programming experience and rolls them into a modern hybrid language that can make full use legacy Java code.&lt;br /&gt;
&lt;br /&gt;
Scala is representative of an entire class of hybrid object/functional languages like OCaml, F# and Fan, and therefore makes a good language for use in the examples in this article.  The intent is not to present highly technical examples, but rather to give readers an impression of how hybrid languages increase expressive power over their single-paradigm counterparts.&lt;br /&gt;
&lt;br /&gt;
==Case Classes==&lt;br /&gt;
Idiomatic object-oriented programming involves encapsulation of data, as previously discussed.  In older object-oriented languages, this required defining internal data values, and then providing necessary get and set methods to access and/or modify those values. Here is an example a class in Java that provides only get methods for some (immutable) values it holds.  It includes all the methods that ''should'' be included in such a class, including a toString, equals and hashCode method.  Note that is an error if such methods are ''not'' included in structural Java classes, which is why I include them here.&lt;br /&gt;
&lt;br /&gt;
  public class UserData {&lt;br /&gt;
      private final String firstName;&lt;br /&gt;
      private final String lastName;&lt;br /&gt;
      private final Integer age;&lt;br /&gt;
      public UserData(String firstName, String lastName, Integer age) {&lt;br /&gt;
          this.firstName = firstName;&lt;br /&gt;
          this.lastName = lastName;&lt;br /&gt;
          this.age = age;&lt;br /&gt;
      }&lt;br /&gt;
      public String getFirstName() {&lt;br /&gt;
          return this.firstName;&lt;br /&gt;
      }&lt;br /&gt;
      public String getLastName() {&lt;br /&gt;
          return this.lastName;&lt;br /&gt;
      }&lt;br /&gt;
      public Integer getAge() {&lt;br /&gt;
          return this.age;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public boolean equals(Object obj) {&lt;br /&gt;
          if (obj == null) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (getClass() != obj.getClass()) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          final UserData other = (UserData) obj;&lt;br /&gt;
          if ((this.firstName == null) ? (other.firstName != null) : !this.firstName.equals(other.firstName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if ((this.lastName == null) ? (other.lastName != null) : !this.lastName.equals(other.lastName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.age != other.age &amp;amp;&amp;amp; (this.age == null || !this.age.equals(other.age))) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          return true;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public int hashCode() {&lt;br /&gt;
          int hash = 7;&lt;br /&gt;
          hash = 19 * hash + (this.firstName != null ? this.firstName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.lastName != null ? this.lastName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.age != null ? this.age.hashCode() : 0);&lt;br /&gt;
          return hash;&lt;br /&gt;
      }&lt;br /&gt;
      public String toString() {&lt;br /&gt;
          StringBuilder sb = new StringBuilder();&lt;br /&gt;
          sb.append(&amp;quot;UserData[firstName: &amp;quot;);&lt;br /&gt;
          sb.append(this.firstName);&lt;br /&gt;
          sb.append(&amp;quot; lastName: &amp;quot;);&lt;br /&gt;
          sb.append(this.lastName);&lt;br /&gt;
          sb.append(&amp;quot; age: &amp;quot;);&lt;br /&gt;
          sb.append(this.age);&lt;br /&gt;
          sb.append(&amp;quot;]&amp;quot;);&lt;br /&gt;
          return sb.toString();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, ''all'' the functionality of the above class can be expressed with:&lt;br /&gt;
&lt;br /&gt;
  case class UserData(val firstName: String, val lastName: String, val age: Int)&lt;br /&gt;
&lt;br /&gt;
To reiterate, the version in Scala actually does include a constructor, accessor methods, three fields that can only be set once, equals and hashCode  methods (comparing the structural equality of the two instances of the class), as well a meaningful toString method which prints the fields.&lt;br /&gt;
&lt;br /&gt;
There are numerous other benefits in using case classes, including automatic destructuring in pattern matching.  We will discuss these features in the next section.&lt;br /&gt;
&lt;br /&gt;
This feature by itself vastly reduces both development and maintenance burden for developers.  Classes in Scala are defined in lines, rather than entire files.  All the potential errors that could creep into that code are removed, and the ''intent'' of the developer is very clear.&lt;br /&gt;
&lt;br /&gt;
==Destructuring Binds and Pattern Matching==&lt;br /&gt;
Lisp, one of the earliest hybrid languages, offered primarily functional features with object-orientation built on top (in a system called CLOS).  One piece of functionality written with Common Lisp's metaprogramming facility was the ability to execute [http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_destructuring-bind.html destructuring binds], which are a powerful way of checking for a particular type ([http://en.wikipedia.org/wiki/Pattern_matching pattern matching]) and simultaneously extracting values from the inside of that type to use them in some computation. In the spirit of Common Lisp, Scala also offers destructuring binds and pattern matching.  Let's take a look at what they can do for us.&lt;br /&gt;
&lt;br /&gt;
Let us suppose we want to make use of our UserData class, defined above.  We want to find all users with ages over 18 and store their names in a database.  If we were to write a method that would simply do the database store for a single user, it might look like this:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      Integer age = user.getAge();&lt;br /&gt;
      if (age &amp;gt; 18) {&lt;br /&gt;
          recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, this would be a trivial pattern match, with a destructuring bind to capture the fields inside the UserData (in this case, we bind them to f, l and a):&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In this case, we don't get an enourmous savings in terms of the number of lines of code used, but we gain tremendously in expressive power.  Let's say we wanted to do the same thing, but not include users named &amp;quot;Bob&amp;quot;.  In Java:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      String firstName = user.getFirstName();&lt;br /&gt;
      if (firstName != &amp;quot;Bob&amp;quot;) {&lt;br /&gt;
          Integer age = user.getAge();&lt;br /&gt;
          if (age &amp;gt; 18) {&lt;br /&gt;
              recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
And now in Scala:&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 &amp;amp;&amp;amp; f != &amp;quot;Bob&amp;quot; =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Hopefully this provides a little bit of insight into how destructuring can improve the expressiveness of your code.  A more in depth discussion on pattern matching and binding can be be found in [http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-4 Part 4] of Code Commit's series &amp;quot;Scala For Java Refugees&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==List Comprehension==&lt;br /&gt;
In imperative languages (including both procedural and object-oriented languages), it is common to loop very often, either with a for loop or a while loop.  Hybrid languages allow for this, and also incorporate more abstract operations on structures seen in functional programming.&lt;br /&gt;
&lt;br /&gt;
For example, suppose we wanted to take in a structure containing a bunch of UserData objects, and return a list of strings, containing the last name, a comma, and then the first name of each user.&lt;br /&gt;
&lt;br /&gt;
In Java, this might look like this:&lt;br /&gt;
&lt;br /&gt;
  public ArrayList&amp;lt;String&amp;gt; toStrings(ArrayList&amp;lt;UserData&amp;gt; users) {&lt;br /&gt;
      ArrayList&amp;lt;String&amp;gt; returnedList = new ArrayList&amp;lt;String&amp;gt;();&lt;br /&gt;
      for (UserData u : users) {&lt;br /&gt;
          returnedList.add(u.getLastName() + &amp;quot;, &amp;quot; + u.firstName);&lt;br /&gt;
      }&lt;br /&gt;
      return returnedList;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In the seven lines of code, only the method declaration and the add to the new list really have anything to do with the business logic.  In Scala, that boiler plate can be avoided:&lt;br /&gt;
&lt;br /&gt;
  def toStrings(users: List[UserData]) = users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This method definition is so short that it is arguable we shouldn't even define the method, and should simply use the map operation inline:&lt;br /&gt;
&lt;br /&gt;
  users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This is a small demonstration of how functional languages and object-oriented languages an combine their strengths.  We retain all the encapsulation of the object-oriented approach (although u.lastName and u.firstName appear to be fields, they are in fact accessor methods), but we also have the power of higher abstraction levels from the functional world (in this case, the map operation).&lt;br /&gt;
&lt;br /&gt;
==Lazy Evaluation==&lt;br /&gt;
The final feature I'd like to touch upon is lazy evaluation.  One of the many implications of lazy evaluation is that we can now program using infinite data structures; we define a way in which deeper parts of the data structure are calculated from the existing parts, and only lazily evaluate parts of the structure as they are accessed.  This allows us to express algorithms quite concisely.  This can be used in a variety of cases like random number generation, methods of successive approximation (like Newton's Method), fractal calculations, and generation of infinite series, as seen in the numerical methods or, more simply, the Fibonacci sequence.  Because it is so well known, I will use the Fibonacci sequence as an example here.  First, in Java:&lt;br /&gt;
&lt;br /&gt;
   public long fib(int k) {&lt;br /&gt;
       if (k &amp;lt;= 2) {&lt;br /&gt;
           return 1;&lt;br /&gt;
       } else {&lt;br /&gt;
           return fib(k-1) + fib(k-2);&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This is a short, inefficient, recursive solution.  It doesn't cache answers, either in a single call or across calls, which means it performs a huge amount of redundant computation.  So it has a number of problems, but it is concise.&lt;br /&gt;
&lt;br /&gt;
In Scala, we can remedy all those problems and remain concise using a [http://www.scala-lang.org/docu/files/api/scala/Stream.html Stream], a lazily evaluated form of a List:&lt;br /&gt;
&lt;br /&gt;
  val fibs: Stream[Int] = Stream(0,1) append fibs.zip(fibs.drop(1)).map(x =&amp;gt; x._1 + x._2)&lt;br /&gt;
&lt;br /&gt;
This definition is concise, offers automatic memoization and is thread-safe.  To add those features to the Java code would require 20 lines of additional code at a minimum.  It returns a Stream that can be queried for the kth Fibonacci number in the same way as the fib method defined in Java could, but calculates the 92rd Fibonacci in a fraction of a second.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
Unfortunately, this article barely scratches the surface of the topic.  There are decades of research and experience that have gone into modern programming languages, and the way in which they blend various programming paradigms blurs what were once quite distinct borders in the landscape of programming languages.  But, that blurring has allowed these modern languages to offer programmers a bigger set of tools that aren't merely an amalgamation of features from every language, but a carefully crafted blend of features that enhance the expressiveness of these languages while not substantially increasing the syntax or API surface area.&lt;br /&gt;
&lt;br /&gt;
=Glossary=&lt;br /&gt;
&lt;br /&gt;
; Dynamic Dispatch&lt;br /&gt;
: The ability of a language to determine at runtime which implementation of a method should be executed.  In object-oriented languages, this is usually on the basis of the object's class.&lt;br /&gt;
&lt;br /&gt;
; Encapsulation&lt;br /&gt;
: The technique of enclosing the data and behavior of an object that are artifacts of its implementation, exposing only behaviors (and data) needed to satisfy its external contract.&lt;br /&gt;
&lt;br /&gt;
; Immutability&lt;br /&gt;
: The property of an object that disallows the object from being changed after it is constructed.  Immutability is often desireable in applications where the object will be used in highly parallel environments (e.g. many threads, over a network, etc.)&lt;br /&gt;
&lt;br /&gt;
; Polymorphism&lt;br /&gt;
: Literally, &amp;quot;many forms&amp;quot;; the technique of using multiple implementations of the same contract (or interface) to enable compenents of a piece of software to be interchanged easily.&lt;br /&gt;
&lt;br /&gt;
; Recursion&lt;br /&gt;
: A methodology for defining an algorithm or data structure in terms of itself.  Often involves a direct self-referential call with a regressing value that is checked before the recursive call is performed, thus terminating the recursion.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
If you want to know more about hybrid languages, its best to choose one (or a few!) and read about what they offer.  If you're familiar with Java, or C#, take a look at the [http://www.scala-lang.org/node/104 tour of Scala] or perhaps some of the [http://www.fandev.org/doc/docIntro/StartHere.html features of Fan].  &lt;br /&gt;
&lt;br /&gt;
There are also a few major dynamically typed hybrid languages.  Chief among these is [http://python.org Python], which has several implementations in [http://python.org C], [http://jython.org/ Java] and [http://codespeak.net/pypy/dist/pypy/doc/ Python](!).  [http://ruby-lang.org Ruby] is also a newer hybrid language, originating in Japan, but was made famous worldwide because of its [http://rubyonrails.org/ Rails] web programming framework that was possible in large part due to its hybrid nature.  It also has a [http://jruby.org/ Java implementation].  Finally, if you're working on the JVM an want a hybrid, dynamically-typed language with syntax that is close to Java's, [http://groovy.codehaus.org/ Groovy] is your best bet.&lt;br /&gt;
&lt;br /&gt;
If you're very interested in performance, Common Lisp may have something to offer you, and there are [http://www.sbcl.org/ several] [http://www.cons.org/cmucl/ performant] [http://clisp.cons.org/ implementations].  If you want to learn more about why hybrid languages are so powerful, Paul Graham's book [http://www.paulgraham.com/onlisp.html On Lisp] explains why.  If you really care about using the power of the JVM and are doing concurrent programming, a very modern lisp called [http://clojure.org Clojure] will be very interesting.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25638</id>
		<title>CSC/ECE 517 Fall 2009/wiki2 6 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25638"/>
		<updated>2009-10-12T06:55:59Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Author's Note=&lt;br /&gt;
Apologies.  This has been here since 9 October, but I was editing under the wrong account.  I made a change with the correct account, but it was a whitespace change that apparently didn't stick in a way that Expertiza picked up.  I have just gone in and made a non-whitespace change, and things seem to be working now.  I'm very sorry for taking so long to get this to appear.&lt;br /&gt;
&lt;br /&gt;
=Topic=&lt;br /&gt;
&lt;br /&gt;
While Smalltalk and Java were instrumental in bringing object-oriented programming into the mainstream, the 1990s also saw the development of hybrid languages that supported multiple programming paradigms, often combining procedural, object-oriented and functional approaches. Discuss the development and design considerations that went into languages like OCaml, Scala, F# and Fan, and how they build upon an object-oriented foundation to offer languages that offer type safety while maintaining brevity and expressive power.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &lt;br /&gt;
&lt;br /&gt;
There are many ways to classify programming languages: on the basis of static or dynamic typing, type safety, high or low levels of abstraction, and by programming paradigm.&lt;br /&gt;
&lt;br /&gt;
In this article, the focus is on programming paradigms, which can loosely be thought of as defining the atomic units a language offers as building block with which to build programs.  There are three primary paradigms in use today:&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Procedural_programming Procedural]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Object-oriented_programming Object-Oriented]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Declarative_programming Declarative]&lt;br /&gt;
&lt;br /&gt;
Declarative languages span a wide array of programming styles.  For simplicity in this article, we will focus on [http://en.wikipedia.org/wiki/Functional_programming functional] languages, which are an important subset of declarative languages.&lt;br /&gt;
&lt;br /&gt;
Many languages provide only one of the paradigms to their users.  [http://www.engin.umd.umich.edu/CIS/course.des/cis400/fortran/fortran.html FORTRAN], [http://www.engin.umd.umich.edu/CIS/course.des/cis400/cobol/cobol.html COBOL], [http://en.wikipedia.org/wiki/Pascal_%28programming_language%29 Pascal], [http://cm.bell-labs.com/cm/cs/who/dmr/chist.html C] and [http://en.wikipedia.org/wiki/BASIC BASIC] are all procedural, [http://www.engin.umd.umich.edu/CIS/course.des/cis400/simula/simula.html Simula], [http://www.smalltalk.org/main/ Smalltalk]] and [http://www.eiffel.com/developers/design_by_contract.html Eiffel] are object-oriented and [http://haskell.org/ Haskell] and [http://en.wikipedia.org/wiki/ML_%28programming_language%29 ML] are functional.  These languages provide a single paradigm for programming, which limits programmers to the particular set of constructs available in that model.&lt;br /&gt;
&lt;br /&gt;
The three paradigms evolved somewhat independently and offer unique constructs with which to solve programming problems.  Some languages are multi-paradigm, however, and allow a programmer to use the tools  most fitting for the problem at hand, sometimes mixing and matching freely within a single program.  The original language of this type is Lisp, which dates back to the mid-1950s.  In the last 20 years, many other hybrid languages have emerged, often derivatives of existing languages.  C++ is derived from C, and offers both procedural and object-oriented approaches.  [http://java.sun.com Java], one of the most widely used languages today, offers both procedural and object-oriented paradigms as well.  [http://caml.inria.fr/ OCaml] is derived from ML, and offers functional and object-oriented styles.  There are many others that have become popular in recent years, like [http://python.org Python] and [http://www.ruby-lang.org/en/ Ruby].&lt;br /&gt;
&lt;br /&gt;
In this article, our goal is to examine what these hybrid languages offer above and beyond strictly object-oriented languages.  In particular, we will examine the features of object-oriented languages and functional languages, and how they have been blended in a modern hybrid language called [http://scala-lang.org Scala].&lt;br /&gt;
&lt;br /&gt;
=Features of Object Oriented Languages=&lt;br /&gt;
The key construct provided by object-oriented languages is the ''object'', which bundles the data and behavior together into a cohesive unit.&lt;br /&gt;
&lt;br /&gt;
==Encapsulation==&lt;br /&gt;
Encapsulation is the technique of rolling behavior and data into an object that exhibits (and is handled in terms of) a particular behavior, rather than a particular composition.  This technique allows the internals of an object to remain hidden from external entities, which in turn enables the object to modify its implementation over time while providing the same external behaviors.&lt;br /&gt;
&lt;br /&gt;
For example, encapsulation would allow a class to add logging functionality without affecting other classes' collaboration with it.  Any feature that is solely an implementation concern (speeding up a sorting algorithm, checking inputs for invalid data, changing the way resource errors are handled, etc.) can be evolved and modified over time within the object without breaking functionality elsewhere in the program that relies on the object in question.&lt;br /&gt;
&lt;br /&gt;
==Dependency Inversion==&lt;br /&gt;
&lt;br /&gt;
One of the major benefits of focusing on the ''behavior'' of objects rather than their ''implementation'' is that the behavior aspects can be well defined and captured in an interface.  This allows code that once would rely on an unstable implementation to instead shift its dependency onto a stable interface, and have the implementation then implement the interface.  This process is known as ''dependency inversion'', because of the way in which it alter the dependency structure of the code.&lt;br /&gt;
&lt;br /&gt;
For example, let us say we have a web server that makes use of a logging facility to log information to disk.  In this case, the web server depends on the logging facility:&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger.png]]&lt;br /&gt;
&lt;br /&gt;
Later, it becomes apparent that the web server also want to be able to log to other destinations.  To facilitate this, we introduce a ''Logger'' interface, and make have the web server depend on that, so as to insulate it from new types of loggers that may be introduced.  This allows us to modify both the server and the loggers in isolation, having them both depend on the interface rather than each other, essentially reversing, or ''inverting'' the dependency diagram.&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger-invert.png]]&lt;br /&gt;
&lt;br /&gt;
In this diagram, the behavior of the logger is well-defined and stable, and is captured in the interface represented by the yellow box.  The blue boxes are classes that are implementations, and are insulated from one another by the interface, allowing them to vary independently without breaking the program as a whole.  This is an example of the robustness that the object-oriented approach lends to a program through use of encapsulation.&lt;br /&gt;
&lt;br /&gt;
==Polymorphism and Dynamic Dispatch==&lt;br /&gt;
                                 &lt;br /&gt;
The object-oriented approach of thinking in terms of behavior lends itself to have multiple implementations of a single behavior.  We can see this is the case of the logger above. To the web server, a logger is simply an object with which logs can be stored.  There are many possible implementations; we could use the file logger or the network logger as seen above, but we could also implement a console logger or a database logger.  Essentially, this means that the web server could call a method to log information without any knowledge of exactly what kind of object it was calling.  The raises the question of how (and when) a programming language decides which log method to call.  Is it compiled in, or is it determined at runtime?&lt;br /&gt;
&lt;br /&gt;
The answer is that it is determined at runtime.  This type of ''late binding'' allows a program to remain flexible even after it is deployed, permitting end-users to determine what kind of logging functionality they want be passing in various implementations of the logger interface when the web server is run, even implementations that were written ''after'' the web server was written and deployed!  This kind of flexibility is a result of ''polymorphism'', which simply means that the an interface (like the logger interface in our example) can have ''many forms'', or implementations.  The way the language determines which one to invoke is through ''dynamic dispatch'', which is essentially a lookup table maintained as the program runs that maps calls to methods like logging to the implementations specified.&lt;br /&gt;
&lt;br /&gt;
The major theme here is that the object-oriented approach of favoring encapsulation has many effects that ripple throughout the design process, almost all of which allow programmers to reduce the brittleness of their software by delaying commitment to particular implementations.&lt;br /&gt;
&lt;br /&gt;
=Features of Functional Languages=&lt;br /&gt;
&lt;br /&gt;
Much like object-oriented languages, functional languages offer a dominant paradigm that has far-reaching consequences in software design.  For object-oriented languages, that element is encapsulation, and for functional languages, it is that functions are first-class entities, which simply means that functions are treated just like any other value in the language.  This allows them to be passed as parameters, delayed, composed, invoked, and returned from other functions.  But what is a function?&lt;br /&gt;
&lt;br /&gt;
A function's most notable trait is that it is free of ''side-effects'', or state changes to the program that occur as a result of its execution.  We could say a lot about side effects, but the general rule is that a function will always return the same value given the same input.  This means that functions are ''stateless''.  Therefore, entities like random number generators and loggers are not functional, because they either store state or have some effect that is not related to the value they return.  Another way to think of functions is that they are completely defined in terms of their input and output.&lt;br /&gt;
&lt;br /&gt;
From this simple feature flows many characteristic language features.  We will discuss them in turn.&lt;br /&gt;
&lt;br /&gt;
==Immutability==&lt;br /&gt;
Maybe the most noticeable feature (or restriction) to programmers of languages that are not functional, [http://en.wikipedia.org/wiki/Immutable_object immutability] is one of the hallmarks of a functional language.  Most non-functional languages allow ''assignment'', or the ability to assign new values to variables as the program runs.  In functional programming, a value is declared only once and then never changes.  This feature of of the language flows out of the notion that functions have no side-effects, and is often viewed as more of a restriction than a feature.&lt;br /&gt;
&lt;br /&gt;
The power of immutability comes from the fact that programs that fully utilize immutability are much simpler than those that do not, making them amenable to automated analysis by a computer.  Computers can then prove various properties about function programs, like concurrent behavior (presence or absence of deadlock/livelock), memory usage, and what within what bounds various values in the program will lie.&lt;br /&gt;
&lt;br /&gt;
==Higher Order Functions==&lt;br /&gt;
&lt;br /&gt;
Higher order functions are simply functions that accept or return other functions as values.  This is made possible because functions are treated as first-class entities, and allows very expressive implementations of many algorithms to be written.&lt;br /&gt;
&lt;br /&gt;
There are several hallmark higher order functions: map, reduce, fold left/right and filter are a few examples.  Going into the intricacies of each is beyond the scope of this article, but Abelson and Sussman's seminal [http://mitpress.mit.edu/sicp/ Structure and Interpretation of Computer Programs] has an [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.1 excellent treatment] of the subject.&lt;br /&gt;
&lt;br /&gt;
==Recursion==&lt;br /&gt;
&lt;br /&gt;
Programmers that are new to functional programming often balk at the notion that values cannot change over time (as variables do in imperative languages).  If values cannot change, how can we execute loops?&lt;br /&gt;
&lt;br /&gt;
The answer lies in recursion, where values are immutable, and loops are implemented as successive calls to the current function with new arguments.  The avoids the complexity of having values change over time while offering all the power of the loops we often see in imperative languages (for...each, do...while, etc.)  Again, a deep treatment of these language features is beyond the scope of this article, but again, Abelson and Sussman have [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.1 addressed] the topic at some length in their book.&lt;br /&gt;
&lt;br /&gt;
==Delayed (Lazy) Evaluation==&lt;br /&gt;
An extremely powerful feature of functional programming that is enabled by immutability is ''lazy evaluation''.  This simply means that expressions can be defined, even recursively, and are not computed until the values that would result from that computation are needed.  This is possible because values in functional programs don't change over time, which means expressions can be evaluated at any point in time as needed.&lt;br /&gt;
&lt;br /&gt;
Take an imperative expression like this (in Java):&lt;br /&gt;
&lt;br /&gt;
  int i = 4;&lt;br /&gt;
  int j = i + 3;&lt;br /&gt;
  i++;&lt;br /&gt;
&lt;br /&gt;
If you evaluate these expressions in order, j will be equal to 7, but if you were to delay the evaluation of j until after the third line, j would be equal to 8.  This is a very simple example of how variables that change over time require expressions be evaluated in a particular order to maintain the correctness of the program.  Functional programming explicitly disallows the third line, and therefore enables the value of j to be calculated only when it is needed.  The implications of this are significant, as we'll see in the next section.&lt;br /&gt;
&lt;br /&gt;
=Hybrid Object-Oriented/Functional Languages=&lt;br /&gt;
&lt;br /&gt;
To programmers of languages like SmallTalk, Simula and Java, many of the features provided in functional languages will seem foreign or strange.  But, as discussed, there are significant advantages to the functional approach for certain types of programs.  While the object-oriented paradigm has proven itself to be very useful, many modern languages have sought to integrate functional features as well to increase the expressiveness and power of the language.  One such language is Scala, which, like Java, runs on the Java Virtual Machine (JVM), and is thus shares Java's libraries and portability while offering many [http://www.ibm.com/developerworks/java/library/j-scala01228.html functional features] that are not available in object-oriented languages like Java.  In the [http://www.scala-lang.org/node/25 overview] of Scala available on its homepage, Scala is briefly described:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
[Scala] smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application.&amp;quot;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
How does Scala allow code sizes to be reduced so much?  It uses sophisticated type inferencing to reduce type signature redundancy, allows for functional programming constructs to be used, and provides syntax for oft-used programming idioms.  Essentially, it takes the lessons learned from decades of functional and object-oriented programming experience and rolls them into a modern hybrid language that can make full use legacy Java code.&lt;br /&gt;
&lt;br /&gt;
Scala is representative of an entire class of hybrid object/functional languages like OCaml, F# and Fan, and therefore makes a good language for use in the examples in this article.  The intent is not to present highly technical examples, but rather to give readers an impression of how hybrid languages increase expressive power over their single-paradigm counterparts.&lt;br /&gt;
&lt;br /&gt;
==Case Classes==&lt;br /&gt;
Idiomatic object-oriented programming involves encapsulation of data, as previously discussed.  In older object-oriented languages, this required defining internal data values, and then providing necessary get and set methods to access and/or modify those values. Here is an example a class in Java that provides only get methods for some (immutable) values it holds.  It includes all the methods that ''should'' be included in such a class, including a toString, equals and hashCode method.  Note that is an error if such methods are ''not'' included in structural Java classes, which is why I include them here.&lt;br /&gt;
&lt;br /&gt;
  public class UserData {&lt;br /&gt;
      private final String firstName;&lt;br /&gt;
      private final String lastName;&lt;br /&gt;
      private final Integer age;&lt;br /&gt;
      public UserData(String firstName, String lastName, Integer age) {&lt;br /&gt;
          this.firstName = firstName;&lt;br /&gt;
          this.lastName = lastName;&lt;br /&gt;
          this.age = age;&lt;br /&gt;
      }&lt;br /&gt;
      public String getFirstName() {&lt;br /&gt;
          return this.firstName;&lt;br /&gt;
      }&lt;br /&gt;
      public String getLastName() {&lt;br /&gt;
          return this.lastName;&lt;br /&gt;
      }&lt;br /&gt;
      public Integer getAge() {&lt;br /&gt;
          return this.age;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public boolean equals(Object obj) {&lt;br /&gt;
          if (obj == null) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (getClass() != obj.getClass()) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          final UserData other = (UserData) obj;&lt;br /&gt;
          if ((this.firstName == null) ? (other.firstName != null) : !this.firstName.equals(other.firstName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if ((this.lastName == null) ? (other.lastName != null) : !this.lastName.equals(other.lastName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.age != other.age &amp;amp;&amp;amp; (this.age == null || !this.age.equals(other.age))) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          return true;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public int hashCode() {&lt;br /&gt;
          int hash = 7;&lt;br /&gt;
          hash = 19 * hash + (this.firstName != null ? this.firstName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.lastName != null ? this.lastName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.age != null ? this.age.hashCode() : 0);&lt;br /&gt;
          return hash;&lt;br /&gt;
      }&lt;br /&gt;
      public String toString() {&lt;br /&gt;
          StringBuilder sb = new StringBuilder();&lt;br /&gt;
          sb.append(&amp;quot;UserData[firstName: &amp;quot;);&lt;br /&gt;
          sb.append(this.firstName);&lt;br /&gt;
          sb.append(&amp;quot; lastName: &amp;quot;);&lt;br /&gt;
          sb.append(this.lastName);&lt;br /&gt;
          sb.append(&amp;quot; age: &amp;quot;);&lt;br /&gt;
          sb.append(this.age);&lt;br /&gt;
          sb.append(&amp;quot;]&amp;quot;);&lt;br /&gt;
          return sb.toString();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, ''all'' the functionality of the above class can be expressed with:&lt;br /&gt;
&lt;br /&gt;
  case class UserData(val firstName: String, val lastName: String, val age: Int)&lt;br /&gt;
&lt;br /&gt;
To reiterate, the version in Scala actually does include a constructor, accessor methods, three fields that can only be set once, equals and hashCode  methods (comparing the structural equality of the two instances of the class), as well a meaningful toString method which prints the fields.&lt;br /&gt;
&lt;br /&gt;
There are numerous other benefits in using case classes, including automatic destructuring in pattern matching.  We will discuss these features in the next section.&lt;br /&gt;
&lt;br /&gt;
This feature by itself vastly reduces both development and maintenance burden for developers.  Classes in Scala are defined in lines, rather than entire files.  All the potential errors that could creep into that code are removed, and the ''intent'' of the developer is very clear.&lt;br /&gt;
&lt;br /&gt;
==Destructuring Binds and Pattern Matching==&lt;br /&gt;
Lisp, one of the earliest hybrid languages, offered primarily functional features with object-orientation built on top (in a system called CLOS).  One piece of functionality written with Common Lisp's metaprogramming facility was the ability to execute [http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_destructuring-bind.html destructuring binds], which are a powerful way of checking for a particular type ([http://en.wikipedia.org/wiki/Pattern_matching pattern matching]) and simultaneously extracting values from the inside of that type to use them in some computation. In the spirit of Common Lisp, Scala also offers destructuring binds and pattern matching.  Let's take a look at what they can do for us.&lt;br /&gt;
&lt;br /&gt;
Let us suppose we want to make use of our UserData class, defined above.  We want to find all users with ages over 18 and store their names in a database.  If we were to write a method that would simply do the database store for a single user, it might look like this:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      Integer age = user.getAge();&lt;br /&gt;
      if (age &amp;gt; 18) {&lt;br /&gt;
          recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, this would be a trivial pattern match, with a destructuring bind to capture the fields inside the UserData (in this case, we bind them to f, l and a):&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In this case, we don't get an enourmous savings in terms of the number of lines of code used, but we gain tremendously in expressive power.  Let's say we wanted to do the same thing, but not include users named &amp;quot;Bob&amp;quot;.  In Java:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      String firstName = user.getFirstName();&lt;br /&gt;
      if (firstName != &amp;quot;Bob&amp;quot;) {&lt;br /&gt;
          Integer age = user.getAge();&lt;br /&gt;
          if (age &amp;gt; 18) {&lt;br /&gt;
              recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
And now in Scala:&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 &amp;amp;&amp;amp; f != &amp;quot;Bob&amp;quot; =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Hopefully this provides a little bit of insight into how destructuring can improve the expressiveness of your code.  A more in depth discussion on pattern matching and binding can be be found in [http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-4 Part 4] of Code Commit's series &amp;quot;Scala For Java Refugees&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==List Comprehension==&lt;br /&gt;
In imperative languages (including both procedural and object-oriented languages), it is common to loop very often, either with a for loop or a while loop.  Hybrid languages allow for this, and also incorporate more abstract operations on structures seen in functional programming.&lt;br /&gt;
&lt;br /&gt;
For example, suppose we wanted to take in a structure containing a bunch of UserData objects, and return a list of strings, containing the last name, a comma, and then the first name of each user.&lt;br /&gt;
&lt;br /&gt;
In Java, this might look like this:&lt;br /&gt;
&lt;br /&gt;
  public ArrayList&amp;lt;String&amp;gt; toStrings(ArrayList&amp;lt;UserData&amp;gt; users) {&lt;br /&gt;
      ArrayList&amp;lt;String&amp;gt; returnedList = new ArrayList&amp;lt;String&amp;gt;();&lt;br /&gt;
      for (UserData u : users) {&lt;br /&gt;
          returnedList.add(u.getLastName() + &amp;quot;, &amp;quot; + u.firstName);&lt;br /&gt;
      }&lt;br /&gt;
      return returnedList;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In the seven lines of code, only the method declaration and the add to the new list really have anything to do with the business logic.  In Scala, that boiler plate can be avoided:&lt;br /&gt;
&lt;br /&gt;
  def toStrings(users: List[UserData]) = users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This method definition is so short that it is arguable we shouldn't even define the method, and should simply use the map operation inline:&lt;br /&gt;
&lt;br /&gt;
  users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This is a small demonstration of how functional languages and object-oriented languages an combine their strengths.  We retain all the encapsulation of the object-oriented approach (although u.lastName and u.firstName appear to be fields, they are in fact accessor methods), but we also have the power of higher abstraction levels from the functional world (in this case, the map operation).&lt;br /&gt;
&lt;br /&gt;
==Lazy Evaluation==&lt;br /&gt;
The final feature I'd like to touch upon is lazy evaluation.  One of the many implications of lazy evaluation is that we can now program using infinite data structures; we define a way in which deeper parts of the data structure are calculated from the existing parts, and only lazily evaluate parts of the structure as they are accessed.  This allows us to express algorithms quite concisely.  This can be used in a variety of cases like random number generation, methods of successive approximation (like Newton's Method), fractal calculations, and generation of infinite series, as seen in the numerical methods or, more simply, the Fibonacci sequence.  Because it is so well known, I will use the Fibonacci sequence as an example here.  First, in Java:&lt;br /&gt;
&lt;br /&gt;
   public long fib(int k) {&lt;br /&gt;
       if (k &amp;lt;= 2) {&lt;br /&gt;
           return 1;&lt;br /&gt;
       } else {&lt;br /&gt;
           return fib(k-1) + fib(k-2);&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This is a short, inefficient, recursive solution.  It doesn't cache answers, either in a single call or across calls, which means it performs a huge amount of redundant computation.  So it has a number of problems, but it is concise.&lt;br /&gt;
&lt;br /&gt;
In Scala, we can remedy all those problems and remain concise using a [http://www.scala-lang.org/docu/files/api/scala/Stream.html Stream], a lazily evaluated form of a List:&lt;br /&gt;
&lt;br /&gt;
  val fibs: Stream[Int] = Stream(0,1) append fibs.zip(fibs.drop(1)).map(x =&amp;gt; x._1 + x._2)&lt;br /&gt;
&lt;br /&gt;
This definition is concise, offers automatic memoization and is thread-safe.  To add those features to the Java code would require 20 lines of additional code at a minimum.  It returns a Stream that can be queried for the kth Fibonacci number in the same way as the fib method defined in Java could, but calculates the 92rd Fibonacci in a fraction of a second.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
Unfortunately, this article barely scratches the surface of the topic.  There are decades of research and experience that have gone into modern programming languages, and the way in which they blend various programming paradigms blurs what were once quite distinct borders in the landscape of programming languages.  But, that blurring has allowed these modern languages to offer programmers a bigger set of tools that aren't merely an amalgamation of features from every language, but a carefully crafted blend of features that enhance the expressiveness of these languages while not substantially increasing the syntax or API surface area.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
If you want to know more about hybrid languages, its best to choose one (or a few!) and read about what they offer.  If you're familiar with Java, or C#, take a look at the [http://www.scala-lang.org/node/104 tour of Scala] or perhaps some of the [http://www.fandev.org/doc/docIntro/StartHere.html features of Fan].  &lt;br /&gt;
&lt;br /&gt;
There are also a few major dynamically typed hybrid languages.  Chief among these is [http://python.org Python], which has several implementations in [http://python.org C], [http://jython.org/ Java] and [http://codespeak.net/pypy/dist/pypy/doc/ Python](!).  [http://ruby-lang.org Ruby] is also a newer hybrid language, originating in Japan, but was made famous worldwide because of its [http://rubyonrails.org/ Rails] web programming framework that was possible in large part due to its hybrid nature.  It also has a [http://jruby.org/ Java implementation].  Finally, if you're working on the JVM an want a hybrid, dynamically-typed language with syntax that is close to Java's, [http://groovy.codehaus.org/ Groovy] is your best bet.&lt;br /&gt;
&lt;br /&gt;
If you're very interested in performance, Common Lisp may have something to offer you, and there are [http://www.sbcl.org/ several] [http://www.cons.org/cmucl/ performant] [http://clisp.cons.org/ implementations].  If you want to learn more about why hybrid languages are so powerful, Paul Graham's book [http://www.paulgraham.com/onlisp.html On Lisp] explains why.  If you really care about using the power of the JVM and are doing concurrent programming, a very modern lisp called [http://clojure.org Clojure] will be very interesting.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25637</id>
		<title>CSC/ECE 517 Fall 2009/wiki2 6 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25637"/>
		<updated>2009-10-12T06:55:44Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-Author's Note=&lt;br /&gt;
Apologies.  This has been here since 9 October, but I was editing under the wrong account.  I made a change with the correct account, but it was a whitespace change that apparently didn't stick in a way that Expertiza picked up.  I have just gone in and made a non-whitespace change, and things seem to be working now.  I'm very sorry for taking so long to get this to appear.&lt;br /&gt;
&lt;br /&gt;
=Topic=&lt;br /&gt;
&lt;br /&gt;
While Smalltalk and Java were instrumental in bringing object-oriented programming into the mainstream, the 1990s also saw the development of hybrid languages that supported multiple programming paradigms, often combining procedural, object-oriented and functional approaches. Discuss the development and design considerations that went into languages like OCaml, Scala, F# and Fan, and how they build upon an object-oriented foundation to offer languages that offer type safety while maintaining brevity and expressive power.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &lt;br /&gt;
&lt;br /&gt;
There are many ways to classify programming languages: on the basis of static or dynamic typing, type safety, high or low levels of abstraction, and by programming paradigm.&lt;br /&gt;
&lt;br /&gt;
In this article, the focus is on programming paradigms, which can loosely be thought of as defining the atomic units a language offers as building block with which to build programs.  There are three primary paradigms in use today:&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Procedural_programming Procedural]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Object-oriented_programming Object-Oriented]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Declarative_programming Declarative]&lt;br /&gt;
&lt;br /&gt;
Declarative languages span a wide array of programming styles.  For simplicity in this article, we will focus on [http://en.wikipedia.org/wiki/Functional_programming functional] languages, which are an important subset of declarative languages.&lt;br /&gt;
&lt;br /&gt;
Many languages provide only one of the paradigms to their users.  [http://www.engin.umd.umich.edu/CIS/course.des/cis400/fortran/fortran.html FORTRAN], [http://www.engin.umd.umich.edu/CIS/course.des/cis400/cobol/cobol.html COBOL], [http://en.wikipedia.org/wiki/Pascal_%28programming_language%29 Pascal], [http://cm.bell-labs.com/cm/cs/who/dmr/chist.html C] and [http://en.wikipedia.org/wiki/BASIC BASIC] are all procedural, [http://www.engin.umd.umich.edu/CIS/course.des/cis400/simula/simula.html Simula], [http://www.smalltalk.org/main/ Smalltalk]] and [http://www.eiffel.com/developers/design_by_contract.html Eiffel] are object-oriented and [http://haskell.org/ Haskell] and [http://en.wikipedia.org/wiki/ML_%28programming_language%29 ML] are functional.  These languages provide a single paradigm for programming, which limits programmers to the particular set of constructs available in that model.&lt;br /&gt;
&lt;br /&gt;
The three paradigms evolved somewhat independently and offer unique constructs with which to solve programming problems.  Some languages are multi-paradigm, however, and allow a programmer to use the tools  most fitting for the problem at hand, sometimes mixing and matching freely within a single program.  The original language of this type is Lisp, which dates back to the mid-1950s.  In the last 20 years, many other hybrid languages have emerged, often derivatives of existing languages.  C++ is derived from C, and offers both procedural and object-oriented approaches.  [http://java.sun.com Java], one of the most widely used languages today, offers both procedural and object-oriented paradigms as well.  [http://caml.inria.fr/ OCaml] is derived from ML, and offers functional and object-oriented styles.  There are many others that have become popular in recent years, like [http://python.org Python] and [http://www.ruby-lang.org/en/ Ruby].&lt;br /&gt;
&lt;br /&gt;
In this article, our goal is to examine what these hybrid languages offer above and beyond strictly object-oriented languages.  In particular, we will examine the features of object-oriented languages and functional languages, and how they have been blended in a modern hybrid language called [http://scala-lang.org Scala].&lt;br /&gt;
&lt;br /&gt;
=Features of Object Oriented Languages=&lt;br /&gt;
The key construct provided by object-oriented languages is the ''object'', which bundles the data and behavior together into a cohesive unit.&lt;br /&gt;
&lt;br /&gt;
==Encapsulation==&lt;br /&gt;
Encapsulation is the technique of rolling behavior and data into an object that exhibits (and is handled in terms of) a particular behavior, rather than a particular composition.  This technique allows the internals of an object to remain hidden from external entities, which in turn enables the object to modify its implementation over time while providing the same external behaviors.&lt;br /&gt;
&lt;br /&gt;
For example, encapsulation would allow a class to add logging functionality without affecting other classes' collaboration with it.  Any feature that is solely an implementation concern (speeding up a sorting algorithm, checking inputs for invalid data, changing the way resource errors are handled, etc.) can be evolved and modified over time within the object without breaking functionality elsewhere in the program that relies on the object in question.&lt;br /&gt;
&lt;br /&gt;
==Dependency Inversion==&lt;br /&gt;
&lt;br /&gt;
One of the major benefits of focusing on the ''behavior'' of objects rather than their ''implementation'' is that the behavior aspects can be well defined and captured in an interface.  This allows code that once would rely on an unstable implementation to instead shift its dependency onto a stable interface, and have the implementation then implement the interface.  This process is known as ''dependency inversion'', because of the way in which it alter the dependency structure of the code.&lt;br /&gt;
&lt;br /&gt;
For example, let us say we have a web server that makes use of a logging facility to log information to disk.  In this case, the web server depends on the logging facility:&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger.png]]&lt;br /&gt;
&lt;br /&gt;
Later, it becomes apparent that the web server also want to be able to log to other destinations.  To facilitate this, we introduce a ''Logger'' interface, and make have the web server depend on that, so as to insulate it from new types of loggers that may be introduced.  This allows us to modify both the server and the loggers in isolation, having them both depend on the interface rather than each other, essentially reversing, or ''inverting'' the dependency diagram.&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger-invert.png]]&lt;br /&gt;
&lt;br /&gt;
In this diagram, the behavior of the logger is well-defined and stable, and is captured in the interface represented by the yellow box.  The blue boxes are classes that are implementations, and are insulated from one another by the interface, allowing them to vary independently without breaking the program as a whole.  This is an example of the robustness that the object-oriented approach lends to a program through use of encapsulation.&lt;br /&gt;
&lt;br /&gt;
==Polymorphism and Dynamic Dispatch==&lt;br /&gt;
                                 &lt;br /&gt;
The object-oriented approach of thinking in terms of behavior lends itself to have multiple implementations of a single behavior.  We can see this is the case of the logger above. To the web server, a logger is simply an object with which logs can be stored.  There are many possible implementations; we could use the file logger or the network logger as seen above, but we could also implement a console logger or a database logger.  Essentially, this means that the web server could call a method to log information without any knowledge of exactly what kind of object it was calling.  The raises the question of how (and when) a programming language decides which log method to call.  Is it compiled in, or is it determined at runtime?&lt;br /&gt;
&lt;br /&gt;
The answer is that it is determined at runtime.  This type of ''late binding'' allows a program to remain flexible even after it is deployed, permitting end-users to determine what kind of logging functionality they want be passing in various implementations of the logger interface when the web server is run, even implementations that were written ''after'' the web server was written and deployed!  This kind of flexibility is a result of ''polymorphism'', which simply means that the an interface (like the logger interface in our example) can have ''many forms'', or implementations.  The way the language determines which one to invoke is through ''dynamic dispatch'', which is essentially a lookup table maintained as the program runs that maps calls to methods like logging to the implementations specified.&lt;br /&gt;
&lt;br /&gt;
The major theme here is that the object-oriented approach of favoring encapsulation has many effects that ripple throughout the design process, almost all of which allow programmers to reduce the brittleness of their software by delaying commitment to particular implementations.&lt;br /&gt;
&lt;br /&gt;
=Features of Functional Languages=&lt;br /&gt;
&lt;br /&gt;
Much like object-oriented languages, functional languages offer a dominant paradigm that has far-reaching consequences in software design.  For object-oriented languages, that element is encapsulation, and for functional languages, it is that functions are first-class entities, which simply means that functions are treated just like any other value in the language.  This allows them to be passed as parameters, delayed, composed, invoked, and returned from other functions.  But what is a function?&lt;br /&gt;
&lt;br /&gt;
A function's most notable trait is that it is free of ''side-effects'', or state changes to the program that occur as a result of its execution.  We could say a lot about side effects, but the general rule is that a function will always return the same value given the same input.  This means that functions are ''stateless''.  Therefore, entities like random number generators and loggers are not functional, because they either store state or have some effect that is not related to the value they return.  Another way to think of functions is that they are completely defined in terms of their input and output.&lt;br /&gt;
&lt;br /&gt;
From this simple feature flows many characteristic language features.  We will discuss them in turn.&lt;br /&gt;
&lt;br /&gt;
==Immutability==&lt;br /&gt;
Maybe the most noticeable feature (or restriction) to programmers of languages that are not functional, [http://en.wikipedia.org/wiki/Immutable_object immutability] is one of the hallmarks of a functional language.  Most non-functional languages allow ''assignment'', or the ability to assign new values to variables as the program runs.  In functional programming, a value is declared only once and then never changes.  This feature of of the language flows out of the notion that functions have no side-effects, and is often viewed as more of a restriction than a feature.&lt;br /&gt;
&lt;br /&gt;
The power of immutability comes from the fact that programs that fully utilize immutability are much simpler than those that do not, making them amenable to automated analysis by a computer.  Computers can then prove various properties about function programs, like concurrent behavior (presence or absence of deadlock/livelock), memory usage, and what within what bounds various values in the program will lie.&lt;br /&gt;
&lt;br /&gt;
==Higher Order Functions==&lt;br /&gt;
&lt;br /&gt;
Higher order functions are simply functions that accept or return other functions as values.  This is made possible because functions are treated as first-class entities, and allows very expressive implementations of many algorithms to be written.&lt;br /&gt;
&lt;br /&gt;
There are several hallmark higher order functions: map, reduce, fold left/right and filter are a few examples.  Going into the intricacies of each is beyond the scope of this article, but Abelson and Sussman's seminal [http://mitpress.mit.edu/sicp/ Structure and Interpretation of Computer Programs] has an [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.1 excellent treatment] of the subject.&lt;br /&gt;
&lt;br /&gt;
==Recursion==&lt;br /&gt;
&lt;br /&gt;
Programmers that are new to functional programming often balk at the notion that values cannot change over time (as variables do in imperative languages).  If values cannot change, how can we execute loops?&lt;br /&gt;
&lt;br /&gt;
The answer lies in recursion, where values are immutable, and loops are implemented as successive calls to the current function with new arguments.  The avoids the complexity of having values change over time while offering all the power of the loops we often see in imperative languages (for...each, do...while, etc.)  Again, a deep treatment of these language features is beyond the scope of this article, but again, Abelson and Sussman have [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.1 addressed] the topic at some length in their book.&lt;br /&gt;
&lt;br /&gt;
==Delayed (Lazy) Evaluation==&lt;br /&gt;
An extremely powerful feature of functional programming that is enabled by immutability is ''lazy evaluation''.  This simply means that expressions can be defined, even recursively, and are not computed until the values that would result from that computation are needed.  This is possible because values in functional programs don't change over time, which means expressions can be evaluated at any point in time as needed.&lt;br /&gt;
&lt;br /&gt;
Take an imperative expression like this (in Java):&lt;br /&gt;
&lt;br /&gt;
  int i = 4;&lt;br /&gt;
  int j = i + 3;&lt;br /&gt;
  i++;&lt;br /&gt;
&lt;br /&gt;
If you evaluate these expressions in order, j will be equal to 7, but if you were to delay the evaluation of j until after the third line, j would be equal to 8.  This is a very simple example of how variables that change over time require expressions be evaluated in a particular order to maintain the correctness of the program.  Functional programming explicitly disallows the third line, and therefore enables the value of j to be calculated only when it is needed.  The implications of this are significant, as we'll see in the next section.&lt;br /&gt;
&lt;br /&gt;
=Hybrid Object-Oriented/Functional Languages=&lt;br /&gt;
&lt;br /&gt;
To programmers of languages like SmallTalk, Simula and Java, many of the features provided in functional languages will seem foreign or strange.  But, as discussed, there are significant advantages to the functional approach for certain types of programs.  While the object-oriented paradigm has proven itself to be very useful, many modern languages have sought to integrate functional features as well to increase the expressiveness and power of the language.  One such language is Scala, which, like Java, runs on the Java Virtual Machine (JVM), and is thus shares Java's libraries and portability while offering many [http://www.ibm.com/developerworks/java/library/j-scala01228.html functional features] that are not available in object-oriented languages like Java.  In the [http://www.scala-lang.org/node/25 overview] of Scala available on its homepage, Scala is briefly described:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
[Scala] smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application.&amp;quot;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
How does Scala allow code sizes to be reduced so much?  It uses sophisticated type inferencing to reduce type signature redundancy, allows for functional programming constructs to be used, and provides syntax for oft-used programming idioms.  Essentially, it takes the lessons learned from decades of functional and object-oriented programming experience and rolls them into a modern hybrid language that can make full use legacy Java code.&lt;br /&gt;
&lt;br /&gt;
Scala is representative of an entire class of hybrid object/functional languages like OCaml, F# and Fan, and therefore makes a good language for use in the examples in this article.  The intent is not to present highly technical examples, but rather to give readers an impression of how hybrid languages increase expressive power over their single-paradigm counterparts.&lt;br /&gt;
&lt;br /&gt;
==Case Classes==&lt;br /&gt;
Idiomatic object-oriented programming involves encapsulation of data, as previously discussed.  In older object-oriented languages, this required defining internal data values, and then providing necessary get and set methods to access and/or modify those values. Here is an example a class in Java that provides only get methods for some (immutable) values it holds.  It includes all the methods that ''should'' be included in such a class, including a toString, equals and hashCode method.  Note that is an error if such methods are ''not'' included in structural Java classes, which is why I include them here.&lt;br /&gt;
&lt;br /&gt;
  public class UserData {&lt;br /&gt;
      private final String firstName;&lt;br /&gt;
      private final String lastName;&lt;br /&gt;
      private final Integer age;&lt;br /&gt;
      public UserData(String firstName, String lastName, Integer age) {&lt;br /&gt;
          this.firstName = firstName;&lt;br /&gt;
          this.lastName = lastName;&lt;br /&gt;
          this.age = age;&lt;br /&gt;
      }&lt;br /&gt;
      public String getFirstName() {&lt;br /&gt;
          return this.firstName;&lt;br /&gt;
      }&lt;br /&gt;
      public String getLastName() {&lt;br /&gt;
          return this.lastName;&lt;br /&gt;
      }&lt;br /&gt;
      public Integer getAge() {&lt;br /&gt;
          return this.age;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public boolean equals(Object obj) {&lt;br /&gt;
          if (obj == null) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (getClass() != obj.getClass()) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          final UserData other = (UserData) obj;&lt;br /&gt;
          if ((this.firstName == null) ? (other.firstName != null) : !this.firstName.equals(other.firstName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if ((this.lastName == null) ? (other.lastName != null) : !this.lastName.equals(other.lastName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.age != other.age &amp;amp;&amp;amp; (this.age == null || !this.age.equals(other.age))) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          return true;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public int hashCode() {&lt;br /&gt;
          int hash = 7;&lt;br /&gt;
          hash = 19 * hash + (this.firstName != null ? this.firstName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.lastName != null ? this.lastName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.age != null ? this.age.hashCode() : 0);&lt;br /&gt;
          return hash;&lt;br /&gt;
      }&lt;br /&gt;
      public String toString() {&lt;br /&gt;
          StringBuilder sb = new StringBuilder();&lt;br /&gt;
          sb.append(&amp;quot;UserData[firstName: &amp;quot;);&lt;br /&gt;
          sb.append(this.firstName);&lt;br /&gt;
          sb.append(&amp;quot; lastName: &amp;quot;);&lt;br /&gt;
          sb.append(this.lastName);&lt;br /&gt;
          sb.append(&amp;quot; age: &amp;quot;);&lt;br /&gt;
          sb.append(this.age);&lt;br /&gt;
          sb.append(&amp;quot;]&amp;quot;);&lt;br /&gt;
          return sb.toString();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, ''all'' the functionality of the above class can be expressed with:&lt;br /&gt;
&lt;br /&gt;
  case class UserData(val firstName: String, val lastName: String, val age: Int)&lt;br /&gt;
&lt;br /&gt;
To reiterate, the version in Scala actually does include a constructor, accessor methods, three fields that can only be set once, equals and hashCode  methods (comparing the structural equality of the two instances of the class), as well a meaningful toString method which prints the fields.&lt;br /&gt;
&lt;br /&gt;
There are numerous other benefits in using case classes, including automatic destructuring in pattern matching.  We will discuss these features in the next section.&lt;br /&gt;
&lt;br /&gt;
This feature by itself vastly reduces both development and maintenance burden for developers.  Classes in Scala are defined in lines, rather than entire files.  All the potential errors that could creep into that code are removed, and the ''intent'' of the developer is very clear.&lt;br /&gt;
&lt;br /&gt;
==Destructuring Binds and Pattern Matching==&lt;br /&gt;
Lisp, one of the earliest hybrid languages, offered primarily functional features with object-orientation built on top (in a system called CLOS).  One piece of functionality written with Common Lisp's metaprogramming facility was the ability to execute [http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_destructuring-bind.html destructuring binds], which are a powerful way of checking for a particular type ([http://en.wikipedia.org/wiki/Pattern_matching pattern matching]) and simultaneously extracting values from the inside of that type to use them in some computation. In the spirit of Common Lisp, Scala also offers destructuring binds and pattern matching.  Let's take a look at what they can do for us.&lt;br /&gt;
&lt;br /&gt;
Let us suppose we want to make use of our UserData class, defined above.  We want to find all users with ages over 18 and store their names in a database.  If we were to write a method that would simply do the database store for a single user, it might look like this:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      Integer age = user.getAge();&lt;br /&gt;
      if (age &amp;gt; 18) {&lt;br /&gt;
          recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, this would be a trivial pattern match, with a destructuring bind to capture the fields inside the UserData (in this case, we bind them to f, l and a):&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In this case, we don't get an enourmous savings in terms of the number of lines of code used, but we gain tremendously in expressive power.  Let's say we wanted to do the same thing, but not include users named &amp;quot;Bob&amp;quot;.  In Java:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      String firstName = user.getFirstName();&lt;br /&gt;
      if (firstName != &amp;quot;Bob&amp;quot;) {&lt;br /&gt;
          Integer age = user.getAge();&lt;br /&gt;
          if (age &amp;gt; 18) {&lt;br /&gt;
              recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
And now in Scala:&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 &amp;amp;&amp;amp; f != &amp;quot;Bob&amp;quot; =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Hopefully this provides a little bit of insight into how destructuring can improve the expressiveness of your code.  A more in depth discussion on pattern matching and binding can be be found in [http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-4 Part 4] of Code Commit's series &amp;quot;Scala For Java Refugees&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==List Comprehension==&lt;br /&gt;
In imperative languages (including both procedural and object-oriented languages), it is common to loop very often, either with a for loop or a while loop.  Hybrid languages allow for this, and also incorporate more abstract operations on structures seen in functional programming.&lt;br /&gt;
&lt;br /&gt;
For example, suppose we wanted to take in a structure containing a bunch of UserData objects, and return a list of strings, containing the last name, a comma, and then the first name of each user.&lt;br /&gt;
&lt;br /&gt;
In Java, this might look like this:&lt;br /&gt;
&lt;br /&gt;
  public ArrayList&amp;lt;String&amp;gt; toStrings(ArrayList&amp;lt;UserData&amp;gt; users) {&lt;br /&gt;
      ArrayList&amp;lt;String&amp;gt; returnedList = new ArrayList&amp;lt;String&amp;gt;();&lt;br /&gt;
      for (UserData u : users) {&lt;br /&gt;
          returnedList.add(u.getLastName() + &amp;quot;, &amp;quot; + u.firstName);&lt;br /&gt;
      }&lt;br /&gt;
      return returnedList;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In the seven lines of code, only the method declaration and the add to the new list really have anything to do with the business logic.  In Scala, that boiler plate can be avoided:&lt;br /&gt;
&lt;br /&gt;
  def toStrings(users: List[UserData]) = users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This method definition is so short that it is arguable we shouldn't even define the method, and should simply use the map operation inline:&lt;br /&gt;
&lt;br /&gt;
  users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This is a small demonstration of how functional languages and object-oriented languages an combine their strengths.  We retain all the encapsulation of the object-oriented approach (although u.lastName and u.firstName appear to be fields, they are in fact accessor methods), but we also have the power of higher abstraction levels from the functional world (in this case, the map operation).&lt;br /&gt;
&lt;br /&gt;
==Lazy Evaluation==&lt;br /&gt;
The final feature I'd like to touch upon is lazy evaluation.  One of the many implications of lazy evaluation is that we can now program using infinite data structures; we define a way in which deeper parts of the data structure are calculated from the existing parts, and only lazily evaluate parts of the structure as they are accessed.  This allows us to express algorithms quite concisely.  This can be used in a variety of cases like random number generation, methods of successive approximation (like Newton's Method), fractal calculations, and generation of infinite series, as seen in the numerical methods or, more simply, the Fibonacci sequence.  Because it is so well known, I will use the Fibonacci sequence as an example here.  First, in Java:&lt;br /&gt;
&lt;br /&gt;
   public long fib(int k) {&lt;br /&gt;
       if (k &amp;lt;= 2) {&lt;br /&gt;
           return 1;&lt;br /&gt;
       } else {&lt;br /&gt;
           return fib(k-1) + fib(k-2);&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This is a short, inefficient, recursive solution.  It doesn't cache answers, either in a single call or across calls, which means it performs a huge amount of redundant computation.  So it has a number of problems, but it is concise.&lt;br /&gt;
&lt;br /&gt;
In Scala, we can remedy all those problems and remain concise using a [http://www.scala-lang.org/docu/files/api/scala/Stream.html Stream], a lazily evaluated form of a List:&lt;br /&gt;
&lt;br /&gt;
  val fibs: Stream[Int] = Stream(0,1) append fibs.zip(fibs.drop(1)).map(x =&amp;gt; x._1 + x._2)&lt;br /&gt;
&lt;br /&gt;
This definition is concise, offers automatic memoization and is thread-safe.  To add those features to the Java code would require 20 lines of additional code at a minimum.  It returns a Stream that can be queried for the kth Fibonacci number in the same way as the fib method defined in Java could, but calculates the 92rd Fibonacci in a fraction of a second.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
Unfortunately, this article barely scratches the surface of the topic.  There are decades of research and experience that have gone into modern programming languages, and the way in which they blend various programming paradigms blurs what were once quite distinct borders in the landscape of programming languages.  But, that blurring has allowed these modern languages to offer programmers a bigger set of tools that aren't merely an amalgamation of features from every language, but a carefully crafted blend of features that enhance the expressiveness of these languages while not substantially increasing the syntax or API surface area.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
If you want to know more about hybrid languages, its best to choose one (or a few!) and read about what they offer.  If you're familiar with Java, or C#, take a look at the [http://www.scala-lang.org/node/104 tour of Scala] or perhaps some of the [http://www.fandev.org/doc/docIntro/StartHere.html features of Fan].  &lt;br /&gt;
&lt;br /&gt;
There are also a few major dynamically typed hybrid languages.  Chief among these is [http://python.org Python], which has several implementations in [http://python.org C], [http://jython.org/ Java] and [http://codespeak.net/pypy/dist/pypy/doc/ Python](!).  [http://ruby-lang.org Ruby] is also a newer hybrid language, originating in Japan, but was made famous worldwide because of its [http://rubyonrails.org/ Rails] web programming framework that was possible in large part due to its hybrid nature.  It also has a [http://jruby.org/ Java implementation].  Finally, if you're working on the JVM an want a hybrid, dynamically-typed language with syntax that is close to Java's, [http://groovy.codehaus.org/ Groovy] is your best bet.&lt;br /&gt;
&lt;br /&gt;
If you're very interested in performance, Common Lisp may have something to offer you, and there are [http://www.sbcl.org/ several] [http://www.cons.org/cmucl/ performant] [http://clisp.cons.org/ implementations].  If you want to learn more about why hybrid languages are so powerful, Paul Graham's book [http://www.paulgraham.com/onlisp.html On Lisp] explains why.  If you really care about using the power of the JVM and are doing concurrent programming, a very modern lisp called [http://clojure.org Clojure] will be very interesting.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25636</id>
		<title>CSC/ECE 517 Fall 2009/wiki2 6 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25636"/>
		<updated>2009-10-12T06:52:58Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Topic=&lt;br /&gt;
&lt;br /&gt;
While Smalltalk and Java were instrumental in bringing object-oriented programming into the mainstream, the 1990s also saw the development of hybrid languages that supported multiple programming paradigms, often combining procedural, object-oriented and functional approaches. Discuss the development and design considerations that went into languages like OCaml, Scala, F# and Fan, and how they build upon an object-oriented foundation to offer languages that offer type safety while maintaining brevity and expressive power.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &lt;br /&gt;
&lt;br /&gt;
There are many ways to classify programming languages: on the basis of static or dynamic typing, type safety, high or low levels of abstraction, and by programming paradigm.&lt;br /&gt;
&lt;br /&gt;
In this article, the focus is on programming paradigms, which can loosely be thought of as defining the atomic units a language offers as building block with which to build programs.  There are three primary paradigms in use today:&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Procedural_programming Procedural]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Object-oriented_programming Object-Oriented]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Declarative_programming Declarative]&lt;br /&gt;
&lt;br /&gt;
Declarative languages span a wide array of programming styles.  For simplicity in this article, we will focus on [http://en.wikipedia.org/wiki/Functional_programming functional] languages, which are an important subset of declarative languages.&lt;br /&gt;
&lt;br /&gt;
Many languages provide only one of the paradigms to their users.  [http://www.engin.umd.umich.edu/CIS/course.des/cis400/fortran/fortran.html FORTRAN], [http://www.engin.umd.umich.edu/CIS/course.des/cis400/cobol/cobol.html COBOL], [http://en.wikipedia.org/wiki/Pascal_%28programming_language%29 Pascal], [http://cm.bell-labs.com/cm/cs/who/dmr/chist.html C] and [http://en.wikipedia.org/wiki/BASIC BASIC] are all procedural, [http://www.engin.umd.umich.edu/CIS/course.des/cis400/simula/simula.html Simula], [http://www.smalltalk.org/main/ Smalltalk]] and [http://www.eiffel.com/developers/design_by_contract.html Eiffel] are object-oriented and [http://haskell.org/ Haskell] and [http://en.wikipedia.org/wiki/ML_%28programming_language%29 ML] are functional.  These languages provide a single paradigm for programming, which limits programmers to the particular set of constructs available in that model.&lt;br /&gt;
&lt;br /&gt;
The three paradigms evolved somewhat independently and offer unique constructs with which to solve programming problems.  Some languages are multi-paradigm, however, and allow a programmer to use the tools  most fitting for the problem at hand, sometimes mixing and matching freely within a single program.  The original language of this type is Lisp, which dates back to the mid-1950s.  In the last 20 years, many other hybrid languages have emerged, often derivatives of existing languages.  C++ is derived from C, and offers both procedural and object-oriented approaches.  [http://java.sun.com Java], one of the most widely used languages today, offers both procedural and object-oriented paradigms as well.  [http://caml.inria.fr/ OCaml] is derived from ML, and offers functional and object-oriented styles.  There are many others that have become popular in recent years, like [http://python.org Python] and [http://www.ruby-lang.org/en/ Ruby].&lt;br /&gt;
&lt;br /&gt;
In this article, our goal is to examine what these hybrid languages offer above and beyond strictly object-oriented languages.  In particular, we will examine the features of object-oriented languages and functional languages, and how they have been blended in a modern hybrid language called [http://scala-lang.org Scala].&lt;br /&gt;
&lt;br /&gt;
=Features of Object Oriented Languages=&lt;br /&gt;
The key construct provided by object-oriented languages is the ''object'', which bundles the data and behavior together into a cohesive unit.&lt;br /&gt;
&lt;br /&gt;
==Encapsulation==&lt;br /&gt;
Encapsulation is the technique of rolling behavior and data into an object that exhibits (and is handled in terms of) a particular behavior, rather than a particular composition.  This technique allows the internals of an object to remain hidden from external entities, which in turn enables the object to modify its implementation over time while providing the same external behaviors.&lt;br /&gt;
&lt;br /&gt;
For example, encapsulation would allow a class to add logging functionality without affecting other classes' collaboration with it.  Any feature that is solely an implementation concern (speeding up a sorting algorithm, checking inputs for invalid data, changing the way resource errors are handled, etc.) can be evolved and modified over time within the object without breaking functionality elsewhere in the program that relies on the object in question.&lt;br /&gt;
&lt;br /&gt;
==Dependency Inversion==&lt;br /&gt;
&lt;br /&gt;
One of the major benefits of focusing on the ''behavior'' of objects rather than their ''implementation'' is that the behavior aspects can be well defined and captured in an interface.  This allows code that once would rely on an unstable implementation to instead shift its dependency onto a stable interface, and have the implementation then implement the interface.  This process is known as ''dependency inversion'', because of the way in which it alter the dependency structure of the code.&lt;br /&gt;
&lt;br /&gt;
For example, let us say we have a web server that makes use of a logging facility to log information to disk.  In this case, the web server depends on the logging facility:&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger.png]]&lt;br /&gt;
&lt;br /&gt;
Later, it becomes apparent that the web server also want to be able to log to other destinations.  To facilitate this, we introduce a ''Logger'' interface, and make have the web server depend on that, so as to insulate it from new types of loggers that may be introduced.  This allows us to modify both the server and the loggers in isolation, having them both depend on the interface rather than each other, essentially reversing, or ''inverting'' the dependency diagram.&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger-invert.png]]&lt;br /&gt;
&lt;br /&gt;
In this diagram, the behavior of the logger is well-defined and stable, and is captured in the interface represented by the yellow box.  The blue boxes are classes that are implementations, and are insulated from one another by the interface, allowing them to vary independently without breaking the program as a whole.  This is an example of the robustness that the object-oriented approach lends to a program through use of encapsulation.&lt;br /&gt;
&lt;br /&gt;
==Polymorphism and Dynamic Dispatch==&lt;br /&gt;
                                 &lt;br /&gt;
The object-oriented approach of thinking in terms of behavior lends itself to have multiple implementations of a single behavior.  We can see this is the case of the logger above. To the web server, a logger is simply an object with which logs can be stored.  There are many possible implementations; we could use the file logger or the network logger as seen above, but we could also implement a console logger or a database logger.  Essentially, this means that the web server could call a method to log information without any knowledge of exactly what kind of object it was calling.  The raises the question of how (and when) a programming language decides which log method to call.  Is it compiled in, or is it determined at runtime?&lt;br /&gt;
&lt;br /&gt;
The answer is that it is determined at runtime.  This type of ''late binding'' allows a program to remain flexible even after it is deployed, permitting end-users to determine what kind of logging functionality they want be passing in various implementations of the logger interface when the web server is run, even implementations that were written ''after'' the web server was written and deployed!  This kind of flexibility is a result of ''polymorphism'', which simply means that the an interface (like the logger interface in our example) can have ''many forms'', or implementations.  The way the language determines which one to invoke is through ''dynamic dispatch'', which is essentially a lookup table maintained as the program runs that maps calls to methods like logging to the implementations specified.&lt;br /&gt;
&lt;br /&gt;
The major theme here is that the object-oriented approach of favoring encapsulation has many effects that ripple throughout the design process, almost all of which allow programmers to reduce the brittleness of their software by delaying commitment to particular implementations.&lt;br /&gt;
&lt;br /&gt;
=Features of Functional Languages=&lt;br /&gt;
&lt;br /&gt;
Much like object-oriented languages, functional languages offer a dominant paradigm that has far-reaching consequences in software design.  For object-oriented languages, that element is encapsulation, and for functional languages, it is that functions are first-class entities, which simply means that functions are treated just like any other value in the language.  This allows them to be passed as parameters, delayed, composed, invoked, and returned from other functions.  But what is a function?&lt;br /&gt;
&lt;br /&gt;
A function's most notable trait is that it is free of ''side-effects'', or state changes to the program that occur as a result of its execution.  We could say a lot about side effects, but the general rule is that a function will always return the same value given the same input.  This means that functions are ''stateless''.  Therefore, entities like random number generators and loggers are not functional, because they either store state or have some effect that is not related to the value they return.  Another way to think of functions is that they are completely defined in terms of their input and output.&lt;br /&gt;
&lt;br /&gt;
From this simple feature flows many characteristic language features.  We will discuss them in turn.&lt;br /&gt;
&lt;br /&gt;
==Immutability==&lt;br /&gt;
Maybe the most noticeable feature (or restriction) to programmers of languages that are not functional, [http://en.wikipedia.org/wiki/Immutable_object immutability] is one of the hallmarks of a functional language.  Most non-functional languages allow ''assignment'', or the ability to assign new values to variables as the program runs.  In functional programming, a value is declared only once and then never changes.  This feature of of the language flows out of the notion that functions have no side-effects, and is often viewed as more of a restriction than a feature.&lt;br /&gt;
&lt;br /&gt;
The power of immutability comes from the fact that programs that fully utilize immutability are much simpler than those that do not, making them amenable to automated analysis by a computer.  Computers can then prove various properties about function programs, like concurrent behavior (presence or absence of deadlock/livelock), memory usage, and what within what bounds various values in the program will lie.&lt;br /&gt;
&lt;br /&gt;
==Higher Order Functions==&lt;br /&gt;
&lt;br /&gt;
Higher order functions are simply functions that accept or return other functions as values.  This is made possible because functions are treated as first-class entities, and allows very expressive implementations of many algorithms to be written.&lt;br /&gt;
&lt;br /&gt;
There are several hallmark higher order functions: map, reduce, fold left/right and filter are a few examples.  Going into the intricacies of each is beyond the scope of this article, but Abelson and Sussman's seminal [http://mitpress.mit.edu/sicp/ Structure and Interpretation of Computer Programs] has an [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.1 excellent treatment] of the subject.&lt;br /&gt;
&lt;br /&gt;
==Recursion==&lt;br /&gt;
&lt;br /&gt;
Programmers that are new to functional programming often balk at the notion that values cannot change over time (as variables do in imperative languages).  If values cannot change, how can we execute loops?&lt;br /&gt;
&lt;br /&gt;
The answer lies in recursion, where values are immutable, and loops are implemented as successive calls to the current function with new arguments.  The avoids the complexity of having values change over time while offering all the power of the loops we often see in imperative languages (for...each, do...while, etc.)  Again, a deep treatment of these language features is beyond the scope of this article, but again, Abelson and Sussman have [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.1 addressed] the topic at some length in their book.&lt;br /&gt;
&lt;br /&gt;
==Delayed (Lazy) Evaluation==&lt;br /&gt;
An extremely powerful feature of functional programming that is enabled by immutability is ''lazy evaluation''.  This simply means that expressions can be defined, even recursively, and are not computed until the values that would result from that computation are needed.  This is possible because values in functional programs don't change over time, which means expressions can be evaluated at any point in time as needed.&lt;br /&gt;
&lt;br /&gt;
Take an imperative expression like this (in Java):&lt;br /&gt;
&lt;br /&gt;
  int i = 4;&lt;br /&gt;
  int j = i + 3;&lt;br /&gt;
  i++;&lt;br /&gt;
&lt;br /&gt;
If you evaluate these expressions in order, j will be equal to 7, but if you were to delay the evaluation of j until after the third line, j would be equal to 8.  This is a very simple example of how variables that change over time require expressions be evaluated in a particular order to maintain the correctness of the program.  Functional programming explicitly disallows the third line, and therefore enables the value of j to be calculated only when it is needed.  The implications of this are significant, as we'll see in the next section.&lt;br /&gt;
&lt;br /&gt;
=Hybrid Object-Oriented/Functional Languages=&lt;br /&gt;
&lt;br /&gt;
To programmers of languages like SmallTalk, Simula and Java, many of the features provided in functional languages will seem foreign or strange.  But, as discussed, there are significant advantages to the functional approach for certain types of programs.  While the object-oriented paradigm has proven itself to be very useful, many modern languages have sought to integrate functional features as well to increase the expressiveness and power of the language.  One such language is Scala, which, like Java, runs on the Java Virtual Machine (JVM), and is thus shares Java's libraries and portability while offering many [http://www.ibm.com/developerworks/java/library/j-scala01228.html functional features] that are not available in object-oriented languages like Java.  In the [http://www.scala-lang.org/node/25 overview] of Scala available on its homepage, Scala is briefly described:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
[Scala] smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application.&amp;quot;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
How does Scala allow code sizes to be reduced so much?  It uses sophisticated type inferencing to reduce type signature redundancy, allows for functional programming constructs to be used, and provides syntax for oft-used programming idioms.  Essentially, it takes the lessons learned from decades of functional and object-oriented programming experience and rolls them into a modern hybrid language that can make full use legacy Java code.&lt;br /&gt;
&lt;br /&gt;
Scala is representative of an entire class of hybrid object/functional languages like OCaml, F# and Fan, and therefore makes a good language for use in the examples in this article.  The intent is not to present highly technical examples, but rather to give readers an impression of how hybrid languages increase expressive power over their single-paradigm counterparts.&lt;br /&gt;
&lt;br /&gt;
==Case Classes==&lt;br /&gt;
Idiomatic object-oriented programming involves encapsulation of data, as previously discussed.  In older object-oriented languages, this required defining internal data values, and then providing necessary get and set methods to access and/or modify those values. Here is an example a class in Java that provides only get methods for some (immutable) values it holds.  It includes all the methods that ''should'' be included in such a class, including a toString, equals and hashCode method.  Note that is an error if such methods are ''not'' included in structural Java classes, which is why I include them here.&lt;br /&gt;
&lt;br /&gt;
  public class UserData {&lt;br /&gt;
      private final String firstName;&lt;br /&gt;
      private final String lastName;&lt;br /&gt;
      private final Integer age;&lt;br /&gt;
      public UserData(String firstName, String lastName, Integer age) {&lt;br /&gt;
          this.firstName = firstName;&lt;br /&gt;
          this.lastName = lastName;&lt;br /&gt;
          this.age = age;&lt;br /&gt;
      }&lt;br /&gt;
      public String getFirstName() {&lt;br /&gt;
          return this.firstName;&lt;br /&gt;
      }&lt;br /&gt;
      public String getLastName() {&lt;br /&gt;
          return this.lastName;&lt;br /&gt;
      }&lt;br /&gt;
      public Integer getAge() {&lt;br /&gt;
          return this.age;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public boolean equals(Object obj) {&lt;br /&gt;
          if (obj == null) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (getClass() != obj.getClass()) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          final UserData other = (UserData) obj;&lt;br /&gt;
          if ((this.firstName == null) ? (other.firstName != null) : !this.firstName.equals(other.firstName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if ((this.lastName == null) ? (other.lastName != null) : !this.lastName.equals(other.lastName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.age != other.age &amp;amp;&amp;amp; (this.age == null || !this.age.equals(other.age))) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          return true;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public int hashCode() {&lt;br /&gt;
          int hash = 7;&lt;br /&gt;
          hash = 19 * hash + (this.firstName != null ? this.firstName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.lastName != null ? this.lastName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.age != null ? this.age.hashCode() : 0);&lt;br /&gt;
          return hash;&lt;br /&gt;
      }&lt;br /&gt;
      public String toString() {&lt;br /&gt;
          StringBuilder sb = new StringBuilder();&lt;br /&gt;
          sb.append(&amp;quot;UserData[firstName: &amp;quot;);&lt;br /&gt;
          sb.append(this.firstName);&lt;br /&gt;
          sb.append(&amp;quot; lastName: &amp;quot;);&lt;br /&gt;
          sb.append(this.lastName);&lt;br /&gt;
          sb.append(&amp;quot; age: &amp;quot;);&lt;br /&gt;
          sb.append(this.age);&lt;br /&gt;
          sb.append(&amp;quot;]&amp;quot;);&lt;br /&gt;
          return sb.toString();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, ''all'' the functionality of the above class can be expressed with:&lt;br /&gt;
&lt;br /&gt;
  case class UserData(val firstName: String, val lastName: String, val age: Int)&lt;br /&gt;
&lt;br /&gt;
To reiterate, the version in Scala actually does include a constructor, accessor methods, three fields that can only be set once, equals and hashCode  methods (comparing the structural equality of the two instances of the class), as well a meaningful toString method which prints the fields.&lt;br /&gt;
&lt;br /&gt;
There are numerous other benefits in using case classes, including automatic destructuring in pattern matching.  We will discuss these features in the next section.&lt;br /&gt;
&lt;br /&gt;
This feature by itself vastly reduces both development and maintenance burden for developers.  Classes in Scala are defined in lines, rather than entire files.  All the potential errors that could creep into that code are removed, and the ''intent'' of the developer is very clear.&lt;br /&gt;
&lt;br /&gt;
==Destructuring Binds and Pattern Matching==&lt;br /&gt;
Lisp, one of the earliest hybrid languages, offered primarily functional features with object-orientation built on top (in a system called CLOS).  One piece of functionality written with Common Lisp's metaprogramming facility was the ability to execute [http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_destructuring-bind.html destructuring binds], which are a powerful way of checking for a particular type ([http://en.wikipedia.org/wiki/Pattern_matching pattern matching]) and simultaneously extracting values from the inside of that type to use them in some computation. In the spirit of Common Lisp, Scala also offers destructuring binds and pattern matching.  Let's take a look at what they can do for us.&lt;br /&gt;
&lt;br /&gt;
Let us suppose we want to make use of our UserData class, defined above.  We want to find all users with ages over 18 and store their names in a database.  If we were to write a method that would simply do the database store for a single user, it might look like this:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      Integer age = user.getAge();&lt;br /&gt;
      if (age &amp;gt; 18) {&lt;br /&gt;
          recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, this would be a trivial pattern match, with a destructuring bind to capture the fields inside the UserData (in this case, we bind them to f, l and a):&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In this case, we don't get an enourmous savings in terms of the number of lines of code used, but we gain tremendously in expressive power.  Let's say we wanted to do the same thing, but not include users named &amp;quot;Bob&amp;quot;.  In Java:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      String firstName = user.getFirstName();&lt;br /&gt;
      if (firstName != &amp;quot;Bob&amp;quot;) {&lt;br /&gt;
          Integer age = user.getAge();&lt;br /&gt;
          if (age &amp;gt; 18) {&lt;br /&gt;
              recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
And now in Scala:&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 &amp;amp;&amp;amp; f != &amp;quot;Bob&amp;quot; =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Hopefully this provides a little bit of insight into how destructuring can improve the expressiveness of your code.  A more in depth discussion on pattern matching and binding can be be found in [http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-4 Part 4] of Code Commit's series &amp;quot;Scala For Java Refugees&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==List Comprehension==&lt;br /&gt;
In imperative languages (including both procedural and object-oriented languages), it is common to loop very often, either with a for loop or a while loop.  Hybrid languages allow for this, and also incorporate more abstract operations on structures seen in functional programming.&lt;br /&gt;
&lt;br /&gt;
For example, suppose we wanted to take in a structure containing a bunch of UserData objects, and return a list of strings, containing the last name, a comma, and then the first name of each user.&lt;br /&gt;
&lt;br /&gt;
In Java, this might look like this:&lt;br /&gt;
&lt;br /&gt;
  public ArrayList&amp;lt;String&amp;gt; toStrings(ArrayList&amp;lt;UserData&amp;gt; users) {&lt;br /&gt;
      ArrayList&amp;lt;String&amp;gt; returnedList = new ArrayList&amp;lt;String&amp;gt;();&lt;br /&gt;
      for (UserData u : users) {&lt;br /&gt;
          returnedList.add(u.getLastName() + &amp;quot;, &amp;quot; + u.firstName);&lt;br /&gt;
      }&lt;br /&gt;
      return returnedList;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In the seven lines of code, only the method declaration and the add to the new list really have anything to do with the business logic.  In Scala, that boiler plate can be avoided:&lt;br /&gt;
&lt;br /&gt;
  def toStrings(users: List[UserData]) = users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This method definition is so short that it is arguable we shouldn't even define the method, and should simply use the map operation inline:&lt;br /&gt;
&lt;br /&gt;
  users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This is a small demonstration of how functional languages and object-oriented languages an combine their strengths.  We retain all the encapsulation of the object-oriented approach (although u.lastName and u.firstName appear to be fields, they are in fact accessor methods), but we also have the power of higher abstraction levels from the functional world (in this case, the map operation).&lt;br /&gt;
&lt;br /&gt;
==Lazy Evaluation==&lt;br /&gt;
The final feature I'd like to touch upon is lazy evaluation.  One of the many implications of lazy evaluation is that we can now program using infinite data structures; we define a way in which deeper parts of the data structure are calculated from the existing parts, and only lazily evaluate parts of the structure as they are accessed.  This allows us to express algorithms quite concisely.  This can be used in a variety of cases like random number generation, methods of successive approximation (like Newton's Method), fractal calculations, and generation of infinite series, as seen in the numerical methods or, more simply, the Fibonacci sequence.  Because it is so well known, I will use the Fibonacci sequence as an example here.  First, in Java:&lt;br /&gt;
&lt;br /&gt;
   public long fib(int k) {&lt;br /&gt;
       if (k &amp;lt;= 2) {&lt;br /&gt;
           return 1;&lt;br /&gt;
       } else {&lt;br /&gt;
           return fib(k-1) + fib(k-2);&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This is a short, inefficient, recursive solution.  It doesn't cache answers, either in a single call or across calls, which means it performs a huge amount of redundant computation.  So it has a number of problems, but it is concise.&lt;br /&gt;
&lt;br /&gt;
In Scala, we can remedy all those problems and remain concise using a [http://www.scala-lang.org/docu/files/api/scala/Stream.html Stream], a lazily evaluated form of a List:&lt;br /&gt;
&lt;br /&gt;
  val fibs: Stream[Int] = Stream(0,1) append fibs.zip(fibs.drop(1)).map(x =&amp;gt; x._1 + x._2)&lt;br /&gt;
&lt;br /&gt;
This definition is concise, offers automatic memoization and is thread-safe.  To add those features to the Java code would require 20 lines of additional code at a minimum.  It returns a Stream that can be queried for the kth Fibonacci number in the same way as the fib method defined in Java could, but calculates the 92rd Fibonacci in a fraction of a second.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
Unfortunately, this article barely scratches the surface of the topic.  There are decades of research and experience that have gone into modern programming languages, and the way in which they blend various programming paradigms blurs what were once quite distinct borders in the landscape of programming languages.  But, that blurring has allowed these modern languages to offer programmers a bigger set of tools that aren't merely an amalgamation of features from every language, but a carefully crafted blend of features that enhance the expressiveness of these languages while not substantially increasing the syntax or API surface area.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
If you want to know more about hybrid languages, its best to choose one (or a few!) and read about what they offer.  If you're familiar with Java, or C#, take a look at the [http://www.scala-lang.org/node/104 tour of Scala] or perhaps some of the [http://www.fandev.org/doc/docIntro/StartHere.html features of Fan].  &lt;br /&gt;
&lt;br /&gt;
There are also a few major dynamically typed hybrid languages.  Chief among these is [http://python.org Python], which has several implementations in [http://python.org C], [http://jython.org/ Java] and [http://codespeak.net/pypy/dist/pypy/doc/ Python](!).  [http://ruby-lang.org Ruby] is also a newer hybrid language, originating in Japan, but was made famous worldwide because of its [http://rubyonrails.org/ Rails] web programming framework that was possible in large part due to its hybrid nature.  It also has a [http://jruby.org/ Java implementation].  Finally, if you're working on the JVM an want a hybrid, dynamically-typed language with syntax that is close to Java's, [http://groovy.codehaus.org/ Groovy] is your best bet.&lt;br /&gt;
&lt;br /&gt;
If you're very interested in performance, Common Lisp may have something to offer you, and there are [http://www.sbcl.org/ several] [http://www.cons.org/cmucl/ performant] [http://clisp.cons.org/ implementations].  If you want to learn more about why hybrid languages are so powerful, Paul Graham's book [http://www.paulgraham.com/onlisp.html On Lisp] explains why.  If you really care about using the power of the JVM and are doing concurrent programming, a very modern lisp called [http://clojure.org Clojure] will be very interesting.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25625</id>
		<title>CSC/ECE 517 Fall 2009/wiki2 6 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki2_6_rp&amp;diff=25625"/>
		<updated>2009-10-11T18:11:41Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Topic=&lt;br /&gt;
&lt;br /&gt;
While Smalltalk and Java were instrumental in bringing object-oriented programming into the mainstream, the 1990s also saw the development of hybrid languages that supported multiple programming paradigms, often combining procedural, object-oriented and functional approaches. Discuss the development and design considerations that went into languages like OCaml, Scala, F# and Fan, and how they build upon an object-oriented foundation to offer languages that offer type safety while maintaining brevity and expressive power.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &lt;br /&gt;
&lt;br /&gt;
There are many ways to classify programming languages: on the basis of static or dynamic typing, type safety, high or low levels of abstraction, and by programming paradigm.&lt;br /&gt;
&lt;br /&gt;
In this article, the focus is on programming paradigms, which can loosely be thought of as defining the atomic units a language offers as building block with which to build programs.  There are three primary paradigms in use today:&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Procedural_programming Procedural]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Object-oriented_programming Object-Oriented]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Declarative_programming Declarative]&lt;br /&gt;
&lt;br /&gt;
Declarative languages span a wide array of programming styles.  For simplicity in this article, we will focus on [http://en.wikipedia.org/wiki/Functional_programming functional] languages, which are an important subset of declarative languages.&lt;br /&gt;
&lt;br /&gt;
Many languages provide only one of the paradigms to their users.  [http://www.engin.umd.umich.edu/CIS/course.des/cis400/fortran/fortran.html FORTRAN], [http://www.engin.umd.umich.edu/CIS/course.des/cis400/cobol/cobol.html COBOL], [http://en.wikipedia.org/wiki/Pascal_%28programming_language%29 Pascal], [http://cm.bell-labs.com/cm/cs/who/dmr/chist.html C] and [http://en.wikipedia.org/wiki/BASIC BASIC] are all procedural, [http://www.engin.umd.umich.edu/CIS/course.des/cis400/simula/simula.html Simula], [http://www.smalltalk.org/main/ Smalltalk]] and [http://www.eiffel.com/developers/design_by_contract.html Eiffel] are object-oriented and [http://haskell.org/ Haskell] and [http://en.wikipedia.org/wiki/ML_%28programming_language%29 ML] are functional.  These languages provide a single paradigm for programming, which limits programmers to the particular set of constructs available in that model.&lt;br /&gt;
&lt;br /&gt;
The three paradigms evolved somewhat independently and offer unique constructs with which to solve programming problems.  Some languages are multi-paradigm, however, and allow a programmer to use the tools  most fitting for the problem at hand, sometimes mixing and matching freely within a single program.  The original language of this type is Lisp, which dates back to the mid-1950s.  In the last 20 years, many other hybrid languages have emerged, often derivatives of existing languages.  C++ is derived from C, and offers both procedural and object-oriented approaches.  [http://java.sun.com Java], one of the most widely used languages today, offers both procedural and object-oriented paradigms as well.  [http://caml.inria.fr/ OCaml] is derived from ML, and offers functional and object-oriented styles.  There are many others that have become popular in recent years, like [http://python.org Python] and [http://www.ruby-lang.org/en/ Ruby].&lt;br /&gt;
&lt;br /&gt;
In this article, our goal is to examine what these hybrid languages offer above and beyond strictly object-oriented languages.  In particular, we will examine the features of object-oriented languages and functional languages, and how they have been blended in a modern hybrid language called [http://scala-lang.org Scala].&lt;br /&gt;
&lt;br /&gt;
=Features of Object Oriented Languages=&lt;br /&gt;
The key construct provided by object-oriented languages is the ''object'', which bundles the data and behavior together into a cohesive unit.&lt;br /&gt;
&lt;br /&gt;
==Encapsulation==&lt;br /&gt;
Encapsulation is the technique of rolling behavior and data into an object that exhibits (and is handled in terms of) a particular behavior, rather than a particular composition.  This technique allows the internals of an object to remain hidden from external entities, which in turn enables the object to modify its implementation over time while providing the same external behaviors.&lt;br /&gt;
&lt;br /&gt;
For example, encapsulation would allow a class to add logging functionality without affecting other classes' collaboration with it.  Any feature that is solely an implementation concern (speeding up a sorting algorithm, checking inputs for invalid data, changing the way resource errors are handled, etc.) can be evolved and modified over time within the object without breaking functionality elsewhere in the program that relies on the object in question.&lt;br /&gt;
&lt;br /&gt;
==Dependency Inversion==&lt;br /&gt;
&lt;br /&gt;
One of the major benefits of focusing on the ''behavior'' of objects rather than their ''implementation'' is that the behavior aspects can be well defined and captured in an interface.  This allows code that once would rely on an unstable implementation to instead shift its dependency onto a stable interface, and have the implementation then implement the interface.  This process is known as ''dependency inversion'', because of the way in which it alter the dependency structure of the code.&lt;br /&gt;
&lt;br /&gt;
For example, let us say we have a web server that makes use of a logging facility to log information to disk.  In this case, the web server depends on the logging facility:&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger.png]]&lt;br /&gt;
&lt;br /&gt;
Later, it becomes apparent that the web server also want to be able to log to other destinations.  To facilitate this, we introduce a ''Logger'' interface, and make have the web server depend on that, so as to insulate it from new types of loggers that may be introduced.  This allows us to modify both the server and the loggers in isolation, having them both depend on the interface rather than each other, essentially reversing, or ''inverting'' the dependency diagram.&lt;br /&gt;
&lt;br /&gt;
[[Image:server-logger-invert.png]]&lt;br /&gt;
&lt;br /&gt;
In this diagram, the behavior of the logger is well-defined and stable, and is captured in the interface represented by the yellow box.  The blue boxes are classes that are implementations, and are insulated from one another by the interface, allowing them to vary independently without breaking the program as a whole.  This is an example of the robustness that the object-oriented approach lends to a program through use of encapsulation.&lt;br /&gt;
&lt;br /&gt;
==Polymorphism and Dynamic Dispatch==&lt;br /&gt;
                                 &lt;br /&gt;
The object-oriented approach of thinking in terms of behavior lends itself to have multiple implementations of a single behavior.  We can see this is the case of the logger above. To the web server, a logger is simply an object with which logs can be stored.  There are many possible implementations; we could use the file logger or the network logger as seen above, but we could also implement a console logger or a database logger.  Essentially, this means that the web server could call a method to log information without any knowledge of exactly what kind of object it was calling.  The raises the question of how (and when) a programming language decides which log method to call.  Is it compiled in, or is it determined at runtime?&lt;br /&gt;
&lt;br /&gt;
The answer is that it is determined at runtime.  This type of ''late binding'' allows a program to remain flexible even after it is deployed, permitting end-users to determine what kind of logging functionality they want be passing in various implementations of the logger interface when the web server is run, even implementations that were written ''after'' the web server was written and deployed!  This kind of flexibility is a result of ''polymorphism'', which simply means that the an interface (like the logger interface in our example) can have ''many forms'', or implementations.  The way the language determines which one to invoke is through ''dynamic dispatch'', which is essentially a lookup table maintained as the program runs that maps calls to methods like logging to the implementations specified.&lt;br /&gt;
&lt;br /&gt;
The major theme here is that the object-oriented approach of favoring encapsulation has many effects that ripple throughout the design process, almost all of which allow programmers to reduce the brittleness of their software by delaying commitment to particular implementations.&lt;br /&gt;
&lt;br /&gt;
=Features of Functional Languages=&lt;br /&gt;
&lt;br /&gt;
Much like object-oriented languages, functional languages offer a dominant paradigm that has far-reaching consequences in software design.  For object-oriented languages, that element is encapsulation, and for functional languages, it is that functions are first-class entities, which simply means that functions are treated just like any other value in the language.  This allows them to be passed as parameters, delayed, composed invoked, and returned from other functions.  But what is a function?&lt;br /&gt;
&lt;br /&gt;
A function's most notable trait is that it is free of ''side-effects'', or state changes to the program that occur as a result of its execution.  We could say a lot about side effects, but the general rule is that a function will always return the same value given the same input.  This means that functions are ''stateless''.  Therefore, entities like random number generators and loggers are not functional, because they either store state or have some effect that is not related to the value they return.  Another way to think of functions is that they are completely defined in terms of their input and output.&lt;br /&gt;
&lt;br /&gt;
From this simple feature flows many characteristic language features.  We will discuss them in turn.&lt;br /&gt;
&lt;br /&gt;
==Immutability==&lt;br /&gt;
Maybe the most noticeable feature (or restriction) to programmers of languages that are not functional, [http://en.wikipedia.org/wiki/Immutable_object immutability] is one of the hallmarks of a functional language.  Most non-functional languages allow ''assignment'', or the ability to assign new values to variables as the program runs.  In functional programming, a value is declared only once and then never changes.  This feature of of the language flows out of the notion that functions have no side-effects, and is often viewed as more of a restriction than a feature.&lt;br /&gt;
&lt;br /&gt;
The power of immutability comes from the fact that programs that fully utilize immutability are much simpler than those that do not, making them amenable to automated analysis by a computer.  Computers can then prove various properties about function programs, like concurrent behavior (presence or absence of deadlock/livelock), memory usage, and what within what bounds various values in the program will lie.&lt;br /&gt;
&lt;br /&gt;
==Higher Order Functions==&lt;br /&gt;
&lt;br /&gt;
Higher order functions are simply functions that accept or return other functions as values.  This is made possible because functions are treated as first-class entities, and allows very expressive implementations of many algorithms to be written.&lt;br /&gt;
&lt;br /&gt;
There are several hallmark higher order functions: map, reduce, fold left/right and filter are a few examples.  Going into the intricacies of each is beyond the scope of this article, but Abelson and Sussman's seminal [http://mitpress.mit.edu/sicp/ Structure and Interpretation of Computer Programs] has an [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_sec_1.3.1 excellent treatment] of the subject.&lt;br /&gt;
&lt;br /&gt;
==Recursion==&lt;br /&gt;
&lt;br /&gt;
Programmers that are new to functional programming often balk at the notion that values cannot change over time (as variables do in imperative languages).  If values cannot change, how can we execute loops?&lt;br /&gt;
&lt;br /&gt;
The answer lies in recursion, where values are immutable, and loops are implemented as successive calls to the current function with new arguments.  The avoids the complexity of having values change over time while offering all the power of the loops we often see in imperative languages (for...each, do...while, etc.)  Again, a deep treatment of these language features is beyond the scope of this article, but again, Abelson and Sussman have [http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.1 addressed] the topic at some length in their book.&lt;br /&gt;
&lt;br /&gt;
==Delayed (Lazy) Evaluation==&lt;br /&gt;
An extremely powerful feature of functional programming that is enabled by immutability is ''lazy evaluation''.  This simply means that expressions can be defined, even recursively, and are not computed until the values that would result from that computation are needed.  This is possible because values in functional programs don't change over time, which means expressions can be evaluated at any point in time as needed.&lt;br /&gt;
&lt;br /&gt;
Take an imperative expression like this (in Java):&lt;br /&gt;
&lt;br /&gt;
  int i = 4;&lt;br /&gt;
  int j = i + 3;&lt;br /&gt;
  i++;&lt;br /&gt;
&lt;br /&gt;
If you evaluate these expressions in order, j will be equal to 7, but if you were to delay the evaluation of j until after the third line, j would be equal to 8.  This is a very simple example of how variables that change over time require expressions be evaluated in a particular order to maintain the correctness of the program.  Functional programming explicitly disallows the third line, and therefore enables the value of j to be calculated only when it is needed.  The implications of this are significant, as we'll see in the next section.&lt;br /&gt;
&lt;br /&gt;
=Hybrid Object-Oriented/Functional Languages=&lt;br /&gt;
&lt;br /&gt;
To programmers of languages like SmallTalk, Simula and Java, many of the features provided in functional languages will seem foreign or strange.  But, as discussed, there are significant advantages to the functional approach for certain types of programs.  While the object-oriented paradigm has proven itself to be very useful, many modern languages have sought to integrate functional features as well to increase the expressiveness and power of the language.  One such language is Scala, which, like Java, runs on the Java Virtual Machine (JVM), and is thus shares Java's libraries and portability while offering many [http://www.ibm.com/developerworks/java/library/j-scala01228.html functional features] that are not available in object-oriented languages like Java.  In the [http://www.scala-lang.org/node/25 overview] of Scala available on its homepage, Scala is briefly described:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
[Scala] smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application.&amp;quot;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
How does Scala allow code sizes to be reduced so much?  It uses sophisticated type inferencing to reduce type signature redundancy, allows for functional programming constructs to be used, and provides syntax for oft-used programming idioms.  Essentially, it takes the lessons learned from decades of functional and object-oriented programming experience and rolls them into a modern hybrid language that can make full use legacy Java code.&lt;br /&gt;
&lt;br /&gt;
Scala is representative of an entire class of hybrid object/functional languages like OCaml, F# and Fan, and therefore makes a good language for use in the examples in this article.  The intent is not to present highly technical examples, but rather to give readers an impression of how hybrid languages increase expressive power over their single-paradigm counterparts.&lt;br /&gt;
&lt;br /&gt;
==Case Classes==&lt;br /&gt;
Idiomatic object-oriented programming involves encapsulation of data, as previously discussed.  In older object-oriented languages, this required defining internal data values, and then providing necessary get and set methods to access and/or modify those values. Here is an example a class in Java that provides only get methods for some (immutable) values it holds.  It includes all the methods that ''should'' be included in such a class, including a toString, equals and hashCode method.  Note that is an error if such methods are ''not'' included in structural Java classes, which is why I include them here.&lt;br /&gt;
&lt;br /&gt;
  public class UserData {&lt;br /&gt;
      private final String firstName;&lt;br /&gt;
      private final String lastName;&lt;br /&gt;
      private final Integer age;&lt;br /&gt;
      public UserData(String firstName, String lastName, Integer age) {&lt;br /&gt;
          this.firstName = firstName;&lt;br /&gt;
          this.lastName = lastName;&lt;br /&gt;
          this.age = age;&lt;br /&gt;
      }&lt;br /&gt;
      public String getFirstName() {&lt;br /&gt;
          return this.firstName;&lt;br /&gt;
      }&lt;br /&gt;
      public String getLastName() {&lt;br /&gt;
          return this.lastName;&lt;br /&gt;
      }&lt;br /&gt;
      public Integer getAge() {&lt;br /&gt;
          return this.age;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public boolean equals(Object obj) {&lt;br /&gt;
          if (obj == null) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (getClass() != obj.getClass()) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          final UserData other = (UserData) obj;&lt;br /&gt;
          if ((this.firstName == null) ? (other.firstName != null) : !this.firstName.equals(other.firstName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if ((this.lastName == null) ? (other.lastName != null) : !this.lastName.equals(other.lastName)) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.age != other.age &amp;amp;&amp;amp; (this.age == null || !this.age.equals(other.age))) {&lt;br /&gt;
              return false;&lt;br /&gt;
          }&lt;br /&gt;
          return true;&lt;br /&gt;
      }&lt;br /&gt;
      @Override&lt;br /&gt;
      public int hashCode() {&lt;br /&gt;
          int hash = 7;&lt;br /&gt;
          hash = 19 * hash + (this.firstName != null ? this.firstName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.lastName != null ? this.lastName.hashCode() : 0);&lt;br /&gt;
          hash = 19 * hash + (this.age != null ? this.age.hashCode() : 0);&lt;br /&gt;
          return hash;&lt;br /&gt;
      }&lt;br /&gt;
      public String toString() {&lt;br /&gt;
          StringBuilder sb = new StringBuilder();&lt;br /&gt;
          sb.append(&amp;quot;UserData[firstName: &amp;quot;);&lt;br /&gt;
          sb.append(this.firstName);&lt;br /&gt;
          sb.append(&amp;quot; lastName: &amp;quot;);&lt;br /&gt;
          sb.append(this.lastName);&lt;br /&gt;
          sb.append(&amp;quot; age: &amp;quot;);&lt;br /&gt;
          sb.append(this.age);&lt;br /&gt;
          sb.append(&amp;quot;]&amp;quot;);&lt;br /&gt;
          return sb.toString();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, ''all'' the functionality of the above class can be expressed with:&lt;br /&gt;
&lt;br /&gt;
  case class UserData(val firstName: String, val lastName: String, val age: Int)&lt;br /&gt;
&lt;br /&gt;
To reiterate, the version in Scala actually does include a constructor, accessor methods, three fields that can only be set once, equals and hashCode  methods (comparing the structural equality of the two instances of the class), as well a meaningful toString method which prints the fields.&lt;br /&gt;
&lt;br /&gt;
There are numerous other benefits in using case classes, including automatic destructuring in pattern matching.  We will discuss these features in the next section.&lt;br /&gt;
&lt;br /&gt;
This feature by itself vastly reduces both development and maintenance burden for developers.  Classes in Scala are defined in lines, rather than entire files.  All the potential errors that could creep into that code are removed, and the ''intent'' of the developer is very clear.&lt;br /&gt;
&lt;br /&gt;
==Destructuring Binds and Pattern Matching==&lt;br /&gt;
Lisp, one of the earliest hybrid languages, offered primarily functional features with object-orientation built on top (in a system called CLOS).  One piece of functionality written with Common Lisp's metaprogramming facility was the ability to execute [http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_destructuring-bind.html destructuring binds], which are a powerful way of checking for a particular type ([http://en.wikipedia.org/wiki/Pattern_matching pattern matching]) and simultaneously extracting values from the inside of that type to use them in some computation. In the spirit of Common Lisp, Scala also offers destructuring binds and pattern matching.  Let's take a look at what they can do for us.&lt;br /&gt;
&lt;br /&gt;
Let us suppose we want to make use of our UserData class, defined above.  We want to find all users with ages over 18 and store their names in a database.  If we were to write a method that would simply do the database store for a single user, it might look like this:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      Integer age = user.getAge();&lt;br /&gt;
      if (age &amp;gt; 18) {&lt;br /&gt;
          recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In Scala, this would be a trivial pattern match, with a destructuring bind to capture the fields inside the UserData (in this case, we bind them to f, l and a):&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In this case, we don't get an enourmous savings in terms of the number of lines of code used, but we gain tremendously in expressive power.  Let's say we wanted to do the same thing, but not include users named &amp;quot;Bob&amp;quot;.  In Java:&lt;br /&gt;
&lt;br /&gt;
  public void storeName(UserData user) {&lt;br /&gt;
      String firstName = user.getFirstName();&lt;br /&gt;
      if (firstName != &amp;quot;Bob&amp;quot;) {&lt;br /&gt;
          Integer age = user.getAge();&lt;br /&gt;
          if (age &amp;gt; 18) {&lt;br /&gt;
              recordToDatabase(user.lastName, user.firstName);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
And now in Scala:&lt;br /&gt;
&lt;br /&gt;
  def storeName(user:UserData) = user match {&lt;br /&gt;
    case UserData(f, l, a) if a &amp;gt; 18 &amp;amp;&amp;amp; f != &amp;quot;Bob&amp;quot; =&amp;gt; recordToDatabase(l, a)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Hopefully this provides a little bit of insight into how destructuring can improve the expressiveness of your code.  A more in depth discussion on pattern matching and binding can be be found in [http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-4 Part 4] of Code Commit's series &amp;quot;Scala For Java Refugees&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==List Comprehension==&lt;br /&gt;
In imperative languages (including both procedural and object-oriented languages), it is common to loop very often, either with a for loop or a while loop.  Hybrid languages allow for this, and also incorporate more abstract operations on structures seen in functional programming.&lt;br /&gt;
&lt;br /&gt;
For example, suppose we wanted to take in a structure containing a bunch of UserData objects, and return a list of strings, containing the last name, a comma, and then the first name of each user.&lt;br /&gt;
&lt;br /&gt;
In Java, this might look like this:&lt;br /&gt;
&lt;br /&gt;
  public ArrayList&amp;lt;String&amp;gt; toStrings(ArrayList&amp;lt;UserData&amp;gt; users) {&lt;br /&gt;
      ArrayList&amp;lt;String&amp;gt; returnedList = new ArrayList&amp;lt;String&amp;gt;();&lt;br /&gt;
      for (UserData u : users) {&lt;br /&gt;
          returnedList.add(u.getLastName() + &amp;quot;, &amp;quot; + u.firstName);&lt;br /&gt;
      }&lt;br /&gt;
      return returnedList;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
In the seven lines of code, only the method declaration and the add to the new list really have anything to do with the business logic.  In Scala, that boiler plate can be avoided:&lt;br /&gt;
&lt;br /&gt;
  def toStrings(users: List[UserData]) = users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This method definition is so short that it is arguable we shouldn't even define the method, and should simply use the map operation inline:&lt;br /&gt;
&lt;br /&gt;
  users.map(u =&amp;gt; u.lastName + &amp;quot;, &amp;quot; + u.firstName)&lt;br /&gt;
&lt;br /&gt;
This is a small demonstration of how functional languages and object-oriented languages an combine their strengths.  We retain all the encapsulation of the object-oriented approach (although u.lastName and u.firstName appear to be fields, they are in fact accessor methods), but we also have the power of higher abstraction levels from the functional world (in this case, the map operation).&lt;br /&gt;
&lt;br /&gt;
==Lazy Evaluation==&lt;br /&gt;
The final feature I'd like to touch upon is lazy evaluation.  One of the many implications of lazy evaluation is that we can now program using infinite data structures; we define a way in which deeper parts of the data structure are calculated from the existing parts, and only lazily evaluate parts of the structure as they are accessed.  This allows us to express algorithms quite concisely.  This can be used in a variety of cases like random number generation, methods of successive approximation (like Newton's Method), fractal calculations, and generation of infinite series, as seen in the numerical methods or, more simply, the Fibonacci sequence.  Because it is so well known, I will use the Fibonacci sequence as an example here.  First, in Java:&lt;br /&gt;
&lt;br /&gt;
   public long fib(int k) {&lt;br /&gt;
       if (k &amp;lt;= 2) {&lt;br /&gt;
           return 1;&lt;br /&gt;
       } else {&lt;br /&gt;
           return fib(k-1) + fib(k-2);&lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
This is a short, inefficient, recursive solution.  It doesn't cache answers, either in a single call or across calls, which means it performs a huge amount of redundant computation.  So it has a number of problems, but it is concise.&lt;br /&gt;
&lt;br /&gt;
In Scala, we can remedy all those problems and remain concise using a [http://www.scala-lang.org/docu/files/api/scala/Stream.html Stream], a lazily evaluated form of a List:&lt;br /&gt;
&lt;br /&gt;
  val fibs: Stream[Int] = Stream(0,1) append fibs.zip(fibs.drop(1)).map(x =&amp;gt; x._1 + x._2)&lt;br /&gt;
&lt;br /&gt;
This definition is concise, offers automatic memoization and is thread-safe.  To add those features to the Java code would require 20 lines of additional code at a minimum.  It returns a Stream that can be queried for the kth Fibonacci number in the same way as the fib method defined in Java could, but calculates the 92rd Fibonacci in a fraction of a second.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
Unfortunately, this article barely scratches the surface of the topic.  There are decades of research and experience that have gone into modern programming languages, and the way in which they blend various programming paradigms blurs what were once quite distinct borders in the landscape of programming languages.  But, that blurring has allowed these modern languages to offer programmers a bigger set of tools that aren't merely an amalgamation of features from every language, but a carefully crafted blend of features that enhance the expressiveness of these languages while not substantially increasing the syntax or API surface area.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
If you want to know more about hybrid languages, its best to choose one (or a few!) and read about what they offer.  If you're familiar with Java, or C#, take a look at the [http://www.scala-lang.org/node/104 tour of Scala] or perhaps some of the [http://www.fandev.org/doc/docIntro/StartHere.html features of Fan].  &lt;br /&gt;
&lt;br /&gt;
There are also a few major dynamically typed hybrid languages.  Chief among these is [http://python.org Python], which has several implementations in [http://python.org C], [http://jython.org/ Java] and [http://codespeak.net/pypy/dist/pypy/doc/ Python](!).  [http://ruby-lang.org Ruby] is also a newer hybrid language, originating in Japan, but was made famous worldwide because of its [http://rubyonrails.org/ Rails] web programming framework that was possible in large part due to its hybrid nature.  It also has a [http://jruby.org/ Java implementation].  Finally, if you're working on the JVM an want a hybrid, dynamically-typed language with syntax that is close to Java's, [http://groovy.codehaus.org/ Groovy] is your best bet.&lt;br /&gt;
&lt;br /&gt;
If you're very interested in performance, Common Lisp may have something to offer you, and there are [http://www.sbcl.org/ several] [http://www.cons.org/cmucl/ performant] [http://clisp.cons.org/ implementations].  If you want to learn more about why hybrid languages are so powerful, Paul Graham's book [http://www.paulgraham.com/onlisp.html On Lisp] explains why.  If you really care about using the power of the JVM and are doing concurrent programming, a very modern lisp called [http://clojure.org Clojure] will be very interesting.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=19795</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=19795"/>
		<updated>2009-09-18T22:46:44Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: /* Distributed Version Control */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=  &lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability to track changes to a document, or set of documents, over many changes, or revisions.  For the vast majority of applications, version control systems have focused on tracking plain text files, such as those used for programming source code, HTML documents, and various markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underlays how data is ''shared'' and ''stored'' in a version control system. It should not be inferred from this structure that other attributes are not important to the history of developments of version control systems. There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is represented within the repository&lt;br /&gt;
&lt;br /&gt;
While these may seem to be three separate topics, we will see in the section on [[#Other Advances]] that they are in fact very closely related.&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems (like [http://en.wikipedia.org/wiki/Source_Code_Control_System  SCCS], 1972) focused on ''local version control''; that is, centralized computer systems that were used by many users, often at the same time. In such a system, there were often many users of the system and the ''repository'', or location in which the data was stored, was simply a directory on the server to which the users had access. Because of this use case, these systems focused on two main features:&lt;br /&gt;
&lt;br /&gt;
* File version tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Version Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in files at various points as they were altered, so that the history of changes made to files under version control was kept permanently. Thus, many users could alter many files over time, and the entire set of documents under version control at a given point in time could be recovered, preventing loss of valuable data, as well a providing a record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file simultaneously, one of the first features developed for version control systems was the ability to ''check out'' and ''lock'' a file. When a user checks out a file, he or she reserves the right to be the sole editor of that file until it is checked back in to version control.  Both SCCS and [http://www.gnu.org/software/rcs/ RCS] were designed for use in a shared environment and, as such, allowed files to be checked out and locked in this way.  Other users could check out the file, but only to view it.  Thus, the files were locked from editing by all but the user that had checked the file out most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems== &lt;br /&gt;
&lt;br /&gt;
These local systems had two primary problems.&lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to edit or access the information in the repository.  This often posed both performance and security risks, in addition to being cumbersome as networks became more prevalent.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at any given time. The next development in version control, embodied by CVS, sought to address both of these problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Version Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their changes to files, the need for a version control system that supported remote operations emerged.  The natural way to implement such remote operations was as an extension of the existing system, and by far the most prominent manifestation of this philosophy was present in [http://www.nongnu.org/cvs/ CVS], the concurrent versions system, which was initially based on RCS and began development in 1984 and matured throughout the mid- to late-1980s.  Version 1.0 was released under the [http://www.gnu.org/copyleft/gpl.html GNU GPL], a free software license, in the second half of 1990.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many users, each on his or her own machine, to be able to perform all the operations present in the original RCS, but over a network connection, and in a way that allowed for concurrent editing to take place.  This led to the development of a client-server model of version control systems, in which one central server would contain the canonical version of the repository, and various clients could connect to the central server and perform file check outs and commits.  This model is very similar to the original RCS model, but rather than requiring users of the system to log into the version control system locally, it allowed users to access and alter the contents of the repository over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among the first version control systems to support a ''non-locking repository''. This system allowed for concurrent editing of files under version control, and generated the need to develop new features that addressed the resulting complexities. Chief among the new features introduced to handle these complexities were the notions of ''branching'' and ''merging''. This allowed CVS to offer a non-locking repository, which is why there is an emphasis on the &amp;quot;concurrent&amp;quot; portion of CVS's name &amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to reconcile conflicting changes to the same file. A ''conflict'' is essentially two or more changes made to the same file that it may be difficult to merge into a final file that contains both sets of changes. An example of a conflict would occur if two users both edited a file on line 49, one changing the word &amp;quot;blue&amp;quot; to &amp;quot;red&amp;quot;, and the other changing the same word &amp;quot;blue&amp;quot; to &amp;quot;green&amp;quot;. The first user would then commit his or her changes back to the repository, and when the second user committed changes, the version control system would detect that the repostory had changed since the second user had obtained the file (since the first user had made a change and then committed it). At that point, the version control system would detect a conflict, and prompt the two users to coordinate to resolve the conflict to determine what text should be on line 49.&lt;br /&gt;
&lt;br /&gt;
The solution to this problem lies in allowing users of the version control system to ''branch'' a version of the repository and make (possibly many) changes to that branch independent of the changes occurring on the main branch of the repository, known as the ''trunk''. Once a logical set of changes was completed on a branch, that branch would then need to have its changes reconciled with the current state of the repository on the trunk. This process of reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature is critical in a multi-user client environment as it allows work to progress on multiple fronts simultaneously, only requiring that the files be merged once the users of the system are ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent access to the repository over the network, version control systems became more adept in the algorithms they used to detect conflicts and merge conflicts. This aspect of version control is discussed further in [[#Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
==Client-Server Beyond CVS==&lt;br /&gt;
&lt;br /&gt;
Although CVS developed good approaches to solving many of these problems, it had many problems that gained attention when it became the most widely used version control system for open source development. An exhaustive list would be lengthy, but to mention a few might be illustrative. &lt;br /&gt;
&lt;br /&gt;
* CVS doesn't provide ''atomic'' operations, which means that if there were a network failure during a commit, the repository could become corrupted. &lt;br /&gt;
* CVS does not version control directories or symbolic links, which means the repository is really a lossy copy of a developer's environment, sometimes resulting in failure to track changes accurately.&lt;br /&gt;
* CVS doesn't track what files were committed at the same time, so if you make a logical group of changes to several files and want to track the fact that those files were changed together, you can only only derive that information from log messages. CVS will not track it for you.&lt;br /&gt;
* CVS cannot track when files are renamed; rather, a rename of a file in CVS looks like the original file was deleted and a new file added, thus losing the file's history.&lt;br /&gt;
* Creating branches and managing the subsequent merges is slow and difficult.&lt;br /&gt;
&lt;br /&gt;
In short, while CVS provided a whole host of new features and advanced the state of the art in version control, it left room for improvement. This resulted in a vast number of client-server version control systems entering the market following CVS. One of the latest and most notable of these is [http://subversion.tigris.org/ Subversion], which seeks to address all of the [http://subversion.tigris.org/features.html issues] mentioned above and a whole lot more.&lt;br /&gt;
&lt;br /&gt;
=Distributed Version Control=&lt;br /&gt;
&lt;br /&gt;
In the late 1990s, a new paradigm of development started to emerge with the development of new, proprietary version control systems.  The first of these was [http://en.wikipedia.org/wiki/Sun_WorkShop_TeamWare Sun WorkShop TeamWare], the lead designer of which went on to found a new company, [http://www.bitkeeper.com/ BitMover], and develop the leading proprietary distributed version control system, BitKeeper.  These were the first distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
''Distributed'' version control system (DVCS) took many of the advances seen in client-server version control systems and moved them into a less centralized architecture. Essentially, the original version control systems were completely centralized, requiring every user to locally log in to the server on which the repository was located. In client-server version control systems, the system was made slightly more distributed, allowing users to connect from across the network to the repository, copy files from the repository to other machines for editing, and then commit them back to the server when edits were complete. Distributed version control continues the trend of decentralization by putting an entire repository, complete with a history of changes and ability to support remote connections, on each user's machine.&lt;br /&gt;
&lt;br /&gt;
One of the strengths of CVS is that it supports file locking even though the main advance it provides is a non-locking repository.. In the same way that CVS supports legacy locking work flows, so do distributed version control systems support the workflows usually associated with a centralized repository. The main improvement distributed version control systems offer, however, is they do not require a central server.  There are three advantages to this decentralized approach.&lt;br /&gt;
&lt;br /&gt;
First, it encourages creation of branches.  Specifically, every time a user &amp;quot;checks out&amp;quot; a file or group of files, a new branch is created on that users machine.  This is in stark contrast to the client-server model in which each time a branch is created, it is carefully planned and coordinated with other users of the system.  Essentially, branching and merging in a centralized system is often difficult and slow, and in a DVCS, it is designed to be natural and fast.&lt;br /&gt;
&lt;br /&gt;
Second, it allows users to commit their changes without disturbing other users of the system.  In typical client-server work flows, the notion of a ''commit'' is tightly coupled to the notion of a ''merge'' with the code that is currently in the repository.  Distributed version control decouples these two notions, allowing developers to commit freely, and merge with other users at a different time.&lt;br /&gt;
&lt;br /&gt;
Third, because each user has an entire copy of the repository, all work is done ''locally'', which allows users to continue doing work even when they don't have access to the internet or to a particular server.  Further, many useful operations which take a long time in a centralized system take an order of magnitude less time in a distributed system simply because the entire repository is local, and therefore no network latency is involved.&lt;br /&gt;
&lt;br /&gt;
All of these changes are made possible as networks have become faster and the computers on which end users now work are often as powerful as the servers that would host a centralized repository.  Thus, and the compute power has moved to the edge of the network, so too has the data in the repositories.&lt;br /&gt;
&lt;br /&gt;
This treatment might make it seem as though DVCS approaches are strictly superior to centralized networked approaches to version control.  In general, DVCS is considered to be an advancement of the state of the art, much as networked systems were considered superior to their local counterparts.  However, one common use case for version control systems is inside the firewall of a corporation, where work is done on possible proprietary or even classified data.  In such scenarios, there is often a strong desire, at least at the management level, to strongly control storage of the version controlled data.  Sometimes, such control is mandated by the customer.  In these cases, it may well be undesirable to have developers replicating data at will, and in places that are not well managed and controlled.  In these circumstances, it often makes sense to use a more centralized approach simply because the possibility of uncontrolled copying of the data represents a security risk.  Products like IBM's [http://www-01.ibm.com/software/awdtools/clearcase/ ClearCase] are designed to perform very centralized and controlled version control in such environments.&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems allowed users to access, modify and share data in the repository, many advances have been made in the way changes are merged, tracked and stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
Merge algorithms are a good way to frame the many of the problems that arise in a concurrent development environment.  It is therefore useful to start by discussing the issue of merge algorithms, even though relatively few advances have been made in recent years on the algorithms themselves.&lt;br /&gt;
&lt;br /&gt;
There are really two kinds of merging algorithm:&lt;br /&gt;
&lt;br /&gt;
* 2-way merge&lt;br /&gt;
* 3-way merge&lt;br /&gt;
&lt;br /&gt;
2-way merge was developed first, so we will discuss it first.&lt;br /&gt;
&lt;br /&gt;
===2-way Merge===&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Merge_%28revision_control%29#Two-way_merge 2-way Merge] takes two files and compares them for differences, merges differences that do not conflict and identifies differences that conflict for human resolution. [http://en.wikipedia.org/wiki/Diff diff] is a very well-known utility for performing such comparisons and its [http://en.wikipedia.org/wiki/Diff#Algorithm algorithm] is based upon a procedure for finding the [http://en.wikipedia.org/wiki/Longest_common_subsequence_problem longest common subsequence] of text in the files to be compared.  Methods for approaching this basic algorithm has gone largely unchanged since 1975, and the algorithm is used in both SCCS and RCS to create ''patches'' as a means of storing multiple versions of files under version control.&lt;br /&gt;
&lt;br /&gt;
While the 2-way merge approach is a good start to manage concurrent modification to the same resource in a version control system, it became apparent that while the merge algorithm was sound, the version control system actually had much more information than the merge program did, and therefore there were many cases in which a merge was ''conceptually'' easy, but proved to be difficult in practice.  In particular, given a knowledge of a ''common ancestor'' from which two files had both originated, a merge program could make more decisions autonomously, streamlining the merge process.  Thus, 3-way merge was born.&lt;br /&gt;
&lt;br /&gt;
===3-way Merge===&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Merge_%28revision_control%29#Three-way_merge 3-way merge] is an approach to merging two differing files with reference to a third file that is a common ancestor of the two differing files.  By comparing each of the differing files first to the ancestor, and then to each other, the merge program can merge conflicts without human intervention more often than is possible in a 2-way merge approach.&lt;br /&gt;
&lt;br /&gt;
This advancement alone made branching a much less risky proposition for development teams, and allowed distributed version control systems (which place special emphasis on a branched development approach) viable in both small and large development teams.  While both CVS and Subversion (and other modern client-server version control systems) made use of a 3-way merge approach, the newer distributed version control systems tracked groups of changes effectively, and represented the changes of sets of files as a directed acyclic graph ([http://en.wikipedia.org/wiki/Directed_acyclic_graph DAG]), making identification of ''useful'' common ancestors easier, and thus streamlining the merge process.  We will discuss each of these features in turn.&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
An issue closely related to merge algorithms is the issue of exactly ''which'' files the version control system inputs into a the 3-way merge.  In early client-server implementations, a file was the both the largest and smallest entity tracked by the version control system; that is, if several files were modified in support of a single logical change to e.g. a piece of software, those version control systems tracked changes to each individual file and had no tracking for the fact that a particular files changes were part of a larger entity (in this case, a group of files part of a single commit).&lt;br /&gt;
&lt;br /&gt;
While the algorithms to perform textual merges improved when the switch was made from 2-way to 3-way merges, most modern improvements for end users in the area of merge stem from how the files input into the merge algorithm are selected.  By tracking ''groups'' of changes, the version control system can make more effective decisions about which files to pick for merge, making the merge algorithms perform optimally.&lt;br /&gt;
&lt;br /&gt;
The ability to track groups of changes most noticeably affects merging improvements in two ways.&lt;br /&gt;
&lt;br /&gt;
First, even when changes are tracked in groups, sometimes a manual merge (one requiring user intervention) is required.  However, because the version control system can match patterns across mulitple files, if a similar merge is needed later (i.e. the same feature needs to be merged into another branch or the same branch at a later time), the version control system can &amp;quot;remember&amp;quot; the steps the user took to merge in that change and apply them automatically.  This feature has an enourmous impact on user productivity in practice.&lt;br /&gt;
&lt;br /&gt;
Second, tracking groups of changes allows the version control system to use algorithms that take advantage of that additional knowledge to better select ancestors for a 3-way merge.  The best way to understand this is to engage in a thought experiment.&lt;br /&gt;
&lt;br /&gt;
Imagine that you have a common code base, the trunk, from which two branches, A and B, are created.  Branch A has a set of changes (Set 1) applied to it.  Branch B has a different set of changes applied to it (Set 2).  Then, in another commit, Branch B has another set of changes applied to it (Set 3).  At this point, the user wishes to merge the two branches.  Let us also suppose that Set 1 and Set 2 are different sets of changes that ''do not conflict'' with one another.  Finally, let us also suppose that changes in Set 1 and Set 3 ''do'' conflict.&lt;br /&gt;
&lt;br /&gt;
In a legacy version control system, when the merge took place and some file were examined that was part of Set 1, 2 and 3, the version control system would pick the trunk as the ancestor of both versions of the file.  This would mean all the changes from Set 1, 2 and 3 would be examined simultaneously, presenting a complicated picture.&lt;br /&gt;
&lt;br /&gt;
In a modern version control system, the file with changes from Set 1 would be easily merged with the files with changes from Set 2.  This new file would then be chosen as the ancestor and merged with Set 3.  This approach vastly simplifies the merging process for both the computer and the user, but it requires that groups of changes be tracked together and applied individually.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Repository Data Representation==&lt;br /&gt;
&lt;br /&gt;
In most client-server (and local) version control implementations, the version control system tracks individual files.  The implication of this approach is that the entire view of the data within the system is file-centric.  CVS, for example, allows annotations, but only on a per-file basis.  One of the major recent advancements (pioneered by Git) is the ability to track the entire repository as a single monolithic entity.  &lt;br /&gt;
&lt;br /&gt;
One of the results of this is that modern systems (usually DVCS) can track single blocks of text (like a single function in a computer program) across several files if it were moved.  This allows users to focus on the actual data in the repository, rather than the files that hold the data.  One of the most well known negative effects of the file-centric approach appeared in CVS in which file renames would appear in the repository as delete-create pairs, resulting in loss of version history.&lt;br /&gt;
&lt;br /&gt;
Another result of decoupling data representation from the file system has already been mentioned: it allows groups of changes across multiple files to be tracked and associated.  A related notion is the the change history that was traditionally represented as a line in most client-server systems is being represented as a DAG in more modern systems.  The DAG is a more restricted data structure in some ways, but make many operations much simpler for the end user.  The most notable example is when merging from a branch multiple times, a DAG can accurately represent what changes have been incorporated, whereas the traditional file-system oriented approach leaves it as an exercise for the user to re-merge the same changes over and over.  This particular example is discussed in depth in Eric Sink's [http://www.ericsink.com/entries/merge_history.html article on merging].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Wikis as an Extension to Version Control=&lt;br /&gt;
&lt;br /&gt;
As use of the internet became more widespread and ''users'' of the web became some of its most important ''contributors'', concepts like the [http://en.wikipedia.org/wiki/Wiki Wiki] allowed users of a website to edit the website itself.  Often, the website was just a collection of files (pages) being served, that visitors could create, modify and remove.  One of the aspects of [http://c2.com/cgi/wiki?WikiCommunity WikiCommunity] is it is discussed on the original Wiki is the notion of a Wiki being open to change, and thus, Wikis tend to allow anonymous modifications to the wiki's pages.  From this simple fact emerged the idea of saving previous versions of the wiki's pages.&lt;br /&gt;
&lt;br /&gt;
So, taken loosely, Wikis are essentially web-enabled version control systems in which the users are anyone who visits the wiki.  This participatory culture lends itself to a distributed model of information exchange, and yet most wikis are still using what amounts to a local or client-server version control system behind the scenes.&lt;br /&gt;
&lt;br /&gt;
Looking to the future, it will be very interesting to see what can be done with wiki communities if they incorporate the important lessons learned from distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
The first (and only) example I have found of a community of users developing wiki-like content using distributed version control systems is [http://orgmode.org/worg/ Worg], a group of [http://www.gnu.org/software/emacs Emacs] [http://orgmode.org/ Org-Mode] users sharing information about the ways they use the Org-Mode software.  Incidentally, Worg is itself a collection of Org-Mode files stored in [http://git-scm.com/ Git], one of the most prominent distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
For quick refreshers on [http://betterexplained.com/articles/a-visual-guide-to-version-control/ Version Control] and [http://betterexplained.com/articles/intro-to-distributed-version-control-illustrated/ Distributed Version Control], BetterExplained has excellent, concise articles.&lt;br /&gt;
&lt;br /&gt;
Linus Torvalds, the creator and maintainer of both Linux kernel and Git, gave a entertaining and inforative [http://www.youtube.com/watch?v=4XpnKHJAok8&amp;amp;feature=player_embedded tech talk] at Google on version control and Git.  A fabulous resource.&lt;br /&gt;
&lt;br /&gt;
An excellent [http://www.ericsink.com/entries/merge_history.html entry] in Eric Sink's blog on how merge history and repostory representation are related.&lt;br /&gt;
&lt;br /&gt;
IBM has an well-written [http://www.ibm.com/developerworks/java/library/j-subversion/index.html DeveloperWorks article]  describing the ways is which Subversion improved upon CVS, along with some history of version control up until Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=19794</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=19794"/>
		<updated>2009-09-18T22:46:09Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: /* Distributed Version Control */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=  &lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability to track changes to a document, or set of documents, over many changes, or revisions.  For the vast majority of applications, version control systems have focused on tracking plain text files, such as those used for programming source code, HTML documents, and various markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underlays how data is ''shared'' and ''stored'' in a version control system. It should not be inferred from this structure that other attributes are not important to the history of developments of version control systems. There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is represented within the repository&lt;br /&gt;
&lt;br /&gt;
While these may seem to be three separate topics, we will see in the section on [[#Other Advances]] that they are in fact very closely related.&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems (like [http://en.wikipedia.org/wiki/Source_Code_Control_System  SCCS], 1972) focused on ''local version control''; that is, centralized computer systems that were used by many users, often at the same time. In such a system, there were often many users of the system and the ''repository'', or location in which the data was stored, was simply a directory on the server to which the users had access. Because of this use case, these systems focused on two main features:&lt;br /&gt;
&lt;br /&gt;
* File version tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Version Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in files at various points as they were altered, so that the history of changes made to files under version control was kept permanently. Thus, many users could alter many files over time, and the entire set of documents under version control at a given point in time could be recovered, preventing loss of valuable data, as well a providing a record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file simultaneously, one of the first features developed for version control systems was the ability to ''check out'' and ''lock'' a file. When a user checks out a file, he or she reserves the right to be the sole editor of that file until it is checked back in to version control.  Both SCCS and [http://www.gnu.org/software/rcs/ RCS] were designed for use in a shared environment and, as such, allowed files to be checked out and locked in this way.  Other users could check out the file, but only to view it.  Thus, the files were locked from editing by all but the user that had checked the file out most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems== &lt;br /&gt;
&lt;br /&gt;
These local systems had two primary problems.&lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to edit or access the information in the repository.  This often posed both performance and security risks, in addition to being cumbersome as networks became more prevalent.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at any given time. The next development in version control, embodied by CVS, sought to address both of these problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Version Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their changes to files, the need for a version control system that supported remote operations emerged.  The natural way to implement such remote operations was as an extension of the existing system, and by far the most prominent manifestation of this philosophy was present in [http://www.nongnu.org/cvs/ CVS], the concurrent versions system, which was initially based on RCS and began development in 1984 and matured throughout the mid- to late-1980s.  Version 1.0 was released under the [http://www.gnu.org/copyleft/gpl.html GNU GPL], a free software license, in the second half of 1990.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many users, each on his or her own machine, to be able to perform all the operations present in the original RCS, but over a network connection, and in a way that allowed for concurrent editing to take place.  This led to the development of a client-server model of version control systems, in which one central server would contain the canonical version of the repository, and various clients could connect to the central server and perform file check outs and commits.  This model is very similar to the original RCS model, but rather than requiring users of the system to log into the version control system locally, it allowed users to access and alter the contents of the repository over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among the first version control systems to support a ''non-locking repository''. This system allowed for concurrent editing of files under version control, and generated the need to develop new features that addressed the resulting complexities. Chief among the new features introduced to handle these complexities were the notions of ''branching'' and ''merging''. This allowed CVS to offer a non-locking repository, which is why there is an emphasis on the &amp;quot;concurrent&amp;quot; portion of CVS's name &amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to reconcile conflicting changes to the same file. A ''conflict'' is essentially two or more changes made to the same file that it may be difficult to merge into a final file that contains both sets of changes. An example of a conflict would occur if two users both edited a file on line 49, one changing the word &amp;quot;blue&amp;quot; to &amp;quot;red&amp;quot;, and the other changing the same word &amp;quot;blue&amp;quot; to &amp;quot;green&amp;quot;. The first user would then commit his or her changes back to the repository, and when the second user committed changes, the version control system would detect that the repostory had changed since the second user had obtained the file (since the first user had made a change and then committed it). At that point, the version control system would detect a conflict, and prompt the two users to coordinate to resolve the conflict to determine what text should be on line 49.&lt;br /&gt;
&lt;br /&gt;
The solution to this problem lies in allowing users of the version control system to ''branch'' a version of the repository and make (possibly many) changes to that branch independent of the changes occurring on the main branch of the repository, known as the ''trunk''. Once a logical set of changes was completed on a branch, that branch would then need to have its changes reconciled with the current state of the repository on the trunk. This process of reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature is critical in a multi-user client environment as it allows work to progress on multiple fronts simultaneously, only requiring that the files be merged once the users of the system are ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent access to the repository over the network, version control systems became more adept in the algorithms they used to detect conflicts and merge conflicts. This aspect of version control is discussed further in [[#Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
==Client-Server Beyond CVS==&lt;br /&gt;
&lt;br /&gt;
Although CVS developed good approaches to solving many of these problems, it had many problems that gained attention when it became the most widely used version control system for open source development. An exhaustive list would be lengthy, but to mention a few might be illustrative. &lt;br /&gt;
&lt;br /&gt;
* CVS doesn't provide ''atomic'' operations, which means that if there were a network failure during a commit, the repository could become corrupted. &lt;br /&gt;
* CVS does not version control directories or symbolic links, which means the repository is really a lossy copy of a developer's environment, sometimes resulting in failure to track changes accurately.&lt;br /&gt;
* CVS doesn't track what files were committed at the same time, so if you make a logical group of changes to several files and want to track the fact that those files were changed together, you can only only derive that information from log messages. CVS will not track it for you.&lt;br /&gt;
* CVS cannot track when files are renamed; rather, a rename of a file in CVS looks like the original file was deleted and a new file added, thus losing the file's history.&lt;br /&gt;
* Creating branches and managing the subsequent merges is slow and difficult.&lt;br /&gt;
&lt;br /&gt;
In short, while CVS provided a whole host of new features and advanced the state of the art in version control, it left room for improvement. This resulted in a vast number of client-server version control systems entering the market following CVS. One of the latest and most notable of these is [http://subversion.tigris.org/ Subversion], which seeks to address all of the [http://subversion.tigris.org/features.html issues] mentioned above and a whole lot more.&lt;br /&gt;
&lt;br /&gt;
=Distributed Version Control=&lt;br /&gt;
&lt;br /&gt;
In the late 1990s, a new paradigm of development started to emerge with the development of new, proprietary version control systems.  The first of these was [http://en.wikipedia.org/wiki/Sun_WorkShop_TeamWare Sun WorkShop TeamWare], the lead designer of which went on to found a new company, [http://www.bitkeeper.com/ BitMover], and develop the leading proprietary distributed version control system, BitKeeper.  These were the first distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
''Distributed'' version control system (DVCS) took many of the advances seen in client-server version control systems and moved them into a less centralized architecture. Essentially, the original version control systems were completely centralized, requiring every user to locally log in to the server on which the repository was located. In client-server version control systems, the system was made slightly more distributed, allowing users to connect from across the network to the repository, copy files from the repository to other machines for editing, and then commit them back to the server when edits were complete. Distributed version control continues the trend of decentralization by putting an entire repository, complete with a history of changes and ability to support remote connections, on each user's machine.&lt;br /&gt;
&lt;br /&gt;
One of the strengths of CVS is that it supports file locking even though the main advance it provides is a non-locking repository.. In the same way that CVS supports legacy locking work flows, so do distributed version control systems support the workflows usually associated with a centralized repository. The main improvement distributed version control systems offer, however, is they do not require a central server.  There are three advantages to this decentralized approach.&lt;br /&gt;
&lt;br /&gt;
First, it encourages creation of branches.  Specifically, every time a user &amp;quot;checks out&amp;quot; a file or group of files, a new branch is created on that users machine.  This is in stark contrast to the client-server model in which each time a branch is created, it is carefully planned and coordinated with other users of the system.  Essentially, branching and merging in a centralized system is often difficult and slow, and in a DVCS, it is designed to be natural and fast.&lt;br /&gt;
&lt;br /&gt;
Second, it allows users to commit their changes without disturbing other users of the system.  In typical client-server work flows, the notion of a ''commit'' is tightly coupled to the notion of a ''merge'' with the code that is currently in the repository.  Distributed version control decouples these two notions, allowing developers to commit freely, and merge with other users at a different time.&lt;br /&gt;
&lt;br /&gt;
Third, because each user has an entire copy of the repository, all work is done ''locally'', which allows users to continue doing work even when they don't have access to the internet or to a particular server.  Further, many useful operations which take a long time in a centralized system take an order of magnitude less time in a distributed system simply because the entire repository is local, and therefore no network latency is involved.&lt;br /&gt;
&lt;br /&gt;
All of these changes are made possible as networks have become faster and the computers on which end users now work are often as powerful as the servers that would host a centralized repository.  Thus, and the compute power has moved to the edge of the network, so too has the data in the repositories.&lt;br /&gt;
&lt;br /&gt;
This treatment might make it seem as though DVCS approaches are strictly superior on centralized networked approaches to version control.  In general, DVCS is considered to be an advancement of the state of the art, much as networked systems were considered superior to their local counterparts.  However, one common use case for version control systems is inside the firewall of a corporation, where work is done on possible proprietary or even classified data.  In such scenarios, there is often a strong desire, at least at the management level, to strongly control storage of the version controlled data.  Sometimes, such control is mandated by the customer.  In these cases, it may well be undesirable to have developers replicating data at will, and in places that are not well managed and controlled.  In these circumstances, it often makes sense to use a more centralized approach simply because the possibility of uncontrolled copying of the data represents a security risk.  Products like IBM's [http://www-01.ibm.com/software/awdtools/clearcase/ ClearCase] are designed to perform very centralized and controlled version control in such environments.&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems allowed users to access, modify and share data in the repository, many advances have been made in the way changes are merged, tracked and stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
Merge algorithms are a good way to frame the many of the problems that arise in a concurrent development environment.  It is therefore useful to start by discussing the issue of merge algorithms, even though relatively few advances have been made in recent years on the algorithms themselves.&lt;br /&gt;
&lt;br /&gt;
There are really two kinds of merging algorithm:&lt;br /&gt;
&lt;br /&gt;
* 2-way merge&lt;br /&gt;
* 3-way merge&lt;br /&gt;
&lt;br /&gt;
2-way merge was developed first, so we will discuss it first.&lt;br /&gt;
&lt;br /&gt;
===2-way Merge===&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Merge_%28revision_control%29#Two-way_merge 2-way Merge] takes two files and compares them for differences, merges differences that do not conflict and identifies differences that conflict for human resolution. [http://en.wikipedia.org/wiki/Diff diff] is a very well-known utility for performing such comparisons and its [http://en.wikipedia.org/wiki/Diff#Algorithm algorithm] is based upon a procedure for finding the [http://en.wikipedia.org/wiki/Longest_common_subsequence_problem longest common subsequence] of text in the files to be compared.  Methods for approaching this basic algorithm has gone largely unchanged since 1975, and the algorithm is used in both SCCS and RCS to create ''patches'' as a means of storing multiple versions of files under version control.&lt;br /&gt;
&lt;br /&gt;
While the 2-way merge approach is a good start to manage concurrent modification to the same resource in a version control system, it became apparent that while the merge algorithm was sound, the version control system actually had much more information than the merge program did, and therefore there were many cases in which a merge was ''conceptually'' easy, but proved to be difficult in practice.  In particular, given a knowledge of a ''common ancestor'' from which two files had both originated, a merge program could make more decisions autonomously, streamlining the merge process.  Thus, 3-way merge was born.&lt;br /&gt;
&lt;br /&gt;
===3-way Merge===&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Merge_%28revision_control%29#Three-way_merge 3-way merge] is an approach to merging two differing files with reference to a third file that is a common ancestor of the two differing files.  By comparing each of the differing files first to the ancestor, and then to each other, the merge program can merge conflicts without human intervention more often than is possible in a 2-way merge approach.&lt;br /&gt;
&lt;br /&gt;
This advancement alone made branching a much less risky proposition for development teams, and allowed distributed version control systems (which place special emphasis on a branched development approach) viable in both small and large development teams.  While both CVS and Subversion (and other modern client-server version control systems) made use of a 3-way merge approach, the newer distributed version control systems tracked groups of changes effectively, and represented the changes of sets of files as a directed acyclic graph ([http://en.wikipedia.org/wiki/Directed_acyclic_graph DAG]), making identification of ''useful'' common ancestors easier, and thus streamlining the merge process.  We will discuss each of these features in turn.&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
An issue closely related to merge algorithms is the issue of exactly ''which'' files the version control system inputs into a the 3-way merge.  In early client-server implementations, a file was the both the largest and smallest entity tracked by the version control system; that is, if several files were modified in support of a single logical change to e.g. a piece of software, those version control systems tracked changes to each individual file and had no tracking for the fact that a particular files changes were part of a larger entity (in this case, a group of files part of a single commit).&lt;br /&gt;
&lt;br /&gt;
While the algorithms to perform textual merges improved when the switch was made from 2-way to 3-way merges, most modern improvements for end users in the area of merge stem from how the files input into the merge algorithm are selected.  By tracking ''groups'' of changes, the version control system can make more effective decisions about which files to pick for merge, making the merge algorithms perform optimally.&lt;br /&gt;
&lt;br /&gt;
The ability to track groups of changes most noticeably affects merging improvements in two ways.&lt;br /&gt;
&lt;br /&gt;
First, even when changes are tracked in groups, sometimes a manual merge (one requiring user intervention) is required.  However, because the version control system can match patterns across mulitple files, if a similar merge is needed later (i.e. the same feature needs to be merged into another branch or the same branch at a later time), the version control system can &amp;quot;remember&amp;quot; the steps the user took to merge in that change and apply them automatically.  This feature has an enourmous impact on user productivity in practice.&lt;br /&gt;
&lt;br /&gt;
Second, tracking groups of changes allows the version control system to use algorithms that take advantage of that additional knowledge to better select ancestors for a 3-way merge.  The best way to understand this is to engage in a thought experiment.&lt;br /&gt;
&lt;br /&gt;
Imagine that you have a common code base, the trunk, from which two branches, A and B, are created.  Branch A has a set of changes (Set 1) applied to it.  Branch B has a different set of changes applied to it (Set 2).  Then, in another commit, Branch B has another set of changes applied to it (Set 3).  At this point, the user wishes to merge the two branches.  Let us also suppose that Set 1 and Set 2 are different sets of changes that ''do not conflict'' with one another.  Finally, let us also suppose that changes in Set 1 and Set 3 ''do'' conflict.&lt;br /&gt;
&lt;br /&gt;
In a legacy version control system, when the merge took place and some file were examined that was part of Set 1, 2 and 3, the version control system would pick the trunk as the ancestor of both versions of the file.  This would mean all the changes from Set 1, 2 and 3 would be examined simultaneously, presenting a complicated picture.&lt;br /&gt;
&lt;br /&gt;
In a modern version control system, the file with changes from Set 1 would be easily merged with the files with changes from Set 2.  This new file would then be chosen as the ancestor and merged with Set 3.  This approach vastly simplifies the merging process for both the computer and the user, but it requires that groups of changes be tracked together and applied individually.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Repository Data Representation==&lt;br /&gt;
&lt;br /&gt;
In most client-server (and local) version control implementations, the version control system tracks individual files.  The implication of this approach is that the entire view of the data within the system is file-centric.  CVS, for example, allows annotations, but only on a per-file basis.  One of the major recent advancements (pioneered by Git) is the ability to track the entire repository as a single monolithic entity.  &lt;br /&gt;
&lt;br /&gt;
One of the results of this is that modern systems (usually DVCS) can track single blocks of text (like a single function in a computer program) across several files if it were moved.  This allows users to focus on the actual data in the repository, rather than the files that hold the data.  One of the most well known negative effects of the file-centric approach appeared in CVS in which file renames would appear in the repository as delete-create pairs, resulting in loss of version history.&lt;br /&gt;
&lt;br /&gt;
Another result of decoupling data representation from the file system has already been mentioned: it allows groups of changes across multiple files to be tracked and associated.  A related notion is the the change history that was traditionally represented as a line in most client-server systems is being represented as a DAG in more modern systems.  The DAG is a more restricted data structure in some ways, but make many operations much simpler for the end user.  The most notable example is when merging from a branch multiple times, a DAG can accurately represent what changes have been incorporated, whereas the traditional file-system oriented approach leaves it as an exercise for the user to re-merge the same changes over and over.  This particular example is discussed in depth in Eric Sink's [http://www.ericsink.com/entries/merge_history.html article on merging].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Wikis as an Extension to Version Control=&lt;br /&gt;
&lt;br /&gt;
As use of the internet became more widespread and ''users'' of the web became some of its most important ''contributors'', concepts like the [http://en.wikipedia.org/wiki/Wiki Wiki] allowed users of a website to edit the website itself.  Often, the website was just a collection of files (pages) being served, that visitors could create, modify and remove.  One of the aspects of [http://c2.com/cgi/wiki?WikiCommunity WikiCommunity] is it is discussed on the original Wiki is the notion of a Wiki being open to change, and thus, Wikis tend to allow anonymous modifications to the wiki's pages.  From this simple fact emerged the idea of saving previous versions of the wiki's pages.&lt;br /&gt;
&lt;br /&gt;
So, taken loosely, Wikis are essentially web-enabled version control systems in which the users are anyone who visits the wiki.  This participatory culture lends itself to a distributed model of information exchange, and yet most wikis are still using what amounts to a local or client-server version control system behind the scenes.&lt;br /&gt;
&lt;br /&gt;
Looking to the future, it will be very interesting to see what can be done with wiki communities if they incorporate the important lessons learned from distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
The first (and only) example I have found of a community of users developing wiki-like content using distributed version control systems is [http://orgmode.org/worg/ Worg], a group of [http://www.gnu.org/software/emacs Emacs] [http://orgmode.org/ Org-Mode] users sharing information about the ways they use the Org-Mode software.  Incidentally, Worg is itself a collection of Org-Mode files stored in [http://git-scm.com/ Git], one of the most prominent distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
For quick refreshers on [http://betterexplained.com/articles/a-visual-guide-to-version-control/ Version Control] and [http://betterexplained.com/articles/intro-to-distributed-version-control-illustrated/ Distributed Version Control], BetterExplained has excellent, concise articles.&lt;br /&gt;
&lt;br /&gt;
Linus Torvalds, the creator and maintainer of both Linux kernel and Git, gave a entertaining and inforative [http://www.youtube.com/watch?v=4XpnKHJAok8&amp;amp;feature=player_embedded tech talk] at Google on version control and Git.  A fabulous resource.&lt;br /&gt;
&lt;br /&gt;
An excellent [http://www.ericsink.com/entries/merge_history.html entry] in Eric Sink's blog on how merge history and repostory representation are related.&lt;br /&gt;
&lt;br /&gt;
IBM has an well-written [http://www.ibm.com/developerworks/java/library/j-subversion/index.html DeveloperWorks article]  describing the ways is which Subversion improved upon CVS, along with some history of version control up until Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=19036</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=19036"/>
		<updated>2009-09-11T06:42:05Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction= &lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability to track changes to a document, or set of documents, over many changes, or revisions.  For the vast majority of applications, version control systems have focused on tracking plain text files, such as those used for programming source code, HTML documents, and various markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underlays how data is ''shared'' and ''stored'' in a version control system. It should not be inferred from this structure that other attributes are not important to the history of developments of version control systems. There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is represented within the repository&lt;br /&gt;
&lt;br /&gt;
While these may seem to be three separate topics, we will see in the section on [[#Other Advances]] that they are in fact very closely related.&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems (like [http://en.wikipedia.org/wiki/Source_Code_Control_System  SCCS], 1972) focused on ''local version control''; that is, centralized computer systems that were used by many users, often at the same time. In such a system, there were often many users of the system and the ''repository'', or location in which the data was stored, was simply a directory on the server to which the users had access. Because of this use case, these systems focused on two main features:&lt;br /&gt;
&lt;br /&gt;
* File version tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Version Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in files at various points as they were altered, so that the history of changes made to files under version control was kept permanently. Thus, many users could alter many files over time, and the entire set of documents under version control at a given point in time could be recovered, preventing loss of valuable data, as well a providing a record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file simultaneously, one of the first features developed for version control systems was the ability to ''check out'' and ''lock'' a file. When a user checks out a file, he or she reserves the right to be the sole editor of that file until it is checked back in to version control.  Both SCCS and [http://www.gnu.org/software/rcs/ RCS] were designed for use in a shared environment and, as such, allowed files to be checked out and locked in this way.  Other users could check out the file, but only to view it.  Thus, the files were locked from editing by all but the user that had checked the file out most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems== &lt;br /&gt;
&lt;br /&gt;
These local systems had two primary problems.&lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to edit or access the information in the repository.  This often posed both performance and security risks, in addition to being cumbersome as networks became more prevalent.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at any given time. The next development in version control, embodied by CVS, sought to address both of these problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Version Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their changes to files, the need for a version control system that supported remote operations emerged.  The natural way to implement such remote operations was as an extension of the existing system, and by far the most prominent manifestation of this philosophy was present in [http://www.nongnu.org/cvs/ CVS], the concurrent versions system, which was initially based on RCS and began development in 1984 and matured throughout the mid- to late-1980s.  Version 1.0 was released under the [http://www.gnu.org/copyleft/gpl.html GNU GPL], a free software license, in the second half of 1990.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many users, each on his or her own machine, to be able to perform all the operations present in the original RCS, but over a network connection, and in a way that allowed for concurrent editing to take place.  This led to the development of a client-server model of version control systems, in which one central server would contain the canonical version of the repository, and various clients could connect to the central server and perform file check outs and commits.  This model is very similar to the original RCS model, but rather than requiring users of the system to log into the version control system locally, it allowed users to access and alter the contents of the repository over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among the first version control systems to support a ''non-locking repository''. This system allowed for concurrent editing of files under version control, and generated the need to develop new features that addressed the resulting complexities. Chief among the new features introduced to handle these complexities were the notions of ''branching'' and ''merging''. This allowed CVS to offer a non-locking repository, which is why there is an emphasis on the &amp;quot;concurrent&amp;quot; portion of CVS's name &amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to reconcile conflicting changes to the same file. A ''conflict'' is essentially two or more changes made to the same file that it may be difficult to merge into a final file that contains both sets of changes. An example of a conflict would occur if two users both edited a file on line 49, one changing the word &amp;quot;blue&amp;quot; to &amp;quot;red&amp;quot;, and the other changing the same word &amp;quot;blue&amp;quot; to &amp;quot;green&amp;quot;. The first user would then commit his or her changes back to the repository, and when the second user committed changes, the version control system would detect that the repostory had changed since the second user had obtained the file (since the first user had made a change and then committed it). At that point, the version control system would detect a conflict, and prompt the two users to coordinate to resolve the conflict to determine what text should be on line 49.&lt;br /&gt;
&lt;br /&gt;
The solution to this problem lies in allowing users of the version control system to ''branch'' a version of the repository and make (possibly many) changes to that branch independent of the changes occurring on the main branch of the repository, known as the ''trunk''. Once a logical set of changes was completed on a branch, that branch would then need to have its changes reconciled with the current state of the repository on the trunk. This process of reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature is critical in a multi-user client environment as it allows work to progress on multiple fronts simultaneously, only requiring that the files be merged once the users of the system are ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent access to the repository over the network, version control systems became more adept in the algorithms they used to detect conflicts and merge conflicts. This aspect of version control is discussed further in [[#Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
==Client-Server Beyond CVS==&lt;br /&gt;
&lt;br /&gt;
Although CVS developed good approaches to solving many of these problems, it had many problems that gained attention when it became the most widely used version control system for open source development. An exhaustive list would be lengthy, but to mention a few might be illustrative. &lt;br /&gt;
&lt;br /&gt;
* CVS doesn't provide ''atomic'' operations, which means that if there were a network failure during a commit, the repository could become corrupted. &lt;br /&gt;
* CVS does not version control directories or symbolic links, which means the repository is really a lossy copy of a developer's environment, sometimes resulting in failure to track changes accurately.&lt;br /&gt;
* CVS doesn't track what files were committed at the same time, so if you make a logical group of changes to several files and want to track the fact that those files were changed together, you can only only derive that information from log messages. CVS will not track it for you.&lt;br /&gt;
* CVS cannot track when files are renamed; rather, a rename of a file in CVS looks like the original file was deleted and a new file added, thus losing the file's history.&lt;br /&gt;
* Creating branches and managing the subsequent merges is slow and difficult.&lt;br /&gt;
&lt;br /&gt;
In short, while CVS provided a whole host of new features and advanced the state of the art in version control, it left room for improvement. This resulted in a vast number of client-server version control systems entering the market following CVS. One of the latest and most notable of these is [http://subversion.tigris.org/ Subversion], which seeks to address all of the [http://subversion.tigris.org/features.html issues] mentioned above and a whole lot more.&lt;br /&gt;
&lt;br /&gt;
=Distributed Version Control=&lt;br /&gt;
&lt;br /&gt;
In the late 1990s, a new paradigm of development started to emerge with the development of new, proprietary version control systems.  The first of these was [http://en.wikipedia.org/wiki/Sun_WorkShop_TeamWare Sun WorkShop TeamWare], the lead designer of which went on to found a new company, [http://www.bitkeeper.com/ BitMover], and develop the leading proprietary distributed version control system, BitKeeper.  These were the first distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
''Distributed'' version control system (DVCS) took many of the advances seen in client-server version control systems and moved them into a less centralized architecture. Essentially, the original version control systems were completely centralized, requiring every user to locally log in to the server on which the repository was located. In client-server version control systems, the system was made slightly more distributed, allowing users to connect from across the network to the repository, copy files from the repository to other machines for editing, and then commit them back to the server when edits were complete. Distributed version control continues the trend of decentralization by putting an entire repository, complete with a history of changes and ability to support remote connections, on each user's machine.&lt;br /&gt;
&lt;br /&gt;
One of the strengths of CVS is that it supports file locking even though the main advance it provides is a non-locking repository.. In the same way that CVS supports legacy locking work flows, so do distributed version control systems support the workflows usually associated with a centralized repository. The main improvement distributed version control systems offer, however, is they do not require a central server.  There are three advantages to this decentralized approach.&lt;br /&gt;
&lt;br /&gt;
First, it encourages creation of branches.  Specifically, every time a user &amp;quot;checks out&amp;quot; a file or group of files, a new branch is created on that users machine.  This is in stark contrast to the client-server model in which each time a branch is created, it is carefully planned and coordinated with other users of the system.  Essentially, branching and merging in a centralized system is often difficult and slow, and in a DVCS, it is designed to be natural and fast.&lt;br /&gt;
&lt;br /&gt;
Second, it allows users to commit their changes without disturbing other users of the system.  In typical client-server work flows, the notion of a ''commit'' is tightly coupled to the notion of a ''merge'' with the code that is currently in the repository.  Distributed version control decouples these two notions, allowing developers to commit freely, and merge with other users at a different time.&lt;br /&gt;
&lt;br /&gt;
Third, because each user has an entire copy of the repository, all work is done ''locally'', which allows users to continue doing work even when they don't have access to the internet or to a particular server.  Further, many useful operations which take a long time in a centralized system take an order of magnitude less time in a distributed system simply because the entire repository is local, and therefore no network latency is involved.&lt;br /&gt;
&lt;br /&gt;
All of these changes are made possible as networks have become faster and the computers on which end users now work are often as powerful as the servers that would host a centralized repository.  Thus, and the compute power has moved to the edge of the network, so too has the data in the repositories.&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems allowed users to access, modify and share data in the repository, many advances have been made in the way changes are merged, tracked and stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
Merge algorithms are a good way to frame the many of the problems that arise in a concurrent development environment.  It is therefore useful to start by discussing the issue of merge algorithms, even though relatively few advances have been made in recent years on the algorithms themselves.&lt;br /&gt;
&lt;br /&gt;
There are really two kinds of merging algorithm:&lt;br /&gt;
&lt;br /&gt;
* 2-way merge&lt;br /&gt;
* 3-way merge&lt;br /&gt;
&lt;br /&gt;
2-way merge was developed first, so we will discuss it first.&lt;br /&gt;
&lt;br /&gt;
===2-way Merge===&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Merge_%28revision_control%29#Two-way_merge 2-way Merge] takes two files and compares them for differences, merges differences that do not conflict and identifies differences that conflict for human resolution. [http://en.wikipedia.org/wiki/Diff diff] is a very well-known utility for performing such comparisons and its [http://en.wikipedia.org/wiki/Diff#Algorithm algorithm] is based upon a procedure for finding the [http://en.wikipedia.org/wiki/Longest_common_subsequence_problem longest common subsequence] of text in the files to be compared.  Methods for approaching this basic algorithm has gone largely unchanged since 1975, and the algorithm is used in both SCCS and RCS to create ''patches'' as a means of storing multiple versions of files under version control.&lt;br /&gt;
&lt;br /&gt;
While the 2-way merge approach is a good start to manage concurrent modification to the same resource in a version control system, it became apparent that while the merge algorithm was sound, the version control system actually had much more information than the merge program did, and therefore there were many cases in which a merge was ''conceptually'' easy, but proved to be difficult in practice.  In particular, given a knowledge of a ''common ancestor'' from which two files had both originated, a merge program could make more decisions autonomously, streamlining the merge process.  Thus, 3-way merge was born.&lt;br /&gt;
&lt;br /&gt;
===3-way Merge===&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Merge_%28revision_control%29#Three-way_merge 3-way merge] is an approach to merging two differing files with reference to a third file that is a common ancestor of the two differing files.  By comparing each of the differing files first to the ancestor, and then to each other, the merge program can merge conflicts without human intervention more often than is possible in a 2-way merge approach.&lt;br /&gt;
&lt;br /&gt;
This advancement alone made branching a much less risky proposition for development teams, and allowed distributed version control systems (which place special emphasis on a branched development approach) viable in both small and large development teams.  While both CVS and Subversion (and other modern client-server version control systems) made use of a 3-way merge approach, the newer distributed version control systems tracked groups of changes effectively, and represented the changes of sets of files as a directed acyclic graph ([http://en.wikipedia.org/wiki/Directed_acyclic_graph DAG]), making identification of ''useful'' common ancestors easier, and thus streamlining the merge process.  We will discuss each of these features in turn.&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
An issue closely related to merge algorithms is the issue of exactly ''which'' files the version control system inputs into a the 3-way merge.  In early client-server implementations, a file was the both the largest and smallest entity tracked by the version control system; that is, if several files were modified in support of a single logical change to e.g. a piece of software, those version control systems tracked changes to each individual file and had no tracking for the fact that a particular files changes were part of a larger entity (in this case, a group of files part of a single commit).&lt;br /&gt;
&lt;br /&gt;
While the algorithms to perform textual merges improved when the switch was made from 2-way to 3-way merges, most modern improvements for end users in the area of merge stem from how the files input into the merge algorithm are selected.  By tracking ''groups'' of changes, the version control system can make more effective decisions about which files to pick for merge, making the merge algorithms perform optimally.&lt;br /&gt;
&lt;br /&gt;
==Repository Data Representation==&lt;br /&gt;
&lt;br /&gt;
In most client-server (and local) version control implementations, the version control system tracks individual files.  The implication of this approach is that the entire view of the data within the system is file-centric.  CVS, for example, allows annotations, but only on a per-file basis.  One of the major recent advancements (pioneered by Git) is the ability to track the entire repository as a single monolithic entity.  &lt;br /&gt;
&lt;br /&gt;
One of the results of this is that modern systems (usually DVCS) can track single blocks of text (like a single function in a computer program) across several files if it were moved.  This allows users to focus on the actual data in the repository, rather than the files that hold the data.  One of the most well known negative effects of the file-centric approach appeared in CVS in which file renames would appear in the repository as delete-create pairs, resulting in loss of version history.&lt;br /&gt;
&lt;br /&gt;
Another result of decoupling data representation from the file system has already been mentioned: it allows groups of changes across multiple files to be tracked and associated.  A related notion is the the change history that was traditionally represented as a line in most client-server systems is being represented as a DAG in more modern systems.  The DAG is a more restricted data structure in some ways, but make many operations much simpler for the end user.  The most notable example is when merging from a branch multiple times, a DAG can accurately represent what changes have been incorporated, whereas the traditional file-system oriented approach leaves it as an exercise for the user to re-merge the same changes over and over.  This particular example is discussed in depth in Eric Sink's [http://www.ericsink.com/entries/merge_history.html article on merging].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Wikis as an Extension to Version Control=&lt;br /&gt;
&lt;br /&gt;
As use of the internet became more widespread and ''users'' of the web became some of its most important ''contributors'', concepts like the [http://en.wikipedia.org/wiki/Wiki Wiki] allowed users of a website to edit the website itself.  Often, the website was just a collection of files (pages) being served, that visitors could create, modify and remove.  One of the aspects of [http://c2.com/cgi/wiki?WikiCommunity WikiCommunity] is it is discussed on the original Wiki is the notion of a Wiki being open to change, and thus, Wikis tend to allow anonymous modifications to the wiki's pages.  From this simple fact emerged the idea of saving previous versions of the wiki's pages.&lt;br /&gt;
&lt;br /&gt;
So, taken loosely, Wikis are essentially web-enabled version control systems in which the users are anyone who visits the wiki.  This participatory culture lends itself to a distributed model of information exchange, and yet most wikis are still using what amounts to a local or client-server version control system behind the scenes.&lt;br /&gt;
&lt;br /&gt;
Looking to the future, it will be very interesting to see what can be done with wiki communities if they incorporate the important lessons learned from distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
The first (and only) example I have found of a community of users developing wiki-like content using distributed version control systems is [http://orgmode.org/worg/ Worg], a group of [http://www.gnu.org/software/emacs Emacs] [http://orgmode.org/ Org-Mode] users sharing information about the ways they use the Org-Mode software.  Incidentally, Worg is itself a collection of Org-Mode files stored in [http://git-scm.com/ Git], one of the most prominent distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
For quick refreshers on [http://betterexplained.com/articles/a-visual-guide-to-version-control/ Version Control] and [http://betterexplained.com/articles/intro-to-distributed-version-control-illustrated/ Distributed Version Control], BetterExplained has excellent, concise articles.&lt;br /&gt;
&lt;br /&gt;
Linus Torvalds, the creator and maintainer of both Linux kernel and Git, gave a entertaining and inforative [http://www.youtube.com/watch?v=4XpnKHJAok8&amp;amp;feature=player_embedded tech talk] at Google on version control and Git.  A fabulous resource.&lt;br /&gt;
&lt;br /&gt;
An excellent [http://www.ericsink.com/entries/merge_history.html entry] in Eric Sink's blog on how merge history and repostory representation are related.&lt;br /&gt;
&lt;br /&gt;
IBM has an well-written [http://www.ibm.com/developerworks/java/library/j-subversion/index.html DeveloperWorks article]  describing the ways is which Subversion improved upon CVS, along with some history of version control up until Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=18665</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=18665"/>
		<updated>2009-09-08T07:26:10Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability to track changes to a document, or set of documents, over many changes, or revisions.  For the vast majority of applications, version control systems have focused on tracking plain text files, such as those used for programming source code, HTML documents, and various markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underlays how data is ''shared'' and ''stored'' in a version control system. It should not be inferred from this structure that other attributes are not important to the history of developments of version control systems. There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is represented within the repository&lt;br /&gt;
&lt;br /&gt;
While these may seem to be three separate topics, we will see in the section on [[#Other Advances]] that they are in fact very closely related.&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems (like [http://en.wikipedia.org/wiki/Source_Code_Control_System  SCCS], 1972) focused on ''local version control''; that is, centralized computer systems that were used by many users, often at the same time. In such a system, there were often many users of the system and the ''repository'', or location in which the data was stored, was simply a directory on the server to which the users had access. Because of this use case, these systems focused on two main features:&lt;br /&gt;
&lt;br /&gt;
* File version tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Version Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in files at various points as they were altered, so that the history of changes made to files under version control was kept permanently. Thus, many users could alter many files over time, and the entire set of documents under version control at a given point in time could be recovered, preventing loss of valuable data, as well a providing a record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file simultaneously, one of the first features developed for version control systems was the ability to ''check out'' and ''lock'' a file. When a user checks out a file, he or she reserves the right to be the sole editor of that file until it is checked back in to version control.  Both SCCS and [http://www.gnu.org/software/rcs/ RCS] were designed for use in a shared environment and, as such, allowed files to be checked out and locked in this way.  Other users could check out the file, but only to view it.  Thus, the files were locked from editing by all but the user that had checked the file out most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems== &lt;br /&gt;
&lt;br /&gt;
These local systems had two primary problems.&lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to edit or access the information in the repository.  This often posed both performance and security risks, in addition to being cumbersome as networks became more prevalent.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at any given time. The next development in version control, embodied by CVS, sought to address both of these problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Version Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their changes to files, the need for a version control system that supported remote operations emerged.  The natural way to implement such remote operations was as an extension of the existing system, and by far the most prominent manifestation of this philosophy was present in [http://www.nongnu.org/cvs/ CVS], the concurrent versions system, which was initially based on RCS and began development in 1984 and matured throughout the mid- to late-1980s.  Version 1.0 was released under the [http://www.gnu.org/copyleft/gpl.html GNU GPL], a free software license, in the second half of 1990.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many users, each on his or her own machine, to be able to perform all the operations present in the original RCS, but over a network connection, and in a way that allowed for concurrent editing to take place.  This led to the development of a client-server model of version control systems, in which one central server would contain the canonical version of the repository, and various clients could connect to the central server and perform file check outs and commits.  This model is very similar to the original RCS model, but rather than requiring users of the system to log into the version control system locally, it allowed users to access and alter the contents of the repository over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among the first version control systems to support a ''non-locking repository''. This system allowed for concurrent editing of files under version control, and generated the need to develop new features that addressed the resulting complexities. Chief among the new features introduced to handle these complexities were the notions of ''branching'' and ''merging''. This allowed CVS to offer a non-locking repository, which is why there is an emphasis on the &amp;quot;concurrent&amp;quot; portion of CVS's name &amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to reconcile conflicting changes to the same file. A ''conflict'' is essentially two or more changes made to the same file that it may be difficult to merge into a final file that contains both sets of changes. An example of a conflict would occur if two users both edited a file on line 49, one changing the word &amp;quot;blue&amp;quot; to &amp;quot;red&amp;quot;, and the other changing the same word &amp;quot;blue&amp;quot; to &amp;quot;green&amp;quot;. The first user would then commit his or her changes back to the repository, and when the second user committed changes, the version control system would detect that the repostory had changed since the second user had obtained the file (since the first user had made a change and then committed it). At that point, the version control system would detect a conflict, and prompt the two users to coordinate to resolve the conflict to determine what text should be on line 49.&lt;br /&gt;
&lt;br /&gt;
The solution to this problem lies in allowing users of the version control system to ''branch'' a version of the repository and make (possibly many) changes to that branch independent of the changes occurring on the main branch of the repository, known as the ''trunk''. Once a logical set of changes was completed on a branch, that branch would then need to have its changes reconciled with the current state of the repository on the trunk. This process of reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature is critical in a multi-user client environment as it allows work to progress on multiple fronts simultaneously, only requiring that the files be merged once the users of the system are ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent access to the repository over the network, version control systems became more adept in the algorithms they used to detect conflicts and merge conflicts. This aspect of version control is discussed further in [[#Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
==Client-Server Beyond CVS==&lt;br /&gt;
&lt;br /&gt;
Although CVS developed good approaches to solving many of these problems, it had many problems that gained attention when it became the most widely used version control system for open source development. An exhaustive list would be lengthy, but to mention a few might be illustrative. &lt;br /&gt;
&lt;br /&gt;
* CVS doesn't provide ''atomic'' operations, which means that if there were a network failure during a commit, the repository could become corrupted. &lt;br /&gt;
* CVS does not version control directories or symbolic links, which means the repository is really a lossy copy of a developer's environment, sometimes resulting in failure to track changes accurately.&lt;br /&gt;
* CVS doesn't track what files were committed at the same time, so if you make a logical group of changes to several files and want to track the fact that those files were changed together, you can only only derive that information from log messages. CVS will not track it for you.&lt;br /&gt;
* CVS cannot track when files are renamed; rather, a rename of a file in CVS looks like the original file was deleted and a new file added, thus losing the file's history.&lt;br /&gt;
* Creating branches and managing the subsequent merges is slow and difficult.&lt;br /&gt;
&lt;br /&gt;
In short, while CVS provided a whole host of new features and advanced the state of the art in version control, it left room for improvement. This resulted in a vast number of client-server version control systems entering the market following CVS. One of the latest and most notable of these is [http://subversion.tigris.org/ Subversion], which seeks to address all of the [http://subversion.tigris.org/features.html issues] mentioned above and a whole lot more.&lt;br /&gt;
&lt;br /&gt;
=Distributed Version Control=&lt;br /&gt;
&lt;br /&gt;
In the late 1990s, a new paradigm of development started to emerge with the development of new, proprietary version control systems.  The first of these was [http://en.wikipedia.org/wiki/Sun_WorkShop_TeamWare Sun WorkShop TeamWare], the lead designer of which went on to found a new company, [http://www.bitkeeper.com/ BitMover], and develop the leading proprietary distributed version control system, BitKeeper.  These were the first distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
''Distributed'' version control system (DVCS) took many of the advances seen in client-server version control systems and moved them into a less centralized architecture. Essentially, the original version control systems were completely centralized, requiring every user to locally log in to the server on which the repository was located. In client-server version control systems, the system was made slightly more distributed, allowing users to connect from across the network to the repository, copy files from the repository to other machines for editing, and then commit them back to the server when edits were complete. Distributed version control continues the trend of decentralization by putting an entire repository, complete with a history of changes and ability to support remote connections, on each user's machine.&lt;br /&gt;
&lt;br /&gt;
One of the strengths of CVS is that it supports file locking even though the main advance it provides is a non-locking repository.. In the same way that CVS supports legacy locking work flows, so do distributed version control systems support the workflows usually associated with a centralized repository. The main improvement distributed version control systems offer, however, is they do not require a central server.  There are three advantages to this decentralized approach.&lt;br /&gt;
&lt;br /&gt;
First, it encourages creation of branches.  Specifically, every time a user &amp;quot;checks out&amp;quot; a file or group of files, a new branch is created on that users machine.  This is in stark contrast to the client-server model in which each time a branch is created, it is carefully planned and coordinated with other users of the system.  Essentially, branching and merging in a centralized system is often difficult and slow, and in a DVCS, it is designed to be natural and fast.&lt;br /&gt;
&lt;br /&gt;
Second, it allows users to commit their changes without disturbing other users of the system.  In typical client-server work flows, the notion of a ''commit'' is tightly coupled to the notion of a ''merge'' with the code that is currently in the repository.  Distributed version control decouples these two notions, allowing developers to commit freely, and merge with other users at a different time.&lt;br /&gt;
&lt;br /&gt;
Third, because each user has an entire copy of the repository, all work is done ''locally'', which allows users to continue doing work even when they don't have access to the internet or to a particular server.  Further, many useful operations which take a long time in a centralized system take an order of magnitude less time in a distributed system simply because the entire repository is local, and therefore no network latency is involved.&lt;br /&gt;
&lt;br /&gt;
All of these changes are made possible as networks have become faster and the computers on which end users now work are often as powerful as the servers that would host a centralized repository.  Thus, and the compute power has moved to the edge of the network, so too has the data in the repositories.&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems allowed users to access, modify and share data in the repository, many advances have been made in the way changes are merged, tracked and stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
Merge algorithms are a good way to frame the many of the problems that arise in a concurrent development environment.  It is therefore useful to start by discussing the issue of merge algorithms, even though relatively few advances have been made in recent years on the algorithms themselves.&lt;br /&gt;
&lt;br /&gt;
There are really two kinds of merging algorithm:&lt;br /&gt;
&lt;br /&gt;
* 2-way merge&lt;br /&gt;
* 3-way merge&lt;br /&gt;
&lt;br /&gt;
2-way merge was developed first, so we will discuss it first.&lt;br /&gt;
&lt;br /&gt;
===2-way Merge===&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Merge_%28revision_control%29#Two-way_merge 2-way Merge] takes two files and compares them for differences, merges differences that do not conflict and identifies differences that conflict for human resolution. [http://en.wikipedia.org/wiki/Diff diff] is a very well-known utility for performing such comparisons and its [http://en.wikipedia.org/wiki/Diff#Algorithm algorithm] is based upon a procedure for finding the [http://en.wikipedia.org/wiki/Longest_common_subsequence_problem longest common subsequence] of text in the files to be compared.  Methods for approaching this basic algorithm has gone largely unchanged since 1975, and the algorithm is used in both SCCS and RCS to create ''patches'' as a means of storing multiple versions of files under version control.&lt;br /&gt;
&lt;br /&gt;
While the 2-way merge approach is a good start to manage concurrent modification to the same resource in a version control system, it became apparent that while the merge algorithm was sound, the version control system actually had much more information than the merge program did, and therefore there were many cases in which a merge was ''conceptually'' easy, but proved to be difficult in practice.  In particular, given a knowledge of a ''common ancestor'' from which two files had both originated, a merge program could make more decisions autonomously, streamlining the merge process.  Thus, 3-way merge was born.&lt;br /&gt;
&lt;br /&gt;
===3-way Merge===&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Merge_%28revision_control%29#Three-way_merge 3-way merge] is an approach to merging two differing files with reference to a third file that is a common ancestor of the two differing files.  By comparing each of the differing files first to the ancestor, and then to each other, the merge program can merge conflicts without human intervention more often than is possible in a 2-way merge approach.&lt;br /&gt;
&lt;br /&gt;
This advancement alone made branching a much less risky proposition for development teams, and allowed distributed version control systems (which place special emphasis on a branched development approach) viable in both small and large development teams.  While both CVS and Subversion (and other modern client-server version control systems) made use of a 3-way merge approach, the newer distributed version control systems tracked groups of changes effectively, and represented the changes of sets of files as a directed acyclic graph ([http://en.wikipedia.org/wiki/Directed_acyclic_graph DAG]), making identification of ''useful'' common ancestors easier, and thus streamlining the merge process.  We will discuss each of these features in turn.&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
An issue closely related to merge algorithms is the issue of exactly ''which'' files the version control system inputs into a the 3-way merge.  In early client-server implementations, a file was the both the largest and smallest entity tracked by the version control system; that is, if several files were modified in support of a single logical change to e.g. a piece of software, those version control systems tracked changes to each individual file and had no tracking for the fact that a particular files changes were part of a larger entity (in this case, a group of files part of a single commit).&lt;br /&gt;
&lt;br /&gt;
While the algorithms to perform textual merges improved when the switch was made from 2-way to 3-way merges, most modern improvements for end users in the area of merge stem from how the files input into the merge algorithm are selected.  By tracking ''groups'' of changes, the version control system can make more effective decisions about which files to pick for merge, making the merge algorithms perform optimally.&lt;br /&gt;
&lt;br /&gt;
==Repository Data Representation==&lt;br /&gt;
&lt;br /&gt;
In most client-server (and local) version control implementations, the version control system tracks individual files.  The implication of this approach is that the entire view of the data within the system is file-centric.  CVS, for example, allows annotations, but only on a per-file basis.  One of the major recent advancements (pioneered by Git) is the ability to track the entire repository as a single monolithic entity.  &lt;br /&gt;
&lt;br /&gt;
One of the results of this is that modern systems (usually DVCS) can track single blocks of text (like a single function in a computer program) across several files if it were moved.  This allows users to focus on the actual data in the repository, rather than the files that hold the data.  One of the most well known negative effects of the file-centric approach appeared in CVS in which file renames would appear in the repository as delete-create pairs, resulting in loss of version history.&lt;br /&gt;
&lt;br /&gt;
Another result of decoupling data representation from the file system has already been mentioned: it allows groups of changes across multiple files to be tracked and associated.  A related notion is the the change history that was traditionally represented as a line in most client-server systems is being represented as a DAG in more modern systems.  The DAG is a more restricted data structure in some ways, but make many operations much simpler for the end user.  The most notable example is when merging from a branch multiple times, a DAG can accurately represent what changes have been incorporated, whereas the traditional file-system oriented approach leaves it as an exercise for the user to re-merge the same changes over and over.  This particular example is discussed in depth in Eric Sink's [http://www.ericsink.com/entries/merge_history.html article on merging].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Wikis as an Extension to Version Control=&lt;br /&gt;
&lt;br /&gt;
As use of the internet became more widespread and ''users'' of the web became some of its most important ''contributors'', concepts like the [http://en.wikipedia.org/wiki/Wiki Wiki] allowed users of a website to edit the website itself.  Often, the website was just a collection of files (pages) being served, that visitors could create, modify and remove.  One of the aspects of [http://c2.com/cgi/wiki?WikiCommunity WikiCommunity] is it is discussed on the original Wiki is the notion of a Wiki being open to change, and thus, Wikis tend to allow anonymous modifications to the wiki's pages.  From this simple fact emerged the idea of saving previous versions of the wiki's pages.&lt;br /&gt;
&lt;br /&gt;
So, taken loosely, Wikis are essentially web-enabled version control systems in which the users are anyone who visits the wiki.  This participatory culture lends itself to a distributed model of information exchange, and yet most wikis are still using what amounts to a local or client-server version control system behind the scenes.&lt;br /&gt;
&lt;br /&gt;
Looking to the future, it will be very interesting to see what can be done with wiki communities if they incorporate the important lessons learned from distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
The first (and only) example I have found of a community of users developing wiki-like content using distributed version control systems is [http://orgmode.org/worg/ Worg], a group of [http://www.gnu.org/software/emacs Emacs] [http://orgmode.org/ Org-Mode] users sharing information about the ways they use the Org-Mode software.  Incidentally, Worg is itself a collection of Org-Mode files stored in [http://git-scm.com/ Git], one of the most prominent distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
For quick refreshers on [http://betterexplained.com/articles/a-visual-guide-to-version-control/ Version Control] and [http://betterexplained.com/articles/intro-to-distributed-version-control-illustrated/ Distributed Version Control], BetterExplained has excellent, concise articles.&lt;br /&gt;
&lt;br /&gt;
Linus Torvalds, the creator and maintainer of both Linux kernel and Git, gave a entertaining and inforative [http://www.youtube.com/watch?v=4XpnKHJAok8&amp;amp;feature=player_embedded tech talk] at Google on version control and Git.  A fabulous resource.&lt;br /&gt;
&lt;br /&gt;
An excellent [http://www.ericsink.com/entries/merge_history.html entry] in Eric Sink's blog on how merge history and repostory representation are related.&lt;br /&gt;
&lt;br /&gt;
IBM has an well-written [http://www.ibm.com/developerworks/java/library/j-subversion/index.html DeveloperWorks article]  describing the ways is which Subversion improved upon CVS, along with some history of version control up until Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=18647</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=18647"/>
		<updated>2009-09-08T05:37:16Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability to track changes to a document, or set of documents, over many changes, or revisions.  For the vast majority of applications, version control systems have focused on tracking plain text files, such as those used for programming source code, HTML documents, and various markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underlays how data is ''shared'' and ''stored'' in a version control system. It should not be inferred from this structure that other attributes are not important to the history of developments of version control systems. There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is represented within the repository&lt;br /&gt;
&lt;br /&gt;
While these may seem to be three separate topics, we will see in the section on [[#Other Advances]] that they are in fact very closely related.&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems (like [http://en.wikipedia.org/wiki/Source_Code_Control_System  SCCS], 1972) focused on ''local version control''; that is, centralized computer systems that were used by many users, often at the same time. In such a system, there were often many users of the system and the ''repository'', or location in which the data was stored, was simply a directory on the server to which the users had access. Because of this use case, these systems focused on two main features:&lt;br /&gt;
&lt;br /&gt;
* File version tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Version Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in files at various points as they were altered, so that the history of changes made to files under version control was kept permanently. Thus, many users could alter many files over time, and the entire set of documents under version control at a given point in time could be recovered, preventing loss of valuable data, as well a providing a record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file simultaneously, one of the first features developed for version control systems was the ability to ''check out'' and ''lock'' a file. When a user checks out a file, he or she reserves the right to be the sole editor of that file until it is checked back in to version control.  Both SCCS and [http://www.gnu.org/software/rcs/ RCS] were designed for use in a shared environment and, as such, allowed files to be checked out and locked in this way.  Other users could check out the file, but only to view it.  Thus, the files were locked from editing by all but the user that had checked the file out most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems== &lt;br /&gt;
&lt;br /&gt;
These local systems had two primary problems.&lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to edit or access the information in the repository.  This often posed both performance and security risks, in addition to being cumbersome as networks became more prevalent.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at any given time. The next development in version control, embodied by CVS, sought to address both of these problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Version Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their changes to files, the need for a version control system that supported remote operations emerged.  The natural way to implement such remote operations was as an extension of the existing system, and by far the most prominent manifestation of this philosophy was present in [http://www.nongnu.org/cvs/ CVS], the concurrent versions system, which was initially based on RCS and began development in 1984 and matured throughout the mid- to late-1980s.  Version 1.0 was released under the [http://www.gnu.org/copyleft/gpl.html GNU GPL], a free software license, in the second half of 1990.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many users, each on his or her own machine, to be able to perform all the operations present in the original RCS, but over a network connection, and in a way that allowed for concurrent editing to take place.  This led to the development of a client-server model of version control systems, in which one central server would contain the canonical version of the repository, and various clients could connect to the central server and perform file check outs and commits.  This model is very similar to the original RCS model, but rather than requiring users of the system to log into the version control system locally, it allowed users to access and alter the contents of the repository over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among the first version control systems to support a ''non-locking repository''. This system allowed for concurrent editing of files under version control, and generated the need to develop new features that addressed the resulting complexities. Chief among the new features introduced to handle these complexities were the notions of ''branching'' and ''merging''. This allowed CVS to offer a non-locking repository, which is why there is an emphasis on the &amp;quot;concurrent&amp;quot; portion of CVS's name &amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to reconcile conflicting changes to the same file. A ''conflict'' is essentially two or more changes made to the same file that it may be difficult to merge into a final file that contains both sets of changes. An example of a conflict would occur if two users both edited a file on line 49, one changing the word &amp;quot;blue&amp;quot; to &amp;quot;red&amp;quot;, and the other changing the same word &amp;quot;blue&amp;quot; to &amp;quot;green&amp;quot;. The first user would then commit his or her changes back to the repository, and when the second user committed changes, the version control system would detect that the repostory had changed since the second user had obtained the file (since the first user had made a change and then committed it). At that point, the version control system would detect a conflict, and prompt the two users to coordinate to resolve the conflict to determine what text should be on line 49.&lt;br /&gt;
&lt;br /&gt;
The solution to this problem lies in allowing users of the version control system to ''branch'' a version of the repository and make (possibly many) changes to that branch independent of the changes occurring on the main branch of the repository, known as the ''trunk''. Once a logical set of changes was completed on a branch, that branch would then need to have its changes reconciled with the current state of the repository on the trunk. This process of reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature is critical in a multi-user client environment as it allows work to progress on multiple fronts simultaneously, only requiring that the files be merged once the users of the system are ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent access to the repository over the network, version control systems became more adept in the algorithms they used to detect conflicts and merge conflicts. This aspect of version control is discussed further in [[#Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
==Client-Server Beyond CVS==&lt;br /&gt;
&lt;br /&gt;
Although CVS developed good approaches to solving many of these problems, it had many problems that gained attention when it became the most widely used version control system for open source development. An exhaustive list would be lengthy, but to mention a few might be illustrative. &lt;br /&gt;
&lt;br /&gt;
* CVS doesn't provide ''atomic'' operations, which means that if there were a network failure during a commit, the repository could become corrupted. &lt;br /&gt;
* CVS does not version control directories or symbolic links, which means the repository is really a lossy copy of a developer's environment, sometimes resulting in failure to track changes accurately.&lt;br /&gt;
* CVS doesn't track what files were committed at the same time, so if you make a logical group of changes to several files and want to track the fact that those files were changed together, you can only only derive that information from log messages. CVS will not track it for you.&lt;br /&gt;
* CVS cannot track when files are renamed; rather, a rename of a file in CVS looks like the original file was deleted and a new file added, thus losing the file's history.&lt;br /&gt;
* Creating branches and managing the subsequent merges is slow and difficult.&lt;br /&gt;
&lt;br /&gt;
In short, while CVS provided a whole host of new features and advanced the state of the art in version control, it left room for improvement. This resulted in a vast number of client-server version control systems entering the market following CVS. One of the latest and most notable of these is [http://subversion.tigris.org/ Subversion], which seeks to address all of the [http://subversion.tigris.org/features.html issues] mentioned above and a whole lot more.&lt;br /&gt;
&lt;br /&gt;
=Distributed Version Control=&lt;br /&gt;
&lt;br /&gt;
''Distributed'' version control took many of the advances seen in client-server version control systems and moved them into a less centralized architecture. Essentially, the original version control systems were completely centralized, requiring every user to locally log in to the server on which the repository was located. In client-server version control systems, the system was made slightly more distributed, allowing users to connect from across the network to the repository, copy files from the repostory to other machines for editing, and then commit them back to the server when edits were complete. Distributed version control continues the trend of decentralization by putting an entire repository, complete with a history of changes and ability to support remote connections, on each user's machine.&lt;br /&gt;
&lt;br /&gt;
One of the strengths of CVS is that it supports file locking even though the main advance it provides is a non-locking repository. This allows for users of RCS to switch to CVS while maintaining their work flow. When users are ready, they can take advantage of the non-locking repository features CVS provides. In the same way that CVS supports legacy locking work flows, so do distributed version control systems support a centralized repository. The main improvement distributed version control systems offer, however, is they do not require a central server, and allow each user to maintain a complete copy of the repository on their local machine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems allowed users to access, modify and share data in the repository, many advances have been made in the way changes are merged, tracked and stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
Merge algorithms are a good way to frame the many of the problems that arise in a concurrent development environment.  It is therefore useful to start by discussing the issue of merge algorithms, even though relatively few advances have been made in recent years on the algorithms themselves.&lt;br /&gt;
&lt;br /&gt;
There are really two kinds of merging algorithm:&lt;br /&gt;
&lt;br /&gt;
* 2-way merge&lt;br /&gt;
* 3-way merge&lt;br /&gt;
&lt;br /&gt;
2-way merge was developed first, so we will discuss it first.&lt;br /&gt;
&lt;br /&gt;
===2-way Merge===&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Merge_%28revision_control%29#Two-way_merge 2-way Merge] takes two files and compares them for differences, merges differences that do not conflict and identifies differences that conflict for human resolution. [http://en.wikipedia.org/wiki/Diff diff] is a very well-known utility for performing such comparisons and its [http://en.wikipedia.org/wiki/Diff#Algorithm algorithm] is based upon a procedure for finding the [http://en.wikipedia.org/wiki/Longest_common_subsequence_problem longest common subsequence] of text in the files to be compared.  Methods for approaching this basic algorithm has gone largely unchanged since 1975, and the algorithm is used in both SCCS and RCS to create ''patches'' as a means of storing multiple versions of files under version control.&lt;br /&gt;
&lt;br /&gt;
While the 2-way merge approach is a good start to manage concurrent modification to the same resource in a version control system, it became apparent that while the merge algorithm was sound, the version control system actually had much more information than the merge program did, and therefore there were many cases in which a merge was ''conceptually'' easy, but proved to be difficult in practice.  In particular, given a knowledge of a ''common ancesotor'' from which two files had both originated, a merge progrom could make more decisions autonomously, streamlining the merge process.  Thus, 3-way merge was born.&lt;br /&gt;
&lt;br /&gt;
===3-way Merge===&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Merge_%28revision_control%29#Three-way_merge 3-way merge] is an approach to merging two differing files with reference to a third file that is a common ancestor of the two differing files.  By comparing each of the differing files first to the ancestor, and then to each other, the merge program can merge conflicts without human intervention more often than is possible in a 2-way merge approach.&lt;br /&gt;
&lt;br /&gt;
This advancement alone made branching a much less risky propostion for development teams, and allowed distributed version control systems (which place special emphasis on a branched development approach) viable in both small and large development teams.  While both CVS and Subversion (and other modern client-server version control systems) made use of a 3-way merge approach, the newer distributed version control systems tracked groups of changes effecively, and represented the changes of sets of files as a directed acyclic graph ([http://en.wikipedia.org/wiki/Directed_acyclic_graph DAG]), making identification of ''useful'' common ancestors easier, and thus streamlining the merge process.  We will discuss each of these features in turn.&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
An issue closely related to merge algorithms is the issue of exactly ''which'' files the version control system inputs into a the 3-way merge.  In early client-server implementations, a file was the both the largest and smallest entity tracked by the version control system; that is, if several files were modified in support of a single logical change to e.g. a piece of software, those version control systems tracked changes to each individual file and had no tracking for the fact that a particular files changes were part of a larger entity (in this case, a group of files part of a single commit).&lt;br /&gt;
&lt;br /&gt;
While the algorithms to perform textual merges improved when the switch was made from 2-way to 3-way merges, most modern improvements for end users in the area of merge stem from how the files input into the merge algorithm are selected.  By tracking ''groups'' of changes, the version control system can make more effective decisions about which files to pick for merge, making the merge algorithms perform optimally.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Repository Data Representation==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Wikis As An Extention To Version Control=&lt;br /&gt;
&lt;br /&gt;
As use of the internet became more widespread and ''users'' of the web became some of its most important ''contributors'', concepts like the [http://en.wikipedia.org/wiki/Wiki Wiki] allowed users of a website to edit the website itself.  Often, the website was just a collection of files (pages) being served, that visitors could create, modify and remove.  One of the aspects of [http://c2.com/cgi/wiki?WikiCommunity WikiCommunity] is it is discussed on the orginial Wiki is the notion of a Wiki being open to change, and thus, Wikis tend to allow anonymous modifications to the wiki's pages.  From this simple fact emerged the idea of saving previous versions of the wiki's pages.&lt;br /&gt;
&lt;br /&gt;
So, taken loosely, Wikis are essentially web-enabled version control systems in which the users are anyone who visits the wiki.  This participatory culture lends itself to a distributed model of information exchange, and yet most wikis are still using what amounts to a local or client-server version control system behind the scenes.&lt;br /&gt;
&lt;br /&gt;
Looking to the future, it will be very interesting to see what can be done with wiki communities if they incorporate the important lessons learned from distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
The first (and only) example I have found of a community of users developing wiki-like content using distributed version control systems is [http://orgmode.org/worg/ Worg], a group of [http://www.gnu.org/software/emacs Emacs] [http://orgmode.org/ Org-Mode] users sharing information about the ways they use the Org-Mode software.  Incidentally, Worg is itself a collection of Org-Mode files stored in [http://git-scm.com/ Git], one of the most prominent distributed version control systems.&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
An excellent [http://www.ericsink.com/entries/merge_history.html entry] on how merge history and repostory representation are related&lt;br /&gt;
&lt;br /&gt;
IBM has an excellent [http://www.ibm.com/developerworks/java/library/j-subversion/index.html DeveloperWorks article]  describing the ways is which Subversion improved upon CVS, along with some history of version control up until Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=18110</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=18110"/>
		<updated>2009-09-07T18:41:33Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability to track changes to a document, or set of documents, over many changes, or revisions.  For the vast majority of applications, version control systems have focused on tracking plain text files, such as those used for programming source code, HTML documents, and various markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underly how data is ''shared'' and ''stored'' in a version control system. It should not be inferred from this structure that other attributes are not important to the history of developments of version control systems. There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is represented within the repository&lt;br /&gt;
&lt;br /&gt;
While these may seem to be three separate topics, we will see in the section on [[#Other Advances]] that they are in fact very closely related.&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems (like [http://en.wikipedia.org/wiki/Source_Code_Control_System  SCCS], 1972) focused on ''local version control''; that is, centralized computer systems that were used by many users, often at the same time. In such a system, there were often many users of the system and the ''repository'', or location in which the data was stored, was simply a directory on the server to which the users had access. Because of this use case, these systems focused on two main features:&lt;br /&gt;
&lt;br /&gt;
* File revision tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Revision Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in files at various points as they were altered, so that the history of changes made to files under version control was kept permanently. Thus, many users could alter many files over time, and the entire set of documents under version control at a given point in time could be recovered, preventing loss of valuable data, as well a providing a record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file simultaneously, one of the first features developed for version control systems was the ability to ''check out'' and ''lock'' a file. When a user checks out a file, he or she reserves the right to be the sole editor of that file until it is checked back in to revision control.  Both SCCS and [http://www.gnu.org/software/rcs/ RCS] were designed for use in a shared environment and, as such, allowed files to be checked out and locked in this way.  Other users could check out the file, but only to view it.  Thus, the files were locked from editing by all but the user that had checked the file out most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems== &lt;br /&gt;
&lt;br /&gt;
These local systems had two primary problems.&lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to edit or access the information in the repository.  This often posed both performance and security risks, in addition to being cumbersome as networks became more prevalent.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at any given time. The next development in revision control, embodied by CVS, sought to address both of these problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Revision Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their changes to files, the need for a revision control system that supported remote operations emerged.  The natural way to implement such remote operations was as an extension of the existing system, and by far the most prominent manifestation of this philosophy was present in [http://www.nongnu.org/cvs/ CVS], the concurrent versions system, which was initially based on RCS and began development in 1984 and matured throughout the mid- to late-1980s.  Version 1.0 was released under the [http://www.gnu.org/copyleft/gpl.html GNU GPL], a free softwore licence, in the second half of 1990.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many users, each on his or her own machine, to be able to perform all the operations present in the original RCS, but over a network connection, and in a way that allowed for concurrent editting to take place.  This led to the development of a client-server model of revision control systems, in which one central server would contain the canoncal version of the repository, and various clients could connect to the central server and perform file check outs and commits.  This model is very similar to the original RCS model, but rather than requiring users of the system to log into the revision control system locally, it allowed users to access and alter the contents of the repository over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among the first version control systems to support a ''non-locking repository''. This system allowed for concurrent editing of files under revision control, and generated the need to develop new features that addressed the resulting complexities. Chief among the new features introduced to handle these complexities were the notions of ''branching'' and ''merging''. This allowed CVS to offer a non-locking repository, which is why there is an emphasis on the &amp;quot;concurrent&amp;quot; portion of CVS's name &amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to reconcile conflicting changes to the same file. A ''conflict'' is essentially two or more changes made to the same file that it may be difficult to merge into a final file that contains both sets of changes. An example of a conflict would occur if two users both edited a file on line 49, one changing the word &amp;quot;blue&amp;quot; to &amp;quot;red&amp;quot;, and the other changing the same word &amp;quot;blue&amp;quot; to &amp;quot;green&amp;quot;. The first user would then commit his or her changes back to the repository, and when the second user committed changes, the version control system would detect that the repostory had changed since the second user had obtained the file (since the first user had made a change and then committed it). At that point, the version control system would detect a conflict, and prompt the two users to coordinate to resolve the conflict to deteremine what text should be on line 49.&lt;br /&gt;
&lt;br /&gt;
The solution to this problem lies in allowing users of the revision control system to ''branch'' a version of the repository and make (possibly many) changes to that branch independent of the changes occurring on the main branch of the repository, known as the ''trunk''. Once a logical set of changes was completed on a branch, that branch would then need to have its changes reconciled with the current state of the repository on the trunk. This process of reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature is critical in a multi-user client environment as it allows work to progress on multiple fronts simultaneously, only requiring that the files be merged once the users of the system are ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent access to the repository over the network, version control systems became more adept in the algorithms they used to detect conflicts and merge conflicts. This aspect of revision control is discussed further in [[#Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
==Client-Server Beyond CVS==&lt;br /&gt;
&lt;br /&gt;
Although CVS developed good approaches to solving many of these problems, it had many problems that gained attention when it became the most widely used revision control system for open source development. An exhaustive list would be lengthy, but to mention a few might be illustrative. &lt;br /&gt;
&lt;br /&gt;
* CVS doesn't provide ''atomic'' operations, which means that if there were a network failure during a commit, the repository could become corrupted. &lt;br /&gt;
* CVS does not version control directories or symbolic links, which means the repostitory is really a lossy copy of a developer's environment, sometimes resulting in failure to track changes accrurately.&lt;br /&gt;
* CVS doesn't track what files were committed at the same time, so if you make a logical group of changes to several files and want to track the fact that those files were changed together, you can only only derive that information from log messages. CVS will not track it for you.&lt;br /&gt;
* CVS cannot track when files are renamed; rather, a rename of a file in CVS looks like the original file was deleted and a new file added, thus losing the file's history.&lt;br /&gt;
* Creating braches and managing the subsequent merges is slow and difficult.&lt;br /&gt;
&lt;br /&gt;
In short, while CVS provided a whole host of new features and advanced the state of the art in version control, it left room for improvement. This resulted in a vast number of client-server version control systems entering the market following CVS. One of the latest and most notable of these is [http://subversion.tigris.org/ Subversion], which seeks to address all of the [http://subversion.tigris.org/features.html issues] mentioned above and a whole lot more.&lt;br /&gt;
&lt;br /&gt;
=Distributed Revision Control=&lt;br /&gt;
&lt;br /&gt;
''Distributed'' revision control took many of the advances seen in client-server version control systems and moved them into a less centralized architecture. Essentially, the original version control systems were completely centralized, requiring every user to locally log in to the server on which the repository was located. In client-server version control systems, the system was made slightly more distributed, allowing users to connect from across the network to the repository, copy files from the repostory to other machines for editing, and then commit them back to the server when edits were complete. Distributed version control continues the trend of decentralization by putting an entire repository, complete with a history of changes and ability to support remote connections, on each user's machine.&lt;br /&gt;
&lt;br /&gt;
One of the strengths of CVS is that it supports file locking even though the main advance it provides is a non-locking repository. This allows for users of RCS to switch to CVS while maintaining their work flow. When users are ready, they can take advantage of the non-locking repository features CVS provides. In the same way that CVS supports legacy locking work flows, so do distributed version control systems support a centralized repository. The main improvement distributed version control systems offer, however, is they do not require a central server, and allow each user to maintain a complete copy of the repository on their local machine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems allowed users to access, modify and share data in the repository, many advances have been made in the way changes are merged, tracked and stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
Merge algorithms are a good way to frame the many of the problems that arise in a concurrent development environment.  It is therefore useful to start by discussing the issue of merge algorithms, even though relatively few advances have been made in recent years on the algorithms themselves.&lt;br /&gt;
&lt;br /&gt;
There are really two kinds of merging algorithm:&lt;br /&gt;
&lt;br /&gt;
* 2-way merge&lt;br /&gt;
* 3-way merge&lt;br /&gt;
&lt;br /&gt;
2-way merge was developed first, so we will discuss it first.&lt;br /&gt;
&lt;br /&gt;
===2-way Merge===&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Merge_%28revision_control%29#Two-way_merge 2-way Merge] takes two files and compares them for differences, merges differences that do not conflict and identifies differences that conflict for human resolution. [http://en.wikipedia.org/wiki/Diff diff] is a very well-known utility for performing such comparisons and its [http://en.wikipedia.org/wiki/Diff#Algorithm algorithm] is based upon a procedure for finding the [http://en.wikipedia.org/wiki/Longest_common_subsequence_problem longest common subsequence] of text in the files to be compared.&lt;br /&gt;
&lt;br /&gt;
===3-way Merge===&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
An issue closely related to merge algorithms is the issue of exactly ''which'' files the revision control system inputs into a the 3-way merge.  In early client-server implementations, a file was the both the largest and smallest entity tracked by the revision control system; that is, if several files were modified in support of a single logical change to e.g. a piece of software, those revision control systems tracked changes to each individual file and had no tracking for the fact that a particular files changes were part of a larger entity (in this case, a group of files part of a single commit).&lt;br /&gt;
&lt;br /&gt;
While the algorithms to perform textual merges improved when the switch was made from 2-way to 3-way merges, most modern improvements for end users in the area of merge stem from how the files input into the merge algorithm are selected.  By tracking ''groups'' of changes, the version control system can make more effective decisions about which files to pick for merge, making the merge algorithms perform optimally.&lt;br /&gt;
&lt;br /&gt;
==Repository Data Representation==&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
An excellent [http://www.ericsink.com/entries/merge_history.html entry] on how merge history and repostory representation are related&lt;br /&gt;
&lt;br /&gt;
IBM has an excellent [http://www.ibm.com/developerworks/java/library/j-subversion/index.html DeveloperWorks article]  describing the ways is which Subversion improved upon CVS, along with some history of version control up until Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=18027</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=18027"/>
		<updated>2009-09-07T09:33:52Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability to track changes to a document, or set of documents, over many changes, or revisions.  For the vast majority of applications, version control systems have focused on tracking plain text files, such as those used for programming source code, HTML documents, and various markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underly how data is ''shared'' and ''stored'' in a version control system. It should not be inferred from this structure that other attributes are not important to the history of developments of version control systems. There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is represented within the repository&lt;br /&gt;
&lt;br /&gt;
While these may seem to be three separate topics, we will see in the section on [[#Other Advances]] that they are in fact very closely related.&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems focused on ''local version control''; that is, centralized computer systems that were used by many users, often at the same time. In such a system, there were often many users of the system and the ''repository'', or location in which the data was stored, was simply a directory on the server to which the users had access. Because of this use case, these systems focused on two main features:&lt;br /&gt;
&lt;br /&gt;
* File revision tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Revision Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in files at various points as they were altered, so that the history of changes made to files under version control was kept permanently. Thus, many users could alter many files over time, and the entire set of documents under version control at a given point in time could be recovered, preventing loss of valuable data, as well a providing a record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file simultaneously, one of the first features developed for version control systems was the ability to ''check out'' and ''lock'' a file. When a user checks out a file, he or she reserves the right to be the sole editor of that file until it is checked back in to revision control.  The first revision control systems designed for use in a shared environment, such as [http://www.gnu.org/software/rcs/ RCS], allowed files to be checked out and locked in this way.  Other users could check out the file, but only to view it.  Thus, the files were locked from editing by all but the user that had checked the file out most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems== These local systems had two primary problems.  &lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to edit or access the information in the repository.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at any given time. The next development in revision control, embodied by [http://www.nongnu.org/cvs/ CVS], sought to address both of these problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Revision Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their changes to files, the need for a revision control system that supported remote operations emerged.  The natural way to implement such remote operations was as an extension of the existing system, and by far the most prominent manifestation of this philosophy was present in CVS, the concurrent versions system, which was initially based on RCS.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many users, each on his or her own machine, to be able to perform all the operations present in the original RCS, but over a network connection, and in a way that allowed for concurrent editting to take place.  This led to the development of a client-server model of revision control systems, in which one central server would contain the canoncal version of the repository, and various clients could connect to the central server and perform file check outs and commits.  This model is very similar to the original RCS model, but rather than requiring users of the system to log into the revision control system locally, it allowed users to access and alter the contents of the repository over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among the first version control systems to support a ''non-locking repository''. This system allowed for concurrent editing of files under revision control, and generated the need to develop new features that addressed the resulting complexities. Chief among the new features introduced to handle these complexities were the notions of ''branching'' and ''merging''. This allowed CVS to offer a non-locking repository, which is why there is an emphasis on the &amp;quot;concurrent&amp;quot; portion of CVS's name &amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to reconcile conflicting changes to the same file. A ''conflict'' is essentially two or more changes made to the same file that it may be difficult to merge into a final file that contains both sets of changes. An example of a conflict would occur if two users both edited a file on line 49, one changing the word &amp;quot;blue&amp;quot; to &amp;quot;red&amp;quot;, and the other changing the same word &amp;quot;blue&amp;quot; to &amp;quot;green&amp;quot;. The first user would then commit his or her changes back to the repository, and when the second user committed changes, the version control system would detect that the repostory had changed since the second user had obtained the file (since the first user had made a change and then committed it). At that point, the version control system would detect a conflict, and prompt the two users to coordinate to resolve the conflict to deteremine what text should be on line 49.&lt;br /&gt;
&lt;br /&gt;
The solution to this problem lies in allowing users of the revision control system to ''branch'' a version of the repository and make (possibly many) changes to that branch independent of the changes occurring on the main branch of the repository, known as the ''trunk''. Once a logical set of changes was completed on a branch, that branch would then need to have its changes reconciled with the current state of the repository on the trunk. This process of reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature is critical in a multi-user client environment as it allows work to progress on multiple fronts simultaneously, only requiring that the files be merged once the users of the system are ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent access to the repository over the network, version control systems became more adept in the algorithms they used to detect conflicts and merge conflicts. This aspect of revision control is discussed further in [[#Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
==Client-Server Beyond CVS==&lt;br /&gt;
&lt;br /&gt;
Although CVS developed good approaches to solving many of these problems, it had many problems that gained attention when it became the most widely used revision control system for open source development. An exhaustive list would be lengthy, but to mention a few might be illustrative. &lt;br /&gt;
&lt;br /&gt;
* CVS doesn't provide ''atomic'' operations, which means that if there were a network failure during a commit, the repository could become corrupted. &lt;br /&gt;
* CVS does not version control directories or symbolic links, which means the repostitory is really a lossy copy of a developer's environment, sometimes resulting in failure to track changes accrurately.&lt;br /&gt;
* CVS doesn't track what files were committed at the same time, so if you make a logical group of changes to several files and want to track the fact that those files were changed together, you can only only derive that information from log messages. CVS will not track it for you.&lt;br /&gt;
* CVS cannot track when files are renamed; rather, a rename of a file in CVS looks like the original file was deleted and a new file added, thus losing the file's history.&lt;br /&gt;
* Creating braches and managing the subsequent merges is slow and difficult.&lt;br /&gt;
&lt;br /&gt;
In short, while CVS provided a whole host of new features and advanced the state of the art in version control, it left room for improvement. This resulted in a vast number of client-server version control systems entering the market following CVS. One of the latest and most notable of these is [http://subversion.tigris.org/ Subversion], which seeks to address all of the [http://subversion.tigris.org/features.html issues] mentioned above and a whole lot more.&lt;br /&gt;
&lt;br /&gt;
=Distributed Revision Control=&lt;br /&gt;
&lt;br /&gt;
''Distributed'' revision control took many of the advances seen in client-server version control systems and moved them into a less centralized architecture. Essentially, the original version control systems were completely centralized, requiring every user to locally log in to the server on which the repository was located. In client-server version control systems, the system was made slightly more distributed, allowing users to connect from across the network to the repository, copy files from the repostory to other machines for editing, and then commit them back to the server when edits were complete. Distributed version control continues the trend of decentralization by putting an entire repository, complete with a history of changes and ability to support remote connections, on each user's machine.&lt;br /&gt;
&lt;br /&gt;
One of the strengths of CVS is that it supports file locking even though the main advance it provides is a non-locking repository. This allows for users of RCS to switch to CVS while maintaining their work flow. When users are ready, they can take advantage of the non-locking repository features CVS provides. In the same way that CVS supports legacy locking work flows, so do distributed version control systems support a centralized repository. The main improvement distributed version control systems offer, however, is they do not require a central server, and allow each user to maintain a complete copy of the repository on their local machine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems allowed users to access, modify and share data in the repository, many advances have been made in the way changes are merged, tracked and stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
Merge algorithms are a good way to frame the many of the problems that arise in a concurrent development environment.  It is therefore useful to start by discussing the issue of merge algorithms, even though relatively few advances have been made in recent years on the algorithms themselves.&lt;br /&gt;
&lt;br /&gt;
There are really two kinds of merging algorithm:&lt;br /&gt;
&lt;br /&gt;
* 2-way merge&lt;br /&gt;
* 3-way merge&lt;br /&gt;
&lt;br /&gt;
2-way merge was developed first, so we will discuss it first.&lt;br /&gt;
&lt;br /&gt;
===2-way Merge===&lt;br /&gt;
&lt;br /&gt;
===3-way Merge===&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
An issue closely related to merge algorithms is the issue of exactly ''which'' files the revision control system inputs into a the 3-way merge.  In early client-server implementations, a file was the both the largest and smallest entity tracked by the revision control system; that is, if several files were modified in support of a single logical change to e.g. a piece of software, those revision control systems tracked changes to each individual file and had no tracking for the fact that a particular files changes were part of a larger entity (in this case, a group of files part of a single commit).&lt;br /&gt;
&lt;br /&gt;
While the algorithms to perform textual merges improved when the switch was made from 2-way to 3-way merges, most modern improvements for end users in the area of merge stem from how the files input into the merge algorithm are selected.  By tracking ''groups'' of changes, the version control system can make more effective decisions about which files to pick for merge, making the merge algorithms perform optimally.&lt;br /&gt;
&lt;br /&gt;
==Repository Data Representation==&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
An excellent [http://www.ericsink.com/entries/merge_history.html entry] on how merge history and repostory representation are related&lt;br /&gt;
&lt;br /&gt;
IBM has an excellent [http://www.ibm.com/developerworks/java/library/j-subversion/index.html DeveloperWorks article]  describing the ways is which Subversion improved upon CVS, along with some history of version control up until Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=18001</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=18001"/>
		<updated>2009-09-07T05:48:56Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: Unfilling, since mediawiki doesn't like line breaks in a lot of its syntax&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability to track changes to a document, or set of documents, over many changes, or revisions.  For the vast majority of applications, version control systems have focused on tracking plain text files, such as those used for programming source code, HTML documents, and various markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underly how data is ''shared'' and ''stored'' in a version control system. It should not be inferred from this structure that other attributes are not important to the history of developments of version control systems. There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is stored&lt;br /&gt;
&lt;br /&gt;
We will discuss these each in turn in [[#Other Advances]].&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems focused on ''local version control''; that is, centralized computer systems that were used by many users, often at the same time. In such a system, there were often many users of the system and the ''repository'', or location in which the data was stored, was simply a directory on the server to which the users had access. Because of this use case, these systems focused on two main features:&lt;br /&gt;
&lt;br /&gt;
* File revision tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Revision Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in files at various points as they were altered, so that the history of changes made to files under version control was kept permanently. Thus, many users could alter many files over time, and the entire set of documents under version control at a given point in time could be recovered, preventing loss of valuable data, as well a providing a record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file simultaneously, one of the first features developed for version control systems was the ability to ''check out'' and ''lock'' a file. When a user checks out a file, he or she reserves the right to be the sole editor of that file until it is checked back in to revision control.  The first revision control systems designed for use in a shared environment, such as [http://www.gnu.org/software/rcs/ RCS], allowed files to be checked out and locked in this way.  Other users could check out the file, but only to view it.  Thus, the files were locked from editing by all but the user that had checked the file out most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems== These local systems had two primary problems.  &lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to edit or access the information in the repository.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at any given time. The next development in revision control, embodied by [http://www.nongnu.org/cvs/ CVS], sought to address both of these problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Revision Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their changes to files, the need for a revision control system that supported remote operations emerged.  The natural way to implement such remote operations was as an extension of the existing system, and by far the most prominent manifestation of this philosophy was present in CVS, the concurrent versions system, which was initially based on RCS.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many users, each on his or her own machine, to be able to perform all the operations present in the original RCS, but over a network connection, and in a way that allowed for concurrent editting to take place.  This led to the development of a client-server model of revision control systems, in which one central server would contain the canoncal version of the repository, and various clients could connect to the central server and perform file check outs and commits.  This model is very similar to the original RCS model, but rather than requiring users of the system to log into the revision control system locally, it allowed users to access and alter the contents of the repository over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among the first version control systems to support a ''non-locking repository''. This system allowed for concurrent editing of files under revision control, and generated the need to develop new features that addressed the resulting complexities. Chief among the new features introduced to handle these complexities were the notions of ''branching'' and ''merging''. This allowed CVS to offer a non-locking repository, which is why there is an emphasis on the &amp;quot;concurrent&amp;quot; portion of CVS's name &amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to reconcile conflicting changes to the same file. A ''conflict'' is essentially two or more changes made to the same file that it may be difficult to merge into a final file that contains both sets of changes. An example of a conflict would occur if two users both edited a file on line 49, one changing the word &amp;quot;blue&amp;quot; to &amp;quot;red&amp;quot;, and the other changing the same word &amp;quot;blue&amp;quot; to &amp;quot;green&amp;quot;. The first user would then commit his or her changes back to the repository, and when the second user committed changes, the version control system would detect that the repostory had changed since the second user had obtained the file (since the first user had made a change and then committed it). At that point, the version control system would detect a conflict, and prompt the two users to coordinate to resolve the conflict to deteremine what text should be on line 49.&lt;br /&gt;
&lt;br /&gt;
The solution to this problem lies in allowing users of the revision control system to ''branch'' a version of the repository and make (possibly many) changes to that branch independent of the changes occurring on the main branch of the repository, known as the ''trunk''. Once a logical set of changes was completed on a branch, that branch would then need to have its changes reconciled with the current state of the repository on the trunk. This process of reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature is critical in a multi-user client environment as it allows work to progress on multiple fronts simultaneously, only requiring that the files be merged once the users of the system are ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent access to the repository over the network, version control systems became more adept in the algorithms they used to detect conflicts and merge conflicts. This aspect of revision control is discussed further in [[#Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
==Client-Server Beyond CVS==&lt;br /&gt;
&lt;br /&gt;
Although CVS developed good approaches to solving many of these problems, it had many problems that gained attention when it became the most widely used revision control system for open source development. An exhaustive list would be lengthy, but to mention a few might be illustrative. &lt;br /&gt;
&lt;br /&gt;
* CVS doesn't provide ''atomic'' operations, which means that if there were a network failure during a commit, the repository could become corrupted. &lt;br /&gt;
* CVS does not version control directories or symbolic links, which means the repostitory is really a lossy copy of a developer's environment, sometimes resulting in failure to track changes accrurately.&lt;br /&gt;
* CVS doesn't track what files were committed at the same time, so if you make a logical group of changes to several files and want to track the fact that those files were changed together, you can only only derive that information from log messages. CVS will not track it for you.&lt;br /&gt;
* CVS cannot track when files are renamed; rather, a rename of a file in CVS looks like the original file was deleted and a new file added, thus losing the file's history.&lt;br /&gt;
* Creating braches and managing the subsequent merges is slow and difficult.&lt;br /&gt;
&lt;br /&gt;
In short, while CVS provided a whole host of new features and advanced the state of the art in version control, it left room for improvement. This resulted in a vast number of client-server version control systems entering the market following CVS. One of the latest and most notable of these is [http://subversion.tigris.org/ Subversion], which seeks to address all of the [http://subversion.tigris.org/features.html issues] mentioned above and a whole lot more.&lt;br /&gt;
&lt;br /&gt;
=Distributed Revision Control=&lt;br /&gt;
&lt;br /&gt;
''Distributed'' revision control took many of the advances seen in client-server version control systems and moved them into a less centralized architecture. Essentially, the original version control systems were completely centralized, requiring every user to locally log in to the server on which the repository was located. In client-server version control systems, the system was made slightly more distributed, allowing users to connect from across the network to the repository, copy files from the repostory to other machines for editing, and then commit them back to the server when edits were complete. Distributed version control continues the trend of decentralization by putting an entire repository, complete with a history of changes and ability to support remote connections, on each user's machine.&lt;br /&gt;
&lt;br /&gt;
One of the strengths of CVS is that it supports file locking even though the main advance it provides is a non-locking repository. This allows for users of RCS to switch to CVS while maintaining their work flow. When users are ready, they can take advantage of the non-locking repository features CVS provides. In the same way that CVS supports legacy locking work flows, so do distributed version control systems support a centralized repository. The main improvement distributed version control systems offer, however, is they do not require a central server, and allow each user to maintain a complete copy of the repository on their local machine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems allowed users to access, modify and share data in the repository, many advances have been made in the way changes are merged, tracked and stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
==Repository Data Storage==&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
IBM has an excellent [http://www.ibm.com/developerworks/java/library/j-subversion/index.html DeveloperWorks article]  describing the ways is which Subversion improved upon CVS, along with some history of version control up until Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=18000</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=18000"/>
		<updated>2009-09-07T05:46:08Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability&lt;br /&gt;
to track changes to a document, or set of documents, over many&lt;br /&gt;
changes, or revisions.  For the vast majority of applications, version&lt;br /&gt;
control systems have focused on tracking plain text files, such as&lt;br /&gt;
those used for programming source code, HTML documents, and various&lt;br /&gt;
markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly&lt;br /&gt;
categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underly how data is&lt;br /&gt;
''shared'' and ''stored'' in a version control system. It should not&lt;br /&gt;
be inferred from this structure that other attributes are not&lt;br /&gt;
important to the history of developments of version control systems.&lt;br /&gt;
There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is stored&lt;br /&gt;
&lt;br /&gt;
We will discuss these each in turn in [[#Other Advances]].&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems focused on ''local version&lt;br /&gt;
control''; that is, centralized computer systems that were used by&lt;br /&gt;
many users, often at the same time. In such a system, there were often&lt;br /&gt;
many users of the system and the ''repository'', or location in which&lt;br /&gt;
the data was stored, was simply a directory on the server to which the&lt;br /&gt;
users had access. Because of this use case, these systems focused on&lt;br /&gt;
two main features:&lt;br /&gt;
&lt;br /&gt;
* File revision tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Revision Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in&lt;br /&gt;
files at various points as they were altered, so that the history of&lt;br /&gt;
changes made to files under version control was kept permanently.&lt;br /&gt;
Thus, many users could alter many files over time, and the entire set&lt;br /&gt;
of documents under version control at a given point in time could be&lt;br /&gt;
recovered, preventing loss of valuable data, as well a providing a&lt;br /&gt;
record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file&lt;br /&gt;
simultaneously, one of the first features developed for version&lt;br /&gt;
control systems was the ability to ''check out'' and ''lock'' a file.&lt;br /&gt;
When a user checks out a file, he or she reserves the right to be the&lt;br /&gt;
sole editor of that file until it is checked back in to revision&lt;br /&gt;
control.  The first revision control systems designed for use in a&lt;br /&gt;
shared environment, such as [http://www.gnu.org/software/rcs/ RCS],&lt;br /&gt;
allowed files to be checked out and locked in this way.  Other users&lt;br /&gt;
could check out the file, but only to view it.  Thus, the files were&lt;br /&gt;
locked from editing by all but the user that had checked the file out&lt;br /&gt;
most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems==&lt;br /&gt;
These local systems had two primary problems.  &lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to&lt;br /&gt;
edit or access the information in the repository.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at&lt;br /&gt;
any given time. The next development in revision control, embodied by&lt;br /&gt;
[http://www.nongnu.org/cvs/ CVS], sought to address both of these&lt;br /&gt;
problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Revision Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their&lt;br /&gt;
changes to files, the need for a revision control system that&lt;br /&gt;
supported remote operations emerged.  The natural way to implement&lt;br /&gt;
such remote operations was as an extension of the existing system, and&lt;br /&gt;
by far the most prominent manifestation of this philosophy was present&lt;br /&gt;
in CVS, the concurrent versions system, which was initially based on&lt;br /&gt;
RCS.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many&lt;br /&gt;
users, each on his or her own machine, to be able to perform all the&lt;br /&gt;
operations present in the original RCS, but over a network connection,&lt;br /&gt;
and in a way that allowed for concurrent editting to take place.  This&lt;br /&gt;
led to the development of a client-server model of revision control&lt;br /&gt;
systems, in which one central server would contain the canoncal&lt;br /&gt;
version of the repository, and various clients could connect to the&lt;br /&gt;
central server and perform file check outs and commits.  This model is&lt;br /&gt;
very similar to the original RCS model, but rather than requiring&lt;br /&gt;
users of the system to log into the revision control system locally,&lt;br /&gt;
it allowed users to access and alter the contents of the repository&lt;br /&gt;
over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among&lt;br /&gt;
the first version control systems to support a ''non-locking&lt;br /&gt;
repository''. This system allowed for concurrent editing of files&lt;br /&gt;
under revision control, and generated the need to develop new features&lt;br /&gt;
that addressed the resulting complexities. Chief among the new&lt;br /&gt;
features introduced to handle these complexities were the notions of&lt;br /&gt;
''branching'' and ''merging''. This allowed CVS to offer a non-locking&lt;br /&gt;
repository, which is why there is an emphasis on the &amp;quot;concurrent&amp;quot;&lt;br /&gt;
portion of CVS's name &amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to&lt;br /&gt;
reconcile conflicting changes to the same file. A ''conflict'' is&lt;br /&gt;
essentially two or more changes made to the same file that it may be&lt;br /&gt;
difficult to merge into a final file that contains both sets of&lt;br /&gt;
changes. An example of a conflict would occur if two users both edited&lt;br /&gt;
a file on line 49, one changing the word &amp;quot;blue&amp;quot; to &amp;quot;red&amp;quot;, and the&lt;br /&gt;
other changing the same word &amp;quot;blue&amp;quot; to &amp;quot;green&amp;quot;. The first user would&lt;br /&gt;
then commit his or her changes back to the repository, and when the&lt;br /&gt;
second user committed changes, the version control system would detect&lt;br /&gt;
that the repostory had changed since the second user had obtained the&lt;br /&gt;
file (since the first user had made a change and then committed it).&lt;br /&gt;
At that point, the version control system would detect a conflict, and&lt;br /&gt;
prompt the two users to coordinate to resolve the conflict to&lt;br /&gt;
deteremine what text should be on line 49.&lt;br /&gt;
&lt;br /&gt;
The solution to this problem lies in allowing users of the revision&lt;br /&gt;
control system to ''branch'' a version of the repository and make&lt;br /&gt;
(possibly many) changes to that branch independent of the changes&lt;br /&gt;
occurring on the main branch of the repository, known as the&lt;br /&gt;
''trunk''. Once a logical set of changes was completed on a branch,&lt;br /&gt;
that branch would then need to have its changes reconciled with the&lt;br /&gt;
current state of the repository on the trunk. This process of&lt;br /&gt;
reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature is critical in a multi-user client environment as it&lt;br /&gt;
allows work to progress on multiple fronts simultaneously, only&lt;br /&gt;
requiring that the files be merged once the users of the system are&lt;br /&gt;
ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent&lt;br /&gt;
access to the repository over the network, version control systems&lt;br /&gt;
became more adept in the algorithms they used to detect conflicts and&lt;br /&gt;
merge conflicts. This aspect of revision control is discussed further&lt;br /&gt;
in [[#Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
==Client-Server Beyond CVS==&lt;br /&gt;
&lt;br /&gt;
Although CVS developed good approaches to solving many of these&lt;br /&gt;
problems, it had many problems that gained attention when it became&lt;br /&gt;
the most widely used revision control system for open source&lt;br /&gt;
development. An exhaustive list would be lengthy, but to mention a few&lt;br /&gt;
might be illustrative. &lt;br /&gt;
&lt;br /&gt;
* CVS doesn't provide ''atomic'' operations, which means that if there&lt;br /&gt;
were a network failure during a commit, the repository could become&lt;br /&gt;
corrupted. &lt;br /&gt;
* CVS does not version control directories or symbolic links, which&lt;br /&gt;
means the repostitory is really a lossy copy of a developer's&lt;br /&gt;
environment, sometimes resulting in failure to track changes&lt;br /&gt;
accrurately.&lt;br /&gt;
* CVS doesn't track what files were committed at the same time, so if&lt;br /&gt;
you make a logical group of changes to several files and want to track&lt;br /&gt;
the fact that those files were changed together, you can only only&lt;br /&gt;
derive that information from log messages. CVS will not track it for&lt;br /&gt;
you.&lt;br /&gt;
* CVS cannot track when files are renamed; rather, a rename of a file&lt;br /&gt;
in CVS looks like the original file was deleted and a new file added,&lt;br /&gt;
thus losing the file's history.&lt;br /&gt;
* Creating braches and managing the subsequent merges is slow and difficult.&lt;br /&gt;
&lt;br /&gt;
In short, while CVS provided a whole host of new features and advanced&lt;br /&gt;
the state of the art in version control, it left room for improvement.&lt;br /&gt;
This resulted in a vast number of client-server version control&lt;br /&gt;
systems entering the market following CVS. One of the latest and most&lt;br /&gt;
notable of these is [http://subversion.tigris.org/ Subversion], which&lt;br /&gt;
seeks to address all of the&lt;br /&gt;
[http://subversion.tigris.org/features.html issues] mentioned above&lt;br /&gt;
and a whole lot more.&lt;br /&gt;
&lt;br /&gt;
=Distributed Revision Control=&lt;br /&gt;
&lt;br /&gt;
''Distributed'' revision control took many of the advances seen in&lt;br /&gt;
client-server version control systems and moved them into a less&lt;br /&gt;
centralized architecture. Essentially, the original version control&lt;br /&gt;
systems were completely centralized, requiring every user to locally&lt;br /&gt;
log in to the server on which the repository was located. In&lt;br /&gt;
client-server version control systems, the system was made slightly&lt;br /&gt;
more distributed, allowing users to connect from across the network to&lt;br /&gt;
the repository, copy files from the repostory to other machines for&lt;br /&gt;
editing, and then commit them back to the server when edits were&lt;br /&gt;
complete. Distributed version control continues the trend of&lt;br /&gt;
decentralization by putting an entire repository, complete with a&lt;br /&gt;
history of changes and ability to support remote connections, on each&lt;br /&gt;
user's machine.&lt;br /&gt;
&lt;br /&gt;
One of the strengths of CVS is that it supports file locking even&lt;br /&gt;
though the main advance it provides is a non-locking repository. This&lt;br /&gt;
allows for users of RCS to switch to CVS while maintaining their work&lt;br /&gt;
flow. When users are ready, they can take advantage of the non-locking&lt;br /&gt;
repository features CVS provides. In the same way that CVS supports&lt;br /&gt;
legacy locking work flows, so do distributed version control systems&lt;br /&gt;
support a centralized repository. The main improvement distributed&lt;br /&gt;
version control systems offer, however, is they do not require a&lt;br /&gt;
central server, and allow each user to maintain a complete copy of the&lt;br /&gt;
repository on their local machine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems&lt;br /&gt;
allowed users to access, modify and share data in the repository, many&lt;br /&gt;
advances have been made in the way changes are merged, tracked and&lt;br /&gt;
stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
==Repository Data Storage==&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
IBM has an excellent&lt;br /&gt;
[http://www.ibm.com/developerworks/java/library/j-subversion/index.html DeveloperWorks article] &lt;br /&gt;
describing the ways is which Subversion improved upon CVS, along with&lt;br /&gt;
some history of version control up until Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17999</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17999"/>
		<updated>2009-09-07T05:44:18Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability&lt;br /&gt;
to track changes to a document, or set of documents, over many&lt;br /&gt;
changes, or revisions.  For the vast majority of applications, version&lt;br /&gt;
control systems have focused on tracking plain text files, such as&lt;br /&gt;
those used for programming source code, HTML documents, and various&lt;br /&gt;
markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly&lt;br /&gt;
categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underly how data is&lt;br /&gt;
''shared'' and ''stored'' in a version control system. It should not&lt;br /&gt;
be inferred from this structure that other attributes are not&lt;br /&gt;
important to the history of developments of version control systems.&lt;br /&gt;
There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is stored&lt;br /&gt;
&lt;br /&gt;
We will discuss these each in turn in [[#Other Advances]].&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems focused on ''local version&lt;br /&gt;
control''; that is, centralized computer systems that were used by&lt;br /&gt;
many users, often at the same time. In such a system, there were often&lt;br /&gt;
many users of the system and the ''repository'', or location in which&lt;br /&gt;
the data was stored, was simply a directory on the server to which the&lt;br /&gt;
users had access. Because of this use case, these systems focused on&lt;br /&gt;
two main features:&lt;br /&gt;
&lt;br /&gt;
* File revision tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Revision Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in&lt;br /&gt;
files at various points as they were altered, so that the history of&lt;br /&gt;
changes made to files under version control was kept permanently.&lt;br /&gt;
Thus, many users could alter many files over time, and the entire set&lt;br /&gt;
of documents under version control at a given point in time could be&lt;br /&gt;
recovered, preventing loss of valuable data, as well a providing a&lt;br /&gt;
record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file&lt;br /&gt;
simultaneously, one of the first features developed for version&lt;br /&gt;
control systems was the ability to ''check out'' and ''lock'' a file.&lt;br /&gt;
When a user checks out a file, he or she reserves the right to be the&lt;br /&gt;
sole editor of that file until it is checked back in to revision&lt;br /&gt;
control.  The first revision control systems designed for use in a&lt;br /&gt;
shared environment, such as [http://www.gnu.org/software/rcs/ RCS],&lt;br /&gt;
allowed files to be checked out and locked in this way.  Other users&lt;br /&gt;
could check out the file, but only to view it.  Thus, the files were&lt;br /&gt;
locked from editing by all but the user that had checked the file out&lt;br /&gt;
most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems==&lt;br /&gt;
These local systems had two primary problems.  &lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to&lt;br /&gt;
edit or access the information in the repository.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at&lt;br /&gt;
any given time. The next development in revision control, embodied by&lt;br /&gt;
[http://www.nongnu.org/cvs/ CVS], sought to address both of these&lt;br /&gt;
problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Revision Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their&lt;br /&gt;
changes to files, the need for a revision control system that&lt;br /&gt;
supported remote operations emerged.  The natural way to implement&lt;br /&gt;
such remote operations was as an extension of the existing system, and&lt;br /&gt;
by far the most prominent manifestation of this philosophy was present&lt;br /&gt;
in CVS, the concurrent versions system, which was initially based on&lt;br /&gt;
RCS.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many&lt;br /&gt;
users, each on his or her own machine, to be able to perform all the&lt;br /&gt;
operations present in the original RCS, but over a network connection,&lt;br /&gt;
and in a way that allowed for concurrent editting to take place.  This&lt;br /&gt;
led to the development of a client-server model of revision control&lt;br /&gt;
systems, in which one central server would contain the canoncal&lt;br /&gt;
version of the repository, and various clients could connect to the&lt;br /&gt;
central server and perform file check outs and commits.  This model is&lt;br /&gt;
very similar to the original RCS model, but rather than requiring&lt;br /&gt;
users of the system to log into the revision control system locally,&lt;br /&gt;
it allowed users to access and alter the contents of the repository&lt;br /&gt;
over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among&lt;br /&gt;
the first version control systems to support a ''non-locking&lt;br /&gt;
repository''. This system allowed for concurrent editing of files&lt;br /&gt;
under revision control, and generated the need to develop new features&lt;br /&gt;
that addressed the resulting complexities. Chief among the new&lt;br /&gt;
features introduced to handle these complexities were the notions of&lt;br /&gt;
''branching'' and ''merging''. This allowed CVS to offer a non-locking&lt;br /&gt;
repository, which is why there is an emphasis on the &amp;quot;concurrent&amp;quot;&lt;br /&gt;
portion of CVS's name &amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to&lt;br /&gt;
reconcile conflicting changes to the same file. A ''conflict'' is&lt;br /&gt;
essentially two or more changes made to the same file that it may be&lt;br /&gt;
difficult to merge into a final file that contains both sets of&lt;br /&gt;
changes. An example of a conflict would occur if two users both edited&lt;br /&gt;
a file on line 49, one changing the word &amp;quot;blue&amp;quot; to &amp;quot;red&amp;quot;, and the&lt;br /&gt;
other changing the same word &amp;quot;blue&amp;quot; to &amp;quot;green&amp;quot;. The first user would&lt;br /&gt;
then commit his or her changes back to the repository, and when the&lt;br /&gt;
second user committed changes, the version control system would detect&lt;br /&gt;
that the repostory had changed since the second user had obtained the&lt;br /&gt;
file (since the first user had made a change and then committed it).&lt;br /&gt;
At that point, the version control system would detect a conflict, and&lt;br /&gt;
prompt the two users to coordinate to resolve the conflict to&lt;br /&gt;
deteremine what text should be on line 49.&lt;br /&gt;
&lt;br /&gt;
The solution to this problem lies in allowing users of the revision&lt;br /&gt;
control system to ''branch'' a version of the repository and make&lt;br /&gt;
(possibly many) changes to that branch independent of the changes&lt;br /&gt;
occurring on the main branch of the repository, known as the&lt;br /&gt;
''trunk''. Once a logical set of changes was completed on a branch,&lt;br /&gt;
that branch would then need to have its changes reconciled with the&lt;br /&gt;
current state of the repository on the trunk. This process of&lt;br /&gt;
reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature is critical in a multi-user client environment as it&lt;br /&gt;
allows work to progress on multiple fronts simultaneously, only&lt;br /&gt;
requiring that the files be merged once the users of the system are&lt;br /&gt;
ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent&lt;br /&gt;
access to the repository over the network, version control systems&lt;br /&gt;
became more adept in the algorithms they used to detect conflicts and&lt;br /&gt;
merge conflicts. This aspect of revision control is discussed further&lt;br /&gt;
in [[#Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
==Client-Server Beyond CVS==&lt;br /&gt;
&lt;br /&gt;
Although CVS developed good approaches to solving many of these&lt;br /&gt;
problems, it had many problems that gained attention when it became&lt;br /&gt;
the most widely used revision control system for open source&lt;br /&gt;
development. An exhaustive list would be lengthy, but to mention a few&lt;br /&gt;
might be illustrative. &lt;br /&gt;
&lt;br /&gt;
* CVS doesn't provide ''atomic'' operations, which means that if there&lt;br /&gt;
were a network failure during a commit, the repository could become&lt;br /&gt;
corrupted. &lt;br /&gt;
* CVS does not version control directories or symbolic links, which&lt;br /&gt;
means the repostitory is really a lossy copy of a developer's&lt;br /&gt;
environment, sometimes resulting in failure to track changes&lt;br /&gt;
accrurately.&lt;br /&gt;
* CVS doesn't track what files were committed at the same time, so if&lt;br /&gt;
you make a logical group of changes to several files and want to track&lt;br /&gt;
the fact that those files were changed together, you can only only&lt;br /&gt;
derive that information from log messages. CVS will not track it for&lt;br /&gt;
you.&lt;br /&gt;
* CVS cannot track when files are renamed; rather, a rename of a file&lt;br /&gt;
in CVS looks like the original file was deleted and a new file added,&lt;br /&gt;
thus losing the file's history.&lt;br /&gt;
* Creating braches and managing the subsequent merges is slow and difficult.&lt;br /&gt;
&lt;br /&gt;
In short, while CVS provided a whole host of new features and advanced&lt;br /&gt;
the state of the art in version control, it left room for improvement.&lt;br /&gt;
This resulted in a vast number of client-server version control&lt;br /&gt;
systems entering the market following CVS. One of the latest and most&lt;br /&gt;
notable of these is [http://subversion.tigris.org/ Subversion], which&lt;br /&gt;
seeks to address [http://subversion.tigris.org/features.html all of&lt;br /&gt;
the issues above] and a whole lot more.&lt;br /&gt;
&lt;br /&gt;
=Distributed Revision Control=&lt;br /&gt;
&lt;br /&gt;
''Distributed'' revision control took many of the advances seen in&lt;br /&gt;
client-server version control systems and moved them into a less&lt;br /&gt;
centralized architecture. Essentially, the original version control&lt;br /&gt;
systems were completely centralized, requiring every user to locally&lt;br /&gt;
log in to the server on which the repository was located. In&lt;br /&gt;
client-server version control systems, the system was made slightly&lt;br /&gt;
more distributed, allowing users to connect from across the network to&lt;br /&gt;
the repository, copy files from the repostory to other machines for&lt;br /&gt;
editing, and then commit them back to the server when edits were&lt;br /&gt;
complete. Distributed version control continues the trend of&lt;br /&gt;
decentralization by putting an entire repository, complete with a&lt;br /&gt;
history of changes and ability to support remote connections, on each&lt;br /&gt;
user's machine.&lt;br /&gt;
&lt;br /&gt;
One of the strengths of CVS is that it supports file locking even&lt;br /&gt;
though the main advance it provides is a non-locking repository. This&lt;br /&gt;
allows for users of RCS to switch to CVS while maintaining their work&lt;br /&gt;
flow. When users are ready, they can take advantage of the non-locking&lt;br /&gt;
repository features CVS provides. In the same way that CVS supports&lt;br /&gt;
legacy locking work flows, so do distributed version control systems&lt;br /&gt;
support a centralized repository. The main improvement distributed&lt;br /&gt;
version control systems offer, however, is they do not require a&lt;br /&gt;
central server, and allow each user to maintain a complete copy of the&lt;br /&gt;
repository on their local machine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems&lt;br /&gt;
allowed users to access, modify and share data in the repository, many&lt;br /&gt;
advances have been made in the way changes are merged, tracked and&lt;br /&gt;
stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
==Repository Data Storage==&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
IBM has an excellent&lt;br /&gt;
[http://www.ibm.com/developerworks/java/library/j-subversion/index.html&lt;br /&gt;
DeveloperWorks article] describing the ways is which Subversion&lt;br /&gt;
improved upon CVS, along with some history of version control up until&lt;br /&gt;
Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17997</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17997"/>
		<updated>2009-09-07T05:42:28Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability&lt;br /&gt;
to track changes to a document, or set of documents, over many&lt;br /&gt;
changes, or revisions.  For the vast majority of applications, version&lt;br /&gt;
control systems have focused on tracking plain text files, such as&lt;br /&gt;
those used for programming source code, HTML documents, and various&lt;br /&gt;
markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly&lt;br /&gt;
categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underly how data is&lt;br /&gt;
''shared'' and ''stored'' in a version control system. It should not&lt;br /&gt;
be inferred from this structure that other attributes are not&lt;br /&gt;
important to the history of developments of version control systems.&lt;br /&gt;
There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is stored&lt;br /&gt;
&lt;br /&gt;
We will discuss these each in turn in [[#Other Advances]].&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems focused on ''local version&lt;br /&gt;
control''; that is, centralized computer systems that were used by&lt;br /&gt;
many users, often at the same time. In such a system, there were often&lt;br /&gt;
many users of the system and the ''repository'', or location in which&lt;br /&gt;
the data was stored, was simply a directory on the server to which the&lt;br /&gt;
users had access. Because of this use case, these systems focused on&lt;br /&gt;
two main features:&lt;br /&gt;
&lt;br /&gt;
* File revision tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Revision Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in&lt;br /&gt;
files at various points as they were altered, so that the history of&lt;br /&gt;
changes made to files under version control was kept permanently.&lt;br /&gt;
Thus, many users could alter many files over time, and the entire set&lt;br /&gt;
of documents under version control at a given point in time could be&lt;br /&gt;
recovered, preventing loss of valuable data, as well a providing a&lt;br /&gt;
record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file&lt;br /&gt;
simultaneously, one of the first features developed for version&lt;br /&gt;
control systems was the ability to ''check out'' and ''lock'' a file.&lt;br /&gt;
When a user checks out a file, he or she reserves the right to be the&lt;br /&gt;
sole editor of that file until it is checked back in to revision&lt;br /&gt;
control.  The first revision control systems designed for use in a&lt;br /&gt;
shared environment, such as [http://www.gnu.org/software/rcs/ RCS],&lt;br /&gt;
allowed files to be checked out and locked in this way.  Other users&lt;br /&gt;
could check out the file, but only to view it.  Thus, the files were&lt;br /&gt;
locked from editing by all but the user that had checked the file out&lt;br /&gt;
most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems==&lt;br /&gt;
These local systems had two primary problems.  &lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to&lt;br /&gt;
edit or access the information in the repository.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at&lt;br /&gt;
any given time. The next development in revision control, embodied by&lt;br /&gt;
[http://www.nongnu.org/cvs/ CVS], sought to address both of these&lt;br /&gt;
problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Revision Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their&lt;br /&gt;
changes to files, the need for a revision control system that&lt;br /&gt;
supported remote operations emerged.  The natural way to implement&lt;br /&gt;
such remote operations was as an extension of the existing system, and&lt;br /&gt;
by far the most prominent manifestation of this philosophy was present&lt;br /&gt;
in CVS, the concurrent versions system, which was initially based on&lt;br /&gt;
RCS.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many&lt;br /&gt;
users, each on his or her own machine, to be able to perform all the&lt;br /&gt;
operations present in the original RCS, but over a network connection,&lt;br /&gt;
and in a way that allowed for concurrent editting to take place.  This&lt;br /&gt;
led to the development of a client-server model of revision control&lt;br /&gt;
systems, in which one central server would contain the canoncal&lt;br /&gt;
version of the repository, and various clients could connect to the&lt;br /&gt;
central server and perform file check outs and commits.  This model is&lt;br /&gt;
very similar to the original RCS model, but rather than requiring&lt;br /&gt;
users of the system to log into the revision control system locally,&lt;br /&gt;
it allowed users to access and alter the contents of the repository&lt;br /&gt;
over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among&lt;br /&gt;
the first version control systems to support a ''non-locking&lt;br /&gt;
repository''. This system allowed for concurrent editing of files&lt;br /&gt;
under revision control, and generated the need to develop new features&lt;br /&gt;
that addressed the resulting complexities. Chief among the new&lt;br /&gt;
features introduced to handle these complexities were the notions of&lt;br /&gt;
''branching'' and ''merging''. This allowed CVS to offer a non-locking&lt;br /&gt;
repository, which is why there is an emphasis on the &amp;quot;concurrent&amp;quot;&lt;br /&gt;
portion of CVS's name &amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to&lt;br /&gt;
reconcile conflicting changes to the same file. A ''conflict'' is&lt;br /&gt;
essentially two or more changes made to the same file that it may be&lt;br /&gt;
difficult to merge into a final file that contains both sets of&lt;br /&gt;
changes. An example of a conflict would occur if two users both edited&lt;br /&gt;
a file on line 49, one changing the word &amp;quot;blue&amp;quot; to &amp;quot;red&amp;quot;, and the&lt;br /&gt;
other changing the same word &amp;quot;blue&amp;quot; to &amp;quot;green&amp;quot;. The first user would&lt;br /&gt;
then commit his or her changes back to the repository, and when the&lt;br /&gt;
second user committed changes, the version control system would detect&lt;br /&gt;
that the repostory had changed since the second user had obtained the&lt;br /&gt;
file (since the first user had made a change and then committed it).&lt;br /&gt;
At that point, the version control system would detect a conflict, and&lt;br /&gt;
prompt the two users to coordinate to resolve the conflict to&lt;br /&gt;
deteremine what text should be on line 49.&lt;br /&gt;
&lt;br /&gt;
The solution to this problem lies in allowing users of the revision&lt;br /&gt;
control system to ''branch'' a version of the repository and make&lt;br /&gt;
(possibly many) changes to that branch independent of the changes&lt;br /&gt;
occurring on the main branch of the repository, known as the&lt;br /&gt;
''trunk''. Once a logical set of changes was completed on a branch,&lt;br /&gt;
that branch would then need to have its changes reconciled with the&lt;br /&gt;
current state of the repository on the trunk. This process of&lt;br /&gt;
reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature is critical in a multi-user client environment as it&lt;br /&gt;
allows work to progress on multiple fronts simultaneously, only&lt;br /&gt;
requiring that the files be merged once the users of the system are&lt;br /&gt;
ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent&lt;br /&gt;
access to the repository over the network, version control systems&lt;br /&gt;
became more adept in the algorithms they used to detect conflicts and&lt;br /&gt;
merge conflicts. This aspect of revision control is discussed further&lt;br /&gt;
in [[#Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
==Client-Server Beyond CVS==&lt;br /&gt;
&lt;br /&gt;
Although CVS developed good approaches to solving many of these&lt;br /&gt;
problems, it had many problems that gained attention when it became&lt;br /&gt;
the most widely used revision control system for open source&lt;br /&gt;
development. An exhaustive list would be lengthy, but to mention a few&lt;br /&gt;
might be illustrative. &lt;br /&gt;
&lt;br /&gt;
* CVS doesn't provide ''atomic'' operations, which means that if there&lt;br /&gt;
were a network failure during a commit, the repository could become&lt;br /&gt;
corrupted. &lt;br /&gt;
* CVS does not version control directories or symbolic links, which&lt;br /&gt;
means the repostitory is really a lossy copy of a developer's&lt;br /&gt;
environment, sometimes resulting in failure to track changes&lt;br /&gt;
accrurately.&lt;br /&gt;
* CVS doesn't track what files were committed at the same time, so if&lt;br /&gt;
you make a logical group of changes to several files and want to track&lt;br /&gt;
the fact that those files were changed together, you can only only&lt;br /&gt;
derive that information from log messages. CVS will not track it for&lt;br /&gt;
you.&lt;br /&gt;
* CVS cannot track when files are renamed; rather, a rename of a file&lt;br /&gt;
in CVS looks like the original file was deleted and a new file added,&lt;br /&gt;
thus losing the file's history.&lt;br /&gt;
* Creating braches and managing the subsequent merges is slow and difficult.&lt;br /&gt;
&lt;br /&gt;
In short, while CVS provided a whole host of new features and advanced&lt;br /&gt;
the state of the art in version control, it left room for improvement.&lt;br /&gt;
This resulted in a vast number of client-server version control&lt;br /&gt;
systems entering the market following CVS. One of the latest and most&lt;br /&gt;
notable of these is [http://subversion.tigris.org/ Subversion], which&lt;br /&gt;
seeks to address [http://subversion.tigris.org/features.html all of&lt;br /&gt;
the issues above] and a whole lot more.&lt;br /&gt;
&lt;br /&gt;
=Distributed Revision Control=&lt;br /&gt;
&lt;br /&gt;
''Distributed'' revision control took many of the advances seen in&lt;br /&gt;
client-server version control systems and moved them into a less&lt;br /&gt;
centralized architecture. Essentially, the original version control&lt;br /&gt;
systems were completely centralized, requiring every user to locally&lt;br /&gt;
log in to the server on which the repository was located. In&lt;br /&gt;
client-server version control systems, the system was made slightly&lt;br /&gt;
more distributed, allowing users to connect from across the network to&lt;br /&gt;
the repository, copy files from the repostory to other machines for&lt;br /&gt;
editing, and then commit them back to the server when edits were&lt;br /&gt;
complete. Distributed version control continues the trend of&lt;br /&gt;
decentralization by putting an entire repository, complete with a&lt;br /&gt;
history of changes and ability to support remote connections, on each&lt;br /&gt;
user's machine.&lt;br /&gt;
&lt;br /&gt;
One of the strengths of CVS is that it supports file locking even&lt;br /&gt;
though the main advance it provides is a non-locking repository. This&lt;br /&gt;
allows for users of RCS to switch to CVS while maintaining their work&lt;br /&gt;
flow. When users are ready, they can take advantage of the non-locking&lt;br /&gt;
repository features CVS provides. In the same way that CVS supports&lt;br /&gt;
legacy locking work flows, so do distributed version control systems&lt;br /&gt;
support a centralized repository. The main improvement distributed&lt;br /&gt;
version control systems offer, however, is they do not require a&lt;br /&gt;
central server, and allow each user to maintain a complete copy of the&lt;br /&gt;
repository on their local machine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems&lt;br /&gt;
allowed users to access, modify and share data in the repository, many&lt;br /&gt;
advances have been made in the way changes are merged, tracked and&lt;br /&gt;
stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
==Repository Data Storage==&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
IBM has an excellent&lt;br /&gt;
[http://www.ibm.com/developerworks/java/library/j-subversion/index.html&lt;br /&gt;
DeveoperWorks article] describing the ways is which Subversion&lt;br /&gt;
improved upon CVS, along with some history of version control up until&lt;br /&gt;
Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17881</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17881"/>
		<updated>2009-09-07T00:05:23Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability&lt;br /&gt;
to track changes to a document, or set of documents, over many&lt;br /&gt;
changes, or revisions.  For the vast majority of applications, version&lt;br /&gt;
control systems have focused on tracking plain text files, such as&lt;br /&gt;
those used for programming source code, HTML documents, and various&lt;br /&gt;
markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly&lt;br /&gt;
categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underly how data is&lt;br /&gt;
''shared'' and ''stored'' in a version control system. It should not&lt;br /&gt;
be inferred from this structure that other attributes are not&lt;br /&gt;
important to the history of developments of version control systems.&lt;br /&gt;
There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is stored&lt;br /&gt;
&lt;br /&gt;
We will discuss these each in turn in [[Other Advances]].&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems focused on ''local version&lt;br /&gt;
control''; that is, centralized computer systems that were used by&lt;br /&gt;
many users, often at the same time. In such a system, there were often&lt;br /&gt;
many users of the system and the ''repository'', or location in which&lt;br /&gt;
the data was stored, was simply a directory on the server to which the&lt;br /&gt;
users had access. Because of this use case, these systems focused on&lt;br /&gt;
two main features:&lt;br /&gt;
&lt;br /&gt;
* File revision tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Revision Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in&lt;br /&gt;
files at various points as they were altered, so that the history of&lt;br /&gt;
changes made to files under version control was kept permanently.&lt;br /&gt;
Thus, many users could alter many files over time, and the entire set&lt;br /&gt;
of documents under version control at a given point in time could be&lt;br /&gt;
recovered, preventing loss of valuable data, as well a providing a&lt;br /&gt;
record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file&lt;br /&gt;
simultaneously, one of the first features developed for version&lt;br /&gt;
control systems was the ability to ''check out'' and ''lock'' a file.&lt;br /&gt;
When a user checks out a file, he or she reserves the right to be the&lt;br /&gt;
sole editor of that file until it is checked back in to revision&lt;br /&gt;
control.  The first revision control systems designed for use in a&lt;br /&gt;
shared environment, such as [http://www.gnu.org/software/rcs/ RCS],&lt;br /&gt;
allowed files to be checked out and locked in this way.  Other users&lt;br /&gt;
could check out the file, but only to view it.  Thus, the files were&lt;br /&gt;
locked from editing by all but the user that had checked the file out&lt;br /&gt;
most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems==&lt;br /&gt;
These local systems had two primary problems.  &lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to&lt;br /&gt;
edit or access the information in the repository.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at&lt;br /&gt;
any given time. The next development in revision control, embodied by&lt;br /&gt;
[http://www.nongnu.org/cvs/ CVS], sought to address both of these&lt;br /&gt;
problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Revision Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their&lt;br /&gt;
changes to files, the need for a revision control system that&lt;br /&gt;
supported remote operations emerged.  The natural way to implement&lt;br /&gt;
such remote operations was as an extension of the existing system, and&lt;br /&gt;
by far the most prominent manifestation of this philosophy was present&lt;br /&gt;
in CVS, the concurrent versions system, which was initially based on&lt;br /&gt;
RCS.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many&lt;br /&gt;
users, each on his or her own machine, to be able to perform all the&lt;br /&gt;
operations present in the original RCS, but over a network connection,&lt;br /&gt;
and in a way that allowed for concurrent editting to take place.  This&lt;br /&gt;
led to the development of a client-server model of revision control&lt;br /&gt;
systems, in which one central server would contain the canoncal&lt;br /&gt;
version of the repository, and various clients could connect to the&lt;br /&gt;
central server and perform file check outs and commits.  This model is&lt;br /&gt;
very similar to the original RCS model, but rather than requiring&lt;br /&gt;
users of the system to log into the revision control system locally,&lt;br /&gt;
it allowed users to access and alter the contents of the repository&lt;br /&gt;
over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among&lt;br /&gt;
the first version control systems to support a ''non-locking&lt;br /&gt;
repository''. This system allowed for concurrent editing of files&lt;br /&gt;
under revision control, and generated the need to develop new features&lt;br /&gt;
that addressed the resulting complexities. Chief among the new&lt;br /&gt;
features introduced to handle these complexities were the notions of&lt;br /&gt;
''branching'' and ''merging''. This allowed CVS to offer a non-locking&lt;br /&gt;
repository, which is why there is an emphasis on the &amp;quot;concurrent&amp;quot;&lt;br /&gt;
portion of CVS's name &amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to&lt;br /&gt;
reconcile conflicting changes to the same file. A ''conflict'' is&lt;br /&gt;
essentially two or more changes made to the same file that it may be&lt;br /&gt;
difficult to merge into a final file that contains both sets of&lt;br /&gt;
changes. An example of a conflict would occur if two users both edited&lt;br /&gt;
a file on line 49, one changing the word &amp;quot;blue&amp;quot; to &amp;quot;red&amp;quot;, and the&lt;br /&gt;
other changing the same word &amp;quot;blue&amp;quot; to &amp;quot;green&amp;quot;. The first user would&lt;br /&gt;
then commit his or her changes back to the repository, and when the&lt;br /&gt;
second user committed changes, the version control system would detect&lt;br /&gt;
that the repostory had changed since the second user had obtained the&lt;br /&gt;
file (since the first user had made a change and then committed it).&lt;br /&gt;
At that point, the version control system would detect a conflict, and&lt;br /&gt;
prompt the two users to coordinate to resolve the conflict to&lt;br /&gt;
deteremine what text should be on line 49.&lt;br /&gt;
&lt;br /&gt;
The solution to this problem lies in allowing users of the revision&lt;br /&gt;
control system to ''branch'' a version of the repository and make&lt;br /&gt;
(possibly many) changes to that branch independent of the changes&lt;br /&gt;
occurring on the main branch of the repository, known as the&lt;br /&gt;
''trunk''. Once a logical set of changes was completed on a branch,&lt;br /&gt;
that branch would then need to have its changes reconciled with the&lt;br /&gt;
current state of the repository on the trunk. This process of&lt;br /&gt;
reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature is critical in a multi-user client environment as it&lt;br /&gt;
allows work to progress on multiple fronts simultaneously, only&lt;br /&gt;
requiring that the files be merged once the users of the system are&lt;br /&gt;
ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent&lt;br /&gt;
access to the repository over the network, version control systems&lt;br /&gt;
became more adept in the algorithms they used to detect conflicts and&lt;br /&gt;
merge conflicts. This aspect of revision control is discussed further&lt;br /&gt;
in [[Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
==Client-Server Beyond CVS==&lt;br /&gt;
&lt;br /&gt;
Although CVS developed good approaches to solving many of these&lt;br /&gt;
problems, it had many problems that gained attention when it became&lt;br /&gt;
the most widely used revision control system for open source&lt;br /&gt;
development. An exhaustive list would be lengthy, but to mention a few&lt;br /&gt;
might be illustrative. &lt;br /&gt;
&lt;br /&gt;
* CVS doesn't provide ''atomic'' operations, which means that if there&lt;br /&gt;
were a network failure during a commit, the repository could become&lt;br /&gt;
corrupted. &lt;br /&gt;
* CVS does not version control directories or symbolic links, which&lt;br /&gt;
means the repostitory is really a lossy copy of a developer's&lt;br /&gt;
environment, sometimes resulting in failure to track changes&lt;br /&gt;
accrurately.&lt;br /&gt;
* CVS doesn't track what files were committed at the same time, so if&lt;br /&gt;
you make a logical group of changes to several files and want to track&lt;br /&gt;
the fact that those files were changed together, you can only only&lt;br /&gt;
derive that information from log messages. CVS will not track it for&lt;br /&gt;
you.&lt;br /&gt;
* CVS cannot track when files are renamed; rather, a rename of a file&lt;br /&gt;
in CVS looks like the original file was deleted and a new file added,&lt;br /&gt;
thus losing the file's history.&lt;br /&gt;
* Creating braches and managing the subsequent merges is slow and difficult.&lt;br /&gt;
&lt;br /&gt;
In short, while CVS provided a whole host of new features and advanced&lt;br /&gt;
the state of the art in version control, it left room for improvement.&lt;br /&gt;
This resulted in a vast number of client-server version control&lt;br /&gt;
systems entering the market following CVS. One of the latest and most&lt;br /&gt;
notable of these is [http://subversion.tigris.org/ Subversion], which&lt;br /&gt;
seeks to address all of the issues above and a whole lot more. In&lt;br /&gt;
fact, the motto of Subversion originally was &amp;quot;CVS Done Right&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Distributed Revision Control=&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems&lt;br /&gt;
allowed users to access, modify and share data in the repository, many&lt;br /&gt;
advances have been made in the way changes are merged, tracked and&lt;br /&gt;
stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
==Repository Data Storage==&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
IBM has an excellent&lt;br /&gt;
[http://www.ibm.com/developerworks/java/library/j-subversion/index.html&lt;br /&gt;
DeveoperWorks article] describing the ways is which Subversion&lt;br /&gt;
improved upon CVS, along with some history of version control up until&lt;br /&gt;
Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17847</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17847"/>
		<updated>2009-09-06T21:16:15Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Introduction=&lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability&lt;br /&gt;
to track changes to a document, or set of documents, over many&lt;br /&gt;
changes, or revisions.  For the vast majority of applications, version&lt;br /&gt;
control systems have focused on tracking plain text files, such as&lt;br /&gt;
those used for programming source code, HTML documents, and various&lt;br /&gt;
markup syntax.  &lt;br /&gt;
&lt;br /&gt;
The history of the development of version control tools can be roughly&lt;br /&gt;
categorized into three main phases:&lt;br /&gt;
&lt;br /&gt;
# Local Version Control&lt;br /&gt;
# Client-Server Version Control&lt;br /&gt;
# Distributed Version Control&lt;br /&gt;
&lt;br /&gt;
This breakdown is focused on the mechanisms that underly how data is&lt;br /&gt;
''shared'' and ''stored'' in a version control system. It should not&lt;br /&gt;
be inferred from this structure that other attributes are not&lt;br /&gt;
important to the history of developments of version control systems.&lt;br /&gt;
There have been many advances in how:&lt;br /&gt;
&lt;br /&gt;
* conflicts are recognized and merges are performed&lt;br /&gt;
* groups of logically coherent changes are tracked&lt;br /&gt;
* and how the data is stored&lt;br /&gt;
&lt;br /&gt;
We will discuss these each in turn in [[#Other Advances]].&lt;br /&gt;
&lt;br /&gt;
=Local Version Control=&lt;br /&gt;
&lt;br /&gt;
The first version control systems focused on ''local version&lt;br /&gt;
control''; that is, centralized computer systems that were used by&lt;br /&gt;
many users, often at the same time. In such a system, there were often&lt;br /&gt;
many users of the system and the ''repository'', or location in which&lt;br /&gt;
the data was stored, was simply a directory on the server to which the&lt;br /&gt;
users had access. Because of this use case, these systems focused on&lt;br /&gt;
two main features:&lt;br /&gt;
&lt;br /&gt;
* File revision tracking&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
&lt;br /&gt;
We will address each of these fundamental features in turn.&lt;br /&gt;
&lt;br /&gt;
==File Revision Tracking==&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in&lt;br /&gt;
files at various points as they were altered, so that the history of&lt;br /&gt;
changes made to files under version control was kept permanently.&lt;br /&gt;
Thus, many users could alter many files over time, and the entire set&lt;br /&gt;
of documents under version control at a given point in time could be&lt;br /&gt;
recovered, preventing loss of valuable data, as well a providing a&lt;br /&gt;
record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
==File Checkout and Locking==&lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file&lt;br /&gt;
simultaneously, one of the first features developed for version&lt;br /&gt;
control systems was the ability to ''check out'' and ''lock'' a file.&lt;br /&gt;
When a user checks out a file, he or she reserves the right to be the&lt;br /&gt;
sole editor of that file until it is checked back in to revision&lt;br /&gt;
control.  The first revision control systems designed for use in a&lt;br /&gt;
shared environment, such as [http://www.gnu.org/software/rcs/ RCS],&lt;br /&gt;
allowed files to be checked out and locked in this way.  Other users&lt;br /&gt;
could check out the file, but only to view it.  Thus, the files were&lt;br /&gt;
locked from editing by all but the user that had checked the file out&lt;br /&gt;
most recently.&lt;br /&gt;
&lt;br /&gt;
==Weaknesses of Local Version Control Systems==&lt;br /&gt;
These local systems had two primary problems.  &lt;br /&gt;
&lt;br /&gt;
First, they required that every user log into a single computer to&lt;br /&gt;
edit or access the information in the repository.&lt;br /&gt;
&lt;br /&gt;
Second, they restricted a particular file to having only one editor at&lt;br /&gt;
any given time. The next development in revision control, embodied by&lt;br /&gt;
[http://www.nongnu.org/cvs/ CVS], sought to address both of these&lt;br /&gt;
problems.&lt;br /&gt;
&lt;br /&gt;
=Networked Revision Control: Client-Server=&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their&lt;br /&gt;
changes to files, the need for a revision control system that&lt;br /&gt;
supported remote operations emerged.  The natural way to implement&lt;br /&gt;
such remote operations was as an extension of the existing system, and&lt;br /&gt;
by far the most prominent manifestation of this philosophy was present&lt;br /&gt;
in CVS, the concurrent versions system, which was initially based on&lt;br /&gt;
RCS.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many&lt;br /&gt;
users, each on his or her own machine, to be able to perform all the&lt;br /&gt;
operations present in the original RCS, but over a network connection,&lt;br /&gt;
and in a way that allowed for concurrent editting to take place.  This&lt;br /&gt;
led to the development of a client-server model of revision control&lt;br /&gt;
systems, in which one central server would contain the canoncal&lt;br /&gt;
version of the repository, and various clients could connect to the&lt;br /&gt;
central server and perform file check outs and commits.  This model is&lt;br /&gt;
very similar to the original RCS model, but rather than requiring&lt;br /&gt;
users of the system to log into the revision control system locally,&lt;br /&gt;
it allowed users to access and alter the contents of the repository&lt;br /&gt;
over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among&lt;br /&gt;
the first version control systems to support a ''non-locking&lt;br /&gt;
repository''. This system allowed for concurrent editing of files&lt;br /&gt;
under revision control, and generated the need to develop new features&lt;br /&gt;
that addressed the resulting complexities. Chief among the new&lt;br /&gt;
features introduced to handle these complexities were the notions of&lt;br /&gt;
''branching'' and ''merging''. This allowed CVS to offer a non-locking&lt;br /&gt;
repository, which put the &amp;quot;concurrent&amp;quot; in CVS's &amp;quot;concurrent versions&lt;br /&gt;
system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Branching and Merging==&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to&lt;br /&gt;
reconcile conflicting changes to the same file.  The solution to this&lt;br /&gt;
problem lay in allowing users of the revision control system to branch&lt;br /&gt;
a version of the repository and make (possibly many) changes to that&lt;br /&gt;
branch independent of the changes occurring on the main branch of the&lt;br /&gt;
repository, known as the trunk.  Once a logical set of changes was&lt;br /&gt;
completed on a branch, that branch would then need to have its changes&lt;br /&gt;
reconciled with the current state of the repository on the trunk.&lt;br /&gt;
This process of reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature was critical in a multi-user client environment as it&lt;br /&gt;
allowed work to progress on multiple fronts simultaneously, only&lt;br /&gt;
requiring that the files be merged once the users of the system were&lt;br /&gt;
ready to reconcile changes with other users.&lt;br /&gt;
&lt;br /&gt;
Along with development of mechanisms to allow this sort of concurrent&lt;br /&gt;
access to the repository over the network, version control systems&lt;br /&gt;
became more adept in the algorithms they used to detect conflicts and&lt;br /&gt;
merge conflicts. This aspect of revision control is discussed further&lt;br /&gt;
in [[#Merge Algorithms]].&lt;br /&gt;
&lt;br /&gt;
=Distributed Revision Control=&lt;br /&gt;
&lt;br /&gt;
=Other Advances=&lt;br /&gt;
&lt;br /&gt;
In addition to the evolution of the way version control systems&lt;br /&gt;
allowed users to access, modify and share data in the repository, many&lt;br /&gt;
advances have been made in the way changes are merged, tracked and&lt;br /&gt;
stored.&lt;br /&gt;
&lt;br /&gt;
==Merge Algorithms==&lt;br /&gt;
&lt;br /&gt;
==Tracking Groups of Changes==&lt;br /&gt;
&lt;br /&gt;
==Repository Data Storage==&lt;br /&gt;
&lt;br /&gt;
=Further Reading= &lt;br /&gt;
&lt;br /&gt;
IBM has an excellent&lt;br /&gt;
[http://www.ibm.com/developerworks/java/library/j-subversion/index.html&lt;br /&gt;
DeveoperWorks article] describing the ways is which Subversion&lt;br /&gt;
improved upon CVS, along with some history of version control up until&lt;br /&gt;
Subversion.&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17813</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17813"/>
		<updated>2009-09-06T17:51:48Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=History Of Version Control=&lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability&lt;br /&gt;
to track changes to a document, or set of documents, over many&lt;br /&gt;
changes, or revisions.  For the vast majority of applications, version&lt;br /&gt;
control systems have focused on tracking plain text files, such as&lt;br /&gt;
those used for programming source code, HTML documents, and various&lt;br /&gt;
markup syntax.  Over the past 30 years or so, notions of how to&lt;br /&gt;
implement such systems have evolved and become more advanced.&lt;br /&gt;
&lt;br /&gt;
==Local Version Control== &lt;br /&gt;
&lt;br /&gt;
The first version control systems focused on local version control;&lt;br /&gt;
that is, centralized computer systems that were used by many users,&lt;br /&gt;
often at the same time.  Because of this use case, these systems&lt;br /&gt;
focused on two main features:&lt;br /&gt;
&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
* File revision tracking&lt;br /&gt;
&lt;br /&gt;
===File Checkout and Locking=== &lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file&lt;br /&gt;
simultaneously, one of the first features developed for version&lt;br /&gt;
control systems was the ability to ''check out'' and ''lock'' a file.&lt;br /&gt;
When a user checks out a file, he or she reserves the right to be the&lt;br /&gt;
sole editor of that file until it is checked back in to revision&lt;br /&gt;
control.  The first revision control systems designed for use in a&lt;br /&gt;
shared environment, such as [http://www.gnu.org/software/rcs/ RCS],&lt;br /&gt;
allowed files to be checked out and locked in this way.  Other users&lt;br /&gt;
could check out the file, but only to view it.  Thus, the files were&lt;br /&gt;
locked from editing by all but the user that had checked the file out&lt;br /&gt;
most recently.&lt;br /&gt;
&lt;br /&gt;
===File Revision Tracking===&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in&lt;br /&gt;
files at various points as they were altered, so that the history of&lt;br /&gt;
changes made to files under version control was kept permanently.&lt;br /&gt;
Thus, many users could alter many files over time, and the entire set&lt;br /&gt;
of documents under version control at a given point in time could be&lt;br /&gt;
recovered, preventing loss of valuable data, as well a providing a&lt;br /&gt;
record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
But, these local systems had two primary problems.  First, they&lt;br /&gt;
required that every user log into a single computer to edit or access&lt;br /&gt;
the information in the repository.  Second, they restricted a&lt;br /&gt;
particular file to having only one editor at any given time.  The next&lt;br /&gt;
development in revision control, embodied by&lt;br /&gt;
[http://www.nongnu.org/cvs/ CVS], sought to address both of these&lt;br /&gt;
problems.&lt;br /&gt;
&lt;br /&gt;
===Networked Revision Control: Client-Server===&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their&lt;br /&gt;
changes to files, the need for a revision control system that&lt;br /&gt;
supported remote operations emerged.  The natural way to implement&lt;br /&gt;
such remote operations was as an extension of the existing system, and&lt;br /&gt;
by far the most prominent manifestation of this philosophy was present&lt;br /&gt;
in CVS, the concurrent versions system, which was initially based on&lt;br /&gt;
RCS.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many&lt;br /&gt;
users, each on his or her own machine, to be able to perform all the&lt;br /&gt;
operations present in the original RCS, but over a network connection,&lt;br /&gt;
and in a way that allowed for concurrent editting to take place.  This&lt;br /&gt;
led to the development of a client-server model of revision control&lt;br /&gt;
systems, in which one central server would contain the canoncal&lt;br /&gt;
version of the repository, and various clients could connect to the&lt;br /&gt;
central server and perform file check outs and commits.  This model is&lt;br /&gt;
very similar to the original RCS model, but rather than requiring&lt;br /&gt;
users of the system to log into the revision control system locally,&lt;br /&gt;
it allowed users to access and alter the contents of the repository&lt;br /&gt;
over the network.&lt;br /&gt;
&lt;br /&gt;
Although CVS supports locking in the same way RCS does, CVS was among&lt;br /&gt;
the first version control systems to support a ''non-locking&lt;br /&gt;
repository''.  This system allowed for concurrent editing of files&lt;br /&gt;
under revision control, and generated the need to develop new features&lt;br /&gt;
that addressed the resulting complexities.  Chief among the new&lt;br /&gt;
features introduced to handle these complexities were the notions of&lt;br /&gt;
''branching'' and ''merging''.  This allowed CVS to offer a&lt;br /&gt;
non-locking repository, which put the &amp;quot;concurrent&amp;quot; in CVS's&lt;br /&gt;
&amp;quot;concurrent versions system&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Branching and Merging===&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to&lt;br /&gt;
reconcile conflicting changes to the same file.  The solution to this&lt;br /&gt;
problem lay in allowing users of the revision control system to branch&lt;br /&gt;
a version of the repository and make (possibly many) changes to that&lt;br /&gt;
branch independent of the changes occurring on the main branch of the&lt;br /&gt;
repository, known as the trunk.  Once a logical set of changes was&lt;br /&gt;
completed on a branch, that branch would then need to have its changes&lt;br /&gt;
reconciled with the current state of the repository on the trunk.&lt;br /&gt;
This process of reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature was critical in a multi-user client environment as it&lt;br /&gt;
allowed work to progress on multiple fronts simultaneously, only&lt;br /&gt;
requiring that the files be merged once the users of the system were&lt;br /&gt;
ready to reconcile changes with other users.  &lt;br /&gt;
&lt;br /&gt;
This approach presented two new problems, however. &lt;br /&gt;
&lt;br /&gt;
First, the merging process was often difficult and time consuming,&lt;br /&gt;
leading many developers to avoid checking in their changes and merging&lt;br /&gt;
with other users because the merging process interrupted their normal&lt;br /&gt;
flow of work.  Users were reluctant to create branches to relieve some&lt;br /&gt;
of this burden because branch operations in CVS were quite slow and&lt;br /&gt;
cumbersome.&lt;br /&gt;
&lt;br /&gt;
Second, because many users checked in changes less frequently, much of&lt;br /&gt;
the current work on the repository was stored at the edges of the&lt;br /&gt;
network, that is, on the users' workstations, rather than in the&lt;br /&gt;
central server.  Thus, while the central server may have been backed&lt;br /&gt;
up regularly and kept secure, a user's workstation could crash and&lt;br /&gt;
take hours, days or even weeks of work with it, and revision control&lt;br /&gt;
would have no record of any of the work that had been lost.&lt;br /&gt;
&lt;br /&gt;
Both of these problems could be remedied by proper use of the revision&lt;br /&gt;
control system, but there were no technical measures that could be&lt;br /&gt;
taken to prevent such abuses.  This left the market open for a&lt;br /&gt;
different approach to revision control.&lt;br /&gt;
&lt;br /&gt;
==Distributed Revision Control==&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17812</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17812"/>
		<updated>2009-09-06T17:28:28Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=History Of Version Control=&lt;br /&gt;
&lt;br /&gt;
The defining characteristic of a version control system is its ability&lt;br /&gt;
to track changes to a document, or set of documents, over many&lt;br /&gt;
changes, or revisions.  For the vast majority of applications, version&lt;br /&gt;
control systems have focused on tracking plain text files, such as&lt;br /&gt;
those used for programming source code, HTML documents, and various&lt;br /&gt;
markup syntax.  Over the past 30 years or so, notions of how to&lt;br /&gt;
implement such systems have evolved and become more advanced.&lt;br /&gt;
&lt;br /&gt;
==Local Version Control== &lt;br /&gt;
&lt;br /&gt;
The first version control systems focused on local version control;&lt;br /&gt;
that is, centralized computer systems that were used by many users,&lt;br /&gt;
often at the same time.  Because of this use case, these systems&lt;br /&gt;
focused on two main features:&lt;br /&gt;
&lt;br /&gt;
* File Checkout and Locking&lt;br /&gt;
* File revision tracking&lt;br /&gt;
&lt;br /&gt;
===File Checkout and Locking=== &lt;br /&gt;
&lt;br /&gt;
Because many users in a shared system may desire to edit a file&lt;br /&gt;
simultaneously, one of the first features developed for version&lt;br /&gt;
control systems was the ability to check out and lock a file.  When a&lt;br /&gt;
user checks out a file, he or she reserves the right to be the sole&lt;br /&gt;
editor of that file until it is checked back in to revision control.&lt;br /&gt;
The first revision control systems designed for use in a shared&lt;br /&gt;
environment, such as RCS, allowed files to be checked out and locked&lt;br /&gt;
in this way.  Other users could check out the file, but only to view&lt;br /&gt;
it.  Thus, the files were locked from editing by all but the user&lt;br /&gt;
that had checked the file out most recently.&lt;br /&gt;
&lt;br /&gt;
===File Revision Tracking===&lt;br /&gt;
&lt;br /&gt;
The primary feature of these early systems was the ability to check in&lt;br /&gt;
files at various points as they were altered, so that the history of&lt;br /&gt;
changes made to files under version control was kept permanently.&lt;br /&gt;
Thus, many users could alter many files over time, and the entire set&lt;br /&gt;
of documents under version control at a given point in time could be&lt;br /&gt;
recovered, preventing loss of valuable data, as well a providing a&lt;br /&gt;
record of what users made changes to files over time.&lt;br /&gt;
&lt;br /&gt;
===Networked Revision Control: Client-Server===&lt;br /&gt;
&lt;br /&gt;
As users moved away from logging into systems locally to make their&lt;br /&gt;
changes to files, the need for a revision control system that&lt;br /&gt;
supported remote operations emerged.  The natural way to implement&lt;br /&gt;
such remote operations was as an extension of the existing system, and&lt;br /&gt;
by far the most prominent manifestation of this philosophy was present&lt;br /&gt;
in CVS, the concurrent versions system, which was initially based on&lt;br /&gt;
RCS.&lt;br /&gt;
&lt;br /&gt;
The main feature driving the development of CVS was the need for many&lt;br /&gt;
users, each on his or her own machine, to be able to perform all the&lt;br /&gt;
operations present in the original RCS, but over a network connection.&lt;br /&gt;
This led to the development of a client-server model of revision&lt;br /&gt;
control systems, in which one central server would contain the&lt;br /&gt;
canoncal version of the repository, and various clients could connect&lt;br /&gt;
to the central server and perform file check outs and commits.  This&lt;br /&gt;
model is very similar to the original RCS model, but rather than&lt;br /&gt;
requiring users of the system to log into the revision control system&lt;br /&gt;
locally, it allowed users to access and alter the contents of the&lt;br /&gt;
repository over the network.&lt;br /&gt;
&lt;br /&gt;
The initial need to simply perform RCS-like operations over a network&lt;br /&gt;
led to a host of new problems associated with the concurrent editing&lt;br /&gt;
of files under revision control, and the need to develop new features&lt;br /&gt;
that addressed the resulting complexities.  Chief among the new&lt;br /&gt;
features introduced to handle these complexities were the notions of&lt;br /&gt;
branching and merging.&lt;br /&gt;
&lt;br /&gt;
===Branching and Merging===&lt;br /&gt;
&lt;br /&gt;
Inherent in the notion of concurrent editing is the problem of how to&lt;br /&gt;
reconcile conflicting changes to the same file.  The solution to this&lt;br /&gt;
problem lay in allowing users of the revision control system to branch&lt;br /&gt;
a version of the repository and make (possibly many) changes to that&lt;br /&gt;
branch independent of the changes occurring on the main branch of the&lt;br /&gt;
repository, known as the trunk.  Once a logical set of changes was&lt;br /&gt;
completed on a branch, that branch would then need to have its changes&lt;br /&gt;
reconciled with the current state of the repository on the trunk.&lt;br /&gt;
This process of reconciliation is known as merging.&lt;br /&gt;
&lt;br /&gt;
This feature was critical in a multi-user client environment as it&lt;br /&gt;
allowed work to progress on multiple fronts simultaneously, only&lt;br /&gt;
requiring that the files be merged once the users of the system were&lt;br /&gt;
ready to reconcile changes with other users.  &lt;br /&gt;
&lt;br /&gt;
This approach presented two new problems, however. &lt;br /&gt;
&lt;br /&gt;
First, the merging process was often difficult and time consuming,&lt;br /&gt;
leading many developers to avoid checking in their changes and merging&lt;br /&gt;
with other users because the merging process interrupted their normal&lt;br /&gt;
flow of work.  Users were reluctant to create branches to relieve some&lt;br /&gt;
of this burden because branch operations in CVS were quite slow and&lt;br /&gt;
cumbersome.&lt;br /&gt;
&lt;br /&gt;
Second, because many users checked in changes less frequently, much of&lt;br /&gt;
the current work on the repository was stored at the edges of the&lt;br /&gt;
network, that is, on the users' workstations, rather than in the&lt;br /&gt;
central server.  Thus, while the central server may have been backed&lt;br /&gt;
up regularly and kept secure, a user's workstation could crash and&lt;br /&gt;
take hours, days or even weeks of work with it, and revision control&lt;br /&gt;
would have no record of any of the work that had been lost.&lt;br /&gt;
&lt;br /&gt;
Both of these problems could be remedied by proper use of the revision&lt;br /&gt;
control system, but there were no technical measures that could be&lt;br /&gt;
taken to prevent such abuses.  This left the market open for a&lt;br /&gt;
different approach to revision control.&lt;br /&gt;
&lt;br /&gt;
==Distributed Revision Control==&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17652</id>
		<title>CSC/ECE 517 Fall 2009/wiki1a 5 rp</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2009/wiki1a_5_rp&amp;diff=17652"/>
		<updated>2009-09-05T22:51:10Z</updated>

		<summary type="html">&lt;p&gt;7r3ad: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=History Of Version Control=&lt;br /&gt;
&lt;br /&gt;
==Centralized Version Control==&lt;br /&gt;
&lt;br /&gt;
===Local Version Control: RCS===&lt;br /&gt;
&lt;br /&gt;
===The First Networked Version Control: CVS===&lt;br /&gt;
&lt;br /&gt;
==Commercial Offerings==&lt;br /&gt;
&lt;br /&gt;
===ClearCase===&lt;br /&gt;
&lt;br /&gt;
===Perforce===&lt;/div&gt;</summary>
		<author><name>7r3ad</name></author>
	</entry>
</feed>