Difference between functional style and functional language?
Difference between functional style and functional language?
Bundling data and functions has pros and cons but has nothing to do with functional programming it.
Also, there isn't really a good definition for either functional style or functional language. If anything, there is a good definition for pure functional programming, but that's another beast alltogether and still is orthogonal to bundling data and functions.
Not necessarily- the functions can still be polymorphic. Rust does a particularly cool thing here, where any struct or trait method can be called in non-method syntax (or even passed as a first-class function!). I believe Julia also has type-based polymorphism while still being considered a functional-adjacent programming language. And then there are other languages where any function in scope can be called in method syntax, without being explicitly associated with the value's type (there's a name for this feature but I can't remember it)
> Difference between functional style and functional language?
I don't know the precise definitions well enough to distinguish them (though I'm not sure they have precise definitions)
Yeah, this is a risk with any language that mixes some functional features/style in with non-functional features. Rust does a pretty good job of letting you mostly delineate the two, though there are still escape-hatches
I've actually been toying with a language design that has both, but draws a hard distinction between them. We'll see how it works out :)
But most of the time, if you're not using a totally pure functional language, functional programming is more a practice/style/ethos/feature-set than a hard constraint
sort(x)
returns the sorted object, but sort!(x)
returns a "nothing" and mutates the object in place. fn do_thing(a_owned: Foo, b_mutating: &mut Foo, c_immutable: &Foo) {
There is a convention to separate the two kinds of functions (consume and return in some, mutate in others), but that's the only commonalityOf course they don't. These "paradigms" like OOP or FP are just human made up terms _without any basis in theory_. Sometimes they can be practically useful when communicating with other humans, like we do now. But more and more people are starting to realize how meaningless/nonsensical these categorizations are (and always have been): FP vs OOP, compiled vs interpreted, static vs dynamic, etc. We might as well categorize languages based on the colour of their mascot.
See this for more https://old.reddit.com/r/ProgrammingLanguages/duplicates/6xt...
The closest thing to the definition of an FP language that I was able to come up with is "based on the Lambda calculus". Haskell is, Scheme is, F# is. But e.g. Scala isn't, it's fundamental building block isn't functions but objects. But many people do consider Scala to be an FP language.
So let's all be aware of the limitations of these (pseudo-)concepts.
In other words, this is not even a property of a programming language. It is a property of the code itself. It's just that some languages make it easy or impossible to build a program in that style - or they even enforce it. Haskell however has escape hatches. And Scala is considered an FP language because, unlike Javascript/Lisp/Clojure/ML/Rust/... it really allows and supports(!) to make the whole program referential transparent.
Can a function-defining expression be transparently replaced with the value it computes?
Let's say `(new function(input) { return input })` is a valid expression. If it then doesn't matter (in any circumstance) whether you do
let myFunction = (new function(input) { return input })
myFunction(1)
myFunction(2)
or (new function(input) { return input })(1)
(new function(input) { return input })(2)
that's when you can call the function-defining expression to be referentially transparent. If, on the contrary, creating a function increases a counter and you use that counter in your programing for something and it makes your program behave differently depending on how many functions are created, then the function creating expression would cease to be referential transparent.I think that's not a bad example actually, because I assume it feels more natural to people to be able to treat an expression that creates a function in the way above and expecting that it won't change how the program behaves. And this is really what functional programming is about - it is exactly this feeling and guarantee that FP enforces throughout the whole application, not just in some places.
If you are talking about creating a named function (i.e. a class member) that is not an expression, then there isn't really much point in talking about it since we are now talking about definitions, not expressions anymore. Unless you can change/create definitions programmatically - in that case the code that does it programmatically is the one that needs to be considered, not the definition itself.
let myFunction = ...
which can replace that whole construct so that the program remains the same? Or is this not functional?A language could certainly treat assignments as expressions (some do) and have them return something, such as the value that is assigned to the variable or always null/unit. But we are now talking about a totally different thing.
Turns out there are non-expressions present; yet somehow if just the expressions are referentially transparent, we have FP?
We have to say something about the kinds of non-expression thingys that are required/allowed and what their properties must be.
Assignments can be expressions, but they are not referentially transparent. If an assignment is replaced by its value, it's no longer performing the assignment. Hence, assignments are easily found to be incompatible with FP under the RT definition, which underscores that it is useful.
Why "just"?
> We have to say something about the kinds of non-expression thingys that are required/allowed and what their properties must be.
Well, if there are syntactical constructs that will execute code at runtime, then we can essentially consider them expressions, even though sometimes they are restricted in how they can be used. For example, in Javascript and Java there is an if-syntax (call it if-statement or whatever) that will execute code but it doesn't return anything and you can "assign" the result to a variable. Obviously this breaks referential transparency (or can't do anything meaningful). We can still see it as an expression for the purpose of the definiton.
Other than that, as I said in my parallel post, if you have something like templates (which are not executing code at runtime), then they can do whatever you want, the only thing that matters is what expressions they will produce and if those are RT or not to fullfill the definition of FP.
> If an assignment is replaced by its value, it's no longer performing the assignment
And the funny thing is, it doesn't matter. Your code might stop compiling because you refer to a variable that isn't declared, yeah. And that's about it. But otherwise in a fully RT program it won't change the bebaviour of the program. EXCEPT if it is a reassignment. Which is why reassignments are violating RT and are therefore not a thing in FP - there can be specific exceptions (i.e. shadowing something in a different scope) but those aren't really reassignments, they just sometimes use the same syntax.
It is a syntax level term, muddying execution model is just not correct usage, see https://stackoverflow.com/questions/210835/what-is-referenti...
What you are looking for is simply and plainly “pureness”.
Referential transparency is not a property of programming languages but expressions (or more general, parts of computer programs).
> It means that one can replace a reference to a thing with the thing itself.
That's not the common definition at all. Read the link I posted. In any case, I'm talking about evaluatable expressions, you talk about "references" - however you define that.
Even in your own stackoverflow link, the accepted answer says this:
> the thing that an expression refers to
What’s missing from side-effect freedom or pureness? That is the property that allows replacing an expression with its value.
Not sure what you are talking about now.
> What’s missing from side-effect freedom or pureness? That is the property that allows replacing an expression with its value.
I think you are just unfamiliar with the terminology, that's all.
See Wikpedia again:
> If a pure function is called with arguments that cause no side-effects, the result is constant with respect to that argument list (sometimes called referential transparency or idempotence), i.e., calling the pure function again with the same arguments returns the same result. (This can enable caching optimizations such as memoization.)
(https://en.wikipedia.org/wiki/Functional_programming#Pure_fu...)
There you go. All 3 terms in once sentence. Maybe, again, you disagree with Wikipedia and the definition and that's your good right, but I don't see any point in prolonging the discussion over that.
On the contrary, this helps with modularity, which is a good thing. You can then swap out the object for another object with the same interface, but where the functions (methods) have different implementations.
That is about name-scope. You can refer to your own method simply by its name via 'this', and when you call it you know it can access the state inside that particular object.
Without 'this' an object in JavaScript and other OOP languages could not access its own properties including it (possibly mutable) state.
Is there an equivalent to 'this' in purely FP languages?