## Where communities thrive

• Join over 1.5M+ people
• Join over 100K+ communities
• Free without limits
##### Activity
• Jan 31 2019 22:17
CrossEye commented #2779
• Jan 31 2019 21:04
ArturAralin commented #2779
• Jan 31 2019 20:08
CrossEye commented #2779
• Jan 31 2019 18:56
buzzdecafe commented #2631
• Jan 31 2019 18:09
ArturAralin commented #2779
• Jan 31 2019 16:18
CrossEye commented #2779
• Jan 31 2019 16:10
CrossEye commented #2631
• Jan 31 2019 16:06
CrossEye commented #2777
• Jan 31 2019 14:44
ArturAralin opened #2779
• Jan 31 2019 07:39
inferusvv commented #2631
• Jan 31 2019 03:07
sespinozj commented #2771
• Jan 31 2019 02:33
• Jan 31 2019 02:26
JeffreyChan commented #2777
• Jan 30 2019 14:30
CrossEye closed #2777
• Jan 30 2019 12:13
• Jan 30 2019 01:42
JeffreyChan commented #2777
• Jan 29 2019 21:06
• Jan 29 2019 16:28
CrossEye commented #2777
• Jan 29 2019 15:50
mbostock commented #2772
• Jan 29 2019 15:48
CrossEye commented #2772
Akira Cai
@blackwindforce

Hi there, does the following combinator have a name? Or, on the other hand, how we usually deal this pattern instead of composing with the combinator? For example:

// ???
const combinator = R.curry((f, g, x, y) => f (  g(x)  )  (  y  )  )

// findById :: ((Record K V -> Boolean) -> [Record K V] -> Maybe Record K V) -> (V -> Record K V -> Boolean) -> V -> [Record K V] -> Maybe Record K V
const findById = combinator(R.find, R.propEq("id"))

findById(1)([{id: 1}])
//> {id: 1}

I know the combinator can be derived from the following 2 functions, where g is identity.
https://github.com/ramda/ramda/blob/ed191e6a476330e37db259a5c2d04bfba0b2d63d/source/useWith.js#L21
https://github.com/fantasyland/fantasy-birds/blob/6f37c6e7daf31f1c31860f0f307555f4c7922ec2/src/dovekie.js#L4

But, is there a more elegant way to deal with it? Any suggestions or perspectives are welcome.

Andy Mac
@zxol
Akira Cai
@blackwindforce

@zxol Thank you, it is exactly the same beta-reduction as mine. And then my following question comes up:
If the function is variadic, then I need a I** combinator to achieve the same functionality, does it make sense?

const idstarstar = R.curry((f, x, y) => f(x)(y))

// right associative
// findById :: (Pred -> [a] -> Maybe a) -> (v -> Pred) -> v -> ([a] -> Maybe a)
const findById = R.compose(R.find, R.propEq("id"))

idstarstar(findById)(1, [{id: 1}])

https://github.com/fantasyland/fantasy-birds/blob/6f37c6e7daf31f1c31860f0f307555f4c7922ec2/src/idstarstar.js#L4
I think the problem is that f(g(x)) returns another function, so I can not give 2 arguments at once and apply to v -> ([a] -> Maybe a).
Is there a more elegant way to deal with it? Any suggestions or perspectives are welcome.

Andy Mac
@zxol
@blackwindforce i don't know of any combinator in the ramda lib, unfortunately. Perhaps the best thing to do is try to structure your program's API so the functor you're operating on is always at the end of a function call on it's own like you used in the first example. Or do the useWith identity trick. Perhaps someone else has a neat answer for you
Akira Cai
@blackwindforce
@zxol Thank you, that make sense to me.
Mike Vosseller

Hi, I'm creating a simple tic-tac-toe style game and game state is stored in a game object.

I've noticed two problems:
1- most of my functions need access to the game object so I need to repeatedly pass it down.
2- because of #1 when I try to compose with a pipeline I often need to curry some functions with the game object.

