Para responder a su pregunta en primer lugar, el compilador se queja de que hay un problema dentro del bucle for
. En F #, let
sirve para declarar valores (que son inmutables y no pueden ser modificados más adelante en el programa). No es una declaración como en C# - let
solo se puede usar como parte de otra expresión. Por ejemplo:
let n = 10
n + n
en realidad significa que desea que el símbolo n
para referirse al valor 10
en la expresión n + n
. El problema con el código es que usted está utilizando let
sin ningún tipo de expresión (probablemente debido a que desea utilizar variables mutables):
for x in seq_ do
let list_ = list_ @ [x] // This isn't assignment!
list_
la línea problemática es una expresión incompleta - let
utilizando de esta manera no se permite , porque no contiene ninguna expresión (no se accederá al valor list_
desde ningún código). Puede utilizar mutable
variable para corregir su código:
let mutable list_ = [] // declared as 'mutable'
let seq_ = seq { for x in 1..n do if x % 2 <> 0 then yield List.nth l (x-1)}
for x in seq_ do
list_ <- list_ @ [x] // assignment using '<-'
Ahora bien, esto debería funcionar, pero en realidad no es funcional, porque usted está utilizando la mutación imprescindible. Además, agregar elementos usando @
es algo realmente ineficiente en lenguajes funcionales. Por lo tanto, si desea que su código sea funcional, probablemente necesite usar un enfoque diferente. Ambas respuestas muestran un gran enfoque, aunque prefiero el ejemplo de Joel, porque la indexación en una lista (en la solución de Chaos) tampoco es muy funcional (no hay aritmética de puntero, por lo que también será más lenta) .
Probablemente la solución funcional más clásico sería el uso de la función List.fold
, que agrega todos los elementos de la lista en un único resultado, caminando desde la izquierda a la derecha:
[1;2;3;4;5]
|> List.fold (fun (flag, res) el ->
if flag then (not flag, el::res) else (not flag, res)) (true, [])
|> snd |> List.rev
Aquí, el estado usa durante la agregación hay una bandera booleana que especifica si se debe incluir el siguiente elemento (durante cada paso, volteamos la bandera al devolver not flag
). El segundo elemento es la lista agregada hasta el momento (agregamos elemento por el::res
solo cuando se establece flag
. Después de que fold
regresa, usamos snd
para obtener el segundo elemento de la tupla (la lista agregada) y revertirlo usando List.rev
, porque se recolectó en el orden inverso (esto es más eficiente que agregarlo al final usando [email protected][el]
).
Tamaño de la lista = 1000; Iteraciones = 100; Resultado (ChaosPandion) = 4200ms; Resultado (Joel Mueller) = 150 ms; – ChaosPandion
¿Qué tal el enfoque 'List.fold' de Tomás? –
Llegó a unos 135ms. – ChaosPandion