These are chat archives for ramda/ramda

9th
Mar 2016
Scott Sauyet
@CrossEye
Mar 09 2016 00:00
Perhaps, but I'm not sure I want to know about that. :smile:
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:05
lol
Well I don't know how it works internally, but it seems like lensIndex, lensProp, lensPath, etc needs to access the object right?
Somewhere down the line lensIndex(1) does something like myArray[1], and lensPath(['a','b','c']) does something like myObj['a']['b']['c']
And in the case of an object, creates the level if it doesn't exist
Couldn't it follow that same path and just print instead of access?
Sebastien Daniel
@SebastienDaniel
Mar 09 2016 00:10
Howdy
Is there a "ramda-way" to provide two arguments to R.find() ?
wait
thats not clear
LeonineKing1199
@LeonineKing1199
Mar 09 2016 00:11
Are you trying to find multiple items?
Sebastien Daniel
@SebastienDaniel
Mar 09 2016 00:11
no, just one
such as
R.find(R.pathOr([], ["path", "to", "array"]), testFunction);
but I need to provide both the initial data to traverse AND an argument to the test function
I could just warp it with a function and provide the arguments separately, but I'm thinking there's a Ramda-way to do this more elegantly
wrap*
LeonineKing1199
@LeonineKing1199
Mar 09 2016 00:15

Looking at what pathOr does, I'm kind of confused as to what you're trying to accomplish.

Buuuuut from your last sentence it sounds like maybe a reduction would do it? Idk...

Scott Sauyet
@CrossEye
Mar 09 2016 00:16
Yes, @SebastienDaniel, I'm afraid I'm not following. Could you give sample inputs/outputs?
Sebastien Daniel
@SebastienDaniel
Mar 09 2016 00:17
I'm working with a tree structure, roughly. Gimme a min to write that up ;)
LeonineKing1199
@LeonineKing1199
Mar 09 2016 00:18
Are you trying to traverse a tree?
Scott Sauyet
@CrossEye
Mar 09 2016 00:18

@Risto-Stevcev: I just don't see how that would work. If

R.compose(lensIndex(1), lensProp('x'), lensPath(['y', 'z'])).toString() 
//=> [1, 'x', 'y', 'z']

Then would

R.compose(add(1), multiply(2), divide(3)).toString()
//=> [1, 2, 3]

? That seems absurd.

