[LINQ via C# series]
Declarative vs. imperative
This post mentioned that LINQ introduced new programming constructs to C#. Take a look at the samples in the beginning post:
int[] source = new int[] { 0, -5, 12, -54, 5, -67, 3, 6 };
List<int> results = new List<int>();
foreach (int integer in source)
{
if (integer > 0)
{
results.Add(integer);
}
}
Comparison<int> comparison = delegate(int a, int b)
{
return b - a;
};
results.Sort(comparison);
foreach (int item in results)
{
Console.WriteLine(item);
}
and
var results = from integer in source
where integer > 0
orderby integer descending
select integer;
or equally:
IEnumerable<int> results = source.Where(integer => integer > 0)
.OrderByDescending(integer => integer);
They are very different from the paradigm's perspective:
- The traditional C# sample is called imperative programming: it describes how to implement the query by providing the concrete algorithm.
- The LINQ sample is called declarative programming: it describes what is the query, like "orderby ... descending". This ordering algorithm looks not so explicit and concrete as the imperative sample, and this kind of code can be reused to other scenarios, like querying SQL, Wikipedia, etc.
Declarative programming is not a patent of C#. The following T-SQL is typically declarative:
SELECT ProductName, UnitPrice FROM Products ORDER BY UnitPrice ASC
This is indicated because when some C# programmers learns something via C#, they automatically consider that is introduced by C#. For example, after learning the in / out keywords in C# 4.0 generic interfaces and delegates, many people thought covariance and contravariance are invented by Microsoft.
Another interesting topic is HTML. Many people think HTML is a declarative programming languages. In CLR via C# 2nd edition, Jeffrey Richter said (This paragraph is removed in the 3rd edition),
An example of declarative programming is when a person creates a text file and explicitly enters HTML tags into the file by using an editor such as Notepad.exe. In this scenario, the HTML tags act as instructions that are eventually processed by the Internet browser so that it can lay out the page in a window. The HTML tags are declaring how the program (Web page) should be displayed and operate, and it's the programmer who decides what tags to use and where. Many hard-core programmers don't consider HTML programming to be real programming, but I do.
Actually, maybe I am one of the hard core programmers. I admit that HTML is declarative, but I totally disagree that HTML is a declarative programming language, because it is even not a programming language. It cannot be used to describe algorithms, like adding numbers. It is not Turning-complete at all.
Programming language paradigms
Imperative, declarative, object-oriented, functional, ... There are too many concepts for programming paradigms. Roughly, common paradigms can be categorized like this:
- Imperative programming
- Structured programming
- Procedural programming (typically implemented via C, etc.)
- Object-oriented programming
- Class-based programming (C#, etc.)
- Prototype-based programming (JavaScript, etc.)
- Declarative programming
- Functional programming (Lisp, Haskell, F#, etc.)
- Reactive programming (Haskell, etc.)
- Event-driven programming
- Metaprogramming (Ruby, etc.)
- Reflective programming (C#, etc.)
- Automatic programming
- Generic programming (C#, etc.)
- ...
In languages’ perspective, one programming language can adopt several paradigm. Take C as an example:
For JavaScript:
And finally, C# is:
- Imperative (by default)
- Procedural (static classes, static methods)
- Class-based Object-oriented (objects)
- Declarative (attributes, data annotation, code contracts, etc.)
- Functional (lambda expression, higher-order functions, etc.)
- Event-driven (events)
- Metaprogramming (compiler as a service, etc.)
- Reflective (reflection)
- Generic (generics)
Thanks to Anders Hejlsberg, C# is a productive language, which is able to work in many different scenarios.
Declarative C#
Actually, declarative programming in C# is not something brand new. C# has attributes from the beginning:
[HandleError]
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return this.View();
}
}
Regular expressions can be considered declarative:
bool result = new Regex(@"\n$").IsMatch(text);
Data Annotation is also obviously declarative:
public class User
{
[Required(ErrorMessage = "User name is required.")]
[StringLength(50, ErrorMessage = "User name should be under 50 characters.")]
public string UserName { get; set; }
[Required(ErrorMessageResourceType = typeof(Resource),
ErrorMessageResourceName = "AgeRequired")]
[Range(0, 20, ErrorMessage = "...")]
public string Age { get; set; }
[Required(ErrorMessage = "...")]
[RegularExpression("...")]
public string Email { get; set; }
}
C# 3.0 introduced LINQ, making C# more declarative and functional:
IEnumerable<int> results = source.Where(integer => integer > 0)
.OrderByDescending(integer => integer);
while Rx (Reactive Extensions) makes C# reactive:
int start = 0;
IObservable<int> observable = Observable.Defer(() => Observable.Return(start++))
// Repeats pushing the data.
.Repeat(int.MaxValue);
IObserver<int> observer = Observer.Create<int>(Console.WriteLine);
IDisposable subscription = null;
while (true)
{
Console.ReadKey();
if (subscription == null)
{
// Subscribes the observable.
subscription = observable.Subscribe(observer);
}
else
{
// Unsubscribes the observable.
subscription.Dispose();
subscription = null;
}
}
And C# 3.0 and 4.0 introduced code contracts, which is also declarative:
public class Person
{
private string _name;
private int _age;
public Person(string name, int age)
{
Contract.Requires(!string.IsNullOrEmpty(name));
Contract.Requires(age > 0);
this._name = name;
this._age = age;
}
public string Name
{
get
{
Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>()));
return this._name;
}
}
public int Age
{
get
{
Contract.Ensures(Contract.Result<int>() > 0);
return this._age;
}
}
}