These are chat archives for ramda/ramda

4th
May 2016
Hardy Jones
@joneshf
May 04 2016 04:18
@Bradcomp don't forget this line:
  1. b must be a value of the same Semigroup
    1. If b is not the same semigroup, behaviour of concat is unspecified.
David Langford
@That-David-Guy
May 04 2016 09:05
Thanks @Bradcomp and @CrossEye again for your help. Learnt much going through your code (like cond!). This is what I ended up going with:
@ram-bot
let isNotNumber = R.compose(R.not, R.is(Number), R.nthArg(1))
let isNotRequiringUpdate = R.either(isNotNumber, R.flip(R.contains))

let maxSort =  R.sort(R.subtract)
let limitedConcat = R.useWith(R.concat, [R.init, R.identity])
let updateArray = R.compose(maxSort, limitedConcat)

//  - Add's value to array, replacing another value (array.length doesn't change)
//  - Won't add duplicate or non-numbers to the array
let addToLengthlimitedArray = R.cond([
  [isNotRequiringUpdate, R.identity],
  [R.T, updateArray]
]);


let data = [1, 5, 10, 25]
R.equals(
[
  addToLengthlimitedArray(data, 36),
  addToLengthlimitedArray(data, 11),
  addToLengthlimitedArray(data, 3),
  addToLengthlimitedArray(data, 5),
  addToLengthlimitedArray(data, undefined),
  addToLengthlimitedArray(data, null),
],
[
  [1, 5, 10, 36], 
  [1, 5, 10, 11], 
  [1, 3, 5, 10], 
  [1, 5, 10, 25], 
  [1, 5, 10, 25],
  [1, 5, 10, 25]
])
ram-bot
@ram-bot
May 04 2016 09:05
false
David Langford
@That-David-Guy
May 04 2016 09:06
hmm, prints true in my ramda window. http://goo.gl/uYQNW2
I'm still not entirely happy with it, it's not super clear. But it's point free. I also tried to use when instead of cond but couldn't get it to work with the multiple arguments
Lewis
@6ewis
May 04 2016 14:32
@ram-bot
const isAString = (text) => R.is(String, text);
const trimString = (text) => R.when(isAString(text), R.trim(text));

console.log(trimString(" frfr "));
ram-bot
@ram-bot
May 04 2016 14:32
console is not defined
Lewis
@6ewis
May 04 2016 14:32
why does it return a function i expected R.trim(text) t be returned
Raine Virta
@raine
May 04 2016 14:33
for one, R.when takes a function as first argument
you're giving it a boolean
Lewis
@6ewis
May 04 2016 14:34
Ah I see thanks @raine
it would be nice to have an error message saying that it expects a func
Tim Navrotskyy
@dypsilon
May 04 2016 14:55
Hi everyone, I'm looking for open source examples of somewhat large projects written in point-free JavaScript. Preferably web applications. Do you know some?
David Chambers
@davidchambers
May 04 2016 14:57
The build script for the Sanctuary website is worth a look, @dypsilon. I don't know of a larger example. Let me know if you find one!
Vladimir Starkov
@iamstarkov
May 04 2016 15:02
@dypsilon i wrote deep recursive resolving of javascript dependencies in almost pure point-free https://github.com/iamstarkov/es-deps-deep/
@dypsilon all the related packages are also point-free https://github.com/iamstarkov/es-deps-deep/#related
feeel free to ask any questions
Lewis
@6ewis
May 04 2016 15:04
@ram-bot
const isAString = R.is(String);
const trimString = R.when(isAString, R.trim);
const isAnEmptyString = (text) => R.isEmpty(trimString(text));
const isANullValue = (text) => R.isNil(text);
const nullOrEmpty = R.either(isANullValue, isAnEmptyString);
const neitherNullNorEmpty = () => !nullOrEmpty;

R.filter(neitherNullNorEmpty, ["aaaa", "       ", nul]) //[]
ram-bot
@ram-bot
May 04 2016 15:04
nul is not defined
Lewis
@6ewis
May 04 2016 15:05
anyways it returns [] instead of ["aaaa"]. given that i spelled null right
ideas?
Brad Compton (he/him)
@Bradcomp
May 04 2016 15:06
This message was deleted
@ram-bot
const isAString = R.is(String);
const trimString = R.when(isAString, R.trim);
const isAnEmptyString = (text) => R.isEmpty(trimString(text));
const isANullValue = (text) => R.isNil(text);
const nullOrEmpty = R.either(isANullValue, isAnEmptyString);
const neitherNullNorEmpty = R.complement(nullOrEmpty);

