Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I 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?



The language is sort-of functional. It's as unfunctional as possible while still highlighting immutability.

The key is to focus on what you can't do. Pointers in C do provide a similar UI to "boxes" that I was describing. But their plain values aren't the same. Consider

    int main() {
      int x;
      x = 3;
      x = 4;
      printf("x = %i\n", x);
    }

    $ gcc test.c -o test
    $ test
    x = 4
Here, I am still able to treat the value `x` as a "box" because `x` is not a name but instead an actual int-sized memory location on the stack. Here's a similar fragment in Haskell

    main = 
      let x = 3
      in let x = 4
         in print x

    $ ghc --make test.hs
    $ test
    4
Now the difference here is that each of those bindings (namings) of `x` have a context delimited by the indentation. In particular, names only have meaning within a delimited scope. In fact, the `x` bound by the inner let is completely different from the outer one. The fact that they share the same name means that the inner one shadows the outer one within the scope of the inner let.

We could demonstrate this with the following program perhaps

    main = 
      let x = 3
      in print ((let x = 4 in x) + x)

    $ ghc --make test.hs
    $ test
    7
Here we can plainly see that the context where `x` names 4 is only as large as that inner, bracketed `let ... in ...`. After we leave that scope, `x` reverts to naming 3.

The trick with figuring out FP is that it actually feels more restrictive at first. It's a typically higher-level form of expression. You can obviously simulate it all in C (FP languages might even compile down to C) but the goal is to determine what kinds of things can be expressed in the FP language itself.

To learn more, I highly suggest learning just the basics of Haskell or OCaml. Scala would probably suffice as well, though I don't know it as well to say.

Generally, the idea I'm talking about is often called "immutability" (though it's slightly different). Programming with immutable things tends to be easier to reason about because names do not change what they refer to within a context (like x changing from 3 to 4 in the C program).


Having different variables under the same name, especially when we have to keep track of which is which (different values in different contexts, defined by indentation) does not sound like a good idea to me.

For example, here's a problem I had in C when I used a local variable with the same name as a global variable: http://stackoverflow.com/questions/19214293/unable-to-modify...

You're saying: "immutable things tends to be easier to reason about because names do not change what they refer to within a context" Can you please provide an example of that? Maybe some code where this 'feature' is useful? Your example of let x = 3 in print ((let x = 4 in x) + x) shows what you mean, but it does not show why would I want to do that.

Thank you very much for your effort to help me understand.


Let me see if I can clarify.

Imagine a (rather useless) program that prints a number.

x = 5 x+=2 print x print x

this prints the number 7 2 times

in the 'context' definition of equality, which we'll denote using let * = ..., each of those assignments generates a context, which I'll show using indentation.

let x = 5 let x = x + 2 print x print x

These two programs do the same thing. However, using names as mathematical variables instead of 'boxes', there is another program we can create using the same 'sequence' of expression tokens (thus giving us greater expressive power).

let x = 5 let x = x + 2 print x print x

this program prints 7, and then it prints 5. In other words, we are able to access previous values of our 'variable' x if we want to, whereas this is not the default behavior of a system with mutable variables. This has an added benefit, not really shown in the previous example, of providing zones of protection from interference from the rest of the program. For example, I can always be assured that within the first context, x will always mean 5, and within the nested context, that x will always mean 7. No function or outside line of code can impact the value that x takes on. This really shines when programming in a team - this gives you assurance that to change the output of your section of the code, another teammate will have to directly alter your code. This localizes the source of future bugs in this code to always be in this section of the code, drastically simplifying the debugging process.

To make these contexts space efficient, modern functional programming compilers analyze when a program no longer needs access to previous value (because they will never again be used in the future), and marks it as 'garbage' to be collected later.

To try and rephrase it one more time - A mutable variable is an actual location in memory. Anyone sharing access to this location in memory in effect has a communication channel open to all of the other linking bits of code. This can be a powerfully simplifying abstraction, in some cases, which is why functional languages generally still provide it by many means, including (in Haskell) the State and IO monads. However, as a default model of resource usage, mutable variables are a poor choice. Generally speaking, you don't really want all parts of the code to be talking to one another. As programmers, whether using procedural, object-oriented, or functional programming, minimizing this kind of communication can help minimize the impacts of future changes. This is why object-oriented languages have private methods and variables, and why there is a trend towards object composition over object inheritance to define more complex behaviors, because both decouple the resulting subsets of code and make them more robust to external forces. Mathematical variables simplify our attempts to achieve this by cutting off the default route for breaking these hierarchical assumptions - shared communication.


Your explanation helps, however, I'm starting to think FP is hard to understand due to my lack of programming experience. And this makes me wonder why would anyone in their right mind try to offer it as the first programming language to teenagers.

The different contexts you're describing look similar to the global/local variables with the same name. For example, I had this problem in C, where I defined a global var and wanted to modify it inside a function. Which failed, because a local var with the same name was created: http://stackoverflow.com/questions/19214293/unable-to-modify... So in this example, 'immutability' was precisely what I didn't want in my program.

Can you please provide a concrete example where this 'feature' is useful?

Also, you're saying "A mutable variable is an actual location in memory". What about the name of immutable variable in FP? How is it implemented? How/where its value is being stored?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: