The reason people still care about Unix pipes is because you can take a bunch of arbitrary commands and string them together in a way that produces some useful results. Moreover, you can configure each pipe to do different things depending on what you need at the moment.
What stops you from stringing together a bunch of arbitrary objects to achieve the same effect? Well, a bunch of things:
1. Verbose syntax of the language.
2. The need to compile new code.
3. Early binding that stops you from calling things you don't know about before compiling code.
4. The fact that objects can't just take arbitrary method arguments.
#1 is self-imposed.
#2 is solved by JIT compilation and some other technique.
#3 is not a problem in dynamically typed languages.
Most importantly, #4 is explicitly what polymorphism in OOP was supposed to solve. Poly = many. Morphos = shapes. The idea that the object adapts to the messages you send it.
With this in mind, ls -a | grep “gear” can be interpreted as code that does the following:
1. Send the object representing 'ls' a message with -a argument. This will supposedly construct a list.
2. Send 'grep' object a message with "gear" argument. This will construct a configured grep instance.
3. Send response from #1 as a message (or stream of messages) to #2. This will generate a filtered list.
4. Send the object resulting from #3 a message that would request a console-friendly representation (e.g. a string with codes for color in console).
5. Display #5.
This is (with some caveats) very close to how OOP was envisioned in the 70s and early 80s. Except pipelines are a very crude way of stringing things together. You can get way more sophisticated with objects. E.g. :
What stops you from stringing together a bunch of arbitrary objects to achieve the same effect? Well, a bunch of things:
1. Verbose syntax of the language.
2. The need to compile new code.
3. Early binding that stops you from calling things you don't know about before compiling code.
4. The fact that objects can't just take arbitrary method arguments.
#1 is self-imposed.
#2 is solved by JIT compilation and some other technique.
#3 is not a problem in dynamically typed languages.
Most importantly, #4 is explicitly what polymorphism in OOP was supposed to solve. Poly = many. Morphos = shapes. The idea that the object adapts to the messages you send it.
With this in mind, ls -a | grep “gear” can be interpreted as code that does the following:
1. Send the object representing 'ls' a message with -a argument. This will supposedly construct a list.
2. Send 'grep' object a message with "gear" argument. This will construct a configured grep instance.
3. Send response from #1 as a message (or stream of messages) to #2. This will generate a filtered list.
4. Send the object resulting from #3 a message that would request a console-friendly representation (e.g. a string with codes for color in console).
5. Display #5.
This is (with some caveats) very close to how OOP was envisioned in the 70s and early 80s. Except pipelines are a very crude way of stringing things together. You can get way more sophisticated with objects. E.g. :
https://www.youtube.com/watch?v=I9LZ6TnSP40
https://www.youtube.com/watch?v=if72CFsF_SY