R.filter(neitherNullNorEmpty, ["aaaa", "       ", null]) //[]
ram-bot
@ram-bot
May 04 2016 15:06
[ 'aaaa', '       ' ]
Brad Compton (he/him)
@Bradcomp
May 04 2016 15:06
Almost there
Tim Navrotskyy
@dypsilon
May 04 2016 15:07
@davidchambers ah thank you, it's already a great example of point-free. If I may ask a question: I noticed, that you don't try to encapsulate side effects like reading environment variables or writing to stdout (e.g. IO Monad or Reader Monad). What is the reasoning behind this decision?
Lewis
@6ewis
May 04 2016 15:07
@Bradcomp it's supposed to be just ["aaaa"] :)
Brad Compton (he/him)
@Bradcomp
May 04 2016 15:07
@6ewis This part: const neitherNullNorEmpty = () => !nullOrEmpty; doesn't take any arguments, so it really just evaluates to () => false
Raine Virta
@raine
May 04 2016 15:07
R.reject(nullOrEmpty, /* ... */)
Brad Compton (he/him)
@Bradcomp
May 04 2016 15:07
I know, that's why I said almost
Lewis
@6ewis
May 04 2016 15:07
This message was deleted
@Bradcomp thanks
@Bradcomp that's silly that I got all the way there and I forgot the argument
Tim Navrotskyy
@dypsilon
May 04 2016 15:11
@iamstarkov ah thank you, your example is very useful, I'm about to do some recursive work, too.
David Chambers
@davidchambers
May 04 2016 15:13
@dypsilon, my "rules" for writing scripts are different from my rules for writing application code. In a script I'm happy to use fs.readFileSync, for example, whereas in application code I'd use the asynchronous equivalent. In a build script I'm also happy to make assumptions in order to keep the code straightforward. I might assume, for example, the existence of a well-formed file at a known path.
Tim Navrotskyy
@dypsilon
May 04 2016 15:17
@davidchambers I see, thank you for explanation. Do you think its useful to encapsulate side effects in application code?
I'm learning to work with monads right now and wonder if it's practical to use them heavily in JS code.
David Chambers
@davidchambers
May 04 2016 15:20
It is absolutely practical, in my view! Many JavaScript developers are happy working with promises which are incredibly complex compared to a Future/Task type.
Lewis
@6ewis
May 04 2016 15:20
@raine thanks reject is even better
Brad Compton (he/him)
@Bradcomp
May 04 2016 15:22
@dypsilon In case it's useful, I've been refactoring an API I wrote to use a more pointfree / functional approach. It's still a WIP, but I've found using monads has forced me to think through the implication of my code more up front, which is nice: https://github.com/Bradcomp/egghunt-server/tree/functional
Tim Navrotskyy
@dypsilon
May 04 2016 15:22
@davidchambers sounds reasonable
Brad Compton (he/him)
@Bradcomp
May 04 2016 15:24
@That-David-Guy I've been bitten by the fact that when expects unary functions as well.
Tim Navrotskyy
@dypsilon
May 04 2016 15:27
@Bradcomp it's very useful, thank you. Your code answers many questions I had about FP.
Lewis
@6ewis
May 04 2016 15:48
R.or does not short circuit the running operation, does it?
why not?
Brad Compton (he/him)
@Bradcomp
May 04 2016 15:49
R.or
Lewis
@6ewis
May 04 2016 15:50
I brought it up a while ago - or doesn't work like || since it's not short-circuited
isn't it unnatural to most developers?
Brad Compton (he/him)
@Bradcomp
May 04 2016 15:51
It's due to JavaScript being an eagerly evaluated language. The arguments to a function are evaluated before the function is called.
Lewis
@6ewis
May 04 2016 15:51
R.either is short circuited (I don't even know if "short-circuited" is proper English lol)
Brad Compton (he/him)
@Bradcomp
May 04 2016 15:52
The s on the ram-bot link points to the implementation (which is why I summoned it)
Lewis
@6ewis
May 04 2016 15:52
I see
Brad Compton (he/him)
@Bradcomp
May 04 2016 15:53
either takes two functions as arguments, so Ramda can determine whether to call them from within the function. or on the other hand takes booleans, so it can't short circuit due to how JavaScript evaluates
Lewis
@6ewis
May 04 2016 15:53
@Bradcomp thanks. shouldn't we add something like if a === false return false otherwise b instead
Brad Compton (he/him)
@Bradcomp
May 04 2016 15:54
to R.or?
Lewis
@6ewis
May 04 2016 15:54
yes since it uses currying. it doesn't have to wait for b to evaluate or am I wrong
Brad Compton (he/him)
@Bradcomp
May 04 2016 15:56
It wouldn't change the semantics. Whatever you pass into a function will be evaluated. Even with currying, you still end up passing two arguments so you run into the same issue.
You could use thunks to create a different function that would short circuit, which would basically be either, but without any arguments.
Lewis
@6ewis
May 04 2016 16:00
@Bradcomp I see. got it
let's call R.Sor then (stand for Special Or) =)
Lewis
@6ewis
May 04 2016 17:25
is there a quick way to filter an object with just certain keys
David Chambers
@davidchambers
May 04 2016 17:54
R.pick
Lewis
@6ewis
May 04 2016 18:00
@davidchambers thanks
@davidchambers I wish I could rename some functions. I would have named pick, selectKeys
David Chambers
@davidchambers
May 04 2016 18:03
I agree that "pick" is not very descriptive.
Brad Compton (he/him)
@Bradcomp
May 04 2016 18:04
I will sometimes get pick and pluck confused and have to look up which is which.
Lewis
@6ewis
May 04 2016 18:04
@davidchambers more over when you look at the doc you are more inclined to type keys...or select - good name is useful when you have no idea if the fct you're looking for exist
Brad Compton (he/him)
@Bradcomp
May 04 2016 18:05
Lewis
@6ewis
May 04 2016 18:06
@Bradcomp I've seen it but I haven't reached that level of smart to memorize it all yet
Brad Compton (he/him)
@Bradcomp
May 04 2016 18:07

I don't mean to memorize, but it's a good lookup table. If you look at the Object section you'll see this:

I want to select specific keys | pick / pickAll

Lewis
@6ewis
May 04 2016 18:17
@Bradcomp good point
I'll keep in mind for future reference
Lewis
@6ewis
May 04 2016 18:27
R.equals
Lewis
@6ewis
May 04 2016 18:28
I would have made equals take an infinite number of arguments
R.equals(1,1,1,1,1,1,1,1,1)
David Chambers
@davidchambers
May 04 2016 18:35
Then it couldn't be curried, @6ewis. Being able to write R.equals(0) is very useful.
Tim Navrotskyy
@dypsilon
May 04 2016 18:35
R.fold
ram-bot
@ram-bot
May 04 2016 18:35
Error: No such function fold
David Chambers
@davidchambers
May 04 2016 18:38
R.reduce
David Chambers
@davidchambers
May 04 2016 18:39
@ram-bot
R.compose(R.propEq('length', 1), R.uniq)([1,1,1,1,1,1,1,1,1])
ram-bot
@ram-bot
May 04 2016 18:39
true
Brad Compton (he/him)
@Bradcomp
May 04 2016 18:40
@ram-bot
R.all(R.equals(1), [1,1,1,1,1,1,1,1,1,1])
ram-bot
@ram-bot
May 04 2016 18:40
true
Brad Compton (he/him)
@Bradcomp
May 04 2016 18:42
@ram-bot
R.unapply(R.all(R.equals(1)))(1,1,1,1,1,1,1,1,1)
ram-bot
@ram-bot
May 04 2016 18:42
true
Brad Compton (he/him)
@Bradcomp
May 04 2016 18:43
If you really need a variadic function, unapply is a good tool
David Chambers
@davidchambers
May 04 2016 18:43
You've hard-coded 1, though. Presumably this function should be allEq rather than allEqOne. ;)
Brad Compton (he/him)
@Bradcomp
May 04 2016 18:45
Good point.
I like the uniq trick, it's what I would probably use IRL
David Chambers
@davidchambers
May 04 2016 18:47
The problem is it doesn't handle [].
We'd need to use R.uniq(xs).length <= 1 (which is not too bad).
Tim Navrotskyy
@dypsilon
May 04 2016 18:49
R.foldmap
ram-bot
@ram-bot
May 04 2016 18:49
Error: No such function foldmap
Robert Plummer
@robertleeplummerjr
May 04 2016 18:50
I want to array.includes() using ramda, is this possible?
David Chambers
@davidchambers
May 04 2016 18:50
R.contains
David Chambers
@davidchambers
May 04 2016 18:50
That'll do the trick, @robertleeplummerjr. :)
Robert Plummer
@robertleeplummerjr
May 04 2016 18:51
I saw that in documentation, but I didn't understand how it applied: R.contains([42], [[42]]);
David Chambers
@davidchambers
May 04 2016 18:51
@ram-bot
R.contains('foo', ['foo', 'bar', 'baz'])
Robert Plummer
@robertleeplummerjr
May 04 2016 18:51
So say we have two different arrays, one were are searching, this will be array1, and one that has the values we want to find, this one is array2, which goes where?
ram-bot
@ram-bot
May 04 2016 18:51
true
David Chambers
@davidchambers
May 04 2016 18:52
The type of R.contains is a -> [a] -> Boolean.
Are you looking for the intersection of two arrays?
Robert Plummer
@robertleeplummerjr
May 04 2016 18:53
I want to know if any of the values exist in an array.
David Chambers
@davidchambers
May 04 2016 18:53
So you have something like [1, 2, 3] and something like [2, 4, 6], and you want to determine whether the intersection is empty or contains at least one value?
Robert Plummer
@robertleeplummerjr
May 04 2016 18:54
YES!
David Chambers
@davidchambers
May 04 2016 18:54
Great!
@ram-bot
R.intersection([1, 2, 3], [2, 4, 6])
ram-bot
@ram-bot
May 04 2016 18:54
[ 2 ]
Brad Compton (he/him)
@Bradcomp
May 04 2016 18:54
beat me to it
Robert Plummer
@robertleeplummerjr
May 04 2016 18:54
Blimey!
Vladimir Starkov
@iamstarkov
May 04 2016 18:54
R.pipe(R.intersection, R.isEmpty)
Robert Plummer
@robertleeplummerjr
May 04 2016 18:55
You guys are blowing my mind.
Vladimir Starkov
@iamstarkov
May 04 2016 18:55
@ram-bot
R.pipe(R.intersection, R.isEmpty)([1, 2, 3], [4, 5, 6])
Robert Plummer
@robertleeplummerjr
May 04 2016 18:56
Beautiful
Vladimir Starkov
@iamstarkov
May 04 2016 18:56
for some reason @ram-bot is ignoring me
Lewis
@6ewis
May 04 2016 18:56
@ram-bot
const isAddress = (attribute) => { 
  const data = ['concatenated_registered_address',
                'concatenated_mailing',
                'concatenated_dividend_address'
               ];
  const curryEqualsAttribute = (acc,next) => R.equals(attribute)(next) || acc;
  return R.reduce(curryEqualsAttribute, false, data);
}


isAddress('concatenated_registered_address')
ram-bot
@ram-bot
May 04 2016 18:56
true
David Chambers
@davidchambers
May 04 2016 18:56
The bot doesn't respect edits, @iamstarkov.
Lewis
@6ewis
May 04 2016 18:57
someone has a better way to do what I did above? (code above)
Robert Plummer
@robertleeplummerjr
May 04 2016 18:58
Better is subjective?
:P
jk
Thanks @davidchambers, @iamstarkov , @Bradcomp, and @6ewis for your fine answers!
David Chambers
@davidchambers
May 04 2016 18:59
You're welcome. :)
Robert Plummer
@robertleeplummerjr
May 04 2016 18:59
and of course... @ram-bot!
You guys are far too kind.
Vladimir Starkov
@iamstarkov
May 04 2016 19:02

@6ewis

@ram-bot

const isAddress = R.complement(R.contains([
  'concatenated_registered_address',
  'concatenated_mailing',
  'concatenated_dividend_address'
]));

isAddress('concatenated_registered_address')
Brad Compton (he/him)
@Bradcomp
May 04 2016 19:04
@iamstarkov I think you mean R.flip
Vladimir Starkov
@iamstarkov
May 04 2016 19:04
even better
Lewis
@6ewis
May 04 2016 19:04
@iamstarkov here you go =)
R.flip
Vladimir Starkov
@iamstarkov
May 04 2016 19:04
@ram-bot
const isAddress = R.contains(R.__, [
  'concatenated_registered_address',
  'concatenated_mailing',
  'concatenated_dividend_address'
]);

