These are chat archives for ramda/ramda

30th
Aug 2016
Aadi Deshpande
@cilquirm
Aug 30 2016 02:45
i’m using R.apply to pass along an array as individual argument. is there a function that can let me slice just one parameter into a specific function
i.e. i’m doing something like this
R.converge(R.concat, [R.apply(myFunc1),R.apply(myFunc2)])
James Forbes
@JAForbes
Aug 30 2016 03:36
how bout R.apply(R.converge(R.concat, [myFunc1, myFunc2])) @cilquirm ?
Churchill Lee
@FeliciousX
Aug 30 2016 09:41
is there a rule of thumb to when u use compose vs pipe ?
Denis Stoyanov
@xgrommx
Aug 30 2016 09:45
@FeliciousX in math all applying from left side (compose). Pretty easy explanation => f (.) g $ x === x ( g ( x ) )
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 09:46
I prefer to use compose because right to left composition is more common when reading about FP. It also better lends itself to currying
Denis Stoyanov
@xgrommx
Aug 30 2016 09:47
But pipe = (...fns) => compose(...fns.reverse())
Churchill Lee
@FeliciousX
Aug 30 2016 09:49
so it's just preference?
Denis Stoyanov
@xgrommx
Aug 30 2016 09:50
@FeliciousX it depend
Churchill Lee
@FeliciousX
Aug 30 2016 09:51
on... ?
to me i thought pipe is for direct execution
and compose is to make a new function
but then again it can be done both ways
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 09:51
no they're just the opposite of each other
both create new fns
Churchill Lee
@FeliciousX
Aug 30 2016 09:52
i think they're the same? just that one is left-to-right and right-to-left
so yeah, preference !
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 09:52
yes, it is preference.
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 09:52
But it's more idiomatic to use right-to-left composition
Churchill Lee
@FeliciousX
Aug 30 2016 09:53
So, composition and currying are used to create functions whereas piping is used for invocation.
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 09:54
In the general sense of the 2 concepts @FeliciousX
Denis Stoyanov
@xgrommx
Aug 30 2016 09:54
@aaronmcadam @FeliciousX Pipe should be like data |> f |> f1 probably smth like fluent interface but without this
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 09:54
yeah, that makes sense
Denis Stoyanov
@xgrommx
Aug 30 2016 09:55
but composition should create a new function. This is idiomatic definition.
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 09:55
That's what I've been saying
Denis Stoyanov
@xgrommx
Aug 30 2016 09:55
In Ramda pipe isn't pipe =) because we don't have infix notation in js
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 09:56
I'm just trying to point out that although Ramda's pipe is the opposite of compose, it's more idiomatic to use compose
Denis Stoyanov
@xgrommx
Aug 30 2016 09:56
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 09:56
Yeah I heard about that one before, do you think it will get anywhere?
Denis Stoyanov
@xgrommx
Aug 30 2016 09:56
I think |> more better than ::
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 09:57
Isn't :: already taken by another proposal?
yeah that one
But I don't like ::
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 09:59
I'm not sure what it would really add
Denis Stoyanov
@xgrommx
Aug 30 2016 09:59
We return to some tricks with this. We need pipe with pure functions. So we need |>
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 10:00
I think it makes it easier to write less ideal code
What do you think of papp? https://github.com/mindeavor/es-papp
Denis Stoyanov
@xgrommx
Aug 30 2016 10:00
Generally we need infix like in livescript =) a op b
@aaronmcadam I think you can use bind for this one. https://passy.svbtle.com/partial-application-in-javascript-using-bind
@aaronmcadam Also Ramda has placeholders
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 10:02
of course you can, I just think it might a nice addition and is a move towards more FP support
I wonder what we'd need in JS to support auto-currying
Denis Stoyanov
@xgrommx
Aug 30 2016 10:03
@aaronmcadam No. We need only infix. All operators will be implemented pretty easy. Also we need symbol names for functions like const (|>) = ... For escaping we need to use ()
@aaronmcadam That isn't possible. Js engine isn't optimized for HOF.
@aaronmcadam use haskell :smile:
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 10:05
It would be nice to know how hard it would be
Or maybe we need another year or 2 of us pushing FP in JS :D
Aaron Mc Adam
@aaronmcadam
Aug 30 2016 10:14
Thanks for that
I wonder if there's anything in FP language design that makes it easier to compile than imperative languages.
Like if there's any optimisations we can make based on pureness, stuff like that
It's been a long time since I've looked at compilers so I can't remember the details hah
Denis Stoyanov
@xgrommx
Aug 30 2016 10:15
@aaronmcadam take a look on http://www.impredicative.com/ur/
Robert Smol
@stereoit
Aug 30 2016 11:05
Hello folks, I would like to filter by gender, so far I have let bySex = (sex) => R.filter(R.whereEq({sex: sex})) however I just started to get intput with "*" and my objects only have "m" or "f". How can I use "*" so any of gender would pass?
Churchill Lee
@FeliciousX
Aug 30 2016 11:19
using an OR?
This message was deleted
Churchill Lee
@FeliciousX
Aug 30 2016 11:24
import { filter, whereEq, or, match } from 'ramda';

