views:

604

answers:

8
  1. I heard F# has native support for immutability but what about it that can not be replicated in C#? What do you get by an F# immutable data that you don't get from a C# immutable data?

  2. Also in F#, is there no way to create mutable data? Is everything immutable?

  3. If you use both C# and F# in an application, can you change the immutable F# data in C#? Or do you just have to create new C# types that uses the immutable F# data and replaces the references that points to those data?

+17  A: 
  1. The way F# works makes it easier to work with immutable data but there's nothing special that can't be done in C# in that regard. It may not provide neat syntax though.

  2. F# supports mutable data with the mutable keyword. F# is not a pure functional language. It supports imperative constructs like loops as well as functional constructs.

  3. No. Immutable types are really immutable. The .NET type system is shared across both languages. You can't change the immutable data from C# either (short of reflection and memory hacks, of course).

Mehrdad Afshari
Technically, you can change the (private) fields backing immutable properties via Reflection, in either F# or C# - if your code has sufficient permissions to override accessibility checks.
Pavel Minaev
@Pavel: Indeed. By "memory hacks" I meant the broad sense of changing stuff indirectly.
Mehrdad Afshari
Thanks, so F# uses a new keyword in IL that C# understands that marks a value as really immutable?
Joan Venge
@Joan: no, F# doesn't use any new IL facilities. It just makes all fields private, and only exposes property gettors and not settors for them. In addition, fields themselves are probably also marked as `readonly` (I haven't checked, though).
Pavel Minaev
+11  A: 

The biggest difference between F# and C# with respect to immutability is that F# is immutable by default. It's possible to replicate all of the immutable constructs and collections in C# but it takes a lot of extra work. In F# you simply get it for free.

F# is a hybrid language and does support mutability in a couple of forms. The simplest in the mutable keyword

let value1 = 42; // immutable
let mutable value2 = value1; // mutable
value2 <- 13;  

Barring reflection tricks, once the data is created in F# it is immutable irrespective of the language you consume it from.

JaredPar
Thanks, your example makes it clear.
Joan Venge
+13  A: 

Mehrdad already answered all your questions, but just to elaborate on #1 - the difference is in the amount of code you need to write. For example, here's the definition and sample use of a readonly point in C#:

class Point
{
    private readonly int x, y;

    public int X { get { return x; } }

    public int Y { get { return y; } }

    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

var p = new Point(1, 2);

You could use automatic properties to make this a little bit shorter, but then immutability is not enforced for code inside the class definition, only for its clients.

In F#, you'd just write:

type Point = { x: int; y: int }
let p = { x = 1; y = 2 }

And if you wanted it to be mutable:

type Point = { mutable x: int; mutable y: int }
let p = { x = 1; y = 2 }
p.x <- 3
p.y <- 4
Pavel Minaev
Thanks for the sample code Pavel.
Joan Venge
Btw this is minor but why p.x has to be changed like p.x <- 3, and not p.x = 3? Or can you use = sign to do the same? Just feels harder to type <-, but maybe that's me.
Joan Venge
Any time you change a value through assignment (something mutable) you have to use <-
gradbot
Because F# is immutable by default, the mutation operator `<-` is different from the assignment operator `=`. This prevents you from accidentally changing state when you didn't mean to, as you must be explicit about it. And it has the bonus benefit of being awkward syntax, discouraging the use of mutable values when they are not absolutely necessary.
Joel Mueller
@Joan: F# (and OCaml) prefer to distinguish between the concepts of assigning a value to a variable (<-) and binding a value to a symbol (=).
Mehrdad Afshari
Thanks. Then what's the = sign used for? You said changing state, how do you change the state? I now see the benefit, just don't know where you can use =, if everything is set using constructors, etc?
Joan Venge
I think I see it now. I didn't notice:let p = { x = 1, y = 2 }
Joan Venge
Also can you use Contracts and LINQ in F# too? Just wondering.
Joan Venge
You should be able to use Contracts quite easily, since the actual implementation is an IL rewriter, which doesn't care about the language used to produce assembly (that said, I haven't actually tried that). It can use LINQ, but it depends on what exactly you mean. You can call static methods on class `Enumerable` directly, but F# doesn't treat them as extension methods, nor is there syntactic sugar for them as in C#. On the other hand, F# has its own, richer library of operations on sequences - see http://msdn.microsoft.com/en-us/library/ee353635(VS.100).aspx
Pavel Minaev
... as well as its own syntactic sugar for sequence comprehensions, which effectively amounts to anonymous iterators (`yield return` inside a lambda), if such were possible in C#. See http://msdn.microsoft.com/en-us/library/dd233209(VS.100).aspx for those. If you mean LINQ to SQL - i.e. analysis of syntax trees at runtime and their conversion to something else - then this is supported in F# PowerPack.
Pavel Minaev
+1: just for my own amusement, I began work on an immutable data structures library in C# using F# coding style, and the amount of boilerplate code needed just for a simple container class is cumbersome to the point of overwhelming. And just about any C# implementation of algebraic data types is nightmare. I much rather prefer F#'s unions and record definitions to the equivalent C# code.
Juliet
+3  A: 