isAddress('concatenated_registered_address')
true
Vladimir Starkov
@iamstarkov
May 04 2016 19:04
@ram-bot
const isAddress = R.contains(R.__, [
  'concatenated_registered_address',
  'concatenated_mailing',
  'concatenated_dividend_address'
]);

isAddress('concatenated_registered_address')
ram-bot
@ram-bot
May 04 2016 19:04
true
Brad Compton (he/him)
@Bradcomp
May 04 2016 19:04
^^^ that one!
Vladimir Starkov
@iamstarkov
May 04 2016 19:05
forgot args order of contains
@6ewis ^
Robert Plummer
@robertleeplummerjr
May 04 2016 19:05
wow!
Lewis
@6ewis
May 04 2016 19:05
@iamstarkov I like that last one better
Vladimir Starkov
@iamstarkov
May 04 2016 19:08
=) glad to help
Lewis
@6ewis
May 04 2016 19:09
@iamstarkov ;)
Jonah
@jonahx
May 04 2016 19:56
can anyone improve my implementation of finding all permutations of an array:
function perm(arr, result=[[]]) {
  return !arr.length ? result :
    chain(r => addIndex(chain)(
      (a,i) => perm(remove(i,1,arr), [r.concat(a)]), arr), result)
}
Vladimir Starkov
@iamstarkov
May 04 2016 20:03
@jonahx can you provide some expectations?
Jonah
@jonahx
May 04 2016 20:04
perm([1,2,3])
// => [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
current version works, i just find it rather ugly
Vladimir Starkov
@iamstarkov
May 04 2016 20:07
trying to play with xprod
Jonah
@jonahx
May 04 2016 20:08
yeah, me too :)
i believe there’s a nice solution to be found there
Vladimir Starkov
@iamstarkov
May 04 2016 20:09
i bet on reduce with xprod
@ram-bot
const perm = R.pipe(
  R.repeat(R.__, 2),
  R.apply(R.xprod)
);

