These are chat archives for ramda/ramda

26th
Apr 2017
Daniil Yastremskiy
@TheBeastOfCaerbannog
Apr 26 2017 05:12

Hi! Can someone please help with this problem: I have an array of strings. If length of a string equals 22, this means what string is encoded and should be retrieved from storage. If string is not found in storage - iteration should be stopped.

const isEncoded = R.propEq('length', 22);
const isUndefined = R.equals(undefined);
const decode = R.pipe(storage.get, R.when(isUndefined, R.reduced));
const onEncoded = R.when(isEncoded, decode);

I ended up with something like this but not sure how to put it all together :(

Kurt Milam
@kurtmilam
Apr 26 2017 06:34
Is there a way to import external scripts into the REPL?
Stephan Meijer
@smeijer
Apr 26 2017 07:47
I can advise https://www.webpackbin.com/ , there you can import any npm package.
Also; since quokkajs was released, I've never used a REPL again; Just take a minute to check it: https://quokkajs.com/
All my testing, prototyping, playing, fiddling; I now do in VSCode with Quokka
Just RAG
@justrag
Apr 26 2017 07:49
Also codesandbox.io (for React-related projects)
Kurt Milam
@kurtmilam
Apr 26 2017 07:51
Thanks for the recommendations. I will check them out.
Stephan Meijer
@smeijer
Apr 26 2017 07:54
https://runkit.com is more like a simple REPL, and has also the entire NPM repo loaded.
For example: a quick play with sanitize-html : https://runkit.com/smeijer/58b81ffda0ccb80014efaa78 So I didn't need to npm install any thing if it wasn't wat I needed
Kurt Milam
@kurtmilam
Apr 26 2017 07:57
That's pretty cool!
Joshua Thornton
@jshthornton
Apr 26 2017 12:17
Hey guys, I am trying to make a library api by making a graph of functions. The code I've got so far feels like it could be heavily streamlined. Does any one have any suggestions?
const makeApi = pipe(
  (graph) => evolve({
    brandApiService: {
      fetchResource: partial(__, [
        window.fetch
      ])
    },
  })(graph),
  (graph) => evolve({
    brandApiService: {
      getResource: partial(__, [
        graph.brandApiService.fetchResource,
      ])
    },
  })(graph),
);

const api = makeApi({
  messages,
  reducer,
  selectors,
  brandApiService,
});
Rick Medina
@rickmed
Apr 26 2017 12:55
@smeijer nice tools thanks for sharing!
Martin Broder
@mrtnbroder
Apr 26 2017 13:09
Hey everyone, I've read somewhere that R.flip is somewhat a code smell that indicates that I should reorder my params. Would you guys agree?
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:11
I would agree with that, but it may come in handy if you have a library that the team uses, but you want to update it for a particular piece of code
Martin Broder
@mrtnbroder
Apr 26 2017 13:12
in my case, I have a function that takes a string and checks wether it is a match with something within an array of regular expressions.
const blacklist = [/PENDING$/, /REJECTED$/],
const actionPass = R.compose(R.flip(R.none)(blacklist), R.flip(R.test))

// passes
actionPass('@@INIT')

// does not pass
actionPass('MY_ACTION_PENDING')
I get the string last
I wouldn't know another solution to get around R.flip here.
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:16
looks like based on the functions you have it’s all you can do, but you could extract out the R.flip functions and rename them as to not confuse anyone
what function are you passing to R.flip(R.none)(blacklist)
R.flip(R.test) looks to return a boolean
Martin Broder
@mrtnbroder
Apr 26 2017 13:18
yes it returns a boolean
blacklist is an array of Regular Expressions
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:19
yes, but doesn’t R.flip(R.none)(blacklist) then be taking in that boolean
and not a function
R.none is like filter, it takes a predicate
but you are passing a boolean
Martin Broder
@mrtnbroder
Apr 26 2017 13:20
oh you are right
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:21
instead of using R.flip(R.none), looks like you can use a good ole anonymous function
or something else
depends on what you are trying to achieve
Martin Broder
@mrtnbroder
Apr 26 2017 13:22
but
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:22
But you may want to look at allPass
Martin Broder
@mrtnbroder
Apr 26 2017 13:22
it still works?
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:22
yes, that is strange
maybe you can throw up an example to ram bot
Martin Broder
@mrtnbroder
Apr 26 2017 13:23
@ram-bot
const blacklistActions = [/PENDING$/, /REJECTED$/]
const actionPass = R.compose(R.flip(R.none)(blacklistActions), R.flip(R.test))

actionPass('IS_PENDING')
ram-bot
@ram-bot
Apr 26 2017 13:23
false
Martin Broder
@mrtnbroder
Apr 26 2017 13:23
@ram-bot
const blacklistActions = [/PENDING$/, /REJECTED$/]
const actionPass = R.compose(R.flip(R.none)(blacklistActions), R.flip(R.test))

actionPass('IS_DIFFERENT')
ram-bot
@ram-bot
Apr 26 2017 13:23
true
Martin Broder
@mrtnbroder
Apr 26 2017 13:23
exactly what I expected/want
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:24
I just did IS_PINT and I still get true
If that works, great!
Martin Broder
@mrtnbroder
Apr 26 2017 13:25
IS_PINT should pass yes
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:25
oh okay
Martin Broder
@mrtnbroder
Apr 26 2017 13:25
if its blacklisted -> do not pass
though, you are right about the function part
lemme take a look at the source
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:28
right
Rick Medina
@rickmed
Apr 26 2017 13:28
@mrtnbroder apart from eternal libs interaction, R.flip is not always a code smell, there are functions that are impossible to design for partial application (eg: divide, subtract). I think about from first arg to last "which would be "configuration" args and which would be "data" args"
also a simple lambda to reorder args could be more readable than flip or placeholder
or rename the function all together as @arecvlohe says
Martin Broder
@mrtnbroder
Apr 26 2017 13:29
looks like it is a function @arecvlohe
this one I think
well actually it's the case: 1 from _arity.js
I'm not sure why though :thinking_face:
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:34
interesting
🤔
Martin Broder
@mrtnbroder
Apr 26 2017 13:34
🤔
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:36
from what i can see you are passing a function, because when I take out the first part, a fucntion is what’s left
so you are passing that function into the next part
with the string
then that test gets pumped into R.none
i wish i could actually see it all play out, but it’s working as expected, but in my mind having to think about it backwards trips me up
Martin Broder
@mrtnbroder
Apr 26 2017 13:39
would you recommend to use a lambda instead?
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:40
i don’t, if it works it works, I would just put comments everywhere :)
Martin Broder
@mrtnbroder
Apr 26 2017 13:44
I don't like comments :D
it should be clear right from the code
Adam Recvlohe
@arecvlohe
Apr 26 2017 13:45
i write comments for my own sake too, when i come back to something months later
thinking WTH
Martin Broder
@mrtnbroder
Apr 26 2017 13:46
haha
Viktor Fröberg
@vikfroberg
Apr 26 2017 14:41
Is there a way to receive the final seed from an unfold? Or am I looking for something else than unfold? I'm trying to do a substitute for a while loop that increments a seed and pushes a value constructed from the current value of the seed to an array.
Viktor Fröberg
@vikfroberg
Apr 26 2017 14:46
What I've come up with so far is to return a pair from the iterator function with the current seed and value, and then extract the last value from the result to receive the final seed.
Adam Recvlohe
@arecvlohe
Apr 26 2017 14:50
can you show the code?
Viktor Fröberg
@vikfroberg
Apr 26 2017 14:53
Sure, I'm just going to clean it up first, so it's easier to reason about.
Adam Recvlohe
@arecvlohe
Apr 26 2017 15:02
ok
Viktor Fröberg
@vikfroberg
Apr 26 2017 15:04
const tokens = ['1', '+', '1']
const newTokens = []
let i = 0
const getToken = _ => tokens[i++]
let r
while (r = getToken()) {
  newTokens.push(r)
}
[i, newTokens]
this is the simplest example I could come up with
Basically I'm trying to convert an OO recursive decent parser into a more functional one: http://www.craftinginterpreters.com/parsing-expressions.html
Viktor Fröberg
@vikfroberg
Apr 26 2017 15:15
Here's what I've come up with so far (which I'm sure can be streamlined)
const tokens = ['1', '+', '1']
const index = 0
const getToken = (tokens, index) => index !== 1 && tokens[index]
const result = unfold(
  seed => getToken(tokens, seed) ? [[getToken(tokens, seed), seed], seed +1 ] : false,
  index
)
const newIndex = last(last(result))
const newTokens = map(head, result)
[newIndex, newTokens]
Kurt Milam
@kurtmilam
Apr 26 2017 15:17
Seems you could just map over tokens, then take the length of the resulting array unless I'm missing something.
Viktor Fröberg
@vikfroberg
Apr 26 2017 15:18
In this case yes, but get token function might not always return something, I've simplified it for the example
@kurtmilam look at my updated example
Viktor Fröberg
@vikfroberg
Apr 26 2017 15:52
Made it a bit easier to follow I think, sorry for spamming:
const tokens = ['1', '+', '1', '-', '1']
const advanceToken = index => index < 3 && tokens[index]

const result = unfold(
  seed => advanceToken(seed) && [{ token: advanceToken(seed), seed }, seed + 1],
  0
)

const getSeed = prop('seed')
const getToken = prop('token')

const newIndex = compose(getSeed, last)(result)
const newTokens = map(getToken, result)

const output = [newIndex, newTokens]
output
Denis Stoyanov
@xgrommx
Apr 26 2017 15:57
What is your goal?
Viktor Fröberg
@vikfroberg
Apr 26 2017 16:04

To be able to parse tokens one after the other and be able to stop and return without going through all of the tokens and then continue from where I stopped and assign that result to another variable and so on.

My big goal is to build a recursive decent parser, as told above ^

Viktor Fröberg
@vikfroberg
Apr 26 2017 17:04
Actually, I think it's works quite nice, guess I'm happy with this solution ^.
Jonah
@jonahx
Apr 26 2017 18:32
forgive a slightly off-topic question, but i think people here may be well-suited to answer it. i have a kind of ghetto ramda repl inside of vim, by way of the following map: nmap <leader>r :w <bar> !node %:p<cr>. so i can play around inside vim, then type ,r and see the results of my ramda statements inside vim. which all works great, unless i want to use babel. ie, if you replace node with babel-node in the above, it still works, but it has a multi-second delay (vs instant with node) because of the babel-node dependency load time. things like babel-watch solve this problem at the command line, but it’s not obvious how you’d integrate that into vim. curious if other vim + ramda users have their own solution to this problem?