Category Archives: F#

Language proliferation

I’ve always been aware that .NET supports multiple languages (obviously) and that Microsoft has been experimenting with this to some extent. It’s only recently struck me just to what extent this is the case though.

Here’s a list – almost certainly incomplete – of .NET languages from Microsoft alone.

Some of these are research languages which are more important for the ideas they’ve contributed to more mainstream ones at a later date than for anything else – but there’s still a lot of effort represented in the list.

In addition, there are third party languages targeting .NET, such as Boo, IronScheme and Scala. (Wikipedia lists loads of them.)

Now, think back to the time before .NET. Was Microsoft actively experimenting with languages back then? Plenty of people were trying things against the JVM, but Sun was pretty much absent from that party. .NET seems to be a "missing ingredient" that has allowed smart folk at Microsoft to let their imaginations loose in ways which they couldn’t previously. (Of course, not everyone in the language business at MS started there: Jim Hugunin was hired by Microsoft precisely because of his work on IronPython.)

I wonder how long this will continue.

Tower of Babel, or land of polyglots?

What does this mean for the average developer? Currently, if you’re writing a non-web application in .NET, you really only need to know a single language – and any of them will do. (Plus potentially SQL of course…) Compare this with web developers who have to be intimately familiar with HTML, CSS and JavaScript – and the differences between various implementations.

How long will it be before backend developers are expected to know a dynamic language, a static OO language and a functional language? Does the benefit of mixing several languages in a project worth the impedance mismatch and the increased skillset requirements? I’m not going to make any predictions on that front – I can certainly see the benefits of each of these approaches in certain situations. They’ve been designed to play well together, but there are bound to be limitations and oddities: times when you need to change how you write your F# so that it’s easily callable from C#, for example.