perm([1, 2, 3])
ram-bot
@ram-bot
May 04 2016 20:11
[ [ 1, 1 ],
  [ 1, 2 ],
  [ 1, 3 ],
  [ 2, 1 ],
  [ 2, 2 ],
  [ 2, 3 ],
  [ 3, 1 ],
  [ 3, 2 ],
  [ 3, 3 ] ]
Vladimir Starkov
@iamstarkov
May 04 2016 20:12
close, but not there
Jonah
@jonahx
May 04 2016 20:14
I dont think you’ll be able to avoid recursion
(in some form)
Vladimir Starkov
@iamstarkov
May 04 2016 20:33

@jonahx its how far i can get

@ram-bot

const _chain = R.curry((arr, r) => addIndex(chain)( (a,i) => perm(remove(i,1,arr), [r.concat(a)]), arr));

const perm = (arr, result=[[]]) => R.ifElse(
  R.always(R.isEmpty(arr)),
    R.identity,
    chain(_chain(arr))
)(result);

perm([1, 2, 3])
Vladimir Starkov
@iamstarkov
May 04 2016 20:41
nah
@jonahx was going to split it into basic functions, but it escalated very quickly
const indexChain = addIndex(chain);

const _perm = R.curry((arr, r, a, i) => perm(remove(i, 1, arr), [r.concat(a)]));

