These are chat archives for ramda/ramda

23rd
Mar 2017
Matt Ross
@amsross
Mar 23 2017 00:10

https://gitter.im/ramda/ramda?at=58d2e23ea84f611959d25394 @xgrommx

const data = { stats: {ranking:2} };
const aLens = R.converge(R.lens, [
  R.path,
  R.assocPath,
])(["stats"]);
const bLens = R.lens(R.path(["stats"]), R.assocPath(["stats"]))

console.log("a", R.view(aLens, data)); // undefined
console.log("b", R.view(bLens, data)); // {"ranking": 2}

I would expect both of these to have the same result

Brad Compton (he/him)
@Bradcomp
Mar 23 2017 00:16
converge sets its arity to the maximum arity of the branch functions. In this case that means 3, because that's the arity of assocPath
Johnny Hauser
@m59peacemaker
Mar 23 2017 01:04
What's the advantage of _arity rather than newFn.length = arguments[0].length ?
oops, I meant Object.defineProperty to change the length
Johnny Hauser
@m59peacemaker
Mar 23 2017 02:51
nm. It's performance
Matt McKellar-Spence
@MattMS
Mar 23 2017 06:59
Is it possible to Futurify a function that returns a Promise?
Kurt Milam
@kurtmilam
Mar 23 2017 07:26
@MattMS I've seen people around here point to this library: https://github.com/futurize/futurize
Matt McKellar-Spence
@MattMS
Mar 23 2017 07:33
Interesting, thanks @kurtmilam :smile:
Kurt Milam
@kurtmilam
Mar 23 2017 07:34
:thumbsup:
Matt McKellar-Spence
@MattMS
Mar 23 2017 07:35
I really like that they've made it agnostic of Future implementations.
diqye
@diqye2014
Mar 23 2017 09:39
My colleague says you are handsome
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 10:33
Hi Guys.. First time ramda user here.
Need a quick review of my first attempt. The function is doing validation and then choosing between two different implementation of host
const relay = (args) => {
    const hostHasEnv = params => R.not(R.isNil(hosts[params.environment]));
    const relayForHost = params => R.clone(hosts[params.environment]);

    return R.cond([
        [
            R.isNil, R.always('No initialization parameters provided'),
        ],
        [
            params => R.isNil(params.bus),
            R.always('Communication bus with parent is required'),
        ],
        [
            R.pipe(
                R.either(
                    R.allPass([
                        params => R.hasIn('sendToHost', params.bus),
                        params => R.hasIn('on', params.bus),
                        params => R.hasIn('emit', params.bus),
                        params => R.hasIn('off', params.bus),
                    ]),
                    params => R.equals(window, params.bus)
                ),
                R.not
            ),
            R.always('Communication bus provided is invalid'),
        ],
        [
            params => R.isNil(params.net),
            R.always('Network bus is required'),
        ],
        [
            params => R.not(R.hasIn('getFromWeb', params.net)),
            R.always('Network bus provided is invalid'),
        ],
        [
            R.pipe(
                R.either(
                    params => R.equals('NATIVE')(params.environment),
                    params => R.equals('WEB')(params.environment),
                ),
                R.not
            ),
            R.always('environment provided has to be one of NATIVE or WEB'),
        ],
        [
            R.pipe(
                params => hostHasEnv,
                R.not
            ),
            params => R.always(`Hosts ${params.environment} not defined`),
        ],
        [
            R.T, relayForHost,
        ],
    ])(args);
};
I m not sure if this code is making use of functional composition correctly.
Kurt Milam
@kurtmilam
Mar 23 2017 11:30
@rahul-dutt-sharma I think you could replace most of these:
params => R.isNil(params.bus)
with something like this:
R.compose( R.isNil. R.prop( 'bus' ) )
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 11:30
thanks let me have a try
I was thinking of it.
Kurt Milam
@kurtmilam
Mar 23 2017 11:31
If you try that out and it works, you could create consts for environment, net and bus and reuse them.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 11:32
One strange issue I am having is by running with tests using webpack+babel
its crashing there but not when run directly
Kurt Milam
@kurtmilam
Mar 23 2017 11:33
params => R.hasIn('sendToHost', params.bus) could probably become R.compose( R.hasIn('sendToHost', prop('bus')), but you'd have to test to make sure that worked correctly.
hm, not sure what the testing issue is.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 11:37
const relayForHost = params => R.clone(hosts[params.environment]); works fine
but const relayForHost = params => R.clone(hostsparams.environment);
does not
it crashes !!
const relayForHost = params => R.clone(hosts[params.environment](params));
does not
R.compose( R.hasIn('sendToHost', prop('bus')) +1
ty
let me re do it
Kurt Milam
@kurtmilam
Mar 23 2017 11:43
Try something like this at the top:
    const getEnv = R.prop( 'environment' )
    const getHostsEnv = R.compose( R.flip( R.prop )(hosts), getEnv )
    const hostHasEnv = R.compose( R.not, R.isNil, getHostsEnv );
    const relayForHost = R.compose(R.clone, getHostsEnv);
I corrected a that just now.
Corrected it again - sorry, I'm not testing this as I go.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 11:46
const getHostsEnv = R.compose( R.flip( R.prop(hosts) ), getEnv ), thats the kind of think I want to do using ramda.
Kurt Milam
@kurtmilam
Mar 23 2017 11:46
Corrected again - I had the R.flip close parens in the wrong place.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 11:46
although.
const getEnv = R.prop( 'environment' )
    const getHostsEnv = R.compose( R.flip( R.prop )(hosts), getEnv )
    const hostHasEnv = R.compose( R.not, R.isNil, getHostsEnv );
    const relayForHost = R.compose(R.clone, getHostsEnv);
is imperative code.
but will use it
Kurt Milam
@kurtmilam
Mar 23 2017 11:46
what's imperative about it?
it's composition of functions
I just abstracted out logic you already had into reusable functions.
This was wrong above: R.compose( R.hasIn('sendToHost', prop('bus'))) should be R.compose( R.hasIn('sendToHost'), prop('bus')) Sorry for the sloppiness.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 12:22
:)
The next post in the series is also relevant. My suggestions will help you implement your logic in a largely point-f style.
point-free
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 13:25
@kurtmilam Thanks :)
Happy days
Kurt Milam
@kurtmilam
Mar 23 2017 13:33
@rahul-dutt-sharma you're welcome. That whole series of posts is very good. Feel free to share what you come up with after you've refactored your function, and I'm sure someone would be happy to look at it to see if they can find any other room for improvement. One thing you could consider is moving any functions that are reusable out of the main function body. R.flip(R.prop), for example, may be something that you need more often, in which case you could define a reusable constant for it outside of the main function body, like const objProp = R.flip(R.prop)
Johnny Hauser
@m59peacemaker
Mar 23 2017 13:56
@MattMS @kurtmilam I think mine are better futurize-p futurize-c
Kurt Milam
@kurtmilam
Mar 23 2017 13:58
@m59peacemaker thanks for sharing. Does your library also work with Fluture?
Johnny Hauser
@m59peacemaker
Mar 23 2017 13:58
I think it should work with any, yeah
Should be the same thing, I just believe in individual packages for individual problems
Kurt Milam
@kurtmilam
Mar 23 2017 13:59
Cool, thanks. Agreed. I think I could get by largely with the p library.
Johnny Hauser
@m59peacemaker
Mar 23 2017 14:01
If you use it and have any trouble, please open an issue! I have only used them for playing with futures. I've never used futures in a real application.
Kurt Milam
@kurtmilam
Mar 23 2017 14:02
Ok, I've also only played with them up until now, but will probably start working with them more seriously soon.
Johnny Hauser
@m59peacemaker
Mar 23 2017 14:06
anyone used benchmarkjs?
.add('concat', () => {
  var x = Array.prototype.concat.call([1, 2], [3, 4])
})
.add('concat again', () => {
  var x = Array.prototype.concat.call([1, 2], [3, 4])
})
// concat x 3,473,570 ops/sec ±16.70% (58 runs sampled)
// concat again x 4,496,582 ops/sec ±6.77% (55 runs sampled)
// Fastest is concat again,concat
I don't get it.
they are both the same code, yet somehow the second one had a million more operations per second, and somehow they are both equally fast? wut?
Yuriy
@djleonskennedy
Mar 23 2017 14:42
Hello i'm new here please clarify why i can't get result
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 14:47
guys, cant figure out why the below does not work.
const bus = {
    sendToHost: () => {},
};
const getBus = R.prop('bus');