Both seem like code smells. Is this typical? Any advice to improve?

(This code uses folktale Result)

import {
pipeWith,
chain,
curry,
multiply,
update,
evolve,
} from "ramda";
import folktale from "folktale";
const { result: Result } = folktale;

const createGame = ({ width, height } = {}) => ({
size: {
width,
height,
},
grid: Array(width * height), // game is a grid but stored as a flat array
// additional game state goes here
});

//
// 1) most of my functions need access to the game object so I'm repeatedly passing it down. is this typical?
//
const gridIndex = (game, pos) => add(pos[0], multiply(pos[1], game.size.width));
const cell = (game, pos) => game.grid[gridIndex(game, pos)];
const updateCell = (game, pos, val) =>
evolve({
grid: (g) => update(gridIndex(game, pos), val, g),
})(game);

// two contrived validators that don't require the game object
const validateColGte0 = (pos) =>
pos[0] >= 0 ? Result.Ok(pos) : Result.Error(col must be >= 0: ${pos[0]}); const validateRowGte0 = (pos) => pos[1] >= 0 ? Result.Ok(pos) : Result.Error(row must be >= 0:${pos[1]});
// three validators that need the game object
const validateColLtWidth = curry((game, pos) =>
pos[0] < game.size.width
? Result.Ok(pos)
: Result.Error(col must be < ${game.size.width}:${pos[0]})
);
const validateRowLtHeight = curry((game, pos) =>
pos[1] < game.size.height
? Result.Ok(pos)
: Result.Error(row must be < ${game.size.height}:${pos[1]})
);
const validateCellIsEmpty = curry((game, pos) =>
!cell(game, pos)
? Result.Ok(pos)
: Result.Error(position is not empty: \${pos})
);
//
// 2) To compose functions in a pipline I need to curry them with the game object
//    would it be better to make the validator signatures take a single object
//    with all possible paramaters? e.g. { game, pos }
//
const validatePosition = (game, pos) =>
pipeWith(chain)([
validateColGte0,
validateRowGte0,
validateColLtWidth(game),
validateRowLtHeight(game),
validateCellIsEmpty(game),
])(pos);
const performMove = (game, pos, val) =>
validatePosition(game, pos).matchWith({
Ok: ({ value: validatedPosition }) =>
updateCell(game, validatedPosition, val),
Error: ({ value: error }) => {
console.log(error);
return game;
},
});

