Hacker News new | ask | show | jobs
by derefr 3918 days ago
I want to rave a little bit about this:

    "moo" |> String.replace("m", "z") |> String.upcase()
This is always what I thought OOP should be, but could never put my finger on. Effectively, you're calling a chain of "methods" of "objects", but each method lives in its own namespaced module, rather than automatically being assumed to live in the class associated with the data. No "this object implements two interfaces that both define add()" confusion; no objects extended to infinity with extra mix-ins and interfaces just so that more methods could be called on the object rather than having the object passed to utility functions; etc.

And when you do use classes (Structs), there's line-local context-free crystal-clarity between code that expects a generic object expressing one of the class's interfaces (where calls are made on the interface's Protocol module) vs. code that expects that particular class (where calls are made on the class's module, which contains the implementations of the Protocol functions.)

2 comments

See also:

Smalltalk faq: "Q28. What is the difference between chaining and cascading?"

http://www.ipass.net/vmalik/smalltalk.html#Q28

So, pretty much whether everything is being applied right to left vs being applied left to right?

Personally I like chaining because, since I read going right to left, in my head I can go "x goes to y then the result of y goes to z" versus "z is the result of y which is the result of x" (reading it backwards)

I wasn't clear, but I meant that mostly as a comment to:

> This is always what I thought OOP should be, but could never put my finger on.

I'm not sure what Simula did, but at least in Smalltalk this is how OOP have worked :-)

> So, pretty much whether everything is being applied right to left vs being applied left to right?

I'm not sure that's the best takeaway; consider:

    $ gst
    GNU Smalltalk ready

    st> 2 * 3; * 3; * 3
    6
    st> 2 * 3 * 3 * 3
    54
Now, if the object on the far left was some kind of accumulator/container, the effect of sending something like three "add the number 3" would be similar to chaining. But even if you mulitply the number 2 by 3, three separate time, 2 * 3 still equals 6.

In fact, in order to get chaining with keyword messages, you apparently need to define it, or especially adapt eg: containers to return ^self. But as should be obvious, I'm not very familiar with Smalltalk. Some more on the subject: http://blog.3plus4.org/2007/08/30/message-chains/

You can do this in other languages just the same with maybe some different syntax, for example C#

"moo".Replace('m', 'z').ToUpper();

Or, fully qualified with "every method in its own namespaced module";

"moo".(string.Replace('m', 'z')).(string.ToUpper());

I'm not sure if elixir is doing anything fancy here that I'm not seeing, though. I still haven't had a chance to try it out.

It's a macro. It takes the result of the prior operation and inserts it as the first parameter of the next operation.

More or less it rewrites

    String.downcase("FOO\0BAR") |> String.split("\0")
to

    String.split(String.downcase("FOO\0BAR"), "\0")