Is there a language where collections can be used as objects without altering the behavior?

As an example, first, imagine those functions work:

function capitalize(str) 
    //suppose this *modifies* a string object capitalizing it
function greet(person):
    print("Hello, " + person)

>> "Pedro"

>> "Hello, Pedro"

Now, suppose we define a standard collection with some strings:

people = ["ed","steve","john"]

Then, this will call toUpper() on each object on that list

>> ["Ed","Steve","John"]

And this will call greet once for EACH people on the list, instead of sending the list as argument

>> "Hello, Ed"
>> "Hello, Steve"
>> "Hello, John"
  • 3
    The only language feature you need is LISP's map. You would do something like (map toUpper arr) in Clojure. Forgive me if I got the order wrong. Everything else should be built as a library. Just adding auto map to a language is not a good idea - it does not give you flexibility. What about upper-casing every second item? A powerful library such as LINQ or python's itertools or basic lisp primitives can let you do that. Anyhow, I have not heard of such language, thank God (I second DeadMG's opinion).
    – Job
    Commented Jun 3, 2012 at 22:15
  • 2
    birds = [myBird1, myBird2, myBird3]; birds.fly(); This is superior to the so-common and repetitive "for (bird in birds): bird.fly()" (in Python, that is already the shortest way to write this). What I mean is that doing something with a group of elements is more common than calling array methods (such as .sort, .push) and thus array.method should cast the method for each element, and the today standard array.sort should be spelled as sort(array) instead. I don't see why it would cause any problem in any way.
    – MaiaVictor
    Commented Jun 4, 2012 at 1:46
  • 1
    Oh, and for the function application part, kill(birds) is, too, more readable than for bird in birds: kill(bird), so it should be the standard behavior. If you want to send a array to a function (this is not so common) you could anotate as foo([birds]), which I don't see as problematic, at all, and would actually even add further to readability, even for unrelated cases.
    – MaiaVictor
    Commented Jun 4, 2012 at 1:49
  • 1
    So, it should not be part of the language. It is just rarely used. There are lots of other standard features that a language might need first. Another point - it forces something down peoples throats that they might not necessarily like. Even Python's white space mandate causes quite a bit of controversy. Suppose C# supported the syntax that you speak of. Also suppose I had an extension method public static void Print(this IList<string> strs) then the "auto-map" feature would conflict with MY EXTENSION METHOD - a feature I find much more valuable. If I can use a map, then why have 2 ways?
    – Job
    Commented Jun 4, 2012 at 3:22
  • 1
    Job, how is calling a function/method for a group of elements rarely used? It is possibly the most used thing at all. Note: not sure why you are coming with languages such as C# or C, which were not designed with this on mind and thus obviously won't mix with the idea nor really have or need to.
    – MaiaVictor
    Commented Jun 4, 2012 at 5:39

3 Answers 3


Yes, there are such languages. Many of them.

In fact, this feature is pretty much the definition of an array language or vector language. Examples of array and vector languages include, but are not limited to, the APL family of languages with its successors, derivatives and cousins (E.g. APL, J, K) and pretty much all mathematical and statistical languages such as Mathematica, MATLAB, Octave, R, and S.

Fortran 90 and Ada also have this feature, as does Fortress.

Interestingly, many modern CPUs also support vector programming, e.g. the x86 architecture with the MMX, SSE, SSE2, SSE3 (Intel) and 3DNow! (AMD) instruction sets, the POWER and PowerPC architectures with the VMX and AltiVec instruction sets, Sparc, MIPS, even ARM.

The language by Microsoft Research has the concept of streams (roughly similar to IEnumerable). Streams pretty much work exactly as you describe. Here's an example from the Cω documentation (emphasis mine):

A key programming feature of Cω is generalized member access: the familiar 'dot' operator is now much more powerful. Thus if the receiver is a stream, then the member access is mapped over the elements, e.g. zones.ToString() implicitly maps the method call over the elements of the stream zones and returns a value of type string*. This feature significantly reduces the burden on the programmer.

A very interesting property of this kind of programming is that it not only allows you to semantically think of "applying an operation to all elements at once", it also allows the language implementor to implement it by literally applying an operation to all elements at once, IOW in parallel.

  • 7
    This is the kind of answer that encorages me using Stack, when everyone just attacked the idea or said with certainty it does not exist (why?). I have much to explore now. Thank you.
    – MaiaVictor
    Commented Jun 4, 2012 at 5:36
  • @Dokkat: Thanks for the kind words. I try my best. Commented Jun 5, 2012 at 10:16
  • Sorry for not choosing your answer before, guess I forgot.
    – MaiaVictor
    Commented Jun 20, 2012 at 4:46
  • I would also add Numpy/Scipy Python libraries to the list: numpy.scipy.org
    – peterhil
    Commented Jul 23, 2012 at 21:21

You can get semantics very similar to what you're asking for in nearly all languages using the composite pattern.

Given you have some type similar to this:

// pseudocode
class CustomString
    CustomString Composite;
    string Value;

... and a Greet method like this:

// pseudocode
public string Greet(CustomString cs)
    string ret;
    if (cs!= null)
        ret += "Hello " + cs.Value + newline;

    if (cs.Composite != null)
        ret += Greet(cs.Composite);

... you can make calls like this:

writeln(Greet(new CustomString("snorfys")))
>> Hello snorfys

cs = new CustomString("snorfys") { Composite = new CustomString("Dokkat") }
>> Hello snorfys
>> Hello Dokkat

If you do a lot of work with trees, programming in this way feels common quickly (that is to say that each tree node is, and can be treated as, a subtree).

  • 1
    I'm trying to understand what you've done there? I should read about that pattern.
    – MaiaVictor
    Commented Jun 4, 2012 at 6:17

In C# for example there are extensions (add the functionality to the collection - underneath it would still be a loop, but nothing visible) and Linq - example:

public static IEnumerble<string> Capitalize(this IEnumerable<string> collection)
   var List<string> rtn = new List<string>(collection.Count());
   foreach (var item in collection) 
      var ci = Thread.CurrentThread.CurrentCulture; 
      var textInfo = ci.TextInfo; 

   return rtn;

[Note: I hand keyed this - so maybe some typos errors]

alternatively, ...

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
   foreach (T element in source)    

with a function for capitalize

public static string Capitalize(this string str)
    var ci = Thread.CurrentThread.CurrentCulture; 
    var textInfo = ci.TextInfo; 

    return textInfo.ToTitleCase(str); 

and then

myColl.ForEach(x => x.Capitalize()); 

The difference is the second allows you to pass any function along and for any collection type.

myCollection.Where(employee => emplyee.Age > 50).ForEach(employee => employee.Fire());

works too (in a heartless sort of way :D )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.