Funny JS - Это серия встреч для фронтэнд-разработчиков и не только. Я не буду читать лекцию или проводить тренинг. Мы будем общаться в живом формате и разбирать интересные и необычные задачи из мира JS, которые помогут лучше разобраться в теме и повысить скиллы. На первом митапе обсудим, что круче: функциональное программирование или объектно-ориентированный подход, прототипное или классическое наследование, ES6 или ES5
Чем могут быть полезны регулярные выражения для разработчика интерфейсов? О каких возможностях следует знать больше? Где находятся «подводные камни» и как обойти их в различных реализациях? И, наконец, что делать, если возможностей встроенной реализации регулярных выражений недостаточно?
В лекции подробно рассмотрены тонкие моменты языка JavaScript, с которыми часто возникают основные проблемы. Наглядные примеры и рецепты помогают лучше понять его особенности.
Шаблоны C++ и базы данных. Сергей Федоров. CoreHard Spring 2019corehard_by
Рассказ о проектировании и реализации драйвера PostgreSQL с человеческим интерфейсом с применением почти всех доступных на данный момент языковых средств C++17. Когда мы работаем с БД, мы зачастую получаем сырые буферы, в то время как хочется получать данные в виде структур, классов и контейнеров C++. Рассказ о проектировании и реализации драйвера PostgreSQL с человеческим интерфейсом с применением почти всех доступных на данный момент языковых средств C++17. Описанный в докладе подход можно адаптировать практически к любому протоколу уровня приложений.
Funny JS - Это серия встреч для фронтэнд-разработчиков и не только. Я не буду читать лекцию или проводить тренинг. Мы будем общаться в живом формате и разбирать интересные и необычные задачи из мира JS, которые помогут лучше разобраться в теме и повысить скиллы. На первом митапе обсудим, что круче: функциональное программирование или объектно-ориентированный подход, прототипное или классическое наследование, ES6 или ES5
Чем могут быть полезны регулярные выражения для разработчика интерфейсов? О каких возможностях следует знать больше? Где находятся «подводные камни» и как обойти их в различных реализациях? И, наконец, что делать, если возможностей встроенной реализации регулярных выражений недостаточно?
В лекции подробно рассмотрены тонкие моменты языка JavaScript, с которыми часто возникают основные проблемы. Наглядные примеры и рецепты помогают лучше понять его особенности.
Шаблоны C++ и базы данных. Сергей Федоров. CoreHard Spring 2019corehard_by
Рассказ о проектировании и реализации драйвера PostgreSQL с человеческим интерфейсом с применением почти всех доступных на данный момент языковых средств C++17. Когда мы работаем с БД, мы зачастую получаем сырые буферы, в то время как хочется получать данные в виде структур, классов и контейнеров C++. Рассказ о проектировании и реализации драйвера PostgreSQL с человеческим интерфейсом с применением почти всех доступных на данный момент языковых средств C++17. Описанный в докладе подход можно адаптировать практически к любому протоколу уровня приложений.
Zeta function for perturbed surfaces of revolutionPedro Morales
Here we explore the Zeta function arising from a small perturbation on a surface of revolution and the effect of this on the functional determinant and in the change of the Casimir energy associated with this configuration.
SINOLAM engaged in producing and export of main laminated heat insulated materials, including aluminum foil jackets and aluminum foil tape which usually be used in construction of wall, roof, pipe, loft, cavity, attic, ductwork insulation and HVAC system.
AZIMUT Azimut 46, 1997, 199.000 € For Sale Brochure. Presented By azimut-yach...Azimut Yacht Club
Category: Motoryacht with cockpit, Condition: Pre-owned, Seller Type: Yacht Broker, AZIMUT, Azimut 46, Year: 1997, LOA: 13m 8, Engine: Caterpillar, Diesel
Provence Côte D'azur, France
For Sale Brochure. Presented By azimut-yachtclub.com. Visit our site for more information http://www.azimut-yachtclub.com
distance learning correspondence course in rohini, distance learning correspondence course bachelor in arts hindi in rohini, distance learning correspondence course bachelor in arts english in rohini, distance learning correspondence course bachelor in arts economics in rohini, distance learning correspondence course bachelor in arts sanskrit in rohini, distance learning correspondence course bachelor in arts history in rohini, distance learning correspondence course bachelor in arts political science in rohini, distance learning correspondence course bachelor in arts sociology in rohini, distance learning correspondence course bachelor in arts hons (b.a.hons) in english in rohini, distance learning correspondence course bachelor in arts hons (b.a.hons) pol. science in rohini, distance learning correspondence course bachelor in arts hons (b.a.hons) sociology in rohini, distance learning correspondence course bachelor in arts hons (b.a.hons) home science in rohini, distance learning correspondence course bachelor in arts hons (b.a.hons) philosophy in rohini, distance learning correspondence course bachelor in arts
Zeta function for perturbed surfaces of revolutionPedro Morales
Here we explore the Zeta function arising from a small perturbation on a surface of revolution and the effect of this on the functional determinant and in the change of the Casimir energy associated with this configuration.
SINOLAM engaged in producing and export of main laminated heat insulated materials, including aluminum foil jackets and aluminum foil tape which usually be used in construction of wall, roof, pipe, loft, cavity, attic, ductwork insulation and HVAC system.
AZIMUT Azimut 46, 1997, 199.000 € For Sale Brochure. Presented By azimut-yach...Azimut Yacht Club
Category: Motoryacht with cockpit, Condition: Pre-owned, Seller Type: Yacht Broker, AZIMUT, Azimut 46, Year: 1997, LOA: 13m 8, Engine: Caterpillar, Diesel
Provence Côte D'azur, France
For Sale Brochure. Presented By azimut-yachtclub.com. Visit our site for more information http://www.azimut-yachtclub.com
distance learning correspondence course in rohini, distance learning correspondence course bachelor in arts hindi in rohini, distance learning correspondence course bachelor in arts english in rohini, distance learning correspondence course bachelor in arts economics in rohini, distance learning correspondence course bachelor in arts sanskrit in rohini, distance learning correspondence course bachelor in arts history in rohini, distance learning correspondence course bachelor in arts political science in rohini, distance learning correspondence course bachelor in arts sociology in rohini, distance learning correspondence course bachelor in arts hons (b.a.hons) in english in rohini, distance learning correspondence course bachelor in arts hons (b.a.hons) pol. science in rohini, distance learning correspondence course bachelor in arts hons (b.a.hons) sociology in rohini, distance learning correspondence course bachelor in arts hons (b.a.hons) home science in rohini, distance learning correspondence course bachelor in arts hons (b.a.hons) philosophy in rohini, distance learning correspondence course bachelor in arts
4. Cell / ctor
Реактивная переменная в warp9 может содержать какое-либо
значение или быть пустой, по умолчанию переменная
создается пустой.
var a = new C e l l ( ) ;
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
5. Cell / set
Для того чтобы положить в неё какое-либо значение
используется метод “set”
var a = new C e l l ( ) ;
a . set ( 42 ) ;
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
6. Cell / ctor(…)
Альтернатива - передать начальное значение в конструкторе
var a = new C e l l ( 4 2 ) ;
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
7. Cell / unset
В любой момент переменную можно сделать пустой
var a = new C e l l ( 4 2 ) ;
a . unset ( ) ;
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
8. Cell / unwrap
У переменной можно вызвать метод unwrap для того, чтобы
получить значение, которое она содержит
var a = new C e l l ( 4 2 ) ;
c o n s o l e . i n f o ( a . unwrap ( ) ) ;
// > 42
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
9. Cell / unwrap(…)
Если переменная была пустой - вылетит исключение, но
unwrap можно передать значение, которое следует вернуть,
если переменная пустая
c o n s o l e . i n f o ( new C e l l ( ) . unwrap ( 4 2 ) ) ;
// > 42
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
10. Cell / li
К существующей переменной можно применить функцию и
получить реактивную переменную, которая связана с первой
этой функцией: при изменении первой - автоматически
меняется вторая
var a = new C e l l ( ) ; // a is unset
var b = a . l i f t ( f u n c t i o n ( a ) {
r e t u r n a+2 ;
} ) ; // b is unset
a . s e t ( 1 ) ; // a contains 1, b contains 3
a . s e t ( 5 ) ; // a contains 1, b contains 7
a . u n s e t ( ) ; // a is unset , b is unset
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
11. Cell / li
Можно сказать, что для метода li выполняется
следующий закон
forall (f ,x) :
new C e l l ( x ) . l i f t ( f ) . unwrap ( ) == f ( x ) ;
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
12. Cell / li
У переменных полученных лифтингом (а врочем и любым
другим способом, кроме как вызовом конструктора Cell)
невозможно вызывать методы set, unset
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
13. Cell / coalesce
Еще один способо создать переменную - вызвать метод coalesce
и передать ему значение по умолчанию. Если исходная
переменная содержит какое-либо значение, то и новая
переменная будет его содержать, если исходная переменная
пустая, то новая переменная будет содержать значение по
умолчанию.
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
14. Cell / coalesce
var a = new C e l l ( ) ;
var b = a . c o a l e s c e ( 4 2 ) ; // b contains 42
a . s e t ( 1 3 ) ; // a contains 13, b contains 13
a . u n s e t ( ) ; // a is unset , b contains 42
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
15. Cell / isSet
Вызов isSet вернет реактивную переменную, которая содержит
true если исходная не пустая, и false в ином случае.
var a = new C e l l ( ) ;
var b = a . i s S e t ( ) ; // b has false
a . s e t ( 1 3 ) ; // a has 13, b has true
a . u n s e t ( ) ; // a is unset , b has false
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
16. Cell / when(…)
Другой способ создать переменную - вызвать метод when. Если
метод вызван с одним параметром, то параметр
рассматривается как фильтр. Если значение фильтра true, то
переменная будет содержать значение, совпадающее с
исходной, иначе переменная будет пустая.
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
17. Cell / when(…)
var a = new C e l l ( ) ;
var b = a . when ( f u n c t i o n ( a ) {
r e t u r n a >3 ;
} ) ; // b in unset
a . s e t ( 4 2 ) ; // a contains 42, b contains 42
a . s e t ( 4 ) ; // a contains 4, b contains 4
a . s e t ( 1 ) ; // a contains 1, b is unset
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
18. Cell / when
Если в качестве фильтра передать не функцию, то значение
исходной переменной будет сравниваться с “фильтром” на
равенство.
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
19. Cell / when(…, …)
Так же методу when можно передать два параметра: фильтр и
трансформер, в это случае трансформер будет применен к
значению исходной переменной, если фильтр вернул true.
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
20. Cell / when(…, …)
var a = new C e l l ( ) ;
var b = a . when (
f u n c t i o n ( a ) { r e t u r n a >3 ; } ,
f u n c t i o n ( x ) { r e t u r n x+1 }
) ; // b in unset
a . s e t ( 4 2 ) ; // a contains 42, b contains 43
a . s e t ( 4 ) ; // a contains 4, b contains 5
a . s e t ( 1 ) ; // a contains 1, b is unset
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
21. Cell / when(…, …)
На самом деле when с двумя аргументами практически
эквивалентен комбинации when и li
forall (f , t , cell ) :
c e l l . when ( f , t ) == c e l l . when ( f ) . l i f t ( t ) ;
Практически, потому что, как и в случае с одним параметром вместо фильтра и трансформера можно передать константы “фильтр’’ будет сравниваться с значением исходной
переменной, а “трансформер’’ вернет себя
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
22. Cell / when(…, …)
var a = new C e l l ( ) ;
var b = a . when ( 4 2 , 1 3 ) ; // b in unset
a . s e t ( 4 2 ) ; // a contains 42, b contains 13
a . s e t ( 4 ) ; // a contains 4, b is unset
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
23. Cell / when(…, …, …)
Последняя форма when - три аргумента: фильтр, трансформер
и алтернативный трансформер, работает точно так же как и
предыдущий, но если фильтр вернул false - применяется
алтернативный трансформер
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
24. Cell / when(…, …, …)
var a = new C e l l ( ) ;
var b = a . when (
f u n c t i o n ( a ) { r e t u r n a >= 0 ; } ,
f u n c t i o n ( x ) { r e t u r n x+1 } ,
f u n c t i o n ( x ) { r e t u r n x−1 ; }
) ; // b in unset
a . s e t ( 0 ) ; // a contains 0, b contains 1
a . s e t (−1 ) ; // a contains -1, b contains -2
a . u n s e t ( ) ; // a is unset , b in unset
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
25. Cell / when(…, …, …)
Вместо функций можно передать значения, в этом случае when
ведет себя как реактивный тернарный оператор
var a = new C e l l ( ) ;
var b = a . when ( t r u e , 1 , 0 ) ; // b is unset
a . s e t ( t r u e ) ; // a has true , b has 1
a . s e t ( f a l s e ) ; // a has false , b has 0
a . u n s e t ( ) ; // a is unset , b is unset
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
26. Cell / when(…, …, …)
За ислючения случая с константами, для when с тремя
аргументами выполняется закон
forall (c , f , t ,a) :
c . when ( f , t , a ) == c . l i f t ( f u n c t i o n ( c ) {
return f ( c ) ? t ( c ) : a ( c )
}) ;
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
27. Cell / bind
Теперь рассмотрим последний метод Cell для создания новых
переменных - bind. Если бы мне пришлось выбирать из li,
when и bind - я бы выбрал bind, так как остальные легко из него
выводятся
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
28. Cell / bind
Bind’у на вход нужно передавать функцию. Эта функция
применяется к значению реактивной переменной и
возвращает Cell, в свою очередь bind возвращает новую
реактивную переменную, которая содержит то же значение,
что и переменная, которую вернула функция. Звучит cтрашно,
но надеюсь после примеров станет понятнее, но вначале…
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
29. Cell / bind
…закон
forall ( cell , f ) :
c e l l . b i n d ( f ) . unwrap ( )
==
f ( c e l l . unwrap ( ) ) . unwrap ( )
Сложно сказать зачем именно нужен этот монстр, так как
применяется он практически везде, но начнем по порядку, я
сказал, что с него помощью можно создать li…
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
30. Cell / bind / li
var c e l l = new C e l l ( ) ;
c e l l . l i f t = function ( f ) {
return t h i s . bind ( function ( x ) {
r e t u r n new C e l l ( f ( x ) ) ;
}) ;
}
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
31. Cell / bind / when
Теперь реализуем самую первую форму when
var c e l l = new C e l l ( ) ;
c e l l . when = f u n c t i o n ( f ) {
return t h i s . bind ( function ( x ) {
r e t u r n f ( x ) ? new C e l l ( x ) : new
Cell () ;
}) ;
};
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
32. Cell / bind / binary
Это далеко не все, например, с помощью bind можно взять
любую бинарную функцию от обычных значений и
возвращающую обычное значение, и применить её к двум
реактивным переменным и получить реактивную переменную
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
33. Cell / bind / binary
var a = new C e l l ( 1 ) ;
var b = new C e l l ( 2 ) ;
var sum = a . b i n d ( f u n c t i o n ( a ) {
return b . bind ( function ( b ) {
r e t u r n new C e l l ( a+b ) ;
}) ;
} ) ; // sum has 3
a . s e t ( 2 ) ; // a has 2, b has 2, sum has 4
b . u n s e t ( ) ; // a has 2, b & sum are unset
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
34. Монады
Как только вы скажете “Ага, я все понял!” - поздравляю, вы
только что познакомились с монадами
(черт, я же не хотел писать очередной туториал по монадам)
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
36. List / ctor
Создаем список
var l i s t = new L i s t ( ) ;
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
37. List / ctor(…)
Списку можно передать начальные значения в конструкторе.
var l i s t = new L i s t ( [ 1 , 2 , 3 ] )
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
38. List / add
Кладем элементы в список
var l i s t = new L i s t ( ) ;
l i s t . add ( " Warp9 " ) ;
l i s t . add ( " React " ) ;
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
39. List / unwrap
Получить содержимое списка можно через unwrap
var l i s t = new L i s t ( ) ;
l i s t . add ( " Warp9 " ) ;
c o n s o l e . i n f o ( l i s t . unwrap ( ) ) ;
// [" Warp9 "]
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
40. List / remove
Метод add возвращает id элемента,
по которому его можно удалить
var l i s t = new L i s t ( ) ;
var w a r p Id = l i s t . add ( " Warp9 " ) ;
var r e a c t I d = l i s t . add ( " React " ) ;
c o n s o l e . i n f o ( l i s t . unwrap ( ) ) ;
// > [" Warp9 ", " React "]
l i s t . remove ( r e a c t I d ) ;
c o n s o l e . i n f o ( l i s t . unwrap ( ) ) ;
// > [" Warp9 "]
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
41. List / add(λ)
Часто id элемента должен содержаться внутри элемента,
поэтому методу add можно передать функцию, эта функция
будет вызвана, аргументом будет id, а в список будет добавлен
результат выполнения этой функции
var l i s t = new L i s t ( ) ;
l i s t . add ( f u n c t i o n ( i d ) {
r e t u r n { i d : i d , name : "Warp" } ;
}) ;
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
42. List / removeWhich
Кроме remove, есть еще один метод - removeWhich, он
принимает предикат и удаляет из списка все элементы,
которые удоволетворяют этому предикату
var l i s t = new L i s t ( [ 1 , 2 , 3 ] ) ;
l i s t . removeWhich ( f u n c t i o n ( x ) {
return x < 2 ;
}) ;
// list contains 2,3
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
43. List / forEach
Так же в списке есть метод forEach, который ведет себя подобно
forEach массива
var l i s t = new L i s t ( [
" Warp9 " , " React "
]) ;
l i s t . forEach ( function ( x ) {
console . info ( x ) ;
}) ;
// > Warp9
// > React
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
44. List / remove, removeWhich и forEach
Методы remove, removeWhich и forEach не учитывают
реактивную природу списка и выполняются один раз в момент
вызова (не перевыполняются при добавлении новых
элементов)
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
45. List / li
Так же как и Cell, в List есть метод li, который создает новый
список и связывает его функцией с исходным, получается
реактивный map
var a = new L i s t ( ) ;
var b = a . l i f t ( f u n c t i o n ( x ) { r e t u r n x+2 ; } ) ;
// b. unwrap () ==[]
var i d 1 = a . add ( 1 ) ;
// a. unwrap () ==[1] , b. unwrap () ==[3]
var i d 2 = a . add ( 2 ) ;
// a. unwrap () ==[1 ,2] , b. unwrap () ==[3 ,4]
a . remove ( i d 1 ) ;
// a. unwrap () ==[2] , b. unwrap () ==[4]
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
47. List / reduce
Все, что я пока рассказал про списки есть и в Knockout и
ReactiveCoffee, но я обещал, что warp9 поддерживает больше, а
именно агрегацию. Начнем с метода reduce и попробуем
просуммировать элементы в списке и получить реактивное
значение суммы
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
48. List / reduce / sum
Первый параметр reduce - значение, которое соответствует
пустому списку, второе значение - функция, которая
занимается сверткой
var l i s t = new L i s t ( ) ;
var sum = l i s t . r e d u c e ( 0 , f u n c t i o n ( a , b ) {
r e t u r n a+b ;
}) ;
l i s t . add ( 4 1 ) ; // sum has 41
l i s t . add ( 1 ) ; // sum has 42
Как мы видим переменная sum получилась реактивной и
изменяется при изменении списка.
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
49. List / reduce / count
После того, как мы посчитали сумму списка, давайте узнаем
кол-во элементов в нем
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
50. List / reduce / count
var l i s t = new L i s t ( ) ;
var c o u n t = l i s t . l i f t ( f u n c t i o n ( x ) {
return 1 ;
} ) . reduce ( 0 , function ( a , b ) {
r e t u r n a+b ;
}) ;
var i d 4 1 = l i s t . add ( 4 1 ) ; // count has 1
l i s t . add ( 1 ) ; // count has 2
l i s t . remove ( i d 4 1 ) ; // count has 1
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
51. List / reduce / count / wrap
Это работающий метод, правда требует создания нового
списка; существует чуть более эффективный путь
var c o u n t = l i s t . r e d u c e ( 0 , f u n c t i o n ( a , b ) {
r e t u r n a+b ;
}, {
wrap : f u n c t i o n ( x ) {
return 1 ;
}
}) ;
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
52. List / wrap
Функция wrap выполняется для каждого элемента списка и уже
её результат агрегируется, очевидно, что выполняется закон
f o r a l l ( l i s t , f , id , f o l d ) :
l i s t . r e d u c e ( i d , f o l d , { wrap : f } )
==
l i s t . l i f t ( f ) . reduce ( id , f o l d )
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
53. List / reduce / эффективность
Раз мы заговорили об эффективности, какова сложноть у
функции reduce, при добавлении элемента в список размера n?
В knockout она равна O(n), в warp9 она O(ln n). Но делать даже
ln n вычислений на каждое добавление элемента в список,
чтобы инкременировать одно значение (sum или count)
странно, поэтому в warp9 есть другой путь
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
54. List / reduceMonoid
Если посмотреть на реализацию функции reduce, видно, что
вызов list.reduce(id, fold) раскрывается в
l i s t . re d uce Mo n o i d ( {
i d e n t i t y : id ,
add : f o l d
}) ;
Искушенный читатель догадается, что раз есть Monoid, то есть
и Group, и будет прав
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
55. List / reduceGroup
Пример с суммой элементов списка:
var sum = l i s t . r e d u c e ( 0 , f u n c t i o n ( a , b ) {
r e t u r n a+b ;
}) ;
можно переписать так:
var sum = l i s t . r e d u c e G r o u p ( {
i d e n t i t y : function ( ) { return 0 } ,
add : f u n c t i o n ( a , b ) { r e t u r n a+b ; } ,
i n v e r t : f u n c t i o n ( x ) { r e t u r n −x ; }
}) ;
И сложность, магическим образом, упадет с O(ln n) до O(1).
Аналогично можно посчитать и кол-во элементов в списке
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
56. List / reduce∗
Понять, можно ли использоват reduce∗ и какой вариант
использовать достаточно просто. Если агрегат списка не
зависит от порядка элементов в списке и по посчитанному
агрегату и вставляемому элементу вы можете посчитать
значение нового агрегата, то агрегат можно выразить через
reduce∗ функции.
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
57. List / reduceGroup
Если зная агрегат и удаляемый элемент вы сможете посчитать
значение, которое совпадет с агрегатом нового списка, то
агрегат можно выразить через reduceGroup
Очевидно, что агрегаты sum и count попадают под оба
определения, а значит мы можем для них использовать
reduceGroup
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
58. List / reduceMonoid
Может сложится впечатление, что любой коммутативный
агрегат попадает под это определение,
но на самом деле это не так.
Допустим, мы хотим посчитать логическое & от списка bool.
Данная задача попадает под reduceMonoid , но не под
reduceGroup
Зная, что агрегат false и зная, что удаляемый элемент тоже
false, мы не обладаем информацией, есть ли в списке еще false,
а от этого зависит будет ли агрегат false или true
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
59. List / reduce(&)
Хотя я вру
На самом деле, задачу логического & можно свести к
reduceGroup. Достаточно каждое true рассматривать как пару
(1,1), каждое false как (0,1), при добавлении элемента покомпонентно складывать пары, при удалении - удалять.
Если в каждой компоненте одинаковое число - значит
значение агрегата true, иначе false. Единственная проблема - в
качестве результата будет пара, а не boolean
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
60. List / reduce / unwrap
Оказывается в warp9 это не проблема, так как есть опция
unwrap
После того как reduce отработает, вызывается unwrap и
преобразовывает результат в нужный тип..
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
61. List / reduce / unwrap
l i s t . reduceGroup ( {
i d e n t i t y : function ( ) { return [ 0 , 0 ] ; } ,
add : f u n c t i o n ( x , y ) {
r e t u r n [ x [ 0 ]+ y [ 0 ] , x [ 1 ]+ y [ 1 ] ] ;
},
invert : function ( x ) {
r e t u r n [−x [ 0 ] , − x [ 1 ] ] ;
}
} ,{
wrap : f u n c t i o n ( x ) {
return x ? [ 1 , 1 ] : [ 0 , 1 ] ;
},
unwrap : f u n c t i o n ( x ) {
r e t u r n x [ 0 ]== x [ 1 ] ;
}
}) ;
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
62. List / reduce∗ / Cell
Особенностью работы reduce∗ является то, что он учитывает не
только реактивность списка, но и реактивность переменных…
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
63. List / reduce∗ / Cell
var
var
var
var
l i s t = new L i s t ( ) ;
i t 1 = new C e l l ( 0 ) ;
i t 2 = new C e l l ( 1 ) ;
sum = l i s t . r e d u c e ( 0 , f u n c t i o n ( a , b ) {
return a + b ;
} ) ; // sum has 0
var i t I d 1 = l i s t . add ( i t 1 ) ; // sum has 0
var i t I d 2 = l i s t . add ( i t 2 ) ; // sum has 1
i t 1 . s e t ( 5 ) ; // sum has 6
i t 2 . s e t ( 2 ) ; // sum has 7
i t 1 . u n s e t ( ) ; // sum is unset
l i s t . remove ( i t I d 1 ) ; // sum has 2
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.
64. List / reduce∗ / Cell / ignoreUnset
Видно, что если внутри реактивный списока есть пустая
переменная, то результат агрегации будет пустым. Это
поведение можно изменить: достаточно в reduce передать
опцию ignoreUnset - все пустые элементы будут заменяться на
единичный элемент моноида или группы
var
var
var
var
i t e m 1 = new C e l l ( ) ;
i t e m 2 = new C e l l ( 1 ) ;
l i s t = new L i s t ( [ i t e m 1 , i t e m 2 ] ) ;
sum = l i s t . r e d u c e ( 0 , f u n c t i o n ( a , b ) {
return a + b ;
}, {
ignoreUnset : true
} ) ; // sum has 1
i t e m 1 . s e t ( 3 ) ; // sum has 4
..
.
..
.
..
.
. . . . . . . . . . . .
.. .. .. .. .. .. .. .. .. .. .. .. ..
.
..
.
..
.
..
.
..
.