69

I have seen this quoted in a lot of places:

"It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures." —Alan Perlis

But I have never seen it explained why this should be true. Is it just the idea that you should try to derive the other 9 data structures from the first to avoid duplicating the data? I feel like I'm missing some context.

Joe Van Dyk
  • 6,434
  • 7
  • 52
  • 72
GlennS
  • 4,490
  • 4
  • 23
  • 30
  • 2
    Because 100 functions > 10 functions. – Jim Balter Nov 19 '14 at 07:11
  • 2
    Because 100 functions on one data structure are more generic thus offering better composition, whereas 10 functions on 10 data structures are specific to their data structure and thus less (or impossible to be) composable across datastructures. – mljrg Feb 09 '18 at 16:49

2 Answers2

94

The quote is from Alan Perlis' Epigrams on Programming, which was published in 1982.

The meaning of this quote is embodied well in Lisp, where there are multitudes of functions that operate and deal specifically with lists, and you could accomplish a lot just with lists and the assortment of functions that operate on lists, which makes them much more powerful than any single-purpose data structure.

Lua, as another example, uses tables to simulate classes. Why use a table to make objects instead of creating language-level classes and objects like object-oriented languages do? Since your object is a table now, you can use any number of the functions defined for tables on your object, free of charge! Better yet, we didn't have to clutter the language with class-specific syntax and have to redefine functions from table that we want for our class.

What Perlis said is definitely a prominent mode of thought in Lisp and in functional programming in general. Those 100 functions on your one data structure can be composed together in lots of unique ways, since they all operate on the same data structure, but you can't really mix the 10 functions on 10 data structures as well, since they were defined only to work on their particular data structure.

A more modern and simpler variation of this is thinking in terms of abstractions. If we were coding in Java, would you rather write a 100 functions on the List interface, or the same set of ten functions, once for ArrayList, once for LinkedList, once for....

Zach L
  • 15,284
  • 3
  • 36
  • 39
  • 1
    I think the last paragraph of this answer highlights why Alan Perlis' quote is no longer applicable. At best, it boils down to what you consider to constitute a "data structure". – J D Jul 10 '11 at 08:47
  • "[...] but you can't really mix the 10 functions on 10 data structures as well, since they were defined only to work on their particular data structure." Partial functions alleviates this to some extent. – TheFooProgrammer Sep 13 '13 at 13:40
  • 24
    @JonHarrop I disagree about it no longer being applicable, see the Clojure world, I did OOP for a long time, and I'm diving in the functional world, and now I'm seeing in practice how true this quote is, once you let the objects go, and most of your structures are just plain maps, and you can keep re-using the same functions and composing on them, I'm finding this to be way more sane to work with then when I was in OOP world. So, give Clojure a try, and see if you still think this quote is outdated :) – Wilker Lucio Jul 15 '14 at 15:39
  • 1
    The last paragraph of this answer demostrates how long ago 2011 was. In the context of the resurgence of functional programming since then, Perlis' aphorism is holding up very well. Much better to have a hundred well tested functions in your toolbox and work with simple data structures. – John Hardy Mar 24 '18 at 22:53
  • Many OOP languages provide a way to share behaviour across multiple different custom types: interfaces with default methods, traits, mixins, composition, inhertiance, etc. There is definitely more complexity and syntax to do this, but you don't have to resort to copy/pasting the same 10 functions for each data type that needs them like the last paragraph seems to say. That being said, it is much less apparent how to re-use functionality in an OOP language than it is when all you have is a data-structure and functions. – jmrah Dec 29 '20 at 00:05
11

Structure and Interpretation of Computer Programs (SICP) answers your question as below:

Screenshot from SICP

You can see the original content of the online version of the book here

EDIT (included from comment):

"In Pascal the plethora of declarable data structures induces a specialisation within functions." Specialisation is bad because it inhibits "serendipity"/creativity - I would say - with my own words.

In other words if functions are too special then they cannot be reused in ways that were not known at the time of the function creation.

Nice example is fold (https://hackage.haskell.org/package/base-4.8.1.0/docs/Data-Foldable.html) which is a data structure agnostic, general higher order function. It can be used on a tree, for example

data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a).
jhegedus
  • 18,516
  • 11
  • 84
  • 147
  • This doesn't answer why. – isomorphismes Jun 15 '15 at 20:20
  • 6
    :) "In Pascal the plethora of declarable data structures induces a specialisation within functions." Specialisation is bad because it inhibits "serendipity" - I would say - with my own words. In other words if functions are too special then they cannot be reused in ways that were not known at the time of the function creation. Nice example is `fold` https://hackage.haskell.org/package/base-4.8.1.0/docs/Data-Foldable.html which is a data structure agnostic, general higher order function. It can be used on a tree, for example `data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)`. – jhegedus Sep 11 '15 at 16:55
  • @jhegedus, I suggest you add your comment into your answer. It's a very good addition. – Sam R. Jun 24 '16 at 16:42