R.compose(R.equals, getBus)(bus)
R.compose(R.equals, getBus)(bus) returns a function
Kurt Milam
@kurtmilam
Mar 23 2017 14:48
I believe it returns a function because R.equals is curried and is still waiting for the second input.
even so, I don't think that code is going to do what you want it to.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 14:49
R.equals takes bus during compose
and then I check against bus
Kurt Milam
@kurtmilam
Mar 23 2017 14:49
it doesn't
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 14:49
:(
Kurt Milam
@kurtmilam
Mar 23 2017 14:50
R.compose(R.equals, getBus)(bus) = R.equals( getBus( bus) ) )
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 14:50
hum
Kurt Milam
@kurtmilam
Mar 23 2017 14:50
compose( f, g )( h) = f( g( h ) ) )
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 14:51
yea yea, R.compose(R.equals, getBus)({ bus} )
Kurt Milam
@kurtmilam
Mar 23 2017 14:51
that looks better
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 14:51
thts what I have
oh dang
got it
:)
R.compose(R.equals, getBus)({ bus} )(bus)
Kurt Milam
@kurtmilam
Mar 23 2017 14:52
or, maybe clearer, R.compose(R.equals(bus), getBus)({ bus} )
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 14:52
was that I had to do. It a trivial REPL scap I m playing with to see why my actual code is failing
Kurt Milam
@kurtmilam
Mar 23 2017 14:53
but you're always going to be comparing bus to bus, so it seems your equal will always end up returning true
Rick Medina
@rickmed
Mar 23 2017 14:54
@m59peacemaker I think in your case bc of deviations is indeed not statistically significant
Johnny Hauser
@m59peacemaker
Mar 23 2017 14:54
yeah, that seems to be the case. I'm messing around with it to get around that
not sure exactly what the trick is
I'm trying to write the fastest possible concat(a, b)
Rick Medina
@rickmed
Mar 23 2017 14:55
I've read a blog article about it in js, can't remember where
Johnny Hauser
@m59peacemaker
Mar 23 2017 14:55
ramda has _concat that looks close, but there are some things that appear slightly less than ideal
Yuriy
@djleonskennedy
Mar 23 2017 14:56
but data goes last, where is my mistake ?
console.clear()