const _chain = R.curry((arr, r) => indexChain(_perm(arr, r), arr));

const perm = (arr, result=[[]]) => R.ifElse(
  R.always(R.isEmpty(arr)),
    R.identity,
    chain(_chain(arr))
)(result);

perm([1, 2, 3]);
i give up
Tobias Pflug
@gilligan
May 04 2016 20:43
waaaah ;)
Jonah
@jonahx
May 04 2016 20:43
lol, thanks anyway vladimir, i think i might have something, still working it out tho...
Vladimir Starkov
@iamstarkov
May 04 2016 20:45
you are right
my own mantra is: while tests are green, im fine, can refactor anything later anyway
Lewis
@6ewis
May 04 2016 20:58
most succinct way to write "filter the array based on id & return the object (theres only one in the array)" - I'm sure there's yet again a shortcut
David Chambers
@davidchambers
May 04 2016 21:00
@ram-bot
function permutations(xs) {
  return (
    xs.length === 0 ? [] :
    xs.length === 1 ? [xs] :
    R.chain(xs$ => R.map(R.insert(R.__, xs[0], xs$), R.range(0, xs$.length + 1)),
            permutations(R.tail(xs)))
  );
}

permutations([1, 2, 3]);
ram-bot
@ram-bot
May 04 2016 21:00
[ [ 1, 2, 3 ],
  [ 2, 1, 3 ],
  [ 2, 3, 1 ],
  [ 1, 3, 2 ],
  [ 3, 1, 2 ],
  [ 3, 2, 1 ] ]
