2015-01-26 4 views
0

Я пишу кое-что очень простое, программа, которая находит все факторы int. Вот что у меня естьНазначение: ожидается, что это выражение будет иметь тип типа

let factor n= 
    let ls=[] 
    for i=1 to n do 
    if i % n =0 then ls = i::ls 
    l 

Если я это сделаю, то появляется сообщение об ошибке. Это выражение должно было иметь тип единицы. Но я попытался выставить выражение, которое печатает что-то после if..then .., которое, как предполагается, возвращает тип единицы, но оно все равно дает ту же ошибку. Я проиграл об этом. Может кто-нибудь помочь, пожалуйста? Thanks

ответ

2

Вы пытаетесь сделать ls в изменяемую переменную nd, присвоив ее =. Хотя это возможно, используя mutable(1) или ref(2) вместе с <- или := операторами присваивания, это обычно обескураживает в функциональном мире.
возможно более идиоматичен реализация алгоритма наивным может быть:

let factor n = 
    let rec factorLoop curr divs = 
     if curr > n then divs 
     else 
      if n % curr = 0 
      then factorLoop (curr+1) (curr::divs) 
      else factorLoop (curr+1) divs 
    factorLoop 1 [] |> List.rev 

> factor 12;; 
val it : int list = [1; 2; 3; 4; 6; 12] 

Здесь главная функция определяет внутреннюю factorLoop функцию, которая является рекурсивным. Рекурсия - это способ избежать многих видов использования изменяемых переменных в функциональных языках. Рекурсивная внутренняя функция выполняет потоки по переменной curr, которая является текущим делителем, подлежащим тестированию, и списком divs найденных в настоящее время делителей. Результат включает 1 и n. Это может быть изменено соответственно путем изменения начального значения curr и условия завершения в первой строке factorLoop.

Стоит отметить, что все это может быть уменьшено до одной линии путем использования F # библиотеки:

let factor n = 
    [1..n] |> List.filter (fun x -> n % x = 0) 

Здесь мы строим список значений 1..n и кормить их List.filter которая относится данный предикат (в конце строки) для выбора только делителей на n. Однако, если n большой, список темпов будет очень большим. Мы можем использовать лениво оцененную последовательность вместо этого, что не будет дуть использование памяти:

Здесь мы фильтруем на «ленивой» последовательности и только конвертировать (намного меньше) последовательность результатов в списке на end:

> factor 10000000;; 
val it : int list = 
    [1; 2; 4; 5; 8; 10; 16; 20; 25; 32; ... etc 
1

= сравнение, не предназначение. Вы хотите, либо

let factor n = 
    let mutable ls = [] 
    for i = 1 to n do 
     if n % i = 0 then ls <- i::ls 
    ls 

или

let factor n = 
    let ls = ref [] 
    for i = 1 to n do 
     if n % i = 0 then ls := i::(!ls) 
    !ls 

Заметим, однако, что оба эти решения являются весьма unidiomatic, поскольку одинаково легко неизменные решения этой проблемы.

+0

Я бы добавил, что эти функции не решают проблему, они эквивалентны 'let factor n = [if n> = 0, а затем дают n]'. Вычисление по модулю неверно, как в вопросе, так и в этом ответе. – Vandroiy

+1

@ Vandroiy: Этот ответ отвечает на вопрос, который был действительно задан, что касается ошибки синтаксиса. ОП не просил об эффективном способе разложения числа. ; -] – ildjarn

Смежные вопросы