I think you are looking at this from a too detailed feature-for-feature point of a view.

I'd see the major advantage of immutability by default of functional programming langauges to be on how it affects the actual programming mind set of the developer. When mutation is the default, the programming mind set is geared towards solutions by mutating the data. When immutability is the default, the programming mind set is geared towards solutions by transforming the data.

To elaborate on why the latter mind set is better. When developing programs through mutating the data, you end up getting bogged down in fine details, so your focus tends to be on how the program works 'in the small'. When developing programs through transforming the data, you don't need to worry about many of the fine details (such as how different mutating parts of your program interact with each other), and your focus tends to be on how the program works 'in the large'. So, the latter mind set gears the developer towards having a better and clearer 'big picture' on how the program works.

While having a nice clean 'big picture' of a program is nice, in some cases, real life concerns can outweigh it. Some data structures (arrays, multi dimensional arrays), are not good candidates for immutability because of the high cost of making new copies, so some common sense should always be applied on when to not use immutability even with functional languages.

Edit to answer the comment:

Functional language purists would argue that it would make the code uglier. I consider myself not to be a purist, so I don't think so; well, perhaps uglier from a theoretical point of a view.

F# is an impure functional programming language, so it supports mutability when it's needed. Having part of your state be mutable doesn't invalidate the benefits of having most of your state be immutable.

In most cases, you end up using a different (pure) data structure where you would normally use an array in an imperative language. E.g. a tuple, a list or a tree (or a set/map build on top of a tree; the standard libraries usually come with implementations with good time complexity).

And if you think that you really need a mutable array (for performance reasons), you have it available, so nothing is stopping you from using one.

Sami
So how do you deal with issues like using an array, where like you said it's costly to make a new copy everytime. Does it make F# code uglier in those parts? Any example would be really helpful.
Joan Venge
Joan: It doesn't usually make the consuming code uglier; that just looks like `let newarr = mangle(oldarr)`. Although it's costly to make a new copy every time, one can design data structures to take advantage of immutability by sharing structure; for example, if you have linked list A = (3, 2, 1) and list B = (4, 3, 2, 1), and both are immutable, list B can be represented by 4 and then a pointer to the head of A. The same thing can be done with trees.
mquander
Note that, obviously, you couldn't pull that trick if A was mutable, since if you changed A, anyone with a reference to B would find that B was different too.
mquander
+5  A: 

As others noted, there are some important benefits of using immutable data. To name a few:

  • Parallelization - It is easier to parallelize program that calculates the result and returns it in an immutable data structure.
  • Understanding code - If you write program using immutable data, the only thing a piece of code can do is to return a result - this makes program more readable, because you see what a function/method does just by analyzing inputs & outputs

Technically seaking, you can write the same immutable data structure in both C# and F#. The problem is, that F# encourages you to do this, while writing true immutable data strctures in C# is a bit painful. This means that when writing F# code, you'll more likely write immutable structures (because it's easier!) and you'll use mutability (which is possible in F# as well) only when you'll really need it (it's harder!)