Lewis
@6ewis
May 04 2016 21:02
@jonahx combinatorics.permutation is you use the library math.combinatorics
Brad Compton (he/him)
@Bradcomp
May 04 2016 21:03
@6ewis R.find should do what you want
Lewis
@6ewis
May 04 2016 21:04
@Bradcomp it returns an array
R.find
Lewis
@6ewis
May 04 2016 21:04
oh really
Brad Compton (he/him)
@Bradcomp
May 04 2016 21:05
@ram-bot
R.find(R.propEq('id', 1), [{id: 1}, {id: 2}])
ram-bot
@ram-bot
May 04 2016 21:05
{ id: 1 }
Lewis
@6ewis
May 04 2016 21:11
@Bradcomp thanks, can't believe I didn't think about find - why did i think it returns the array with the result
Scott Sauyet
@CrossEye
May 04 2016 21:11
Tail-recursive permutation I did some time ago: https://gist.github.com/CrossEye/f7c2f77f7db7a94af209
Lewis
@6ewis
May 04 2016 21:12
R.chain
Lewis
@6ewis
May 04 2016 21:13
another name I don't like :/
@ram-bot you're like my ramda mentor lol
Scott Sauyet
@CrossEye
May 04 2016 21:22
chain is a name I don't much like either, but Fantasy-land integration is too important.
Jonah
@jonahx
May 04 2016 21:24
@CrossEye agreed, flatmap is more descriptive imo
@CrossEye @davidchambers thanks for your answers
Lewis
@6ewis
May 04 2016 21:25
or, chain, pick : few names I don't like
Lewis
@6ewis
May 04 2016 21:31
R.assoc
Lewis
@6ewis
May 04 2016 21:32
@ram-bot
R.assoc("test", () => "return func", {})
ram-bot
@ram-bot
May 04 2016 21:32
{ test: [Function] }
Jonah
@jonahx
May 04 2016 21:46
@iamstarkov @CrossEye @davidchambers Finally got a version with xprod that I like. This reflects how I think about the algo intuitively:
var perm = (arr, result=[[]]) => {
  return !arr.length ? map(flatten, result) :
    chain(i => perm(remove(i,1,arr), xprod(result, of(arr[i])))
    , range(0, arr.length))
}
Scott Sauyet
@CrossEye
May 04 2016 22:11
I'll try to look at it when I'm in front of a computer.
Jonah
@jonahx
May 04 2016 22:18
in that case, here is a very slight improvement:
var perm = (arr, result=[[]]) => 
  !arr.length ? map(flatten, result) :
    addIndex(chain)(
      (x,i) => perm(remove(i,1,arr), xprod(result, of(x)))
    , arr)
Jonah
@jonahx
May 04 2016 22:28
i suppose map(concat([x]), result) might be clearer than xprod too
also, looking over your solution more closely now scott, i realize this is almost identical…
Brad Compton (he/him)
@Bradcomp
May 04 2016 22:34
R.lensIndex