#sml #smlnj
#sml #smlnj
Вопрос:
В настоящее время я использую что-то вроде этого в одной из своих функций: (все переменные используются с более сложными функциями, но для того, что я буду спрашивать, это не имеет значения, и я упрощаю)
fun RecursiveCall (p, q, r, s) =
let
val (ra, rb, rc) = returnResult (p, q, s)
in
RecursiveCall (p, ra, rb, rc)
end
Как я могу написать это более коротким и (возможно) более приятным способом? То есть, как я могу извлечь элементы кортежа, который был возвращен из функции, и передать их в качестве аргументов другого кортежа?
Примечание: можно было бы также написать просто RecursiveCall (p, #1 (returnResult (p, q, s)) , #2 (returnResult (p, q, s)), #3 (returnResult (p, q, s)))
, но (вероятно) это в некоторых случаях приведет к тому, что одно и то же будет выполняться три раза, т.Е. returnResult .
Ответ №1:
Очень сложно сказать что-то общее, не зная о вашей реальной проблеме, но вы могли бы сгруппировать последние три элемента кортежа вместе (похоже, что они являются единым целым), например
fun RecursiveCall p (q, r, s) = RecursiveCall p (returnResult (p, q, s))
Комментарии:
1. Нет, в целом это не так. Я не прошу о какой-либо конкретной проблеме, только если в SML / NJ существует общее предложение.
Ответ №2:
(p, #1 (returnResult (p, q, s)), #2 (returnResult (p, q, s)), #3 (returnResult (p, q, s)))
это […] приведет к тому, что одно и то же будет выполняться три раза
Да, это верно. И это также более подробно, чем ваше первоначальное предложение.
Вы также можете написать, например
case returnResult (p, q, s) of
(ra, rb, rc) => recursiveCall (p, ra, rb, rc)
в качестве альтернативы let-in-end.
Вы могли бы создавать функции и использовать returnResult
recursiveCall
uncurry3
:
fun curry3 f x y z = f (x, y, z)
fun uncurry3 f (x, y, z) = f x y z
fun returnResult p q s = (p 1, q 2, s 3)
fun recursiveCall p q r s =
uncurry3 (recursiveCall p) (returnResult p q s)
Здесь, recursiveCall p
частично применяется к одному из его четырех аргументов, что делает его функцией, которая принимает три аргумента curried. uncurry3 (recursiveCall p)
таким образом, становится функцией, которая принимает 3-кортеж, что является точным результатом returnResult p q s
.
Этот метод основан на порядке аргументов, которые удобно сочетаются друг с другом.
Но я думаю, что это признак returnResult
возврата слишком многих вещей.
В идеале функции возвращают то, что, как предполагает их название, оно вычисляет.
Возможно, некоторые из выполняемых вычислений returnResult
можно разделить на несколько функций, или, возможно, они действительно представляют собой одно целое и должны быть обернуты в общий тип данных, или, возможно p
, q
и s
лучше передаются как неявные аргументы монады чтения / состояния. У меня нет хорошего примера того, как последнее выглядит в ML, но я также не могу сказать, чего требует ситуация, поскольку код гипотетический.
Комментарии:
1. Ну, поскольку некоторые предварительно вычисленные структуры существуют и находятся в структурах данных ra, rb, rc, я думал о том, чтобы снова воспользоваться ими, а не повторно вычислять, поскольку они действительно могут найти применение в другой функции.