const data = {
  name: 'Joe',
  skills: ['Java', 'Elm', 'Haskell'],
  adress: {
    house: 74
  }
}

const upper = x => x.toUpperCase()

const result = R.compose(R.map(upper), R.over, R.lensProp('skills'))

result(data)
Johnny Hauser
@m59peacemaker
Mar 23 2017 14:56
not that I have any reason to know better about perf than Ramda authors. It's probably really good... I just want to know why I'm wrong if I am
Like accessing result[result.length in a loop seems like it would perform worse than result[resultLength] where you increment the var yourself
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 14:57
The errors I get in the stack trace aren't helpful. Is there a config associated to get better stacktrace?
Johnny Hauser
@m59peacemaker
Mar 23 2017 14:57
For some reason, I thought accessing the length property was more expensive
Alex Deas
@alex-deas
Mar 23 2017 15:14
So I'm trying to figure out likely causes for the bug shown here: https://goo.gl/rGQzpT looks to be an issue with the curry, anyone else got any other thoughts?
Kurt Milam
@kurtmilam
Mar 23 2017 15:18
@djleonskennedy I think you're looking for this: https://goo.gl/q4AHhz
Yuriy
@djleonskennedy
Mar 23 2017 15:19
@kurtmilam i see, thank you
Kurt Milam
@kurtmilam
Mar 23 2017 15:21
@rahul-dutt-sharma share a link to the REPL, and I'll take a look.
Brad Compton (he/him)
@Bradcomp
Mar 23 2017 15:35
@djleonskennedy You want to use over with the lensProp and mapping as the first two parameters
@ram-bot
const data = {
  name: 'Joe',
  skills: ['Java', 'Elm', 'Haskell'],
  adress: {
    house: 74
  }
}

const upper = x => x.toUpperCase()

const result = over(lensProp('skills'), map(upper))

result(data)
ram-bot
@ram-bot
Mar 23 2017 15:35
{ name: 'Joe',
  skills: [ 'JAVA', 'ELM', 'HASKELL' ],
  adress: { house: 74 } }
Brad Compton (he/him)
@Bradcomp
Mar 23 2017 15:35
Sorry, missed that it had already been said
Yuriy
@djleonskennedy
Mar 23 2017 15:36
@Bradcomp anyway thank you for help)
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 15:38
I cant seem to make the share feature on ramda repl work
const hosts = {
    NATIVE: () => 'native',
    WEB: () => 'web',
};

const net = {
    getFromWeb: () => {},
};

const bus = {
    sendToHost: () => {},
};

const ipcRenderer = {
    on: () => {},
    off: () => {},
    emit: () => {},
    sendToHost: () => {},
};

const relay = (args) => {
    const getEnv = R.prop('environment')
    const getBus = R.prop('bus');
    const getNetworkBus = R.prop('net');
    const validateBus = R.either(
        R.allPass([
            R.compose(R.hasIn('sendToHost'), getBus),
            R.compose(R.hasIn('on'), getBus),
            R.compose(R.hasIn('emit'), getBus),
            R.compose(R.hasIn('off'), getBus),
        ]),
        R.compose(R.equals(bus), getBus)
    );
    const validateEnvironment = R.either(
        R.compose(R.equals('NATIVE'), getEnv),
        R.compose(R.equals('WEB'), getEnv)
    );
    const getHostsEnv = R.compose(R.flip(R.prop)(hosts), getEnv)
    const hostHasEnv = R.compose(R.not, R.isNil, getHostsEnv);
    const relayForHost = R.compose(R.clone, getHostsEnv);

    const noInitializationParameters = 'No initialization parameters provided';
    const noCommunicationBus = 'Communication bus with parent is required';
    const invalidCommunicationBus = 'Communication bus provided is invalid';
    const noNetworkBus = 'Network bus is required';
    const invalidNetworkBus = 'Network bus provided is invalid';
    const noEnvironment = 'environment is required';
    const invalidEnvironment =
        'environment provided has to be one of NATIVE or WEB';

    const makeError = (message) => {
        return {
            error: {
                message,
            },
        };
    };

    return R.cond([
        [
            R.isNil, R.always(makeError(noInitializationParameters)),
        ],
        [
            R.compose(R.isNil, getBus),
            R.always(makeError(noCommunicationBus)),
        ],
        [
            R.compose(R.not, validateBus),
            R.always(makeError(invalidCommunicationBus)),
        ],
        [
            R.compose(R.isNil, getNetworkBus),
            R.always(makeError(noNetworkBus)),
        ],
        [
            R.compose(R.not, R.hasIn('getFromWeb'), getNetworkBus),
            R.always(makeError(invalidNetworkBus)),
        ],
        [
            R.compose(R.isNil, getEnv),
            R.always(makeError(noEnvironment)),
        ],
        [
            R.compose(R.not, validateEnvironment),
            R.always(makeError(invalidEnvironment)),
        ],
        [
            R.compose(R.not, hostHasEnv),
            params =>
            R.always(makeError(`Hosts ${params.environment} not defined`)),
        ],
        [
            R.T, relayForHost,
        ],
    ])(args);
};

