2016-04-11 4 views
3

У меня есть рекурсивная функция в f #, которая выполняет итерацию строки [] команд, которые нужно запустить, каждая команда запускает новую команду для создания карты, которая будет передана следующей функции.форматирование Композитная функция в f #

Команды выполняются правильно, но являются большими и громоздкими для чтения, я считаю, что есть лучший способ упорядочить/форматировать эти составные функции, используя синтаксис труб, однако, исходя из C#, поскольку многие из нас делают для меня жизнь похоже, не может заставить его работать.

моя команда:

let rec iterateCommands (map:Map<int,string array>) commandPosition = 
    if commandPosition < commands.Length then 
     match splitCommand(commands.[0]).[0] with 
     |"comOne" -> 
      iterateCommands (map.Add(commandPosition,create(splitCommand commands.[commandPosition])))(commandPosition+1) 

Ближайший я сумел это углубленными функцию, но это неаккуратно:

iterateCommands 
(map.Add 
    (commandPosition,create 
     (splitCommand commands.[commandPosition]) 
    ) 
) 
(commandPosition+1) 

Возможно ли это переформатировать это в F #? Из того, что я прочитал я считаю, это возможно, любая помощь будет принята с благодарностью

The command/variable types are: 
commandPosition - int 
commands - string[] 
splitCommand string -> string[] 
create string[] -> string[] 
map : Map<int,string[]> 

и конечно map.add карты -> карта + х

+0

Просьба поделиться определениями функций, которые вы хотите скомпоновать, или, по крайней мере, их типов. –

+0

Я отредактировал свой ответ, чтобы включить типы всех функций и переменных –

ответ

2

Было бы немного проще составить вызов, если вы изменили аргументы вокруг:

let rec iterateCommands commandPosition (map:Map<int,string array>) = 
    // ... 

Это позволит вам написать что-то вроде:

splitCommand commands.[commandPosition] 
|> create 
|> (fun x -> commandPosition, x) 
|> map.Add 
|> iterateCommands (commandPosition + 1) 

Тот факт, что commandPosition появляется трижды в композиции, на мой взгляд, запах дизайна, как и тот факт, что тип всего этого выражения равен unit. Это не выглядит особенно функциональным, но поскольку я не понимаю, что именно делает эта функция, я не могу предложить лучший дизайн.

Если вы не контролируете iterateCommands, и, следовательно, не может изменить порядок аргументов, вы всегда можете определить стандартную функцию полезности функционального программирования:

let flip f x y = f y x 

Это позволяет написать следующее против оригинальная версия iterateCommands:

splitCommand commands.[commandPosition] 
|> create 
|> (fun x -> commandPosition, x) 
|> map.Add 
|> (flip iterateCommands) (commandPosition + 1) 
+0

Спасибо, что это было именно то, что я был после =) iterateCommands проходит через каждую команду, выполняющую функции на переданной карте, и как только все команды завершаются текстовым файлом и приложение заканчивается. Я не считал, что функция iterateCommands требовала что-то другое, кроме элемента unit, как только функция будет завершена, выйдет из приложения, вы бы порекомендовали изменить это в любом случае, в настоящее время вызов функции iserateCommands Map.empty 0 скоро будет iterateCommands 0 Map. пусто? –

+1

@Matthewkingston Правильно, если это «верхняя» функция, «единица» - это совершенно прекрасный тип возврата. Виноват. –

3

Это часто бывает трудно понять, что происходит в большом заявлении с несколькими входами. Я бы дал имена отдельным выражениям, чтобы читатель мог перейти в любую позицию и иметь приблизительное представление о том, что находится в значениях, используемых при вычислении, например.

let inCommands = splitCommand commands.[commandPosition] 
let map' = map.Add (commandPosition, inCommands) 
iterateCommands map' inCommands 

Поскольку я не знаю, что здесь делается, имена не очень значимы. В идеальном случае они помогут понять отдельные этапы расчета.