Whether or not you learn multiple languages to a professional level is one thing, but becoming familiar with them is a different matter. In the course of co-authoring Functional Programming for the Real World (where "co-author" is a bit of a stretch title – I’ve played more of an editorial role really, with the added bonus of picking on Tomas whenever I felt he was perhaps a little harsh towards C#) I’ve learned to appreciate many of F#’s qualities, but I don’t really know the language. If someone asked me to write a complete application in it (rather than just a toy experiment) I’d be reaching for books every other minute. I hope I’ll learn more over the course of time, but I doubt that I’ll ever be sufficiently experienced in it to put it on my CV. The same goes for IronPython, although I’m considerably more likely to need Python at work than I am F#. (Python is one of the three "approved" languages at Google, along with Java and C++.) None of this means that time spent in these languages is wasted: I’ll be able to apply a lot of what I’ve learned about F# to my C# coding, even if it will make me pine for things like pattern matching and asynchronous workflows periodically.

I think it’s pretty much a given that these days we all need to bring a wide range of technologies to bear in most jobs. While it used to be just about feasible in the .NET 1.1 days to have a pretty good grasp of all the major aspects (ASP.NET for sites and web services, ADO.NET, WinForms, Windows services, class libraries, interop) it’s just impossible these days. We learn something new when we need to – but usually against the background of a familiar language. How well would we cope if we had to learn whole new languages (to the level of being able to use them for production code) as often as we have to learn new libraries?

This worries me a little. I’m pleased to see that C# 4 is a much smaller change than the previous versions were. Admittedly I’d rather have had immutability support than dynamic, but that’s just me… and that’s the problem, too. While I worry about our ability to actually learn everything that’s becoming available, it’s all good stuff. Can there be "too much of a good thing"?

What I really don’t want to see is developers having to know multiple languages, and everyone knowing them poorly. I’m a big believer in having a thorough understanding of your language, so that even if everything else is new, you can rely on your understanding of that aspect of your code. It would be a shame if the pressure of knowing many languages turned many of us into cargo cult programmers. The utopia would be for us all to turn into language renaissance developers. I suspect the reality will be somewhere between the two.

Still, as long as I get to keep helping authors write about languages I know almost nothing about, I’m sure I’ll be happy…

Getting started with F#

Updated 13th November: Robert pickering has answered the questions. I’ve included his answers inline. Thanks Robert!

The talks I went to at TechEd today (Friday) were mostly related to concurrency and F#. I’ve decided that although it’s fairly unlikely I’ll use it in a serious manner, it’s worth learning F# mostly to become more comfortable with functional programming in general. Apart from anything else, this is likely to help in terms of LINQ and general concurrency.

I was fortunate enough to win a copy of Robert Pickering’s “Foundations of F#” today at the final talk, answering a “pop quiz” question set by Joe Duffy. (Whoever claims that there’s no point in a C# developer knowing details of the CLR memory model is thus proven wrong in a most bizarre way.) I’ll probably buy Don Syme’s “Expert F#” when it comes out. I’ve been the Foundations book on the plane, where I’m currently hunched over my laptop, desperately hoping it doesn’t run out of power before we land. My situation has one important impact on this post: I haven’t actually written any F# yet. As it happens, with the VS2008 release being pretty imminent, I’ll probably wait until that’s out before installing F#.

In a way, my complete inexperience with the language is a good thing, for the sake of what I’m writing here: these are my raw impressions of F# based solely on what I’ve read. Now, some of the points I’m going to make here are potentially about the book instead of F# – I want to make it perfectly clear that I’m not trying to criticize the book. In general, it’s been an easy read so far (I’ve read about 70 pages) and my main problem with it is that there are typos. Normally that’s fine, but there are some cases where I don’t know whether I’m missing something about F# or whether there’s just a typo. Errors like this are to be expected, however hard we try to avoid them. I know that I’m still finding typos in chapters of C# in Depth that I’ve read several times, and I’m sure there will be some in the finished product. Anyway, with that disclaimer, along with the reiteration that these are just first impressions, here are my thoughts so far. They’re numbered for the sake of ease of reference, and as I find out answers to any questions, I’ll include them at the end of the point in italics.

  1. Byte literal strings – what encoding is used? This feels like a bad idea, although I’m sure it’s useful sometimes. (At least the normal strings are plain .NET strings; as I understand it IronRuby uses non-Unicode strings internally by default and only converts to/from Unicode when calling .NET code. The things we do in the name of compatibility…)

    Robert: It doesn’t say what encode is used in the language specification, however I strongly supect its UTF-8 as the spec says that unicode characters are allowed but “A”B comes out as [|65uy|]. I think they were added to help out Ocaml users who are used to having mutable strings thus providing an easier migration for ocaml programs which take advantage of mutable strings (although having non-mutable strings generally feels like a good design choice for an FP).
  2. #light is used at the start of every listing , and Robert explains that he’s not going to explain the non-light syntax. I know this is only a single book, but isn’t that at least a good indiciation that perhaps it should be the default syntax style?

    Robert: The light syntax really isn’t that different from the non-light syntax, it just means you can miss out certainty tokens such as “in” and semi-colon (;) when the context is clear from the whitespacing. This small change does however make listings look a lot neater and forces you to make whitespacing reflect the structure of the program (which is a very good thing). The choice not to explain it was made for two reasons 1) I though explaining would be more confusing that just telling beginners not to worry about it 2) it provides beginners very clear guidance to what syntax they should be using. Should the F# compiler be light by default? I can see the advantages, but adds a little extra complexity for people trying to do F#/Ocaml cross compilation.
  3. List comprehensions: why do I need [] round the range when declaring a value, but not for iteration? I can do “for i in 1..5″ but not “let x = 1..5″. Isn’t this inconsistent?

    Robert: This is because the surrounding bracket types denote the type of collection [] is list [||] is array and {} is Seq/IEnumerable, this is directly copied from creating a literal list of these types. Also you can’t use say “for i in 1..5” you need to say “for i in do …” which you can also do in list comprehension [for i in 1..5 -> (i, i*i) ] for a list of tuples of squares.
  4. The “when” clause in a for loop – I’m sure it’s to look like OCaml, but coming at a time when the non-functional world is used to “where”, it’s unfortunate. I’m not saying that F# has made the wrong decision here – it’s just a pain when two different histories collide.

    Robert: No comment :)
  5. P28 has ‘let objList = [box 1; box 2.0; box "three"]‘. The box operator here isn’t fully explained as far as I can see – but the main interesting idea is that a string could be boxed. In “classic” .NET boxing refers to creating a reference type instance out of a value type value – but string is already a reference type. What’s going on here?

    Robert: box is not just for boxing structs, it also performs an upcast to type object. A result of F#’s type inference is that there is no implicit upcasts as there are in C#. F# provides the box keyword and :> operator to compensate for this

    Jon: That seems pretty unfortunate to me, when box already has a clearly defined meaning in .NET. I suspect this will confuse quite a few people.

  6. P37 looks like it’s using a C-style pre-decrement: ‘| x -> luc (x – 1) + luc (–x – 2)’ – is that –x just a typo for x?

    Robert: –x is just a strange and embarrassing typo (already listed in the errata)
  7. Another possible typo: P41, first listing the final line is ‘| [] -> ()’ where in the previous example the result had been [] instead of (). That makes more sense to me, as otherwise the function returns unit where otherwise it’s returning a list. Typo, or am I missing something?

    Robert: This is correct, in the other rules of this pattern matching we’re printing to the console, which has type unit as a result, so we need to use unit for the final rule as well.

    Jon: Oops. Doh!
  8. Union/record types: as a C# guy, my natural question is how these things look in IL. Is a union just a name and a value, and if so is it in a struct or a class? Will have to dig out reflector when I’ve got the compiler…

    Robert: Record types are classes with properties for the each of the fields. The union type is represented as class with inner classes to represent each of the cases. The outer class provides methods and properties for working with each of the cases from C#. There is a good description of what a union type looks like in the final chapter of the book.
  9. There are quotes in the output at the bottom of P48, from calling print_any: ‘”one”, “two”, “three”, “four”‘ – are these genuinely in the output? I haven’t found a specific description of print_any yet, but I don’t think we’ve seen quotes round all strings. I could be wrong though :)

    Robert: print_any tries to reconstruct its input into its literal equivalent, so strings come out quoted listed look like ["one"; "two"; "three"]

    Jon: Ah, handy. A bit like Groovy’s inspect() method.

  10. Another terminology clash: “raise” for exceptions rather than “throw” is likely to confusion me for a while; “raise” sounds like an event to my C#-tuned ears.

    Robert: Again, no comment
  11. Supposedly OCaml is really efficient when it comes to exceptions. Now, I usually find that when people talk about exceptions being expensive in .NET they’re basing that on experience under the debugger. Are OCaml exceptions really significantly faster than under .NET? It’s far from impossible, but I’d be interested to know.

    Robert: I believe OCaml exceptions are a lot faster that .NET exceptions, but then they don’t carry any of the debugging information that .NET exceptions do. It is reasonably common to use exceptions as follow control in OCaml which is a bit of a no no in .NET
  12. Why is “lazy” a keyword but “force” isn’t? It feels odd for part of a feature to be in the language but its other side (which is necessary, as far as I can see) being in the library instead.

    Robert: I believe lazy is a keyword because it helps tidy up the precedence when you are creating lazy values. It maps directly to a function in the F# libraries that can be used instead. I believe this is a design decision inherited from OCaml.
  13. “unit” is an interesting name for what I’d normally think of as “void” – I wonder what the history is here? “void” isn’t as descriptive as it might be, but “unit” is even less obvious…

    Robert: Wikipedia has some more info here: http://en.wikipedia.org/wiki/Unit_type but is doesn’t cover the history of the name.
  14. It took me a little while to get the hang of () really being like void instead of like null – so () as a function return is the equivalent of “return;” which requires a void return type – it’s not “return null;”. Nothing in the book suggests that it is null – that was my own misunderstanding, and I don’t know what caused it.

    Robert: No comment :)
  15. P59 talks about mutable record types, and states that “this operation [updating a record] changes the contents of the record’s field rather than changing the record itself”. Now, I suspect the difference being alluded to is the same as “changing a value within a reference type instance’s data is not the same as making a variable refer to a different instance” – but if it’s not, I don’t know what it is meant to be saying.

    Robert: Yes, you are change the value with the reference
  16. P67/68: Do while and for loops require a “done” terminator or not? The text claims they do, but the examples don’t include it. My guess is that the language specification changed while the book was being written, and that the examples are correct, but I’d appreciate clarification :)

    Robert: They only require done when there’s no #light declaration and yes #light declarations were added half way though writing the book
  17. P69: I assume “for x in y” works where y is any sequence (i.e. anything implementing IEnumerable)?

    Robert: Yes, its works for anything that implements IEnumerable<T> or IEnumerable.
  18. P70: Calling methods and specifying parameter names – in the example, the parameter names are actually in the same order as they’re declared in the method itself. Is this always the case? Can you reorder the use of the parameters? Note that (at least in C#) reordering could have an effect on what the eventual arguments were, if the evaluation of the arguments has side effects. I’d really like to see this feature in C# though – it would save on all those comments explaining which parameter method means what!

    Robert: Just tested:
    System.Console.WriteLine(arg = [| box 1 |], format = “{0}”)
    And it compiles okay, so named arguments can be reordered.

    Jon: Ooh, I’ve got feature envy :)

  19. Why can’t I use a .NET method as a value, just as I can use an F# function value? If the method were overloaded I might have to provide some type information to the compiler to tell it which overload I mean, but otherwise I should be able to use it just like anything else without wrapping it. I assume there’s a deep implementation reason why this is impossible, but it seems a bit of a shame.

    Robert: Actually you can now, it’s another case of the language spec changing while [the book was being written]

    Jon: Cool. Always good to hear news like that.

  20. P73: Indexers aren’t always called Item – that’s just the default name for the default indexer. You can have other named ones, although C# will only use whichever has the appropriate attribute applied. (Even in C# you can change the name emitted when you declare an indexer though.)

    Robert: I’ve just read sections 10.9 of C# 3.0 specification and I see no reference to attributes or the ability to change the indexer name. Also section 10.3.9.3 “Member names reserved for indexers” seems to suggest that Item is the only reserved name. What am I missing?

    Jon: The attribute in question is System.Reflection.DefaultMemberAttribute – but it appears that you can’t apply it in C# when there’s already an indexer, contrary to my previous belief. However, if you use IL which specifies a DefaultMemberAttribute other than Item, it works fine.
  21. Also on P73, there’s this line: ‘let temp = new ResizeArray<string>() in’ – is the ‘in’ part here a typo, or is it another bit of syntax that I’ve missed somewhere?

    Robert: “in” is optional here because of the #light syntax
  22. What’s the :> operator shown  on P77?

    Update: P82 explains that it’s the upcasting operator
  23. What is ‘try … match’ referred to on P77?

    Robert: This is try … match is the equivalent of try … catch
  24. Is box actually a keyword or not? It’s not listed in the list of keywords, but it looks like it should be…

    Robert: box is a function not an keyword, its defined in Microsoft.Fsharp.Core.Operators if you want to see its definition (prim-types.fs).

I don’t intend to make notes as I read the rest of the book – it takes too long. However, I hope any F# evangelists find these initial reactions useful to some extent.