/* eslint-disable no-console */
console.log(1, relay());
console.log(2, relay({
    net,
}));
console.log(3, relay({
    bus: {},
}));
console.log(4, relay({
    bus,
    environment: 'NATIVE',
}));
console.log(5, relay({
    net: {},
    bus,
    environment: 'NATIVE',
}));
console.log(6, relay({
    net,
    bus: ipcRenderer,
    environment: 'NATIVE',
}));
console.log(7, relay({
    net,
    bus: ipcRenderer,
    environment: 'nmnm',
}));
console.log(8, relay({
    net,
    bus,
    environment: 'WEB',
}));
console.log(9, relay({
    bus: ipcRenderer,
    environment: 'nmnm',
}));
console.log(10, relay({
    net: {},
    bus: ipcRenderer,
    environment: 'NATIVE',
}));
console.log(11, relay({
    net: {},
    bus,
    environment: 'WEB',
}));
console.log(12, relay({
    net,
    bus: ipcRenderer,
    environment: 'NATIVE',
}));
Brad Compton (he/him)
@Bradcomp
Mar 23 2017 15:38
@alex-deas I think it's because compose doesn't return a curried function. So in both cases the 'number' you're passing in is undefined. Any comparison with undefined is always false.
@rahul-dutt-sharma I think that's too much code for the share to work
Yuriy
@djleonskennedy
Mar 23 2017 15:39
:)
Kurt Milam
@kurtmilam
Mar 23 2017 15:42
@rahul-dutt-sharma What's the code supposed to be doing? I pasted it into the repl and didn't notice any exceptions.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 15:43
yea,
i refactored it from first attempt
want some feedback around if I am learning ramda right
the exceptions I get dun have mention about on which line my code breaks on
ramda just complains
Kurt Milam
@kurtmilam
Mar 23 2017 15:49
@rahul-dutt-sharma I think you're moving in the right direction from the first code you posted. I'd generally suggest trying to refactor a small part of the code at a time so you can make sure your refactoring worked.
If you were writing this from scratch and testing as you went, you'd add small pieces of functionality and test until the functionality worked, then move on to the next piece.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 15:50
yea I had tests in place
but not along this refactor
Kurt Milam
@kurtmilam
Mar 23 2017 15:58

@rahul-dutt-sharma change your makeError function to this:

const makeError = message =>
    R.always( R.assocPath(['error', 'message'], message, {}) )

and you can remove all of the R.always wrappers you have around the functions in the cond.

Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 16:04
that was wonderful :)
Kurt Milam
@kurtmilam
Mar 23 2017 16:12
@rahul-dutt-sharma I usually put this at the top of my REPL experiments:
console.clear()
const log = tap( console.log )
you can use log inside compose to see what the values look like at different stages.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 16:13
awesome
Kurt Milam
@kurtmilam
Mar 23 2017 16:13
like R.compose(log, R.isNil, log, getBus, log) <- this will tell you what value you have at each stage in the compose.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 16:14
:O
Kurt Milam
@kurtmilam
Mar 23 2017 16:14
and having console.clear() at the top of the REPL will clear out the console every time you make a change to the code.
I also often put console.log(Date.now()) after console.clear() as a sanity check. The date will update each time the console is cleared and the code is re-run.
Kurt Milam
@kurtmilam
Mar 23 2017 16:30
@rahul-dutt-sharma Another suggestion:
const hostNotDefined = params => `Hosts ${ getEnv(params) } not defined`
  const dynamicError = message =>
    R.assocPath(['error', 'message'], message, {})