Aside from declaring immutable types by default, F# also has some nice features that make working with them easier. For example when working with records:

type MyRect = { X : int; Y : int; Width : int; Height : int }
let r = { X = 0; Y = 0; Width = 200; Height = 100 }

// You'll often need to create clone with one field changed:
let rMoved1 = { X = 123; Y = r.Y; Width = r.Width; Height = r.Height }

// The same thing can be written using 'with' keyword:
let rMoved2 = { r with  X = 123 }

You can write the same thing in C# too, but you'll need to declare immutable data structure with method WithX that returns a clone with modified X field, WithY, WithWidth, etc... Here is an incomplete example:

class MyRect {
  readonly int x, y, width, height;

  MyRect WithX(int newX) {
    return new MyRect(newX, y, width, height);
  }
  // etc...
}

This is a lot of work without any help from the compiler.

Tomas Petricek
Thanks, also what about string values? I heard strings in .NET isn't truely immutable. Does F# use the same string values?
Joan Venge
.NET strings are truly immutable. All methods for working with them return a new string without modifying the original one (just like my WithX method above). For example 'string s2 = s1.Substring(0, 4)' returns a new string without modifying 's1'. So, F# can safely use the same string type as .NET.
Tomas Petricek
+1  A: 

I don't know the intimate details of the F# compiler but it should be able to do more simple optimizations with immutable data. If the compiler knows a variable is immutable then it can assume that its value is always the same no matter where it appears in the code.

gradbot
It turns out that F# makes no attempts to optimize based on immutable data. Taken from http://stackoverflow.com/questions/2211478/advantages-of-compilers-for-functional-languages-over-compilers-for-imperative-la
gradbot
+2  A: 

What do you get by an F# immutable data that you don't get from a C# immutable data?

The first benefit is that an F# function doesn't have any other effect besides returning its result. No global data is changed, no mutable data is depended upon, and so you are guaranteed that, provided you stick to immutable data, the same call produces the same result, reliably, every time.

This first benefit is already nice by itself, because it makes your code easier to understand, but the big benefit kicks in because F# functions can safely be composed. Programming by function composition turns out to be an incredibly powerful, modular way to program with reusable parts. And you can build really powerful parts which can be put together in lots of different ways, so you can write more programs with less code.

These ideas are explained better than I ever could in John Hughes's landmark paper Why Functional Programming Matters. John explains how removing the ability to mutate actually adds expressive power to the language over all. Read the paper!

Norman Ramsey
+1  A: 

What do you get by an F# immutable data that you don't get from a C# immutable data?

F# allows you to easily make modified copies of immutable data, this is very tedious and time consuming to from C#. Consider creating a record in F#:

type Person = { FirstName: string; MiddleName: string; LastName: string }
let me = { FirstName = "Robert"; MiddleName = "Frederick"; LastName = "Pickering" }

Say I wanted alter the last name field, in F# I can do this by making a copy using the "with" keyword:

let me' = { me with LastName = "Townson" }

If you wanted to do this in C# you'd have to create methods that copied each field into a new structure and there's a strong possibility you'd get the fields mixed up.

There are other suitable advantages to do with collections. For example C# supports the immutable ReadOnlyCollection. However each time you want to add a new item to this collection you must make a copy of the whole collections. F# build in list allows you to just add a new item to the end of the list without making a copy of it, i.e. newly the resulting list will actually share most of the old list. i.e.:

let myList = [3; 2; 1]
let myList' =  4 :: myList

When creating "myList'", the whole of "myList" is preserved unchanged and "4" is added to it's head to create "myList'".

Robert
Thanks. What's the ' symbol you used after let myList'?
Joan Venge
It's a single quotation mark, it's just part of the identifier name. In F# it's often used in place of the prime symbol http://en.wikipedia.org/wiki/Prime_(symbol), to mean an alter version of a previously declared identifier.
Robert