For example, I do _both_ Pure Functional Programming _and_ OOP (in the "module system" way) in Scala daily. And it works very nice IMHO, I encourage everybody to give it a try.
Use traits as interfaces for logical pieces of your business logic. Implement them in (case) classes which receive interfaces to other pieces of logic in their class constructor. Use a so called "Functional Effect System" like Cats Effect or ZIO to avoid raw side effects. And that's it, enjoy and profit.
My point here was that all "OOP" languages (that I know) allow you, with all their "OOP feautres", to work with objects which actually don't contain any mutable state.
I'll let you be the judge whether it is still "OOP", but I know from experience that it's very practical for Software Engineering.
Technical terms can be overloaded, I don't think this is either surprising or problematic. Astrophysicists classify carbon as a metal; they're not wrong, it's just a peculiarity of the field that's almost always clear from context.
In the context of FP, the term "referential transparency" means that variables can be replaced with their definitions, and vice versa, without changing the semantics of the program. The term coincides with pureness, but IMO it emphasizes something different. "Pureness" is a negative definition, it the property of there not being any side effects. "Referential transparency" to me indicates what you can do with that purity: it allows you to reason algebraically about your program.
> most languages without macros are referentially transparent
I don't think so. In most languages, you cannot syntactically replace a variable with its definition and expect the semantics of your program to remain unchanged. For instance, in Python, given the following shared prefix:
state = 0
def f():
nonlocal state
state += 1
return state
x = f()
The programs x + x
and f() + f()
do not yield the same result, which is what you'd expect if referential transparency holds.
To program in a functional style means no more or less than to construct your program by composing referentially transparent functions (that is, functions that have no side effects, and whose output is deterministic based on the inputs -- in other words: the mathematical notion of a function). The solutions that are marked as functional in the post fulfill this criterium, so it's correct to call them functional solutions.
Whether your functions are written in method notation or not is not relevant to determining whether the program is written in a functional style.