R.compose( dynamicError, hostNotDefined )
Hopefully it's clear what I mean there. You're replacing the makeError in the hostHasEnv check in the cond with R.compose( dynamicError, hostNotDefined )
I also renamed makeError to staticError to make it clear.
Galileo Sanchez
@galileopy
Mar 23 2017 16:33
Does pick respect the order of the keys passed to it?
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 16:33
yay!
Galileo Sanchez
@galileopy
Mar 23 2017 16:34
Props is what I want
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 16:39
so heres the last piece of the puzzle.. I get the error objects back alright. But the function I get back needs args to be re-applied
so to get the relay object I need to call relay(args)(args)
that breaks the entire code..:(
cause relay(args) returns the error object
so for error the code would blow up
also relay(args)(args) looks stupid
Kurt Milam
@kurtmilam
Mar 23 2017 16:40
@rahul-dutt-sharma Slightly nicer dynamicTemplate and how to call it:
  const dynamicError = templ => params =>
    R.assocPath(['error', 'message'], templ( params ), {} )
dynamicError( hostNotDefined )
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 16:42
I am trying to use R.apply to fix the issue
no joy
Denis Stoyanov
@xgrommx
Mar 23 2017 16:44
Fn(arg)(arg) is a monadic join or W combinator :smile:
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 16:45
:(
got that
wondering how I will present this to my team :)
Brad Compton (he/him)
@Bradcomp
Mar 23 2017 16:47
To clarify, do you mean that you get back an object in the error case, but a function in the success case that needs to be called again with the arguments?
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 16:48
yea
exactly
Denis Stoyanov
@xgrommx
Mar 23 2017 16:48
@ram-bot
var joinM = chain(identity)

joinM(repeat)(2)
ram-bot
@ram-bot
Mar 23 2017 16:48
[ 2, 2 ]
[ 2, 2 ]
Kurt Milam
@kurtmilam
Mar 23 2017 16:49
@rahul-dutt-sharma Another improvement:
    const validateBus = R.compose( R.either(
        R.allPass([
            R.hasIn('sendToHost'),
            R.hasIn('on'),
            R.hasIn('emit'),
            R.hasIn('off'),
        ]),
        R.equals(bus)
        )
        , getBus
    );
from
    const validateBus = R.either(
        R.allPass([
            R.compose(R.hasIn('sendToHost'), getBus),
            R.compose(R.hasIn('on'), getBus),
            R.compose(R.hasIn('emit'), getBus),
            R.compose(R.hasIn('off'), getBus),
        ]),
        R.compose(R.equals(bus), getBus)
    );
Brad Compton (he/him)
@Bradcomp
Mar 23 2017 16:51
Why not invoke the function conditionally in the case of success?
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 16:51
yea
but dunno how
Brad Compton (he/him)
@Bradcomp
Mar 23 2017 16:52
const result = R.cond([/*...*/])(args);

return result.error ? result : result(args);
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 16:53
const relayForHost = R.compose(R.clone, getHostsEnv);
is wrong
cause I need to clone the value of result(args)
If I can rewrite
const relayForHost = R.compose(R.clone, getHostsEnv); to be able to return value of getHostsEnv(args) kinda thing
after cloning :)
try R.apply
m trying*
Kurt Milam
@kurtmilam
Mar 23 2017 17:01
now about sending a clone of args into cond?
const clonedArgs = R.clone( args ), then pass clonedArgs into the cond?
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:02
I dun have a special need of clone
the problem is that I either get an error object
or a function
f(args)(args) would work
wondering if there is a way to beat this within ramda
looks unlikely cause the args are used at the end
Kurt Milam
@kurtmilam
Mar 23 2017 17:03
sure there is - Brad Compton's way should do the trick.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:03
so they would always be gone
yea
Kurt Milam
@kurtmilam
Mar 23 2017 17:04
no, you still have access to them. they're not gone.
you have access to args in the entire main function body.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:04
how to access them, even if I do would it be functional?
Kurt Milam
@kurtmilam
Mar 23 2017 17:05
access them via their name, args. It could be done functionally.
Kurt Milam
@kurtmilam
Mar 23 2017 17:11
@rahul-dutt-sharma
  const result = R.cond([ /*...*/ ])
  return R.when( R.compose( R.equals( 'Function'), R.type )
          , R.identity
          , R.always
          )( result( args ) )( args )
That works and is functional.
Galileo Sanchez
@galileopy
Mar 23 2017 17:11
ramda doesn't work wiht node iterators?
R.reduce(R.sum, 0, buff.values()) throws TypeError: reduce: list must be array or iterable and buff.values() is an iterator according to node docs
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:12
thats interesting
Galileo Sanchez
@galileopy
Mar 23 2017 17:12
buff is a node Buffer
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:12
need to push ramda at office
so need to stick to the pitch
Galileo Sanchez
@galileopy
Mar 23 2017 17:14
nor does it work with TypedArrays
and typed arrays define a .reduce method
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:15
although understanding ternary operators is easier :)
Galileo Sanchez
@galileopy
Mar 23 2017 17:16
ok, my mistake
reduce(add, 0) === sum
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:21
hey, it works now
I changed it to
return R.when(
        isFunction,
        R.identity,
        R.always
    )(check(args))(args);
