Y a-t-il une alternative pour la construction de F # "SEQ" dans Erlang? Par exemple, dans F # Je peux écrire une fonction O (1) Mémoire Intégration de la fonction
create(Dx, N)->[0| create(Dx, N,[])]. create(Dx, 0, Init)->Init; create(Dx, N, Init)->create(Dx,N-1, [Dx*N |Init]). integral(X1,X2,Dx, F) -> N=trunc((X2-X1)/Dx), Points = create(Dx,N), Vals = lists:map(fun(X)->F(X)*Dx end, Points), lists:sum(Vals).
4 Réponses :
Ceci n'est pas testé, mais est une façon de le faire.
L'idée est de transformer la liste en un processus qui donne la valeur suivante lorsqu'il est demandé. Vous pouvez facilement généraliser l'idée si vous avez besoin de le faire. P>
Alternativement, vous pouvez écrire un déroulement qui peut ensuite déplier la liste un peu à la fois et l'utiliser comme entrée sur le processeur générique. P>
Autre moyen est de mettre en place des flux paresseux, Basé sur l'idée que tout La solution basée sur le retard / la force est quelque chose comme: p> mais non testé. p> p> expr code> peut être retardé par
amusement () -> expr fin code> peut-être mieux écrit comme
-define (retard (x), amusant () -> x fin). Code> comme macro puis utilisé avec
-define (force (x), x ()). Code> p>
Beaucoup trop compliqué ... La multithreading est une étape plus loin. Pour savoir que je préférerais avoir la solution la plus simple possible.
Si vous le nettoyez un peu, ce n'est pas compliqué. La majeure partie de la structure peut être hissée dans une bibliothèque. En outre, il a la valeur ajoutée qu'il peut produire des valeurs parallèlement à votre calcul, ce qui est bon pour certains problèmes. Cependant, j'ai ajouté l'idée de retard / force pour faire des flux explicites.
Disclaimer: Les éléments suivants sont écrits sous l'hypothèse que Erlang ignore la mutation complètement, dont je ne suis pas sûr, car je ne sais pas assez bien Erlang. em> seq est mutation basé. Il maintient «l'état actuel» et la mute sur chaque itération. Donc, lorsque vous faites une itération, vous obtenez la "valeur suivante", mais vous obtenez également un effet secondaire, c'est que l'état interne de l'énumérateur a changé et lorsque vous effectuez une prochaine itération, vous obtiendrez une "valeur suivante" différente. , etc. Ceci est généralement gentiment recouvert de complètes de la recherche fonctionnelle, mais si vous avez déjà travaillé avec Une autre façon de Pensez-y, étant donné une "séquence", vous obtenez deux résultats: "valeur suivante" et "reste de séquence", puis "reste de séquence" devient votre nouvelle "séquence", et vous pouvez répéter le processus. (et la "séquence" originale est partie pour toujours) p> Cette ligne de pensée peut être directement exprimée en F #: p> Signification: "Une séquence paresseuse est une fonction qui, lorsqu'elle est appliquée, renvoie sa tête et sa queue, où la queue est une autre séquence paresseuse ». Mais alors, voyant comment les séquences sont généralement finies, tout devrait être facultatif: p> donné cette définition, vous pouvez faire de manière triviale des constructeurs: p> carte et pli sont également triviaux: p> et de Voici comment l'utiliser: P> ienumerator code> directement, vous verrez la non-pureté avec un œil nu. P>
myseq de code> est inclus pour garder le type de devenir infini.
(Désolé, je vais utiliser f #, je ne sais pas assez bien Erlang; je suis sûr que vous pouvez traduire) p> pli code> Vous pouvez tout construire, ce qui n'est pas une séquence paresseuse elle-même. Mais pour construire des séquences paresseuses, vous avez besoin d'un "pli roulant" (parfois appelé "scan"): p>
1> c(seq).
{ok,seq}
2> FiveTwos = seq:repeat(5,2).
#Fun<seq.2.133838528>
3> Doubles = seq:map( fun(A) -> A*2 end, FiveTwos ).
#Fun<seq.3.133838528>
5> seq:fold( fun(S,A) -> S+A end, 0, Doubles ).
20
6> seq:fold( fun(S,A) -> S+A end, 0, FiveTwos ).
10
11> seq:count( FiveTwos ).
5
Merci de l'aide, mais votre code ne compile pas sous VS 2012. Dans "Certains (A, répétez (N-1) a)" ou "Certains (a, infinis a)" il se plaint: MisMatch de type. S'attendant à une option "A mais donné une unité -> (" B * "A), le type résultant serait infini lorsqu'unification" A "" et "Unité" -> ("B *" A) " code> malheureusement je Connaître Erlang pour environ 3 heures, donc je ne sais pas comment traduire la majeure partie de cela, surtout quand je ne peux pas le regarder courir.
@Jacekgajek, tu dois me pardonner pour un code non compilateur, je le tapitais sur mon téléphone à l'époque. Je pensais que l'idée devrait être suffisamment claire par elle-même et ne comprenait que le code d'illustration. J'ai remplacé tous les exemples avec le code vérifié correct.
@Jacekgajek J'ai également produit une version erlang maintenant, n'hésitez pas à l'utiliser pour référence.
Le moyen le plus populaire de créer un traitement stable de la mémoire consiste à définir la fonction récursive de la queue. Par exemple: mais ça n'a pas l'air clair ... J'avais le même problème une fois et j'ai fait Helper court Malheureusement, il est un peu plus lent que direct Récursion: p> pour code> fonction
qui vous permet d'itérer sans listes: p> benchmark() ->
X1 = 0,
X2 = math:pi(),
DX = 0.0000001,
F = fun math:sin/1,
IntegrateFuns = [fun integrate_rec/4, fun integrate_for/4],
Args = [X1, X2, DX, F],
[timer:tc(IntegrateFun, Args) || IntegrateFun <- IntegrateFuns].
> [{3032398,2.000000000571214},{4069549,2.000000000571214}]
J'aime l'expression concise, c'est pourquoi je propose une solution de quatrième solution (définie dans la coquille, mais il devrait être facile de s'adapter à un module):