const bySex = sex => filter( or( whereEq({sex: sex }) ,  match('*', sex) ))
does that work? @stereoit
Michael Hurley
@buzzdecafe
Aug 30 2016 11:27
or(propEq('sex', sex), propEq('sex', '*')) perhaps?
Ryan Zeigler
@rzeigler
Aug 30 2016 11:36
I would think you need to converge with or rather than using or directly.
Robert Smol
@stereoit
Aug 30 2016 12:26
super thanks
Robert Smol
@stereoit
Aug 30 2016 12:33
interestingly, I am using rollup.js for bundling and I can't use import {} from syntax;` have you run into this as well?
I can only do import R from 'ramda'
James Forbes
@JAForbes
Aug 30 2016 13:30

@FeliciousX pipe vs compose is definitely just a preference.

I personally use pipe almost exclusively. I just find it confusing to read the sequence bottom to top / right to left.
But I also see valid reasons why people use compose.

But it is completely equivalent functionally.

Robert Smol
@stereoit
Aug 30 2016 13:36

ok, I am still bit strugling with my case, I've managed to get to this code:

const bySex = (sex) => sex == "*" ?  R.always(undefined) : R.filter(R.whereEq({sex: sex}))

Basically if filter is set to: "*" I do want to return everything, but I did not find any R.noop (I only found ticket #701) but this R.always() is not working, it complains later about Cannot read property 'map' of undefined(…)

Syaiful Bahri
@syaiful6
Aug 30 2016 13:37
@JAForbes your typescript declaration file for rambda look cool, i try ts 2.1 last nite and it better than 1.8 i guess. :)
James Forbes
@JAForbes
Aug 30 2016 13:38
@syaiful6 :D yeah it is much better, non nullables and control flow analysis are great for FP
thank you for saying so

I got really excited when I found out you can get type checking for disciminated unions in TS

https://basarat.gitbooks.io/typescript/content/docs/types/discriminated-unions.html

Which supports way more literals in 2.0