and const isFunction = R.compose(R.equals('Function'), R.type);
but I can not understand the R.when thing
Kurt Milam
@kurtmilam
Mar 23 2017 17:22
When has a check and two actions.
so, if isFunction(check(args)) is true, it returns R.identity(check(args)).
Otherwise, check(args) is an error object, and it returns R.always(check(args))
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:24
okies
Kurt Milam
@kurtmilam
Mar 23 2017 17:24
So, we can call either of those with (args). R.always(check(args))(args) will return the error message.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:24
thats what I dun get
Kurt Milam
@kurtmilam
Mar 23 2017 17:24
R.identity(check(args))(args) will return the result of calling the relay function with args.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:25
R.always(check(args)) is the error object right ?
Kurt Milam
@kurtmilam
Mar 23 2017 17:26
yep
if check(args) is the error message, then always(check(args))(anythingAtAll) will always return the error message.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:26
so error_object(args) is error_obj :O
Kurt Milam
@kurtmilam
Mar 23 2017 17:26
nope
read up on always.
Bravi
@Bravilogy
Mar 23 2017 17:26
guys, can anyone help me out rewriting this bit in ramda please?
const get_fn = id => getUser(id)
     .chain(user => getPosts(user.id)
         .chain(traverse(Task.of, post => getComments(post.id)
             .map(comments => ({ ...dissoc('userId', post), comments }))))
         .map(posts => ({ ...user, posts }) ));
I'm trying to use composeK
Kurt Milam
@kurtmilam
Mar 23 2017 17:27
the error_obj is not called with args because it's wrapped in always()
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:27
okies
so its the same always no matter what called with
Kurt Milam
@kurtmilam
Mar 23 2017 17:28
yep
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:28
so always(check(args))
is a function
always(check(args))(..) is the error object
Kurt Milam
@kurtmilam
Mar 23 2017 17:28
exactly. It is a function that will always return check(args), no matter what we pass to it.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:28
got it
theres one last thing
const getHostsEnv = R.compose(R.flip(R.prop)(hosts), getEnv)
    const hostHasEnv = R.compose(R.not, R.isNil, getHostsEnv);
    const relayForHost = R.compose(R.call, getHostsEnv);
is now incorrect
cause relayForHost is getHostsEnv
so hostHasEnv relies on the end result
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:35
@kurtmilam thanks man
that was awesome first day
but when we look at it.. it changing a bunch of if elses into ramda function
it would be hard convincing others with what I have today.
Kurt Milam
@kurtmilam
Mar 23 2017 17:36
Well, there's still more you could do there to improve things.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:37
please do tell
Kurt Milam
@kurtmilam
Mar 23 2017 17:37
And just refactoring a single large function won't necessarily show the benefits of using a functional style.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:37
yea
Kurt Milam
@kurtmilam
Mar 23 2017 17:37
Part of fp is breaking out reusable functions, for instance.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:37
the example wast good to start with
yea
all our functions are whole
Kurt Milam
@kurtmilam
Mar 23 2017 17:38
yeah, it was good to start with. You could probably continue to work on it. Maybe put it in a gist, and we could take a second look at it.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:40
sure
so one last thing
if I have explain using f(args)(args)
in plain terms what do I say?
I get it myself how first and second invocations differ
Kurt Milam
@kurtmilam
Mar 23 2017 17:43
It's not that uncommon of a thing to do. You're calling f with args to return the actual function you want to call with args (where the actual function will either be one that returns an error message or one that doesSomething).
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:43
yea
I got that and its make a good amount of sense
Kurt Milam
@kurtmilam
Mar 23 2017 17:44
here's a list of common combinators: https://gist.github.com/Avaq/1f0636ec5c8d6aed2e45
You can see the W combinator listed.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:46
I recalled my mathematics studies
:)
Kurt Milam
@kurtmilam
Mar 23 2017 17:46
It's fn(x)(x) so the concept is useful enough that it gets its own combinator.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:46
too bad I left that years ago
Kurt Milam
@kurtmilam
Mar 23 2017 17:46
:thumbsup:
deriving all combinators via SK basis
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:50
this is gonna take some heavy investment at home
office peeps wont get into this
Denis Stoyanov
@xgrommx
Mar 23 2017 17:50
monadic bind
const B1 = B(B)(B)
const MO = B1(W)(B)
const MO1 = B(B(W))(B)
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 17:50
ny idea how I can get into practical exposure
also I really like cyclejs' design
thoughts ?
Bravi
@Bravilogy
Mar 23 2017 17:53
oh well.. I did it :D
const addRemoveKey = (withKey, withoutKey) =>
        lift(compose(objOf(withKey), map(dissoc(withoutKey))));

const mergeWithResource = (withKey, withoutKey, fn) => converge(lift(merge), [
    Task.of,
    compose(addRemoveKey(withKey, withoutKey), fn, prop('id'))
]);

const postWithComments = traverse(Task.of, mergeWithResource('comments', 'postId', getComments));
const userWithPosts = mergeWithResource('posts', 'userId', compose(chain(postWithComments), getPosts));

