Programming languages

From WhyNotWiki
Revision as of 04:41, 14 May 2008 by Tyler (Talk | contribs)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to: navigation, search

Programming languages  edit   (Category  edit)


Concepts / Features

Lambda functions/expressions

"The ability to write a function as an expression" [1]


"The ability to access variables from an enclosing scope inside a function." [2]


Dynamically typed Retrieved on 2007-05-11 11:18.

Lua is a dynamically typed language. This means that variables do not have types; only values do. There are no type definitions in the language. All values carry their own type.

All values are first-class values Retrieved on 2007-05-11 11:18.

All values in Lua are first-class values. This means that all values can be stored in variables, passed as arguments to other functions, and returned as results.

(what alternatives are there? Would an alternative be having objects and primitives and only primitives and references to objects being storable in variables, etc.?)

Language comparisons Retrieved on 2007-05-11 11:18.

I'm sorry did I miss the point where we started caring about what language we are writing in. This was a discussion point 5 years ago, now it should be "what job do I want to get done?" and "what technology (ie language + framework + tools + people with skills) is going to deliver that the quickest, cheapest and highest quality? If you're still arguing over language then you deserve to be unemployed (unless you really care that much in which case you should be working at a university). Retrieved on 2007-05-11 11:18.

Anton van Straaten,2007-05-11

Comparing gross features across languages, such as loops, is very close to a Turing-completeness argument, and the conclusion that differences between languages are superficial is equivalent to Turing-completeness — it's true, but it's orthogonal to the problem that you're interested in. If you do some work with language implementation — even just to the degree encouraged by books like SICP, EOPL and some of the other favorites from the Getting Started thread (hint hint) — you quickly gain respect for the degree to which tradeoffs in language design are unavoidable, and pervasive. There really are limits to how much you can jam into a single language. You can only have your cake and eat if if you choose quite carefully what kind of cake you want. For example, the desire for "optional garbage collection" is quite a problematic one — are there any languages you'd like to propose as having a model implementation of optional garbage collection? As you start adding in other requirements, such as first-class functions and strong types as mentioned in one of your wishlists, you're likely to run into serious trouble. For a humorous take on this, see The Two Doofuses, or Why Type Safety and the Garbage Collector Really Exist (previously on LtU). The Lisp example might shed some light on this issue. Lisp supports embedded DSLs well: it allows you to embed languages in Lisp that have different semantics from standard Lisp. But embedding such a DSL in Lisp doesn't somehow eliminate differences between the semantics of the DSL and of the host language. What happens instead is that multiple languages are integrated using a similar surface syntax. However, the semantics remain different. For example, if you embed logic programming in Lisp, or relational data manipulation (e.g. SQL semantics), it becomes very clear that you're dealing with languages with different semantics, whose characteristics have to be learned and understood independently of the host language. You also still run into issues of communication between the different DSLs since they have different ways of dealing with data. If that satisfies your desire for a single all-purpose language, then you're in luck, because that's achievable. It's also useful — as it happens, this capability is a big reason I enjoy using Scheme. But if anything, this only underscores that differences between languages aren't just superficial. Performing a task using a relational data manipulation language, whether or not it's embedded in Lisp, requires a significantly different approach than performing that same task using, say, a network of objects. And it turns out that there are some tasks which are more easily done with one approach than the other, which explains why everyone didn't just dump SQL when object-oriented languages (and databases) came along, or why people still use logic programming for some tasks but not others. The differences are not all superficial. There's no question that it's possible to have general-purpose languages that meet a wide variety of needs. Looking at your wishlists, it seems to me that something like C# might, on paper, already come close to what you're looking for, or at least could reasonably evolve into it (think Linq, for example). Perhaps you agree with that. But if you disagree, you might find that it's because when you get beyond the high-level wishlist into the nitty-gritty details of language feature tradeoffs, there are many choices you don't get to make entirely freely, and they add up. So while C# might, at a marketing bullet-point level, satisfy much of your wishlist, the devil is in the details. Unless you take the position that the details are all superficial, in which case any language is good enough.

It's important to have 'political' discussions about programming languages from time to time, as the progress in programming languages is directly tied to the wishes of the people involved.

My view is that programming languages could be much better than what they currently are.

The only alternatives would be either (a) The perfect PL already exists; or (b) There are fundamental laws of the universe that prevent us from improving PLs. The assumption that underlies LtU is that PLs can be improved, so you've won this argument without the need for debate.

The devil's in the detail. The question is not whether PLs can be improved but rather what actually constitutes an improvement, and what the cost of those improvements are in terms of tradeoffs.

Ruby vs. Python Retrieved on 2007-05-11 11:18.