Sebastien Daniel
@SebastienDaniel
Mar 09 2016 00:19
there we go
So I would provide the data Tree, and then an "ID", the method I want to build would determine which leaf holds the ID (Person, Organization, Department or HumanResource)
LeonineKing1199
@LeonineKing1199
Mar 09 2016 00:21
Oh, so you wanted to use R.find() to traverse each individual array...
Sebastien Daniel
@SebastienDaniel
Mar 09 2016 00:21
well, at first
but I'm sure there's a more elegant way
rather, I'm "thinking" there's a more elegant way ;)
LeonineKing1199
@LeonineKing1199
Mar 09 2016 00:22
Well, you can have a view_ of the object and then you might be able to apply the function _over it
Man, I suck at markdown...
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:24
@CrossEye I'm thinking more along the lines of writing something like what view or set does, but print it instead. Those functions use their given lens to traverse the object to the location and get or set. Instead of doing that, it would be given a dummy object and just accumulate the printed path and return that instead of the dummy.
Sebastien Daniel
@SebastienDaniel
Mar 09 2016 00:24
is a lens a pre-determined path ?
Scott Sauyet
@CrossEye
Mar 09 2016 00:25
@SebastienDaniel: A bit more than that. It's a way to focus on a specific part of a data structure, so that you can get, set, or alter it.
Sebastien Daniel
@SebastienDaniel
Mar 09 2016 00:25
problem is, my tree is immutable, so references change all the time
Scott Sauyet
@CrossEye
Mar 09 2016 00:26
is mutable?
Sebastien Daniel
@SebastienDaniel
Mar 09 2016 00:26
no
immutable
LeonineKing1199
@LeonineKing1199
Mar 09 2016 00:26
What if you used like an array of views that you could map or forEach over and apply the find function as needed?
Sebastien Daniel
@SebastienDaniel
Mar 09 2016 00:26
I was thinking of doing something of the sort
either that or concatenating all arrays and finding, and then determining based on some unique props of a given leaf
I'm not sure what the diff is between a lookup function that is essentially a pre-determined R.path() vs a lens()
Brad Compton (he/him)
@Bradcomp
Mar 09 2016 00:28
@SebastienDaniel Do you have a set number of paths you are searching on?
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:28
Even if it's roughly doing something like get( get( get(obj['a']) ['b'] )['c'] ) internally (or set), it would instead just do print( R.append( 'c', print( R.append('b', print( ['a'] ) ) ))
Scott Sauyet
@CrossEye
Mar 09 2016 00:28
What sort of output are you looking for, a string such as "humanResources"? A path such as ["entitiy", "internalEntity", "humanResources"], the humanResources object?
Sebastien Daniel
@SebastienDaniel
Mar 09 2016 00:28
@Bradcomp yes, the tree structure is quite static
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:29
Or something like that
Sebastien Daniel
@SebastienDaniel
Mar 09 2016 00:29
@CrossEye it could be either. The final result will be a string. But I could map the output to that string, ultimately.
@Bradcomp the tree-structure is static, if that's your question. So the paths are known ahead of time.
Brad Compton (he/him)
@Bradcomp
Mar 09 2016 00:30
Thanks.
Scott Sauyet
@CrossEye
Mar 09 2016 00:30
@Risto-Stevcev: I'm noting that many lenses are built by composing other lenses, using the generic compose function. It doesn't know that it's creating lenses.
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:31
I'm not talking about compose though
How does view work under the hood?
It would be similar to those functions
LeonineKing1199
@LeonineKing1199
Mar 09 2016 00:31
I would just R.find(function, R.path([])) to victory!
Scott Sauyet
@CrossEye
Mar 09 2016 00:33
@Risto-Stevcev: I'm afraid I'm simply not seeing it.
view is pretty simple. The depth is really in lens.
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:35
A naive hack of what I'm trying to say is something like:
@ram-bot
var lens = R.compose(R.lensIndex(0), R.lensPath(['y', 'z']), R.lensPath(['w']))
JSON.stringify(R.set(lens, true, [{}]))
@ram-bot
var lens = R.compose(R.lensIndex(0), R.lensPath(['y', 'z']), R.lensPath(['w']))
JSON.stringify(R.set(lens, true, [{}]))
ram-bot
@ram-bot
Mar 09 2016 00:35
'[{"y":{"z":{"w":true}}}]'
Scott Sauyet
@CrossEye
Mar 09 2016 00:36
Right, but that requires you to know the [{}] up front, which is a huge part of the battle.
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:37
If you're only dealing with composed lensPaths, you could essentially roll your own print function like this:
var print = lens => JSON.stringify(R.set(lens, true, {}))
Scott Sauyet
@CrossEye
Mar 09 2016 00:37
Sure, if all you're worried about is lensPath/lensProp.
But lenses are much more general-purpose than that. Those are simply some useful sugar.
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:38
There's no way to programmatically zero fill an array up to the desired lensIndex?
Scott Sauyet
@CrossEye
Mar 09 2016 00:39
Lenses aren't meant for that job. The Ramda-Lens side project is looking at Prisms and Isos, which might handle some of that.
Ideally, we probably shouldn't be using assoc to fill in the blanks in lensProp, lensPath either, I believe. That was the easy solution, but perhaps not the best one.
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:41
What do you mean?
Is it using assoc in the background?
Scott Sauyet
@CrossEye
Mar 09 2016 00:44
function lensProp(k) {
  return lens(prop(k), assoc(k));
}
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:45
i c
Scott Sauyet
@CrossEye
Mar 09 2016 00:45
similar for lensPath.
These concepts were borrowed from Haskell, and I don't know the Haskell implementation, not really. (It's honestly quite scary!) But I would rather stay reasonably close to the original ideas.
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:45
Yeah
I'd definitely like to find the time to play around more with Haskell and Idris
Scott Sauyet
@CrossEye
Mar 09 2016 00:46
I'm pretty sure that in Haskell, a lens like this would not build up intermediate structures if they weren't there. It would only operate on the path as found.
I could be wrong about this, but that's my understanding.
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:46
What would it's behavior be if the structure isn't found?
Because I find the fact that it creates the nested object if it doesn't exist to be extremely useful
Scott Sauyet
@CrossEye
Mar 09 2016 00:47
Don't know if it would be a no-op or an error. lensIndex is a no-op now.
assoc and assocPath do that fine.
But I'm not so sure that this is the correct behavior for a lens.
Of course we're defining it, so we can decide for ourselves, but there was a great deal of thought put into Haskell's implementation.
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:48
But there's no R.over for paths (no mapPath), just lenses. Which means that if I'm using lenses to eventually do some R.overs, I like the fact that it creates the nested object if it doesn't exist so I don't have to add a whole bunch of logic for htat
Brad Compton (he/him)
@Bradcomp
Mar 09 2016 00:48
@SebastienDaniel
let paths = [
  ['entity', 'externalEntity', 'persons'],
  ['entity', 'externalEntity', 'organizations'],
  ['entity', 'internalEntity', 'humanResources'], 
  ['entity', 'internalEntity', 'departments']
]
let tree = {
    entity: {
        externalEntity: {
            persons: [],
            organizations: ['brad']
        },
        internalEntity: {
            humanResources: [],
            departments: []
        }
    }
}

