14

I just started learning F#, and tried a code from the wiki:

I prefer tabs to spaces, so I change the code a bit into this:

#indent "off"
open System
open System.Windows.Forms

let form = new Form(Visible=true, TopMost=true, Text="Welcome to F#")

let label =
    let temp = new Label()
    let x = 3 + (4 * 5)
    temp.Text <- sprintf "x = %d" x
    temp

form.Controls.Add(label)

[<STAThread>]
Application.Run(form)

The output is:

Microsoft (R) F# 2.0 Compiler build 4.0.30319.1 Copyright (c) Microsoft Corporation. All Rights Reserved.

fstest2.fs(1,1): warning FS0062: This construct is for ML compatibility. Conside r using a file with extension '.ml' or '.mli' instead. You can disable this warn ing by using '--mlcompatibility' or '--nowarn:62'.

fstest2.fs(9,2): error FS0010: Unexpected keyword 'let' or 'use' in expression. Expected 'in' or other token.

fstest2.fs(13,1): error FS0597: Successive arguments should be separated by spac es or tupled, and arguments involving function or method applications should be parenthesized

fstest2.fs(9,14): error FS0374: Invalid expression on left of assignment

fstest2.fs(16,1): error FS0010: Unexpected identifier in definition

Guess the error is somewhere in the let label block, but couldn't figure it out.

anta40
  • 6,511
  • 7
  • 46
  • 73

2 Answers2

18

If you use "#indent off", then you lose all the simpler whitespace-aware syntax, and have to go back to using e.g.

#indent "off"

open System
open System.Windows.Forms

let label =   
    let temp = new Label() in
    let x = 3 + (4 * 5) in   
    temp.Text <- sprintf "x = %d" x;   
    temp;;

let form = 
    let f = new Form() in
    f.Controls.Add(label);
    f;;

[<STAThread>]   
do Application.Run(form)     

with semicolons and ins and all other kinds of syntactic noise everywhere. You'll probably be happier just having your editor convert tabs to spaces (and having a smart editor that can treat spaces as though they are tabs, e.g. so that backspace can back up one tab-stop).

Brian
  • 117,631
  • 17
  • 236
  • 300
7

This topic was already discussed in this StackOverflow question. As Brian explains, turning off the "lightweight" syntax means that you'll have to write in the OCaml-compatible syntax.

I believe that in most of the cases, the syntax based on indentation is more readable (and so it is worth switching from tabs to spaces). However, the syntax with additional noise (such as in and ;;) reveals more about the structure of the language, so it may be useful to play with it briefly while learning F#.

The following example shows all the additional things that you need to write:

let add a b c =  
  let ab = a + b in // 'in' keyword specifies where binding (value 'ab') is valid 
  printfn "%d" ab;  // ';' is operator for sequencing expressions 
  c - ab;;          // ';;' is end of a function declaration 

For more discussions, see also this post.

Community
  • 1
  • 1
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • 2
    anta40 says “I prefer tabs to spaces”. It is not quite clear why tabs are not allowed for indentation in F# for light syntax? Imagine, somebody has his favorite text editor and some text tools and just habits grown and polished for years for tabs, not for spaces… and now there are only two choices for F#: spaces-light-on, tabs-light-off. – Roman Kuzmin Apr 30 '10 at 17:48
  • 6
    @anta40 - IIRC, the problem is different editors could use different width tab stops and also mix in spaces. Since changes to the tab width could change the indentation level of any given line, that could also change the meaning of the program itself, resulting in very hard to notice bugs. – James Hugard May 01 '10 at 00:36
  • 1
    @JamesHugard The tab is just a character by itself. It has no 'width'. Tab width is just a graphical concept for displaying text. I do agree that mixing tabs and spaces could result in hard to notice bugs though. – MEMark Oct 22 '13 at 14:44
  • 6
    Mixing of tabs and spaces is irresponsible for control structure, but given that even Python allows one or the other at any unique scope level, it is preposterous for F# to simply ban tabs entirely. – Zoey May 03 '14 at 01:30
  • @zoey, or you an just be happy that code will look the same on each system, and there's no need anymore for the tab vs spaces war. Vertical alignment is important, and there are subtle outdenting rules for one or two positions, which wouldn't be possible at all with tabs. Moving back to allow tabs, would mean a more limited syntax and loss of clarity. – Abel Aug 05 '20 at 12:29
  • @Abel The whole point of the tab is that people prefer different indentation distances so not everyone would see the "look the same on each system" as a win. Now you just have the wars between people preferring single space indentation, double space indentation, triple space indentation and so on :P – Kim Jan 18 '21 at 12:45
  • @Kim, I know, and with less-complex syntaxes that might work. But since you can un-indent by less-then-full indent width (i.e. you can place the `[` char unindented by two positions so that statements align vertically), and there's no such thing with tabs (there's no half-tab or quarter-tab), it's literally impossible to code properly with tabs.That was the point I was trying to make: a lot of things are now possible that wouldn't be possible with tabs. – Abel Jan 20 '21 at 18:28