One example is the HTTP GET request. This was originally conceived of as a file download, where the URL path is mapped directly to filesystem paths. GET as an RPC: "download the file at this location."
But in modern thinking, HTTP GET is a request with abstract semantics. The URL's path is abstract, and may be interpreted arbitrarily by the server. The client has no idea whether the request is serviced by a simple sendfile() or a fully dynamic program. HTTP GET is no longer an RPC, it is now a message.
A key difference is whether your function call is a request for concrete or abstract behavior. If you answer "abstract," then the call itself must be reifiable data, which can be sliced and diced in ways hidden from the caller.
As defined in both RFC 1945 and 2616 (that is, as always has been defined): "The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI."
The thing is that there's no difference between abstract and concrete semantics in terms of definition of what is a function or message and what is not. You can send a message or call a function with very concrete semantics ("please, check if that file exists") or with something very abstract ("please, execute a job").
The real difference of the message and function definitions is how they are executed. With message you pass the information on what do you expect to be done to the underlying infrastructure, which has to find the actual code to complete the delivery. With functions you are supposed to know, what exactly code you are calling.
In modern world the discussion about these differences in context of OOP classes does not make much sense: virtual methods of interfaces do their job as well for local invocations (JVM in Java world or VMT in C++ does the binding job), so it does not matter whether you call them messages (which may be right, considering dynamic nature of the call) or functions (again, it's correct, because as in C++ case there's no special mediator passing the call and in Java JVM is practically invisible to application programmer). The cases, when message delivery does not coincide with invocation of single method are rare and normally solved with application level architecture (design patterns like Facade are good example of the solution).
What's more important, IMHO, is that this talk about importance of messages is no more relevant to current problems of object-oriented programming. I do not think today we are really concerned about object interactions, rather we have to fight the enormous complexity of big projects, finding better ways of generalization (by means of more expressive languages and metamodels) and API contract clarification and enforcement (by elimination of side effects and correct handling of corner cases).
HTTP GET was initially defined to "Please transfer a named document back." [1]. The idea of interpreting the path to dynamically generate a document came later. If you like, you can think of it as a shift from Apache-circa-1999 servers that expect to deal primarily in files, to Rails-style servers that primarily route requests to dynamic code.
You're right that design patterns like Facade are often used instead of exploiting messaging. But this comes at a price: clients are necessarily aware that they are talking to a Facade. Discovery and negotiation are done statically, via the type checker. Versioning is static too. Everything it tightly coupled.
Say you have a String, and you want to concatenate it with another String. You check the docs, or StackOverflow, or IntelliSense, right? What you don't do is use Reflection to list all the methods, and pick based on their name. And you certainly don't feed an input to each method, and pick the one that gives the right output! (This strategy is routine in Smalltalk! [2])
Now say you want to build a web search engine. Do you try to statically build up website descriptions? Maybe you check StackOverflow for the HN link structure, catalog it for everyone? No, you start at the root, interrogate it, and build the link graph as you go. You have a conversation with the remote site, and perform discovery dynamically.
That's messaging! And that's why URLs are a better example than most modern programming languages: the value of OO is best realized when you have loosely coupled components, like on the Internet. (Alan Kay wrote that every object should have a URL. [3])
Well, the remark about the acceptable format in the same definition from 1992 means that there's dynamic processing of the request, which may involve the document conversion at least. And it does not say "file", which means that there can be a database as a document storage. In 1999 the web was mostly dynamic (I myself was using PHP, Informix WebConnect, Java and C for web development by that time) and more abstract RFC 1945 came in 1996 (just 4 years later), 1 year after Amazon went online. The period of time, when GET could mean only "give me a file" was in fact very short, if ever existed.
Then, you write that Facade is "tightly coupled". In fact, it's not more coupled than any native messaging. Let's say, the client code wants an object, representing a coffee machine, to prepare latte with temperature about 40C. There are other things, that coffee machine can do (e.g. self-check), so you need to pass 3 facts to it: "prepare drink", "drink type is latte", "temperature is 50C". You indeed can send a message to this object, containing these 3 facts as message data. Or you can call a method "prepare" of API with 2 parameters. See, there's no difference in amount of information you use for this operation: either way, there are 3 facts, for which you use 2 different syntactic forms. Coupling by definition is amount of shared information about mutual state and behavior between components (number of facts fixed in interaction contract). Here it's the same.
With all that in mind, modern languages are so rich in syntax, that there's almost no use case for messages as the means of interaction between objects at this moment. When you mention reflection, I'd say it's not the same. You use reflection to discover the address of the routine to call (that is, do not rely on infrastructure for delivery), rather than deliver the message to the object so it could dispatch it itself. Well, of course, there's one remark - this depends on how you define the message. Reflective calls are late binding just the same way as dependency injection: in runtime some container or reflection API provides an address of the code, implementing given interface, that will be invoked. If reflection means messages, then DI means messages, then VMT means messages, then messages=methods and all this talk is about outdated definition of what everyone uses.
Web crawlers are a bit different story: search engines do not deal with objects, they always deal with documents, that do not expose any behavior. The only thing in the net that comes to my mind is the semantic web. There were talks about it in early 2000s, when there was a lot of hype about web services, runtime discovery, web ontology language etc, but it's now as dead as CORBA.
Reifying means to take the abstract and make it concrete. Reflection is an example: take a language feature, like a class, and make it into real data. Many languages have some reflection capabilities for types; message sending takes this even further.
For example, in Java, I can take a class and make data out of it: dynamically look up fields, etc. I can also do that with a method. But I cannot take a method call and turn it into data. I can sort of do it with a lambda, but lambdas make poor data:
1. A lambda is concrete, not abstract. It's literally "run this code."
2. Even if your lambda merely invokes a method on an object, it's still opaque. I can't pick it apart, get the parameters or method name out, etc.
Here's some practical objects you can't make in Java:
1. Envelope: wraps an arbitrary remote object Contents. Any method you invoke on Envelope gets sent over the wire and invoked on Contents.
2. Delegator: represents the union of one or more objects, the Delegates. Any method invoked on Delegator gets re-sent to the first Delegate that understands it.
3. Tee: Any method you invoke on the Tee gets multicast to its wrapped objects.
4. Mapper: wraps a list. Any message you send to Mapper sends it the elements of its list, and returns the resulting list.
etc. Put directly, Java method invocations are procedure calls, not messaging. But once you reify method invocations into object, it opens up all sorts of dynamic possibilities.
"reifiable" = "able to be reified", where "to reify" means "to make something abstract concrete or real".
So, for example, Scheme's call/cc function reifies continuations- it take a continuation, an abstract control-flow concept, and turns it into a concrete object that you can pass around and manipulate in code. Therefore, continuations are reifiable in Scheme.
The other comments have already answered this well enough. If you want a little more reading this is a nice example of an application of reification [0]. The first few paragraphs define it well, and then shows examples for implementing it for handling user/actor input and actions in a video game.
But in modern thinking, HTTP GET is a request with abstract semantics. The URL's path is abstract, and may be interpreted arbitrarily by the server. The client has no idea whether the request is serviced by a simple sendfile() or a fully dynamic program. HTTP GET is no longer an RPC, it is now a message.
A key difference is whether your function call is a request for concrete or abstract behavior. If you answer "abstract," then the call itself must be reifiable data, which can be sliced and diced in ways hidden from the caller.