BTW, immutability has nothing to do with encapsulation. Encapsulation is the hiding, or access restriction, of data structures from "foreign" functions. Those foreign functions may only manipulate the encapsulated data through a prescribed set of functions.
We achieve this in clojure through clojure's lovely typing mechanism which allows you to declare types that have publicly known functions without any data declarations; and private implementations of those functions that know the data they are manipulating.
One last note. C was much more encapsulated than C++, Java, or C# because in C you would declare your functions in a .h file, and your variables in a .c file. No other .c file could see your variables, so they _had_ to use your functions. The public/private keywords were added to C++, and then to Java and C# because the act of putting variable and function declarations in the same source file broke encapsulation, and we needed a way to re-assert it. That reassertion was only partially effective.
The bottom line is that all the C based OO languages are _less_ encapsulated than C.
We achieve this in clojure through clojure's lovely typing mechanism which allows you to declare types that have publicly known functions without any data declarations; and private implementations of those functions that know the data they are manipulating.
One last note. C was much more encapsulated than C++, Java, or C# because in C you would declare your functions in a .h file, and your variables in a .c file. No other .c file could see your variables, so they _had_ to use your functions. The public/private keywords were added to C++, and then to Java and C# because the act of putting variable and function declarations in the same source file broke encapsulation, and we needed a way to re-assert it. That reassertion was only partially effective.
The bottom line is that all the C based OO languages are _less_ encapsulated than C.