let findPerson = R.curry((tree, path, name) => R.compose(R.contains(name), R.path(path))(tree));
findPerson(tree, paths[1], 'brad')
R.converge((a, b, c, d) => {console.log(a, b, c, d)}, R.map(findPerson(tree), paths))('brad')
Replace the final function in converge with something ... useful
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 00:49
Yeah
Thats true
Sebastien Daniel
@SebastienDaniel
Mar 09 2016 00:57
thx @Bradcomp !
Scott Sauyet
@CrossEye
Mar 09 2016 01:13
@Risto-Stevcev: I'm not at all certain about this. And I want to investigate other lens implementations, but if I'm right, then I might want to change these functions a bit, and I would be much more willing to consider something like mapPath.
Brian Gates
@brian-gates
Mar 09 2016 04:49
What's the best way to 'rename' properties on an object?
David Chambers
@davidchambers
Mar 09 2016 04:51
Via a lambda, I would say. ;)
Brian Gates
@brian-gates
Mar 09 2016 04:51
suppose I could just map over them.
mapObjIndexed
Keith Alexander
@kwijibo
Mar 09 2016 08:40
as @davidchambers says, it's hard to beat something like o => { return { firstName: o.first_name, lastname: o.surname }} for brevity and declaritiveness
(if you want to be explicit about the output object; if you just want to rename some properties, leaving the rest, this isn't the best way)
Aldwin Vlasblom
@Avaq
Mar 09 2016 08:49
I like:
const create = curry((spec, val) => map(f => f(val), spec))

create({
  firstName: prop('first_name'),
  lastName: prop('last_name')
  fullName: o => `${o.first_name} ${o.last_name}`
})
Maybe overkill to rename a key though.
Especially if you want to keep all other keys.
Hardy Jones
@joneshf
Mar 09 2016 16:13
Since the last day has been about lenses, why not a lens solution :)
@ram-bot
const getter = o => ({...o, fullName: `${o.first} ${o.last}`});
const setter = ({fullName}, o) => {
  const [first, last] = fullName.split(' ', 2);
  return {...o, first, last};
};
const upper = R.lens(getter, setter);
const character = {first: 'Pat', last: 'Riley'};
const actress = {fullName: 'Julia Sweeny', first: 'Julia', last: 'Sweeny'};

[R.view(upper, character), R.set(upper, actress, character)];
ram-bot
@ram-bot
Mar 09 2016 16:14
SyntaxError: Unexpected token ...
Hardy Jones
@joneshf
Mar 09 2016 16:14
beh
Gives back
[{"first": "Pat", "fullName": "Pat Riley", "last": "Riley"}, {"first": "Julia", "last": "Sweeny"}]
uhh, pretend upper is named something sensible :blush:
Jigar Gosar
@jigargosar
Mar 09 2016 16:31
ramda doesn't have map with index, any simple way to construct it? since I wan't to use the index in the computation.
LeonineKing1199
@LeonineKing1199
Mar 09 2016 16:32
There's R.addIndex
Jigar Gosar
@jigargosar
Mar 09 2016 16:32
thanks will check
LeonineKing1199
@LeonineKing1199
Mar 09 2016 16:32
let indexedMapFunction = R.addIndex(R.map);
Jigar Gosar
@jigargosar
Mar 09 2016 16:33
thanks, I was looking for it from past 1 hour, but at wrong place :)
Raine Virta
@raine
Mar 09 2016 16:37
12
Raine Virta
@raine
Mar 09 2016 16:44
@joneshf I could fix that if I knew how to pass --es_staging as environment variable to node. linux doesn't like arguments in shebang
Irakli Safareli
@safareli
Mar 09 2016 17:14
if i call this with any arguments R.add will only get 2 and 5 R.compose(R.add(2), R.always(5))(7,8,9). could i rewrite it so that i dont need to use R.always?
like R.partial(R.add(2), [5])(7,8,9) but partial will call add with 7,8,9 too and i want only 2 and 5 to be passed to R.add
LeonineKing1199
@LeonineKing1199
Mar 09 2016 17:31
First off, what are you trying to do?
Irakli Safareli
@safareli
Mar 09 2016 18:41
i want some function to which i could give f:function and args:arguments and it would return a nullary function which, then will call f with args.
const desiredFunction = (f, args) => {
  return () => {
    return f(...args);
  }
}
LeonineKing1199
@LeonineKing1199
Mar 09 2016 18:47
Hmm... Why not just use bind? You can bind arguments to any function and then you can just invoke it without args
Irakli Safareli
@safareli
Mar 09 2016 18:52
const sumArgs = (...args) => R.sum(args)
const bindedF = sumArgs.bind(undefined,1,2)
bindedF(3) // 6
i want it bindedF(3) to return 3
Brad Compton (he/him)
@Bradcomp
Mar 09 2016 18:55
R.nAry might help you with that
Brad Compton (he/him)
@Bradcomp
Mar 09 2016 19:02
const sumArgs = (...args) => R.sum(args)
const bindedF = R.nAry(0, sumArgs.bind(undefined,1,2))
bindedF(3, 4)   //3
Irakli Safareli
@safareli
Mar 09 2016 19:05
:3
yeh R.nAry was what i needed thans
Drew
@dtipson
Mar 09 2016 19:06
attempt to explain how view works: lenses are defined as a setter function that runs .map on the result of the getter function. With view, the getter function wraps the value found at the key location in a Const, and Const's .map is just x=>_=>x, so the setter just returns the value unaltered (i.e. the setting operation is just thrown out, it's what _ is)
it's really elegant: so much mileage out of reusing the same structures. It's almost worth extracting just all the different lense modules into their own file and looking at them all at once to see how they fit together
Kevin Wallace
@kedashoe
Mar 09 2016 19:10

