Does using a function declared outside the scope of the function it is being used in violate a Functional principle like immutability? Or is that referring specifically to data like arrays, strings, etc.
For example:
var data ["cat", "dog", "bird"];
function doThing (val) {
return val + ", go away!"
}
function alterData (data) {
return data.map(doThing);
}
alterData(data);
Would the above code be acceptable? or would the "doThing" function need to be passed into the alterData function as an argument?
The reason I am confused is because in Functional Programming examples I often see functions native to the language being used without being first passed to the function. However, the examples are never complicated enough to show how one would work with a library of functions.
Regards
It is important to understand that each of the functions we write can be used and called from other functions we write. This is one of the most important ways that computer scientists take a large problem and break it down into a group of smaller problems.
Nested Functions Call a function within another function.
In a functional language, there are only functions. Although it might seem that a language like Haskell has a lot of different objects and constructs, they can all be reduced to functions. We will demonstrate how variables, tuples, lists, conditionals, Booleans and numbers can all be constructed from lambda functions.
Series of operations when we call a function:Stack Frame is pushed into stack. Sub-routine instructions are executed. Stack Frame is popped from the stack. Now Program Counter is holding the return address.
Functional programming is no different from procedural in that regard—you write definitions that you can reuse anywhere that they are in scope. You control what's in scope where with a variety of mechanisms, for example with module definitions, module export lists and module imports. So for example (in Haskell):
module My.Module
-- List of definitions exported from this module
( doThing
, alterData
) where
-- Any definitions exported from `My.Other.Module` will be in scope
-- in this one
import My.Other.Module
-- Can't name this `data` because it's a reserved word in Haskell
yourData :: [String]
yourData = ["cat", "dog", "bird"]
doThing :: String -> String
doThing val = val ++ ", go away!"
alterData :: [String] -> [String]
alterData strings = map doThings strings
It's fine to rely on scoping in FP code.
Immutability means that something represented by a name can't change its value. I wouldn't call it a "principle" of functional programming, though.
Anyway, this is not related to scoping at all. Passing things as arguments makes sense if you want to parametrize a function over another function - essentially making it a Higher-Order function. A good example of such is fold
(also known as reduce
) - but map
is also one.
In your case alterData
function isn't adding much value, though. map
ping something over something is so common, that it's typically better to provide only the one-element function, as it's fundamentally more reusable.
If you've passed doThing
to alterData
, you'd make that function essentially useless; why would I use it, if I could simply use map
? However, packing the operation together with the mapping can sometimes be an useful abstraction.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With