Still, as always limited, but a huge improvement
Syaiful Bahri
@syaiful6
Aug 30 2016 13:40
@JAForbes i thin for union it just support string literal key on the object, right?
James Forbes
@JAForbes
Aug 30 2016 13:41
in 2.0 you've got numbers true/false and a few others as well I think
@stereoit what happens if the sex is null/undefined or neither M/F/* ?
Robert Smol
@stereoit
Aug 30 2016 13:41
@JAForbes then it is ok to return empty list
Syaiful Bahri
@syaiful6
Aug 30 2016 13:42
look great, i struggle giving type to fyd's combine function
Robert Smol
@stereoit
Aug 30 2016 13:42
I mean, this is my DB:
[ { position: { lat: 50.0705381, lng: 14.3978005 },
    type: 'player',
    sex: 'f' },
  { position: { lat: 50.0755381, lng: 14.4318005 },
    type: 'player',
    sex: 'm' },
  { position: { lat: 50.0685381, lng: 14.4385655 },
    type: 'coach',
    sex: 'm' } ]
James Forbes
@JAForbes
Aug 30 2016 13:43
R.converge(
  R.filter
  ,[
    R.cond([
      [R.equals('M'),R.equals('M')]
      ,[R.equals('F'),R.equals('F')]
      ,[R.equals('*'), R.T]
      ,[R.T, R.always([])]
    ])
   ,R.identity
   ]
)
Wait that is wrong haha
Robert Smol
@stereoit
Aug 30 2016 13:44
basically players select the filter (m,f or *) and I need to filter the available players
Syaiful Bahri
@syaiful6
Aug 30 2016 13:45
maybe need identity function for * @stereoit
Ryan Zeigler
@rzeigler
Aug 30 2016 13:48
@JAForbes interesting. I prefer compose because it matches the order of how the functional calls would be if they were nested. ie f . g x = f(g(x))
Syaiful Bahri
@syaiful6
Aug 30 2016 13:49
@stereoit try change to *, f, or m, it will give results that you want, right?
James Forbes
@JAForbes
Aug 30 2016 13:51
I'm getting there @stereoit, just fooling around in the repl. fun problem!
Ryan Zeigler
@rzeigler
Aug 30 2016 13:55
wait, what exactly is the goal here, I find myself slightly confused
select either m and or f and ?
whoops, the star went through funny
James Forbes
@JAForbes
Aug 30 2016 13:56
var f = R.useWith(R.filter, [
  R.cond([
      [R.equals('m'), R.always(R.propEq('sex','m'))]
      ,[R.equals('f'), R.always(R.propEq('sex','f'))]
      ,[R.equals('*'), R.always(R.T) ]
      ,[R.T, R.always(R.F)]
  ])
  , R.identity
])

// usage:
f('m', data)
f('f', data)
f('*', data)
@rzeigler yeah good reasoning.
Robert Smol
@stereoit
Aug 30 2016 14:00
wooohoo both works, i'll be happy to read to documentation for the rest of the afternoon :) thanks guys
James Forbes
@JAForbes
Aug 30 2016 14:07
:)
Robert Smol
@stereoit
Aug 30 2016 14:10
btw to me it looks like the R.identity was the missing noop I was looking for
Syaiful Bahri
@syaiful6
Aug 30 2016 14:11
yeah identity look useless first but then i find my self it usefull for default predicate/action. :)
Eshan Singh
@naiveaiguy
Aug 30 2016 14:17
Is there a function that filters through the properties of an object instead of the indexes of an array?
James Forbes
@JAForbes
Aug 30 2016 14:18
R.filter(R.equals(2), {a:1,b:2}) // => { b:2 } @eshansingh
or where you after filtering the keys @eshansingh ?
Eshan Singh
@naiveaiguy
Aug 30 2016 14:19
Actually thanks that works
No wait
The filter function in my case needs access to the name of the keys
Sorry!
Maybe I can use Object.keys?
yeah I think so
James Forbes
@JAForbes
Aug 30 2016 14:27
@eshansingh can you show us an example

@stereoit here is a really silly metaprogramming attempt at your problem

var K = always
var I = identity
var zipCall = zipWith(call)
var f = useWith(filter, [
  pipe(
    K(['m','f'])
    ,map( ap([I, propEq('sex')]) )
    ,append(['*', T])
    ,map( zipCall([equals,I]))
    ,append([T,F])
    ,map( zipCall([I,K]))
    ,cond
  )()
  ,I
])

It basically generates the previous sample

James Forbes
@JAForbes
Aug 30 2016 14:48
Denis Stoyanov
@xgrommx
Aug 30 2016 14:57
@JAForbes what is idea?
James Forbes
@JAForbes
Aug 30 2016 14:59

@xgrommx the original code is way clearer, but it bothered me how repetitive it was.

This example only wraps the functions in always once, and only wraps the strings in equals once. We just add conditions to the stack as we go as well ( append(['*', T]) and append([T, F])), by the end of the pipe we've got a nice nested array of conditions and we just pass it to cond.

So this is a kind of "code is data" approach
Denis Stoyanov
@xgrommx
Aug 30 2016 15:00
@JAForbes this is overcomplicated and not optimized =)
James Forbes
@JAForbes
Aug 30 2016 15:01
definitely
Derek Duncan
@derek-duncan
Aug 30 2016 17:12
anyone have some good examples of FP in a frontend codebase without a JS framework (something that uses jQuery, or even an FRP library)?
Brad Compton (he/him)
@Bradcomp
Aug 30 2016 17:33
This message was deleted
@derek-duncan there's also these videos.
Derek Duncan
@derek-duncan
Aug 30 2016 18:04
thanks! @xgrommx @Bradcomp
Michael Hurley
@buzzdecafe
Aug 30 2016 20:50
Aadi Deshpande
@cilquirm
Aug 30 2016 21:46
is there a ramda function that combines more than 2 lists into a single list?
LeonineKing1199
@LeonineKing1199
Aug 30 2016 21:46
Ha!
I love you, cilquirm
Denis Stoyanov
@xgrommx
Aug 30 2016 21:49
@cilquirm reduce(concat)([])
Aadi Deshpande
@cilquirm
Aug 30 2016 21:52
@LeonineKing1199 :worried: uh, what did i do?
R.reduce(R.concat)([])([1])([2])
that throws an error
Derek Duncan
@derek-duncan
Aug 30 2016 21:54
use R.concat(list1, list2)
Aadi Deshpande
@cilquirm
Aug 30 2016 21:54
@derek-duncan what if i need 3 lists
Denis Stoyanov
@xgrommx
Aug 30 2016 21:54
@cilquirm reduce(concat)([])([[1,2],[3,4],[5,6]])
Aadi Deshpande
@cilquirm
Aug 30 2016 21:56
@xgrommx that’s a list of lists. i could just flatten that, no?
i apologize for the newbie-ish questions. i’m still trying to grok the spirit of ramda.
Derek Duncan
@derek-duncan
Aug 30 2016 21:57
so you want to pass the arrays as 3 separate arguments?
Aadi Deshpande
@cilquirm
Aug 30 2016 21:57
yes
Raine Virta
@raine
Aug 30 2016 21:58
but why?
Aadi Deshpande
@cilquirm
Aug 30 2016 21:58
i’m using R.converge
Brad Compton (he/him)
@Bradcomp
Aug 30 2016 21:58
@ram-bot
unapply(flatten)([1], [2], [3], [4])
ram-bot
@ram-bot
Aug 30 2016 21:58
[ 1, 2, 3, 4 ]
Aadi Deshpande
@cilquirm
Aug 30 2016 21:59
@raine i have an array that gets processed in multiple ways
wow, thanks
Raine Virta
@raine
Aug 30 2016 21:59
that doesn't exactly conform to "spirit of ramda"
Aadi Deshpande
@cilquirm
Aug 30 2016 22:00
@raine that’s a fair criticism.
Brad Compton (he/him)
@Bradcomp
Aug 30 2016 22:01
variadic functions can be harder to deal with, especially in functional pipelines. In most cases it makes sense to wrap up your arguments into a list if they are all the same type. Then you could use flatten or unnest and not have to do any weird unapplying
Aadi Deshpande
@cilquirm
Aug 30 2016 22:02
i have an array of content of which parts of the array each have to be handled differently
I then have to compose it back to a “normalized” list. i thought the best approach here was to use converge
but in fairness to your point, i’m doing unseemly ‘plucks’ of the elements into each function
i’m going to think about it a bit more based on the feedback, but thanks for the assist!
Denis Stoyanov
@xgrommx
Aug 30 2016 22:26
@cilquirm so, converge is lift, lift is fn => unapply(reduce(ap)(of(fn))) So, all has start with applicative functor
@cilquirm converge = (fn, transformers) => lift(fn)(...transformers)