¿Es esta una implementación razonable de la función de Bézier cuadrática en OCaml?
Pregunta
Un amigo se encontró con una función de curva de B y # 233; cuadrática en su base de código que usaba un nido de ratas gigantescas de una tabla de interruptores para realizar el cálculo. Me desafió a encontrar una expresión corta y única que le permitiera reemplazar el bloque de código gigantesco.
Al intentar satisfacer dos curiosidades diferentes, pensé que intentaría implementar la función en OCaml. Soy un programador OCaml muy novato y tampoco estoy familiarizado con la función y esta implementación específica es difícil de conseguir a través de Google.
Las críticas sobre el rendimiento / corrección de la función, así como su implementación, son muy apreciadas.
Implementación de Quadratic B & # 233; zier Curve :
let rec b2 n =
let p1 = -10. in
let p2 = 10. in
let q = n*.n in
let rec b2i n i hd =
if i > n then
List.rev hd
else
let t = i /. n in
b2i n (i+.1.) ((((1.-.t)**2.)*.p1+.(2.*.t*.(1.-.t)*.q)+.(t**2.)*.p2) :: hd)
in b2i n 0. []
;;
let floatprint lst = List.iter (fun f -> Printf.printf "%f; " f) lst ;;
floatprint (b2 8.);;
Solución
b2 no es recursivo, por lo que no es necesario [vamos a rec b2 n =]. Dado que n nunca cambia, no es necesario tenerlo como argumento para b2i, solo use n del ámbito que lo incluye. Su función interna debe depender de p0, p1 y p2, pero la veo dependiendo de -10., N ** 2 y 10. La función también tiene la forma de un mapa de [0.0; 1.0; 2.0; ...; n.0] a los valores finales. Podrías escribirlo:
let b i =
let t = i /. n in
let tminus = (1.-.t) in
(tminus *. tminus *. p0) +. (2. *. t *. tminus *. p1) +. (t *. t * p2)
in
List.map b ([generate list 1.0; 2.0; ... n.0])
Una función para generar la lista 1.0 ... n.0 podría ser: (para n pequeña)
let rec count m n = if m > n then [] else m :: (count (m+.1.) n)
Otros consejos
Tengo dos sugerencias:
Debería llamar a List.rev
después de que b2i
regrese para que ocaml pueda explotar sus optimizaciones de recursión de cola. No estoy seguro de qué tan bien tratará Ocaml con la implementación actual, aunque List.rev
es recursivo. Notarás que en esta publicación se hace como que.
Además, puede hacer que la resolución de la iteración sea un argumento opcional como ? (epsilon = 0.1)
.
Como programador de Ocaml, no veo mucho mal aquí aparte de eso, siempre y cuando P1 y P2 sean en realidad constantes. Compílelo y vea cuál es la diferencia en el ensamblaje al mover List.rev dentro o fuera de la recursión de la cola.
Esto puede ser picayune, pero hd
no es un buen nombre para un parámetro de lista. List.hd
es una función estándar que devuelve el primer elemento de una lista. El uso de hd
como nombre para una lista dará lugar a confusión.