const getUserWithPosts = composeK(userWithPosts, getUser);
maybe not as readable
Brad Compton (he/him)
@Bradcomp
Mar 23 2017 17:59
@rahul-dutt-sharma Start with refactoring into small, obviously named functions. Then building up larger functions from compositions of the small ones. Seems obvious, but it can cause a clear improvement to your codebase in a way that's pretty obvious to everybody.
Kurt Milam
@kurtmilam
Mar 23 2017 18:03
@rahul-dutt-sharma I think your example is a good one to start with if you want to learn how to refactor into fp, but not necessarily a good one if you're looking to show co-workers the benefits of programming in an fp style.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:03
yea
thoughts around cyclejs?
lets discuss how I can improve this very example even further
I will put it up on a gist
any obvious candidates?
const R = require('ramda');

const hosts = {
    NATIVE: () => 'native',
    WEB: () => 'web',
};

const net = {
    getFromWeb: () => {},
};

const bus = {
    sendToHost: () => {},
};

const ipcRenderer = {
    on: () => {},
    off: () => {},
    emit: () => {},
    sendToHost: () => {},
};

const relay = (args) => {
    const noInitializationParameters = 'No initialization parameters provided';
    const noCommunicationBus = 'Communication bus with parent is required';
    const invalidCommunicationBus = 'Communication bus provided is invalid';
    const noNetworkBus = 'Network bus is required';
    const invalidNetworkBus = 'Network bus provided is invalid';
    const noEnvironment = 'environment is required';
    const invalidEnvironment =
        'environment provided has to be one of NATIVE or WEB';

    const makeError = message =>
        R.always(R.assocPath([
            'error', 'message',
        ], message, {}));

    const getEnv = R.prop('environment')
    const getBus = R.prop('bus');
    const getNetworkBus = R.prop('net');
    const validateBus = R.compose(R.either(
        R.allPass([
            R.hasIn('sendToHost'),
            R.hasIn('on'),
            R.hasIn('emit'),
            R.hasIn('off'),
        ]),
        R.equals(bus)
    ), getBus);

    const validateEnvironment = R.either(
        R.compose(R.equals('NATIVE'), getEnv),
        R.compose(R.equals('WEB'), getEnv)
    );
    const getHostsEnv = R.compose(R.flip(R.prop)(hosts), getEnv)
    const hostHasEnv = R.compose(R.not, R.isNil, getHostsEnv);
    const relayForHost = R.compose(R.call, getHostsEnv);
    const isFunction = R.compose(R.equals('Function'), R.type);
    const hostNotDefined = params => `Hosts ${getEnv(params)} not defined`;
    // const dynamicError = templ => params =>
    //     R.assocPath(['error', 'message'], templ(params), {});

    const check = R.cond([
        [
            R.isNil, makeError(noInitializationParameters),
        ],
        [
            R.compose(R.isNil, getBus),
            makeError(noCommunicationBus),
        ],
        [
            R.compose(R.not, validateBus),
            makeError(invalidCommunicationBus),
        ],
        [
            R.compose(R.isNil, getNetworkBus),
            makeError(noNetworkBus),
        ],
        [
            R.compose(R.not, R.hasIn('getFromWeb'), getNetworkBus),
            makeError(invalidNetworkBus),
        ],
        [
            R.compose(R.isNil, getEnv),
            makeError(noEnvironment),
        ],
        [
            R.compose(R.not, validateEnvironment),
            makeError(invalidEnvironment),
        ],
        [
            R.compose(R.not, hostHasEnv),
            hostNotDefined,
        ],
        [
            R.T, relayForHost,
        ],
    ]);

    return R.when(
        isFunction,
        R.identity,
        R.always
    )(check(args))(args);
};