Personally, I like the significant white-space of Python [I don't], but I can't stand the explicit receivers so it never stuck with me since I already knew Ruby.

Ruby vs. IronRuby Retrieved on 2007-05-11 11:18.

I think that IronRuby will inevitably win over people from the Ruby community - if and only if it's compatible with C Ruby and not some opportunistic pathetic bastardization like J++. Folks in the Ruby community that I have asked this question to are receptive to the opportunities that yet-another-Ruby-platform brings to their software business endeavors.

On having many different languages Retrieved on 2007-05-11 11:18.

[...] I stand by my opinion that differences in programming languages are superficial, and I would like it very much to go into any technical details, if you want. ... [...] I found no evidence that having to use 5+ programming languages is how things are supposed to be. ... Perhaps you might not care about it, but I certainly do, and lots of other programmers that have to deal with the horrible mess of html, xml, javascript, java, php and hack upon hack that makes even the simplest task so incredibly difficult care as well. And increasing productivity and making our lives easier in programming is directly connected to programming language theory.

Languages (instances of)

Programming languages  edit   (Category  edit)

C# Retrieved on 2007-05-11 11:18.

he further makes his point by showing the beauty of ruby: 10.times { |i| puts i } Which is the equivalent of this in C# for (int i = 0; i < 10; i++) { Console.Write(i); } However it is important to note that things are getting a lot better in C# with extension methods. Once you import your favorite library of extension methods all sorts of things are possible in C# 3.0:

1.To(10).ForEach(i => Console.Write(i));

Or even better:

10.Times(i => Console.Write(i));

All you need is a library of extension methods which includes these:

public static IEnumerable<int> To(this int start, int end)
    if (end < start)
        for (int i = start; i > end - 1; i--)
            yield return i;
        for (int i = start; i < end + 1; i++)
            yield return i;
public static void Times(this int number, Action<int> action)
    for (int i = 0; i < number; i++)


Groovy (programming language) - Wikipedia, the free encyclopedia ( Retrieved on 2007-05-11 11:18.

Groovy is an object-oriented programming language for the Java Platform as an alternative to the Java programming language. It can be viewed as a scripting language for the Java Platform, as it has features similar to those of Python, Ruby, Perl, and Smalltalk. In some contexts, the name JSR 241 is used as an alternate identifier for the Groovy language. Groovy uses a Java-like curly bracket syntax which is dynamically compiled to JVM bytecodes and that works seamlessly with other Java code and libraries. The Groovy compiler can be used to generate standard Java bytecode to be used by any Java project or it can be used dynamically as a scripting language. ...

Language Features

Groovy has a number of features not found in standard Java:

Syntax Comparison



def list = ["Rod", "Carlos", "Chris"]

list.findAll { it.size() <= 4 }.each { println it }

That looks even slicker than Ruby's iterators! It looks like it just assumes you want to use the variable it inside the block, which makes it very concise, because you don't have to specify the variable like you do in Ruby (.each {|it| println it }.

Markup Language Support

One noteworthy feature of Groovy is its native support for various markup languages such as XML and HTML. This feature enables the definition and manipulation of many types of heterogeneous data assets with a uniform syntax and programming methodology. For example:

the following Groovy code ...

   import groovy.xml.MarkupBuilder
   def myXMLDoc = new MarkupBuilder()
   myXMLDoc.workbook {
      worksheet(caption:"Employees") {
         row(fname:"John", lname:"McDoe")
         row(fname:"Nancy", lname:"Davolio")
      worksheet(caption:"Products") {
         row(name:"Veeblefeetzer", id:"sku34510")
         row(name:"Prune Unit Zappa", id:"sku3a550")
   println myXMLDoc

... produces the XML result:

      <worksheet caption='Employees'>
         <row fname="John" lname="McDoe" />
         <row fname="Nancy" lname="Davolio" />
      <worksheet caption='Products'>
         <row name="Veeblefeetzer" id="sku34510" />
         <row name="Prune Unit Zappa" id="sku3a550" />

Polyphonic C#

The Basic Idea

In Polyphonic C#, methods can be defined as either synchronous or asynchronous. When a synchronous method is called, the caller is blocked until the method returns, as is normal in C#. However, when an asynchronous method is called, there is no result and the caller proceeds immediately without being blocked. Thus from the caller's point of view, an asynchronous method is like a void one, but with the useful extra guarantee of returning immediately. We often refer to asynchronous methods as messages, as they are a one-way communication from caller to receiver (think of posting a letter rather as opposed to asking a question during a face-to-face conversation).

By themselves, asynchronous method declarations are not particularly novel. Indeed, .NET already has a widely-used set of library classes which allow any method to be invoked asynchronously (though note that in this standard pattern it is the caller who decides to invoke a method asynchronously, whereas in Polyphonic C# it is the callee (defining) side which declares a particular method to be asynchronous). The significant innovation in Polyphonic C# is the way in which method bodies are defined.

In most languages, including C#, methods in the signature of a class are in bijective correspondence with the code of their implementations - for each method which is declared, there is a single, distinct definition of what happens when that method is called. In Polyphonic C#, however, a body may be associated with a set of (synchronous and/or asynchronous) methods. We call such a definition a chord, and a particular method may appear in the header of several chords. The body of a chord can only execute once all the methods in its header have been called. Thus, when a polyphonic method is called there may be zero, one, or more chords which are enabled:

  • If no chord is enabled then the method invocation is queued up. If the method is asynchronous, then this simply involves adding the arguments (the contents of the message) to a queue. If the method is synchronous, then the calling thread is blocked.
  • If there is a single enabled chord, then the arguments of the calls involved in the match are de-queued, any blocked thread involved in the match is awakened, and the body runs.
  • When a chord which involves only asynchronous methods runs, then it does so in a new thread.
  • If there are several chords which are enabled then an unspecified one of them is chosen to run.
  • Similarly, if there are multiple calls to a particular method queued up, we do not specify which call will be de-queued when there is a match.

Example: A Simple Buffer

Here is the simplest interesting example of a Polyphonic C# class:

public class Buffer {
   public String get() & public async put(String s) {
      return s;

This class declares two methods: a synchronous one, get(), which takes no arguments and returns a string, and an asynchronous one, put(), which takes a string argument and (like all asynchronous methods) returns no result. These two methods appear (separated by an ampersand) in the header of a single chord, the body of which consists of the return statement.

Now assume that b is an instance of Buffer and that producer and consumer threads wish to communicate via b. Producers make calls to put(), which, since the method is asynchronous, do not block. Consumers make calls to get(), which, since the method is synchronous, will block until or unless there is a matching call to put(). Once b has received both a put() and a get(), the body runs and the argument to the put() is returned as the result of the call to get(). Multiple calls to get() may be pending before a put() is received to reawaken one of them and multiple calls to put() may be made before their arguments are consumed by subsequent get()s. Note that

1. The body of the chord runs in the (reawakened) thread corresponding to the matched call to get(). Hence no new threads are spawned in this example. 2. The code which is generated by the class definition above is completely thread safe. The compiler automatically generates the locking necessary to ensure that, for example, the argument to a particular call of put() cannot be delivered to two distinct calls to get(). Furthermore (though it makes little difference in this small example), the locking is fine-grained and brief - polyphonic methods to not lock the whole object and are not executed with "monitor semantics". 3. The reader may wonder how we know which of the methods involved in a chord gets the returned value. The answer is that it is always the synchronous one, and there can be at most one synchronous method involved in a chord.

Example: A Reader-Writer Lock

Controlling concurrent access to a shared, mutable resource is a classic problem. Clients request, and later release, either read-only or read-write access to the resource. To preserve consistency but minimize waiting, one usually wishes to allow either any number of readers or a single writer, but not both, to have access at any one time. A solution using traditional shared-memory concurrency primitives may be found in Andrew Birrell's "An Introduction to Programming with Threads"; it is instructive to compare that code with the class below, which implements a reader-writer lock in Polyphonic C#:

class ReaderWriter {

   ReaderWriter() {

   void Exclusive() & private async Idle() {

   void ReleaseExclusive() {

   void Shared() & private async Idle() {

   void Shared() & private async S(int n) {

   void ReleaseShared() & private async S(int n) {
      if (n == 1) Idle(); else S(n-1);

Again, we use private messages, Idle() and S(n), to carry the state. And once more, there is a simple declarative reading of the constructor and chords which allows one to understand the implementation:

  • When the lock is created there are no readers or writers, so it is Idle().
  • If a writer requests Exclusive() access and the lock is Idle() then he may proceed (but the lock is no longer Idle()).
  • If a writer indicates he is finished by calling ReleaseExclusive() then the lock is Idle() again.
  • If a reader requests Shared() access and the lock is Idle() then the lock moves to the state S(1), meaning there is now one reader, and he may proceed.
  • If a reader requests Shared() access and there are currently n readers, then there are now n+1 readers, and the new one may proceed.
  • If a reader indicates he is finished by calling ReleaseShared() and there were previously n readers, then if n was 1 then lock is Idle() again, otherwise there are now n-1 shared readers. In either case, the reader who has just relinquished access may proceed with whatever else he has to do.

Assuming that all the clients obey the request-release protocol, the invariant is that there is at most one pending private async message representing the state:

     none <--> Idle() <--> S(1) <--> S(2) <--> S(3) …

Programming languages / Sources of information

Programming languages / Sources of information edit Lambda the Ultimate | Programming Languages Weblog John Resig - Blog


D Retrieved on 2007-05-11 11:18.

D is a systems programming language. Its focus is on combining the power and high performance of C and C++ with the programmer productivity of modern languages like Ruby and Python. Special attention is given to the needs of quality assurance, documentation, management, portability and reliability. The D language is statically typed and compiles directly to machine code. It's multiparadigm, supporting many programming styles: imperative, object oriented, and metaprogramming. It's a member of the C syntax family, and its appearance is very similar to that of C++. For a quick comparison of the features, see this comparison of D with C, C++, C# and Java. It is not governed by a corporate agenda or any overarching theory of programming. The needs and contributions of the D programming community form the direction it goes. There are currently two implementations, the Digital Mars DMD package for Win32 and x86 Linux, and the GCC D Compiler package for several platforms, including Windows and Mac OS X. A large and growing collection of D source code and projects are at dsource. More links to innumerable D wikis, libraries, tools, media articles, etc. are at dlinks.

Programming languages  edit   (Category  edit)

Personal tools