4 ms·
Some other descriptions here do a good job. It's worth being clear that "functional programming" is more of a set of similar but different programming cultures
by tel 12y ago
Some other descriptions here do a good job. It's worth being clear that "functional programming" is more of a set of similar but different programming cultures than a hard-and-fast language property.
That said, one thing that's more common in FP than anywhere else is an adherence to the notion that a variable stands for an "unknown" and not a mutable slot. Thus, you cannot assign to a variable but instead can only define it within a context.
x = 3
This is neat in that you can even write recursive definitions sometimes like
x = x + x
which, mathematically, means that either x is 0 or it's "undefined". Functional languages do not necessarily allow you to write the above recursive definition, but some might. It's certainly a well-defined notion.
Typically, functional languages operate by giving "first class" domain to functions (thus their namesake). What this means is that you can both create and define functions as though they were mere values like integer or characters. To do so, to say define a function of one argument which doubles that argument, you use what's called abstraction
x . x * x
where the period separates the function body on the right from the variables introduced in that scope on the left. You can then apply functions to other values
(x . x * x)(3)
3 * 3
9
but you could also give that function another name by defining a variable.
square = x . x * x
square(3)
(x . x * x)(3)
3 * 3
9
Sometimes abstraction is written as
λ x . x * x
which is why it's often known as λ-abstraction or lambda abstraction. A very popular, simple functional language is called the λ-calculus which uses only abstraction and application and is as expressive as any other language... if horrifically laborious to use.
So why does all this matter? In short, variables which behave as unknowns instead of mutable slots are very easy to reason about and functions as first class values are very expressive. When affixed to many of the other trappings of normal languages you have a very powerful basis for programming.
- p1esk 12y agoThanks for you response. >>>a variable stands for an "unknown" and not a mutable slot. Thus, you cannot assign to a variable but instead can only define it within a context. I'm struggling to understand this. A variable in C is also 'unknown' until you assigned a value to it. Do you, or do you not, assign a value to a variable in FP? If not, then what do you mean when you write "x = 3"? >>>variables which behave as unknowns instead of mutable slots are very easy to reason about and functions as first class values are very expressive. Can you show me an example? A short FP code that illustrates your point when compared to an equivalent code in Python or C?
- tel 12y agoAn unassigned variable in C is not "an unknown", though it is (as an adjective) unknown. It's uninitialized and thus equal to some value though it must be initialized first in order to be useful since only then do we know how to predict its behavior. To break down the difference, consider the idea of names versus the idea of "boxes" or "slots". In some languages those two concepts are undistinguishable because names always refer to locations in memory. In "functional"[1] languages they are separate. As an example, consider a function in a hypothetical language def foo (y, x): let z = get(x) assign(x, y*y+z) The (side) effect of this function is merely to update the value stored in the slot named `x` using a function of the value named `y`. To do so, we read from the slot `x`, bind a local name `z` with that value, and then assign back to the slot named `x`. We would call it in a block like this let box = newBox(1) let inp = 3 foo(box, inp) let newVal = get(box) print(newVal) and it would print `7` (3*3+1). I'm being really explicit about the idea of things being "named" by variables instead of just "being" variables. I'm also being really explicit about the notion of how boxes undergo mutation. The reason I do this is to isolate this "naming" property and show how simple it is. Variables-as-unknowns are merely names of values given to them in some context. Usually this is either a function abstraction or a let let x = 3 # now, here, the name `x` refers to a value `3` def foo(x): # now, here, the name `x` refers to some value that # will later be passed to `foo` If we need mutation we have to introduce the box idea noted earlier. Boxes with names behave quite similarly to "memory address variables" like what you have in C. [1] For this given definition of "functional"
- p1esk 12y agoI don't know, something must be wrong with my head, because I'm not any closer to understanding the point of FP. I really do want to understand it though. Your hypothetical language - is it functional? Because if it is, I don't see how it's different from C. If it's not, can you show me the equivalent code in a functional language? This is how I understand your code example: def foo (y, x): let z = get(x) assign(x, y*y+z) Jump to address 'foo', passing a value stored in register y, and an address stored in register x. Load value at address(x) to register z, then manipulate values of y and z, and store the result at address(x). So far so good. let box = newBox(1) let inp = 3 foo(box, inp) let newVal = get(box) print(newVal) Allocate memory for an int, put 1 in there, and store a pointer at register 'box'. Next, put 3 into register 'inp', and jump to 'foo', passing values at 'box' and 'inp' as x and y (registers don't change). 'Foo' updates the value at the address which we refer to as 'box' or 'x', and we load this value to register 'newVal', and print it. The way I see it, if you are using a concept of a 'slot' or a 'box' in your code, you have to use some name (label) to refer to the address of this slot. This label would be the name of a pointer in C, or the name of a variable in Python. If you are using a variable which stores a value directly, the name of such variable points to a register. How can you separate a name from what it points to? What would it mean, and most importantly, why would you want to do that?