/* eslint-disable no-console */
console.log(1, relay());
console.log(2, relay({
    net,
}));
Kurt Milam
@kurtmilam
Mar 23 2017 18:05
I've looked at cyclejs a little. I understand that it is very fp and reactive-focused, but I don't know enough about it to say much. There's a cyclejs room here in gitter if you'd like to ask some specific questions there.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:05
yea
I am wondering what project I can involve myself in
to get going with fp
at my workplace OO Based js is hardly pro-efficient
Kurt Milam
@kurtmilam
Mar 23 2017 18:12
Would any of the functions defined at the top of the main function body be reusable elsewhere?
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:13
not yet
Kurt Milam
@kurtmilam
Mar 23 2017 18:13
If so, I'd move them out of the function body. Some of them (like isFunction), I would move to a utility module so they can be used across the project.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:13
yea thats there
if the object that I m looking at has domain related props, a lot of these validation functions can be imorted into
Kurt Milam
@kurtmilam
Mar 23 2017 18:15
What would probably be a better example of fp would be to take a few related functions or methods and refactor them.
This would better show the power of composition.
a simple function with one if...else block that contains a bunch of elses isn't the best candidate for showing off composition.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:17
:)
is it possible to go completely class less ?
Kurt Milam
@kurtmilam
Mar 23 2017 18:18
in what way?
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:18
if so then that refactoring would stand out
I tried and failed
not have any this
Kurt Milam
@kurtmilam
Mar 23 2017 18:19
I don't use classes.
I don't use this
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:19
or class
Kurt Milam
@kurtmilam
Mar 23 2017 18:19
ever
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:19
do u use type check against a classType
Kurt Milam
@kurtmilam
Mar 23 2017 18:20
no
R.type can help you out with that, I believe.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:20
so if I check myobj has a,b,c thats good enuf
Kurt Milam
@kurtmilam
Mar 23 2017 18:21
there's R.is and R.type to help you with that kind of thing if you need it.
but I don't use classes or this.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:21
yea but they would matter if the object that they use is from a class
Kurt Milam
@kurtmilam
Mar 23 2017 18:22
yes, that's where R.is and R.type come into play.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:22
yea looked em
is there a project u know that uses ramda heavily ?
Kurt Milam
@kurtmilam
Mar 23 2017 18:24
I'm working on a toy project with mithril (framework like react or cyclejs). I have 11 files and probably 800 lines of code in it, and not a single this anywhere in it :D
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:24
I can probably try to read and start contributing
I refactored my current code without this and class
Kurt Milam
@kurtmilam
Mar 23 2017 18:24
not even in the comments ;)
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:24
but it didnt look good
cause I did so entire via Object.assign
and other vanila stuff
could not convince myself if I was going in right direction
we are using vuejs at work place
what are your opinions on that?
Kurt Milam
@kurtmilam
Mar 23 2017 18:26
I have only looked at vuejs a little, but have not played with it yet.
I was playing with react, then saw someone here mention mithril and decided to take a look at it.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:27
u may wnna look at preact
Kurt Milam
@kurtmilam
Mar 23 2017 18:27
react seemed too heavy, whereas mithril is a lot smaller with a lot fewer moving parts, or so it seemed.
yeah, I should take a look at preact, too.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:27
I back react cause they have a universally usable model
react-native
etc
even if that makes it heavy
Kurt Milam
@kurtmilam
Mar 23 2017 18:28
yeah, I may go back to react since it's the big thing atm. Probably better for my resume :D
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 18:29
do u knw of Monotype?
Kurt Milam
@kurtmilam
Mar 23 2017 18:31
have heard of it but am not familiar with it. do you have a link?
Its the type company
the url is for india
but the company is from US
Johnny Hauser
@m59peacemaker
Mar 23 2017 18:45
What's the best way to make [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, etc] ?
Denis Stoyanov
@xgrommx
Mar 23 2017 18:46
@m59peacemaker range?
Johnny Hauser
@m59peacemaker
Mar 23 2017 18:47
word
new Array(10).fill(0).map((_, idx) => idx) what I had before :)
Denis Stoyanov
@xgrommx
Mar 23 2017 18:48
Johnny Hauser
@m59peacemaker
Mar 23 2017 18:49
haha
fantastic
Denis Stoyanov
@xgrommx
Mar 23 2017 18:50
@m59peacemaker more in comments
Kurt Milam
@kurtmilam
Mar 23 2017 19:02
@rahul-dutt-sharma ok, I have heard of monotype, then. I was thinking you might be referring to a js library or framework named 'monotype'.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 19:03
nah
I wrk here
Kurt Milam
@kurtmilam
Mar 23 2017 19:04
You might also find this interesting - the book was just published this month by O'Reilly press: http://refactoringjs.com/files/refactoring-javascript.pdf
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 19:04
crazy movement here in nodejs and electron areas
Kurt Milam
@kurtmilam
Mar 23 2017 19:04
I've just started looking over it. He uses ramda, sanctuary, etc.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 19:05
that it man, m gonna b in that book for the next 4-5 mnths atleast
work hours are crazy at office as well
thanks a ton!
lemme knw if u wnna join Monotype
Kurt Milam
@kurtmilam
Mar 23 2017 19:07
by 'join monotype', do you mean get a job there?
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 19:07
yea!
Kurt Milam
@kurtmilam
Mar 23 2017 19:08
do they hire remote workers?
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 19:08
Not from India.
There are a few in UK
Kurt Milam
@kurtmilam
Mar 23 2017 19:09
I'm located in Austria and plan to stay here, but I could do some travelling.
Rahul Dutt Sharma
@rahul-dutt-sharma
Mar 23 2017 19:09
but the key opportunity here is for an architect level dev
humm
Matthew Willhite
@miwillhite
Mar 23 2017 21:24
We’re close to hiring and all remote ;)
I’m the only one on the JS/client team, but we’re going to be expanding the team over the next year.
This may not be an appropriate place to advertise, but since we’re on the topic :joy:
Stefano Vozza
@svozza
Mar 23 2017 22:44
I have never used this or class in my code either