Я думаю, что простая реализация с использованием списков и рекурсии была бы проще в этом случае. Альтернативная реализация класса Polynomial
может выглядеть примерно так:
// The type is immutable and takes initial list as constructor argument
type Polynomial(coeffs:float list) =
// Local recursive function implementing the addition using lists
let rec add l1 l2 =
match l1, l2 with
| x::xs, y::ys -> (x+y) :: (add xs ys)
| rest, [] | [], rest -> rest
member self.Coefficients = coeffs
static member (+) (v1:Polynomial, v2:Polynomial) =
// Add lists using local function
let newList = add v1.Coefficients v2.Coefficients
// Wrap result into new polynomial
Polynomial(newList)
Стоит отметить, что вам действительно не нужно изменяемое поле в классе, поскольку оператор +
создает и возвращает новый экземпляр типа, поэтому тип является полностью неизменяемым (как обычно требуется в F #).
Приятной особенностью функции add
является то, что после обработки всех элементов, доступных в обоих списках , вы можете просто вернуть хвост непустого списка в качестве остальных.
Если вы хотите реализовать ту же функциональность с использованием массивов, то может быть лучше использовать простой цикл for
(поскольку массивы, в принципе, являются императивными, обычные императивные шаблоны обычно являются лучшим вариантом для работы с ними ). Однако я не думаю, что есть какая-то конкретная причина для предпочтения массивов (возможно, производительности, но это должно быть оценено позже во время разработки).
Как указывает Павел, оператор ::
добавляет один элемент в начало списка (см. Выше функцию add
, которая демонстрирует это). Вы можете написать то, что хотели, используя @
, который объединяет списки, или Array.concat
(который объединяет последовательность массивов).
Возможна также реализация с использованием функций и массивов высшего порядка - лучшая версия, которую я могу придумать, будет выглядеть так:
let add (a1:_[]) (a2:_[]) =
// Add parts where both arrays have elements
let l = min a1.Length a2.Length
let both = Array.map2 (+) a1.[0 .. l-1] a2.[0 .. l-1]
// Take the rest of the longer array
let rest =
if a1.Length > a2.Length
then a1.[l .. a1.Length - 1]
else a2.[l .. a2.Length - 1]
// Concatenate them
Array.concat [ both; rest ]
add [| 6; 5; 3 |] [| 7 |]
При этом используются слайсы (например, a.[0 .. l]
), которые дают вам часть массива - вы можете использовать их, чтобы взять части, где оба массива имеют элементы, а оставшуюся часть длинного массива. 1029 *