javascript - ecmascript 6 support
Iterando con el bucle while en lugar de para el bucle (4)
¿Te gustaría algo como esto?
var sequence = fibonacci();
var value;
while ((value = sequence.next()) < 1000) {
console.log(value);
}
Además, tal vez incluso una solución mejor sería algo como:
function* fibonacci(limit){
let previous = 0;
let current = 1;
while(previous + current < limit) {
let temp = previous;
previous = current;
yield current = temp + current;
}
}
for(let value of fibonacci(1000)) {
console.log(value);
}
ECMAScript 6 presenta generadores, iteradores y sintaxis de azúcar para iteración. Node.JS v0.11.4 con las banderas
--harmony --use_strict --harmony_generators
entiende el siguiente generador
function* fibonacci() {
let previous = 0;
let current = 1;
while(true) {
let temp = previous;
previous = current;
yield current = temp + current;
}
}
Entonces puedo imprimir los números de Fibonacci menos de 1000.
for(let value of fibonacci()) {
if(value > 1000) { break; }
console.log(value);
}
Para este ejemplo, un bucle while en lugar de un bucle for
sería más natural, similar a
while(value of fibonacci() < 1000) {
console.log(value);
}
¿Se puede realizar una iteración de iteradores con un bucle while en lugar de un bucle for
?
Hay dos formas posibles de continuar con esto, dados otros idiomas que admiten este comportamiento:
1) Uno que usa proxies de Harmony, que le permitiría hacer metacuadros (algo así como lua ) y permitir iterables perezosos. Esto proporcionaría la siguiente notación:
var arr = ...; // create the resource
for(var i=0;arr[i]<1000;i++){
arr[i]; // consume fibonacci numbers
}
2) El segundo con una función de take
que le permite consumir un iterable con .forEach
como en C # o python . Lo que permitiría la siguiente notación:
takeWhile(fibGenerator,(item) => item<1000).forEach(... // consume with predicate
Primer acercamiento - usando proxies de armonía
Nota ... for of
bucles a través de objetos. No garantiza el orden en absoluto. Sin embargo, puede hacer algo como lo siguiente para obtener la idea de una iteración perezosa.
--harmony_generators
ejecutar el nodo con los indicadores --harmony_generators
y --harmony_proxies
:
var arr = ...; // create an array and proxy it, use a generator internally
arr[50]; // will calculate the 50th fibonacci element and return it.
arr[100];// will calculate the 100th fibonacci element and return it.
for(var i=0;arr[i]<1000;i++){
arr[i];//the i-th fibonacci number
}
Sólo calculará los números que aún no se han recuperado, esto le permitirá utilizar un bucle for
simple.
Aquí es cómo*:
var cache = [];
var handler = {
get: (function(){
function fibIterator(){
var t=0,a=0,b=0;
return function(){
t=a;
a+=b;
b=t;
return a;
}
}
var iterator = fibIterator();
return function (target, fibNumber) {
if (name in cache) {
return cache[name];
}
while(iterator < fibNumber){
// update indexes.
}
})()
}
};
var arr = Proxy.create(handler);
(Simplemente no esperes que sea muy rápido)
* (usando la notación de proxy anterior, ya que la nueva aún no es compatible con el nodo, se actualizará una vez que reciba soporte)
Nota al margen, en JavaScript, ya que las funciones pueden tener un estado interno a través de cierres, ni siquiera necesitas un generador.
Segundo enfoque, utilizando un iterador Take
función.
Esto es lo que normalmente haría en idiomas como C # para este caso de uso.
function takeWhile(generating, predicate){
var res = [],last;
do{
res.push(last=generating())
}while(predicate(last));
return res;
}
Entonces haz algo como
var res = takeWhile(fibIterator,function(item){
return item<1000;
});
res.forEach(function(){ ...
O por cuenta:
function take(generating,numToTake){
var res = [],num;
do{
res.push(last=generating())
}while(num++ < numToTake);
return res;
}
var res = take(fibIterator,1000);//first 1000 numbers
Sí, es posible hacer esto usando los métodos de generador regulares.
var fib = fibonacci(), value;
while( (value = fib.next()) < 1000 ) {
console.log(value);
}
Aunque parece que prefiero la instrucción for...of
que se encarga de manejar esas próximas llamadas y tratar con StopIteration
(si la secuencia es finita).
function *bar(){
yield 1;
yield 2;
yield 3;
return 4;
}
var value,
g = bar();
while((value = g.next()).value){
console.log(value);
}
//Object {value: 1, done: false}
//Object {value: 2, done: false}
//Object {value: 3, done: false}
//Object {value: 4, done: true}