Как отформатировать многострочную функцию F # в VisualStudio * .fsx

#f# #formatting #visual-studio-2019

#f# #форматирование #visual-studio-2019

Вопрос:

Q1: Я хочу отформатировать функцию F # по нескольким строкам в * .fsx в Visual Studio 2019, но когда я пытаюсь, я получаю синтаксические ошибки. (См. Ниже.)

Q2: В Haskell (насколько я помню) порядок, в котором вы объявляете функции, не имеет значения. Верно ли то же самое в F #?

 (* 
2.3 Declare the F# function 
isIthChar: string * int * char -> bool 
where the value of isIthChar(str,i,ch) is true 
if and only if ch is the i’th character in the string str 
(numbering starting at zero).

Hansen, Michael R.. Functional Programming Using F# (p. 39). Cambridge University Press. Kindle Edition. *)

let isIthChar (str: string, i, ch) = (ch = str.[i])

(* 
2.4 Declare the F# function 
occFromIth: string * int * char -> int where 

occFromIth(str, i, ch) = 
    the number of occurances of character ch
        in positions j in the string str
        with j >= i

Hint: the value should be 0 for i ≥ size str.

Hansen, Michael R.. Functional Programming Using F# (p. 39). Cambridge University Press. Kindle Edition. 
*)

let rec countChar(str, i, j, ch, cnt) = if j < i then cnt else if isIthChar(str, j, ch) then countChar(str, i, j - 1, ch, cnt   1) else countChar(str, i, j - 1, ch, cnt);; // all one line


let occFromIth(str, i, ch) = if (i >= String.length str) then 0 else countChar(str, i, (String.length str) - 1, ch, 0);; // all one line


//WANT something like:

let rec countChar(str, i, j, ch, cnt) = if j < i 
    then cnt 
    else if isIthChar(str, j, ch) 
    then countChar(str, i, j - 1, ch, cnt   1) 
    else countChar(str, i, j - 1, ch, cnt);;

let occFromIth(str, i, ch) = if (i >= String.length str) 
    then 0 
    else countChar(str, i, (String.length str) - 1, ch, 0);;

// but these give syntax errors.


(* 2.5 Declare the F# function occInString: string * char -> int where

occInString(str, ch) = the number of occurences of a character ch in the string str.

Hansen, Michael R.. Functional Programming Using F# (p. 39). Cambridge University Press. Kindle Edition. *)

let occInString(str, ch) = occFromIth(str, 0, ch)
  

Ответ №1:

Форматирование: then и else должно быть как минимум таким же правым, как и их предыдущее if , но в обоих ваших случаях они находятся слева от него. Просто переместите if на следующую строку:

 let rec countChar(str, i, j, ch, cnt) = 
    if j < i 
    then cnt 
    else if isIthChar(str, j, ch) 
    then countChar(str, i, j - 1, ch, cnt   1) 
    else countChar(str, i, j - 1, ch, cnt)
  

Также обратите внимание, что двойная точка с запятой не требуется, если код находится в fsx файле, а не вводится в FSI с клавиатуры.


Порядок объявления: в отличие от Haskell, в F # все имена должны быть определены до их использования, поэтому ваша программа читается сверху вниз. На первый взгляд это может показаться ограничивающим, но на практике это творит чудеса с удобочитаемостью кода.

Исключением из этого правила является группа взаимно рекурсивных функций (или типов):

 let rec f x = g (x 1)
and g x = f (x-1)
  

В этом примере g используется до его определения.

Недавно в F # также появились рекурсивные модули, внутри которых все определения считаются одной большой рекурсивной группой:

 module rec A =
  let f x = g (x 1)
  let g x = f (x-1)
  

Несколько замечаний, не связанных строго с вашими вопросами:

  • else if может быть сокращено elif
  • Хотя параметры можно определить как кортеж countChar(str, i, j, ch, cnt) , обычно (и на практике гораздо удобнее) определять их в сокращенной форме countChar str i j ch cnt

Комментарии:

1. Спасибо! Ваш ответ был ОЧЕНЬ полезен.