ramda
<img class="emoji" title=":ram:" alt=":ram:" src="https://assets-cdn.github.com/images/icons/emoji/unicode/1f40f.png" height="20" width="20" align="absmiddle"> Practical functional Javascript
I'm just starting to play with Ramda a bit, and I'm relatively new to functional programming in general. I'm starting to get the hang of how to structure my programs, but I keep getting hung up on a certain aspect. I feel that I must be missing some key concept.
I'm not even certain of how to word my question, so I am going to start with an example. This code snippet is a portion of the calculation for the centroid of an arbitrary polygon:
var centroidX = R.converge(
R.divide,
R.compose(
R.sum,
R.map(
R.converge(
R.multiply,
R.converge(R.add, x1, x2),
diffOfProducts
)
),
makeVertexPairs
),
sixTimesPolyArea
);
var centroidY = R.converge(
R.divide,
R.compose(
R.sum,
R.map(
R.converge(
R.multiply,
R.converge(R.add, y1, y2),
diffOfProducts
)
),
makeVertexPairs
),
sixTimesPolyArea
);
Geom.centroid = R.curry(function(vertices) {
return [ centroidX(vertices), centroidY(vertices) ];
});
Notice that the only difference between centroidX
and centroidY
is that the X coordinate calls x1
and x2
near the middle, and the Y coordinate calls y1
and y2
near the middle.
Is there some simple way to refactor out this commonality such that I can do something like the following:
var centroidCoord = R.converge(
R.divide,
R.compose(
R.sum,
R.map(
R.converge(
R.multiply,
R.converge(R.add, R.__, R.__),
diffOfProducts
)
),
makeVertexPairs
),
sixTimesPolyArea
);
Geom.centroid = R.curry(function(vertices) {
return [ centroidX(x1, x2, vertices), centroidY(y1, y2, vertices) ];
});
I know that this isn't even close. I'm just trying to express what I want to accomplish. Any recommendations?
Source: (StackOverflow)
I want to stop using lodash.js
and switch to ramda.js
but I don't see any function like _.toArray()
for objects, is there something like this in ramda
that I should compose or should I continue using lodash
for these functions (and possibly more cases that I have not run into yet.)
For example
In lodash
if you have an Object like :
{"key1": {"inner": "val"}, "key2" : {"inner": "val"}}
you can convert it to an array like this:
[{"inner": "val"}, {"inner": "val"}]
using the function _.toArray()
Source: (StackOverflow)
So I have a list of divs: list
i want a subset of the list removing the divs with the .fade
class.
and also just grabbing the list from the div with .selected
class.
so using R.takeWhile
and R.dropWhile
.
then i want to map over that new list and add a .active
class on a subset of that list with R.take
and R.forEach
or R.map
something like :
var takeFromSelected = R.dropWhile(function(item){!$(item).hasClass('selected')};
var removeFadeItems = R.takeWhile(function(item){!$(item).hasClass('fade')});
var addActiveClass = function(x){ $(x).addClass('.active')};
var processList = R.pipe(R.map(addActiveClass), removeFadeItems, takeFromSelected);
processList(list);
Im really new to this FP stuff and trying to get the grip of it.
Any insight would be greatly apreciated!! Thanks! :)
Update
for future reference this is what i did :
@addActiveClass = (x)->
$(x).addClass('active')
return
@takeFromSelected = R.dropWhile((item)-> !$(item).hasClass('selected'))
@removeFadeItems = R.takeWhile((item)-> !$(item).hasClass('fade'))
@addWeekView = R.compose(addActiveClass, removeFadeItems, takeFromSelected)
Source: (StackOverflow)
This question already has an answer here:
EDIT: I've marked this as a duplicate of Can I make this function defenition [sic] even shorter?, which is functionally identical (two puns intended) and has a good answer from one of the authors of the Ramda library.
This is a question more of academic curiosity than practical need.
I'm trying out the Ramda library, which emphasises a "point-free" style of function composition.
Suppose I have an array of objects, like
var things = [
{id: "a", value: 234},
{id: "b", value: 345},
{id: "c", value: 456}
]
and I wanted a function to return the element by id (or at least, for the moment, a list matching by id). In native javascript, I can say
var byId = function(id, arr) { return arr.filter(function(o) { return o.id === id; }); };
then byId('c', things)
will give me an array containing just the third item.
In Ramda, I can do this more concisely and with no reference to the data:
var byIdRam = function(id) { return R.filter(R.propEq('id', id)); }
The result is a "curried" function, so byIdRam('c')(things)
gives the same result as the first version.
I sense that the remaining lambda is also unnecessary, but I don't know how to compose the function without explicit reference to the id. Does anyone know a better way to write this?
UPDATE The answer is simply
var byId = R.useWith(R.find, R.propEq('id'))
This also gives the semantics I want, where it either returns a single element or undefined
. Nice!
Source: (StackOverflow)
var _ = require('ramda');
var obj1 = {
innerNum: 1,
innerObj: {
innerStr: 'a',
innerStrB: 'Z'
}
};
var obj2 = {
innerNum: 2,
innerObj: {
innerStr: 'b'
}
};
var mixedObj = _.mixin(obj1, obj2);
mixedIObj does not include the inner object's innerStrB.
Any ramda solution?
Source: (StackOverflow)
Why when I run the ifElse
method here does false
log "function two (onTruthy)"?
var x = R.ifElse(R.T, function(){
console.log("function two (onTruthy)")
// console.log(arguments)
}, function(){
console.log("function three (onFalsy)")
// console.log(arguments)
})
x(false)
I'm thinking it's because R.T is always returning true. Perhaps using _.isMatch I can match it?
Update: Just tried:
var x = R.pipe(
R.partialRight(R.match, true),
R.partialRight(R.ifElse, function(){
console.log("function two (onTruthy)")
// console.log(arguments)
}, function(){
console.log("function three (onFalsy)")
// console.log(arguments)
})
)
Source: (StackOverflow)
I'm playing around with functional/tacit style programming, specifically creating the snake game (example of game: http://patorjk.com/games/snake/)
The specific question is that I'm taking an array of strings like:
[
['2 '],
['10']
]
and wanting to get the list of coordinates in numerical order of the 'value'. In the domain, 0 is the head of the snake, 2 is the tail, the whole thing is the board.
So I built:
var findSnake = function(rendered_board) {
return r.map(function(x) {
return r.map(function (y) {
return {
x: x,
y: y,
val: rendered_board[x][y]
};
})(r.keys(r.split('', rendered_board[x])));
})(r.keys(rendered_board));
};
which gives me back:
[ [ { x: '0', y: '0', val: '2' }, { x: '0', y: '1', val: ' ' } ],
[ { x: '1', y: '0', val: '1' }, { x: '1', y: '1', val: '0' } ] ]
which I can then sort and get my list of coordinates. It works but I have questions on style.
Is there a way to write findSnake in point free style? Is there a more idiomatic approach to this problem?
Source: (StackOverflow)
I'm trying to accomplish this in a functional manner (with Ramda). My JSON is structured like this
[
{username: 'bob', age: 30, tags: ['work', 'boring']},
{username: 'jim', age: 25, tags: ['home', 'fun']},
{username: 'jane', age: 30, tags: ['vacation', 'fun']}
]
and I am trying to filter based on a value in the 'tags' property, but have not been successful. I am able to filter on ints/strings (age and username), but I can't figure out how to do so with values in nested arrays (tags). Any help would be much appreciated.
Source: (StackOverflow)
How do I map through array of objects and based on that create another object (based on element properties), without temporary object? So if I have something like:
foos = [ { name: 'A' }, { name: 'B' }, { name: 'C' } ]
objx = {}
foos.map (x)->
objx[x.name] = 'name is ' + x.name.toLowerCase()
# objx = { A: 'name is a', B: 'name is b', C: 'name is c' }
How can I accomplish the same thing without objx
thing?
Either with or without using whatever helper library - lodash, ramda, jquery, angular, etc.
Source: (StackOverflow)
I'm writing a d.ts file for ramda. The lib has a function mapObj
and mapObj.idx
.
interface RamdaStatic {
...
mapObj(
fn: Function,
obj: any
): any;
...
}
My question is how to add mapObj.idx that has a similar type def? I am aware of answer, but that requires a seperate interface and I would like to avoid that.
Source: (StackOverflow)
Does Ramda have a function to remove false values from a list?
I know we can simply do var compact = R.filter(R.identity);
but am I missing the ready-made function?
Source: (StackOverflow)
All examples uses Ramda
as _
(it's clear what methods do in examples contexts) and kefir
as frp
(almost same API as in bacon.js)
I have a stream, that describes change of position.
var xDelta = frp
.merge([
up.map(_.multiply(1)),
down.map(_.multiply(-1))
])
.sampledBy(frp.interval(10, 0))
.filter();
It emits +1
when I press UP
key, and -1
on DOWN
.
To get position I scan
this delta
var x = xDelta
.scan(_.add)
.toProperty(0);
That's work as expected. But I want to limit value of x
from 0
to 1000
.
To solve this problem I found two solution:
Change function in scan
var x = xDelta.scan(function (prev, next) {
var newPosition = prev + next;
if (newPosition < 0 && next < 0) {
return prev;
}
if (newPosition > 1000 && next > 0) {
return prev;
}
return newPosition;
}, 0);
It looks Ok, but later, as new rules will be introduced, this method will grow. So I mean it doesn't look composable and FRPy.
I have current
position. And delta
. I want to apply delta
to current
, only if current after applying
will not be out of limits.
current
depends on delta
delta
depends on current after applying
current after applying
depends on current
So it looks like circular dependency. But I solved it using flatMap
.
var xDelta = frp
.merge([
up.map(_.multiply(1)),
down.map(_.multiply(-1))
])
.sampledBy(frp.interval(10, 0))
.filter();
var possibleNewPlace = xDelta
.flatMap(function (delta) {
return x
.take(1)
.map(_.add(delta));
});
var outOfLeftBoundFilter = possibleNewPlace
.map(_.lte(0))
.combine(xDelta.map(_.lte(0)), _.or);
var outOfRightBoundFilter = possibleNewPlace
.map(_.gte(1000))
.combine(xDelta.map(_.gte(0)), _.or);
var outOfBoundFilter = frp
.combine([
outOfLeftBoundFilter,
outOfRightBoundFilter
], _.and);
var x = xDelta
.filterBy(outOfBoundFilter)
.scan(_.add)
.toProperty(0);
You can see full code example at iofjuupasli/capture-the-sheep-frp
And it's working demo gh-pages
It works, but using circular dependencies is probably anti-pattern.
Is there a better way to solve circular dependency in FRP?
The second more general question
With Controller
it's possible to read some values from two Model
and depending on it's values update both of them.
So dependencies looks like:
---> Model
Controller ---|
---> Model
With FRP there is no Controller
. So Model
value should be declaratively calculated from other Model
. But what if Model1
calculating from another Model2
which is the same, so Model2
calculates from Model1
?
Model ----->
<----- Model
For example two players with collision detection: both players have position
and movement
. And movement
of first player depends on position
of second, and vice versa.
I'm still newbie in all this stuff. It's not easy to start think in declarative FRP style after years of imperative coding. Probably I'm missing something.
Source: (StackOverflow)
var take = R.curry(function take(count, o) {
return R.pick(R.take(count, R.keys(o)), o);
});
This function takes count
keys from an object, in the order, in which they appear. I use it to limit a dataset which was grouped.
I understand that there are placeholder arguments, like R.__
, but I can't wrap my head around this particular case.
Source: (StackOverflow)
Given a rotate function like the one below, which rotates the array a set number of slots.
Is there an equivalent Ramda.js function or composition that will do this rotation?
var test = [1,2,3,4,5,6,7,8,9];
function rotate(arr, count) {
arr = arr.slice();
while (count < 0) {
count += arr.length;
}
count %= arr.length;
if (count) {
arr.splice.apply(arr, [0, 0].concat([].slice.call(arr.splice(arr.length - count, count))));
}
return arr;
}
example
rotate(test, 2) // -> [8, 9, 1, 2, 3, 4, 5, 6, 7]
Source: (StackOverflow)