?

Log in

No account? Create an account
Нэцкэ

Выделение из списка

В хаскелле первые элегантных конструкции, которые встречаются новичку -- это операции со списками значений. Например выделение из списка1 (list comprehension, варианты перевода на русский разнятся): взять из множества значения, удовлетворяющие некоторому условию (предикату) и произвести некоторые действия.

И правда, выглядит красиво -- предикат (x*2 >= 12), список ([1..10]), лямбда-функция (x*2):
ghci>[x*2 | x <- [1..10], x*2 >= 12]  
[12,14,16,18,20]  



Красиво! Однако, оказывается, и в новом JS есть такие же конструкции:
var range = function(start,end){for (var i=start; i<=end; i++) yield i}
var s = [2*i for (i in range(0,100)) if (i*i>3)]


Или даже, еще симпатичнее:
Number.prototype.__iterator__=function(){for (var i=0; i<this; i++) yield i}
var s = [2*i for (i in 101) if (i*i>3)]


Обзор того, как делают такие операции имеется в википедии:
http://en.wikipedia.org/wiki/List_comprehension

В питоне такие конструкции называются генераторами.


Очень печально этот прием выглядин на Си++:
#include <algorithm>
#include <list>
 
int linspace() { static int i=1; return i++; }
bool sqrle3(int x) { return x*x <= 3; }
void into2(int &x) { x*=2; }
 
int main()
{
  list<int> N1(10), N2(10);  
      // N1 and N2 are both empty lists of 10 elements each
  generate_n(N1.begin(), 10, linspace);
      // N1 now contains 1,2,...,10
  for_each(N2.begin(),
     remove_copy_if(N1.begin(), N1.end(), N2.begin(), sqrle3),
     into2);
      // N2 now contains 4,6,...,20
}


Однако библиотека Boost.Range позволяет выразиться не хуже других:
counting_range(1,10) | filtered( _1*_1 > 3 ) | transformed(ret<int>( _1*2 ))


Полный пример тут.




1Термин происходит из аксиомы выделения из множества: Из каждого множества можно выделить [по меньшей мере одно] подмножество, высказав суждение о каждом элементе данного множества.

Tags: , , ,

Comments

Ну есть они ещё в FC++ с синтаксисом, почти как в х-е. Должны перейти к Phoenix 3, когда выйдет.
Common Lisp:
~~~~~~~~~~~
(remove-if
...(lambda (x)
......(<= 12 (* 2 x)))
...'(1 2 3 4 5 6 7 8 9 10))
~~~~~~~~~~~
Кажется еще более красиво и понятно - разве нет?
ну, скажем, не хуже :)
просто ЛИСП я пока даже не нюхал ....
аромат божественный - рекомендую