I remember one of my CS profs in college telling the class that when we graduate, we will come out knowing this much (petite two-finger gesture here) about programming. Well, I don't know about that, as programming in the real world is considerably further up the curve on mechanics, tools reliance, and development fads, but far behind the curve on applying theory and good engineering practice. But there you have it. The academic view on Bachelor's degree candidates. There is some truth to the statement.
In my education, we were never taught outright functional programming methodologies - at least not enough from what I recall. I certainly never had a 100-level course called A survey of formal programming methodologies. Should I have? Almost all of my education was spent studying CS techniques, applications, languages and processes from the perspective of procedural and object-oriented design, under Waterfall process and CMM buiness methodology. Nothing of Agile development methods, no web/cloud programming coursework, no JavaScript/HTML. Everything was taught from an imperative programming approach with languages like C, C++ and Java, and implemented as console applications. I feel deprived in a way, because although we were taught most of these principles, it was never presented as pure methodology.
Since I am in the process of learning Scala on my own now, I've experienced some "methodology shock" with the language - a discomfort in the ways of programming with Functional methods. Douglas Crockford, in his Google Tech Talk about Monads Monads and Gonads starts by defining Functional Programming as having two kinds of meanings.
Programming with Functions
The first meaning of Functional Programming, according to Crockford, is the simple abiity to program using functions. This entails the familiar C-like structures of storing sequential code in an enclosing block, whose entry point for data is defined by a parameter list, and whose result can be returned outside the block to the caller.
Some pactices or developments occurred to enhance this model: First Class Functions, High Order Functions and Lexical Closure.
First Class Functions are functions that can be treated like data. First-Class functions can be assigned to fields, given as arguments to other functions, and stored in data structures (just as the Integer data type can be, for example.)
High Order Functions are functions that can operate on other functions as arguments.
Lexical Closure is an enclosed function that has access to a variable in an outer function. A big breakthrough, according to Crockford.
Pure Functional Programming
The second meaning of Functional Programming is called Pure Functional Programming. This is where functions in code are given the same tangible properties as mathematical functions. Like math functions of the form: $$ y = f(x) $$, mutation of existing data is not allowed. For each input $$ x $$ into the function, there is one and only one result $$ y $$. Nothing can change this. There can be no side-effects (modifcations to internal or external data).
In Pure Functional design, immutable data is input to a function, calculation is done on that data, and separate, immutable data returned. Re-running the function with the same input will always result in the same output. Due to the limitations of the contract for no side-effects, no I/O can be performed while the function is running: no disk writes, network activity or output of any kind which modifies pre-existing state anywhere. No values passed into the function can be modified. Modified copies can be returned, but original input stays intact.
The advantage of doing it this way is that pure functions can be treated as entities whose input and output are conceptually identical to static mathematical data coming in and out of math functions. Just as $$ f(x) $$ is effectively replaced by its result, the program function becomes interchangable with its result, a static value that is calculated (or mapped by the function) on the fly behind the scenes. Therefore, the distinction between functions and data are erased. Functions become First Class, one in the same with data. This leads to higher reliability; consistent, more testable correctness; and a kind of comprehensive simplicity.
The disadvantage here is that if you make everything immutable in a program, you won't be able to do much of anything useful with it (a sentiment echoed by Haskell guy Simon Peyton Jones in his chat about Useful vs. Safe languages.) In summary, Crockford said immutability makes it hard to work with real-world programming problems where data changes and mutability is needed.
What bails functional languages out of this usefulness problem, according to Crockford, is the loophole in the No Side Effects Contract offered by High Order Functions, which embues immutable functions with dynamic behavior. Permitting one function to recieve another writes a kind of blank check of pseudo-mutability to Pure Functions, enabling things like IO to be performed without side-effects. This is aided/accomplished/abetted somehow by Monads, which is where I stop trying to make sense of it.
In as much as Pure Functional Programming is concerned, there are other variants of the definition, which all sort of agree. In the book Programming in Scala 2nd Ed. the authors state there are two concepts central to functional programming style.
First that functions are First Class, and second, that operations of a program should map to input-output values, never changing data in-place (e.g. no side effects.) They say functional languages either require or encourage Referential Transparency (the ability to replace a datum with a function transparently) and use immutable data structures. Scala falls into the "Encourage functional style" category, since you can always fall back to Imperative Style if needed, and have full access to mutable data structures as well as immutable ones.