// create and run the game
let game = createGame({ width: 3, height: 3 });
console.log(game);
game = performMove(game, [1, 1], "X"); // works
console.log(game);
game = performMove(game, [1, 1], "O"); // position is not empty: 1,1
console.log(game);
6 replies
Charles Hughes
@chughes87
Is there a more elegant way to do this?
compose(join(''), converge(Array, [getDateTitle, always('\n\n'), getBodyWithoutMarkup])
4 replies
QP
@theqp
any developer for @types/ramda here?
I have made a more accurate cond type definition but I don't want to download the whole @types repo
export function cond<A, B>(fns: Array<[SafePred<A>, (...a: readonly A[]) => B]>): (...a: readonly A[]) => B | undefined;
export function cond<A, B>(
fns: [
...[SafePred<A>, (...a: readonly A[]) => B],
...[SafePred<A>, (...a: readonly A[]) => B]
]
): (...a: readonly A[]) => B;
also the one with any makes no sense to me, B can be any
Mike Vosseller

Looks like Ramda doesn't include implementations of the various Fantasy Land "algebraic structures" like
Result, Either, Maybe, State, Reader, Future

Do folks typically just use the libraries listed on the Fantasy Land website here:
https://github.com/fantasyland/fantasy-land/blob/master/implementations.md

So If I wanted all of the above structures maybe I'd include and use:

Folktale: Result, Future
Sanctuary: Either, Maybe
Monastic: State

Just want to make sure there is no obvious single library that I should be using.

Thanks!

6 replies
Nils Riedemann
@nocksock

I'm sure there's a more elegant way to write this:

const seq = list => fns => r.call(r.apply(r.pipe, fns), list);

Still trying to wrap my head around currying, composing, piping etc.

wangzengdi
@nocksock You can use R.pipeWith(R.identity) to do almost the same thing, but I think writing simple and readable code is more important than pursuing for point-free/curry code.
const seq = R.curry((list, fns) => R.pipe(...fns)(list))
Nils Riedemann
@nocksock

writing simple and readable code is more important than pursuing for point-free/curry code.

@adispring Absolutely! However in my case it's just about embracing the pointfree style to fully grok it. This is just for a small utility package in a side project of mine that I specifically started to learn the ins and outs of FP. :D Using spread gave me a TS Error earlier, going to try yours after lunch! Thanks!

Andreas Herd
@mendrik
ahoy-hoy. How can I do a map(x -> x - min(...arr), arr) just with function composition. I tried to use converge but somehow getting the minimum to the map function didn't work
2 replies
Mike Vosseller
Hi all. I implemented a small game using Ramda. It's a connect-four command line game and my first attempt at functional programming. If anyone wants to review the code and give some feedback I'd love to hear it!
https://github.com/mpvosseller/connect-four-ramda
21 replies
Nils Riedemann
@nocksock
I'm currently working through the "Mostly Adequate to Functional Programming" (currently re-reading the monad-chapter) and I found the exercises to be really helpful. Is there a resource with more and similar exercises to understand Container Types and Monads better?
3 replies
zhangyd
@zydmayday

I have a question about how to combine multiple functions with compose/pipe,
Is there any possibility to combine funcA and funcB in ramda way?
(or any reason we shouldn't do something like this.

const funcA = (a, b) => a + b;
const funcB = (ab, c) => ab * c;

const funcC = (a, b, c) => {
const ab = funcA(a, b);
return funcB(ab, c)
}

funcC(1,2,3) // 9
Andy Mac
@zxol

@zydmayday if we look at funcB we see it's a 2-arity function. Remember that piping or composing functions only works when they're 1-arity or curried. But lets assume funcb is curried, then using compose would work, with one caveat, you have to call it like funcC(1,2)(3). That's because the result of compose is a 2-arity function (the same as funcA) - it'll just just throw away the 3rd argument. This will often work in the context of a larger program, if you're always calling it partially.

You can use a combinator to get around this. in this case it's a (f, g) => (a, b, c) => g(f(a,b), c) I don't think that one has a special name in FPland.

The ramda version of that combinator would be something like converge(funcB, [funcA, nthArg(2)])

zhangyd
@zydmayday
Ken Okabe
@stken2050
Hi, I wonder if ramda developers notice TC39 pipeline-operator is now Stage2 and people are upset against the decision of Hack-style proposal.
5 replies
RxJS author has just announced he considers the Hack proposal is not worth adopting, and will never cooperate with and ignore it.
https://github.com/tc39/proposal-pipeline-operator/issues/228#issuecomment-925465598
Andy Mac
@zxol
I'm thinking about making an atom (ide) package that functions like the ramdajs.com repl. I'd like to include options too, to include other popular FP packages. If anyone has any feature suggestions or is interested in helping, let me know.
Ken Okabe
@stken2050
TC39/proposal-pipeline-operator Hack-style |> hijacks Grouping operator ( ) https://dev.to/stken2050/the-current-tc39-proposal-pipeline-operator-hack-style-hijacks-grouping-operator-1dam Give me comments thanks.
Mike Lambert
@lax4mike
is there another proposal somewhere that would be an alternative to the hack-style proposal?
Mike Lambert
@lax4mike
I'm reading up, looks like the other is the F# style (https://github.com/tc39/proposal-pipeline-operator#why-the-hack-pipe-operator)
Nils Riedemann
@nocksock
As someone, who's just getting into FP... I, well... prefer the hack pipe? :D Much clearer what's happening to me. It might not look as elegant, but I'm hoping that's not the only argument against it?
5 replies
Andreas Herd
@mendrik
This message was deleted
2 replies
Charles Hughes
@chughes87
Does anyone have an SVG of the Ramda logo?
4 replies
mlivi25
@mlivi25
Does ramda have any issues in IE ?
#!/bin/BasH
@bas080

I finished working on an initial version of a pattern matching library and wanted to share it with you guys. Please share your thoughts if you have the time and are interested. Yes this is a bit of a shameless plug, but I don't know of other communities where I can share this.

https://github.com/bas080/patroon

Pedro Ávila

Hi, I'm trying to make this peace of code more functional like, and more elegant, so this:

checkActive(service).then(
isActive => isActive
? stopService(service)
: startService(service)
)

Became this:

checkActive(service).then(
ifElse(
identity,
partial(stopService, [service]),
partial(startService, [service])
)
)

But to me, the first one seems easier to understand. Maybe there's a better approach? Would love any insights on this... thanks!

14 replies
Stefano Vozza
@svozza
frist one is much clearer imo
4 replies
Scott Sauyet
@CrossEye
Yes, that last is quite nice.
Pedro Ávila
Thank you guys!
Ben Carp
@carpben
Hi,
What is the deal with Ramda's tree shaking? Is it similar to Lodash? U need to manually import 'ramda/pick'?
vinodsudini
@vinodsudini
Hi, when can I expect the new version with security fix for Redos ?
ed@sharpertool.com
@kutenai
I am using this const hasRequiredKeys = R.allPass(R.map(R.has, disallowed_keys)) to insure required keys are in an object. I now want to reverse that, and check to insure a set of 'disallowed' keys are NOT in there.
2 replies
Pedro Ávila

I think I found a bug in includes:

const fn = includes(__) (['foo', 'bar'])
const fn2 = includes(__, ['foo', 'bar'])

console.log(
fn('foo'), // false
fn('bar'), // false
fn2('foo'), // true
fn2('bar'), // true
fn2('not present'), // false
)
6 replies
Joshua Travis
@jktravis
Hi. We have several projects that were using lodash. We’ve started introducing Ramda. But now we want to see what it would take to replace lodash completely. My question is, does anyone have a codemod or similar to help facilitate this process?
James Ramm
@JamesRamm

Does ramda have a point-free way to do this:

const callMethod = obj => obj.someMethod;

I could do:

const callMethod = R.compose(R.call, R.prop('someMethod'))

But that does not seem any clearer and certainly less concise. I was thinking perhaps ramda has a builtin fn for it, but I couldn't find it...

Ideally, generically, e.g.:

const callMethod = curry((name, obj)  => obj[name]())
4 replies
nik so
Hello James that method is call invoker
Aron Griffis
@agriffis
The Ramda docs reference the Maybe type, for example for traverse, but it's not part of Ramda that I can tell. Is there an implementation people commonly use?
KAMi KZ
@agriffis so I'd say any ADT libraries that implements the fantasy-land specifications would do the trick. So personally I use folktales, but i think crocks will do the trick, too.
Aron Griffis
@agriffis
Soya
@Soya-xy
Is there a _.get (Object, 'a.b.c', 'default ") like Lodash; method is taken from the string
8 replies
Joshua Travis
@jktravis
No. But you can create your own wrapper for it pretty easily.
Dennie de Lange
@tkvw
is there a better way to do this in typescript? I need to do all kind of type assertions because of nth:
R.pipe(
R.toPairs,
R.filter(R.pipe(
R.nth(1) as (value: [string,string]) => string,
R.both(R.pipe(R.isNil, R.not), R.pipe(R.startsWith('workspace:'), R.not))
) as (v: [string,string]) => boolean),
R.fromPairs
) as (data: Record<string,string>) =>Record<string,string>