@raine i'm not sure exactly how ram-bot works, but what about putting an executable file on the server, node-harmony, with contents along the lines of

#!/bin/bash

file=$1
shift
node --harmony "$file" "$@"

and then using that in place of node

Irakli Safareli
@safareli
Mar 09 2016 19:13
@dtipson this video helped me to get some understanding of lenses https://vimeo.com/104807358
Drew
@dtipson
Mar 09 2016 19:15
yeah, that's what gave me the a ha
it also clarifies a lot about where and what is mapped, and thus why the structures of things at and above the level of focus of the lens can't be changed
Drew
@dtipson
Mar 09 2016 19:47
then he casually used over on an iso and another lightbulb went off that I'm still processing https://gist.github.com/DrBoolean/595dcf05424f86b1dabb/
Vladimir Starkov
@iamstarkov
Mar 09 2016 20:11
hi everybody
can you help me with R.pipeP?
i have a function which looks like this:
// saveToDeps :: Array[String] -> Object
const saveToDeps = deps => {
  if (R.not(R.is(Array, deps))) {
    return Promise.reject('deps should be an Array[String]');
  }
  if (R.not(R.all(R.is(String), deps))) {
    return Promise.reject('deps should be an Array[String]');
  }
  return Promise.all(deps.map(completeDep)).then(R.pipe(
    R.mergeAll,
    sorted
  ));
};
i want to try R.pipeP
i tried this approach:
const saveToDeps = R.pipeP(
  R.unless(R.is(Array), () => Promise.reject('error')),
  R.unless(R.all(R.is(String)), () => Promise.reject('error')),
  R.map(completeDep),
  Promise.all,
  R.mergeAll,
  sorted
);
but it didnt work out
Brad Compton (he/him)
@Bradcomp
Mar 09 2016 20:18
let toP = Promise.resolve.bind(Promise);
const saveToDeps = R.pipeP(
  toP,
  R.unless(R.is(Array), () => Promise.reject('error')),
  R.unless(R.all(R.is(String)), () => Promise.reject('error')),
  R.map(completeDep),
  Promise.all,
  R.mergeAll,
  sorted
);
That will ensure that whatever you pass in will automatically be wrapped in a Promise
You may need to bind Promise.all, but I'm not sure
Vladimir Starkov
@iamstarkov
Mar 09 2016 20:23
that worked out
thank you
Promise.all should be binded of course
Brad Compton (he/him)
@Bradcomp
Mar 09 2016 22:45
Surprised to find Ramda doesn't have a flatMap function
David Chambers
@davidchambers
Mar 09 2016 22:45
R.chain
Brad Compton (he/him)
@Bradcomp
Mar 09 2016 22:45
:sunglasses:
David Chambers
@davidchambers
Mar 09 2016 22:45
It's named chain, @Bradcomp. ;)
Brad Compton (he/him)
@Bradcomp
Mar 09 2016 22:50
ugh, I really should have been able to find that. Thanks!
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 22:50
Yeah FP peoples need to come up with some standard naming convention... pure, return, unit, or flatMap, bind, chain
Too many aliases
David Chambers
@davidchambers
Mar 09 2016 22:51
Indeed.
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 22:51
fold vs reduce....
David Chambers
@davidchambers
Mar 09 2016 22:51
Don't forget >>= and all the other "symbols".
Risto Stevcev
@Risto-Stevcev
Mar 09 2016 22:53
Yeah, definitely. I think Cabal and use of "symbols" by Haskell are it's biggest downer. That's possibly the worst thing to bring from math conventions.
Everything's electronic now, there's no good reason to save space on a piece of paper using symbols
Another stupid thing with math conventions is the reuse of a symbol to indicate a completely different operation, possibly in a completely different and incompatible branch of math
(facepalm)
Facepalm