Комментарии 19
Оспади, когда уже JS-библиотекам начнут давать нормальные названия O_o
Ну а если по делу — навскидку выглядит круто, надо будет обязательно попробовать. Вообще, движение в этом направлении очень радует
Ну а если по делу — навскидку выглядит круто, надо будет обязательно попробовать. Вообще, движение в этом направлении очень радует
Также я стараюсь делать Kefir максимально простым для изучения, примерно как Underscore или LoDash.Это здорово, API Бекона и Rx какие-то неэлегантные. Было бы круто иметь FRP с API в духе Underscore/LoDash.
Надежда на то что FRP можно будет применять в боевых условиях, демки впечатляют, спасибо!
Вопрос, насколько можно будет сочетать потоки Kefir'a с методами LoDash? В API Bacon'a функциональщины все-таки не хватает…
Вопрос, насколько можно будет сочетать потоки Kefir'a с методами LoDash? В API Bacon'a функциональщины все-таки не хватает…
Или LazyJS который идиоматичен, резок и ленив. Хотя и менее популярен.
Хотя Lodash тоже планирует лень.
Упс, пардон, невнимательно прочитал вопрос.
Хотя Lodash тоже планирует лень.
Упс, пардон, невнимательно прочитал вопрос.
Kefir, кстати, по определению ленив и работает похоже на LazyJS. Так как он обрабатывает поток значений, а не массив значений, и не может создавать временные массивы с результатами при всём желании.
В LazyJS тоже можно DOM события фильтровать и т.д. посмотрите в описание Event sequences
Даже не знаю. LoDash можно например активно использовать внутри кефировских .map, .filter и пр. Еще можно его использовать во внешнем коде который, что-то делает с потоками. А так чтобы LoDash прям как-то взаимодействовал с Kefir — ничего особо в голову и не приходит.
Вот если бы LoDash умел создавать трансдьюсеры, и Kefir поддерживал трансдьюсеры, тогда они могли бы прям клёво взаимодействовать. Если трансдьюсеры станут модными в JavaScript, тогда может это будет…
Вот если бы LoDash умел создавать трансдьюсеры, и Kefir поддерживал трансдьюсеры, тогда они могли бы прям клёво взаимодействовать. Если трансдьюсеры станут модными в JavaScript, тогда может это будет…
Можно еще Elm упомянуть.
Во всех подобных библиотеках меня смущает один момент. Допустим у меня есть одно редко меняющееся свойство (конфиг) и часто меняющееся (координата мыши), и нужно, в зависимости от состояния, показывать координаты, например, в заголовке окна. Реализация в лоб будет примерно такой:
Когда config содержит true — всё ок, но когда он содержит false, то будет куча пустых вычислений при движении мыши. Как эта проблема решается при использовании таких библиотек?
config = Kefir.constant( false )
coords = Kefir.constant( [0,0] )
printer = Kefir.merge([ config, coords ]).scan( 0, functon( config, coords ){
return 'Hello' + ( config ? coords : '' )
})
Когда config содержит true — всё ок, но когда он содержит false, то будет куча пустых вычислений при движении мыши. Как эта проблема решается при использовании таких библиотек?
Вы что-то странное написали, оно не будет работать :)
В
Реализация в лоб скорее будет такая:
Но как вы верно заметили будут ненужные вычисления. Чтобы их избежать можно использовать .filterBy:
В
.scan
первый аргумент — предыдущее значение, а второй новое значение из источника, и вы должны вернуть значение которое выйдет из printer
и станет «предыдущим значением» на следующем шаге. А .merge
просто берет два потока и все события из них отправляет в новый поток. Ну т.е. вы никак не получите config и coords как параметры в .scan
.Реализация в лоб скорее будет такая:
printer = Kefir.combine([config, coords], function(config, coords) {
return 'Hello' + ( config ? coords : '' )
});
Но как вы верно заметили будут ненужные вычисления. Чтобы их избежать можно использовать .filterBy:
printer = coords.filterBy(config).map(function(coords) {
return 'Hello' + coords
});
.filterBy
он как .filter
, только вместо функции принимает проперти или поток.То есть filterBy будет отписывать стрим от coords, до тех пор пока config не станет true?
А что если нужно не просто фильтровать, а выбирать один поток из двух?
А что если нужно не просто фильтровать, а выбирать один поток из двух?
printer = Kefir.combine([ config, mouseCoords, mouseTarget ], function( config, coords, target ) {
return 'Hello ' + ( config ? coords : target )
});
Тогда можно так:
Я еще не успел написать документацию для .flatMapLatest, можно почитать в доках бекона пока: github.com/baconjs/bacon.js#observable-flatmaplatest
printer = config.flatMapLatest(function(config) {
// возвращаем поток. Т.е. как бы переключаемся с потока на поток в зависимости от config
return config ? mouseCoords : mouseTarget;
}).map(function (coordsOrTarget) {
// тут уже обрабатываем конкретные значения из mouseCoords или mouseTarget
return 'Hello ' + coordsOrTarget;
});
Я еще не успел написать документацию для .flatMapLatest, можно почитать в доках бекона пока: github.com/baconjs/bacon.js#observable-flatmaplatest
То есть в общем случае будет нечто-типа:
printer = config.flatMapLatest( function(config) {
if( config ){
return mouseCoords.map( function( coords ){
return 'Mouse coords is ' + coords
}
} else {
return mouseTarget.map( function( target ){
return 'Mouse target is ' + target
}
}
} )
Да, можно так.
Согласен с вами по поводу документации для RxJS и поэтому я решил сделать вот такой вариант xgrommx.github.io/rx-book/
Могу ошибаться но трансдьюсеры мне напоминают оператор compose из функционального программирования, также удалось найти пару интересных постов jlongster.com/Transducers.js--A-JavaScript-Library-for-Transformation-of-Data и phuu.net/2014/08/31/csp-and-transducers.html
Compose там замешан, но это только часть истории. Планирую скоро написать пост про трансдьюсеры.
Половину написал habrahabr.ru/post/237613/
А еще примеры будут?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Kefir.js — новая библиотека для функционального реактивного программирования (FRP) в JavaScript