Reason: Omitting `;` from the last expression in a function

Created on 10 Mar 2017  路  6Comments  路  Source: reasonml/reason

I was playing around with imperative control structures and had the following code:

type result 'a = {mutable list: list 'a};

let firstN (n: int) (l: list 'a) :list 'a => {
  let result: result 'a = {list: []};
  let start = 0;
  let stop = min (n - 1) (List.length l);
  for i in start to stop {
    result.list = List.append [List.nth l i] result.list
  }
};

The formatter would work, but I'd get a compile error that the return type was unit. That made sense, so I tried to return the result.list:

type result 'a = {mutable list: list 'a};

let firstN (n: int) (l: list 'a) :list 'a => {
  let result: result 'a = {list: []};
  let start = 0;
  let stop = min (n - 1) (List.length l);
  for i in start to stop {
    result.list = List.append [List.nth l i] result.list
  }
  result.list;
};

Now the formatter wouldn't work and the compiler said it was looking for a closing block for the for-loop. I was confused and couldn't figure out what was wrong.

The solution ended up being this:

type result 'a = {mutable list: list 'a};

let firstN (n: int) (l: list 'a) :list 'a => {
  let result: result 'a = {list: []};
  let start = 0;
  let stop = min (n - 1) (List.length l);
  for i in start to stop {
    result.list = List.append [List.nth l i] result.list
  };
  result.list
};

I noticed that when I put semi-colons at the end of the for loop block and at the end of the List.append expression in the first example, the formatter took them away. By complete coincidence, I put at the end of the for-loop block after putting result.list in there, and ah-ha! it worked.


long story short, semi-colons being omitted from the last expression in a block can cause a lot of confusion! when the formatter gets rid of a semi-colon, I don't expect to have to add it back when I add another line to try to make the compiler happy.

Most helpful comment

I don't think you'd get any objection to adding the final semicolons back. Feel free to send a PR (I think this one is pretty easy).

All 6 comments

Interestingly, @yunxing and I realized that enforcing final semicolons eliminates some confusion around punning of single field records. Doing so might kill two birds with one stone.

ah, so this _had_ been logged already. I'd also like to see semicolons retained at the end of functions that have multiple expressions to avoid confusion. They are already implicitly mandatory for single-expression functions, due to the lack of braces:

let f = (x) => x + 1;

I don't think you'd get any objection to adding the final semicolons back. Feel free to send a PR (I think this one is pretty easy).

I like more rust's approach on semicolon, it's more similar to ocaml's one, the expression to be returned does not have semicolons

Reason's current parser also does not require the final semicolon. It does, however, print it - and this is so that you can more easily copy/paste lines between easily. Also, printing the final semicolon prepares us to finally accept single field punned records like {this}.

I think I'll close this out unless there's any specific request in light of recent changes (we automatically add the final ; back)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gustavopinto picture gustavopinto  路  3Comments

chenglou picture chenglou  路  3Comments

ondrejsevcik picture ondrejsevcik  路  3Comments

bobzhang picture bobzhang  路  3Comments

TrakBit picture TrakBit  路  3Comments