These are chat archives for ramda/ramda

27th
Sep 2017
David Langford
@That-David-Guy
Sep 27 2017 00:39

Hi ramda people.

I have a question more to do with general code flow than specific ramda help. Ramda has really changed the way I think about architecture, so I thought I would ask here.

Here is the relevant sections of my code. It is the core part of a library I'm writing to help simplify the e2e tests at my company.

const getElementNameKey = (elem) => {
  // ...
  switch(tagName) {
    case 'textarea':
      return 'TEXTAREA'
    case 'date-input'
      return 'DATE_INPUT
    // ...
  }
  // ...
}

// Different elements have different ways to get and set its values
const valueGetters = {
   // ...
   TEXTAREA: (elem) => methodToGetValueForTextArea(elem)
   DATE_INPUT: (elem) => methodToGetValueForDateInput(elem)
   // ...
}

const valueSetters = {
   // ...
   TEXTAREA: (elem, value) => methodToSetValueForTextArea(elem, value)
   DATE_INPUT: (elem, value) => methodToSetValueForDateInput(elem, value)
   // ...
}


// Example of what I'm given to work with
const givenSelector =  '.myTextArea'
const givenValue = 'Some message'

// There are two things I need to do (with my implementations, before using Ramda)
// 1. Set the value for the element the selector refers to
const element = getElement(giveSelector)
const elementType = getElementNameKey(element)
const setValue = valueSetters[elementType]  
setValue(element, value)


// 2. Or, Get the value for the element the selector refers to,  and compare it against the givenSelector
const element = getElement(giveSelector)
const elementNameKey = getElementNameKey(element)
const getValue = valueGetters[elementNameKey] 
const elementValue = getValue(element)
expect(elementValue).to.be(givenValue)

My Questions are:

  1. Is my architecture reasonable? I was aiming to make the user not care 'how' the value is set or get
  2. My concern is the use of the elementNameKey, but I couldn't see another way to do it functionally.
  3. In the non-functional way, I would have made getElement return a custom object that had a getValue & setValue method on it. My problem with this is that I would have to use element.setValue(value), whereas I much prefer setValue(element, value).
  4. What is the best Ramda methods to use. I'm expecting a simple compose?
Neeraj Singh
@neerajdotname_twitter
Sep 27 2017 00:47
I'm currently using Array.from(nodeList). Does R have something that will convert my nodelist into an Array ?
Dmitry
@zerobias
Sep 27 2017 05:40
@That-David-Guy R.lens - is exactly value getter & value setter, you can use it instead of separated getters and setters and give benefits from over, set and view methods for lenses
David Langford
@That-David-Guy
Sep 27 2017 06:05
Thanks for the reply @zerobias . Looking at the docs I can roughly see how it relates. But I'm having trouble coming up with a concrete example. Would I make a textareaLens for example?
Then use it like R.set(textareaLens, value)
David Langford
@That-David-Guy
Sep 27 2017 06:13
Something like this?
const getElementNameKey = (elem) => {
  // ...
  switch(tagName) {
    case 'textarea':
      return 'TEXTAREA'
    case 'date-input'
      return 'DATE_INPUT
    // ...
  }
  // ...
}

const elementLenses = {
  // ...
  TEXTAREA = R.lens(methodToGetValueForTextarea, methodToSetValueForTextarea)
  DATE_INPUT = R.lens(methodToGetValueForDateArea, methodToSetValueForDateInput)
  // ...
}

// Example of what I'm given to work with
const givenSelector =  '.myTextArea'
const givenValue = 'Some message'

// 1. Set the value for the element the selector refers to
const element = getElement(giveSelector)
const elementType = getElementNameKey(element)
const elementLens = elementLenses[elementType]
R.set(elementLens, value, element)

// 2. Or, Get the value for the element the selector refers to,  and compare it against the givenSelector
const element = getElement(giveSelector)
const elementType = getElementNameKey(element)
const elementLens = elementLenses[elementType]
const elementValue = R.view(elementLens, element)
expect(elementValue).to.be(givenValue)
Or I skip the elementNameKey concept completely:
const elementLenses = (elem) => {
  // ...
  switch(tagName) {
    case 'textarea':
      return R.lens(methodToGetValueForTextarea, methodToSetValueForTextarea)
    case 'date-input'
      return R.lens(methodToGetValueForDateArea, methodToSetValueForDateInput)
    // ...
  }
  // ...
}

// Example of what I'm given to work with
const givenSelector =  '.myTextArea'
const givenValue = 'Some message'

// 1. Set the value for the element the selector refers to
const element = getElement(giveSelector)
const elementLens = elementLenses[elementType]
R.set(elementLens, value, element)

// 2. Or, Get the value for the element the selector refers to,  and compare it against the givenSelector
const element = getElement(giveSelector)
const elementLens = elementLenses[elementType]
const elementValue = R.view(elementLens, element)
expect(elementValue).to.be(givenValue)
Julio Borja Barra
@juboba
Sep 27 2017 06:31
@kurtmilam Thanks Kurt!, sorry for the late reply, had to go.
that's what I want :D
Kurt Milam
@kurtmilam
Sep 27 2017 07:08
@That-David-Guy I think the last one looks pretty good. Where is elementType coming from in the last code block?
Kurt Milam
@kurtmilam
Sep 27 2017 07:22
@That-David-Guy Some ideas based on your last example.
David Langford
@That-David-Guy
Sep 27 2017 09:52
@kurtmilam That was a typo, elementType is meant to be element in the last one
// 1. Set the value for the element the selector refers to
const element = getElement(giveSelector)
const elementLens = elementLenses[element]
R.set(elementLens, value, element)

// 2. Or, Get the value for the element the selector refers to,  and compare it against the givenSelector
const element = getElement(giveSelector)
const elementLens = elementLenses[element]
const elementValue = R.view(elementLens, element)
expect(elementValue).to.be(givenValue)
The other thing that might be an issue is the the getters and setters are promises. They are protractor methods like getTagName() which return promises. Would that work with lens?
David Langford
@That-David-Guy
Sep 27 2017 09:58
Thanks for the ideas @kurtmilam . It's nighttime here, so I'll mull over it overnight. Did you mean to use o on line 41? Or is that meant to be R.setValue
Kurt Milam
@kurtmilam
Sep 27 2017 09:58
o is correct there.
David Langford
@That-David-Guy
Sep 27 2017 09:58
elementType in my original version, is a key for the element. So textarea is TEXTAREA, etc, but also more complex ones like currency which is a specific type of input field .
I then used it to work out which getter to use
ahh really? what does o do?
I found it in the docs :)
In your example, the only thing I'm not sure on is how elementType would be discovered, or if it is even needed?
Jack Leigh
@leighman
Sep 27 2017 11:04
Why does the example R.chain(R.append, R.head)([1, 2, 3]); //=> [1, 2, 3, 1] from the chain documentation work?
Stefano Vozza
@svozza
Sep 27 2017 11:10
because when you give chain a function rather than an array it treats function like a monad.
chain(f, g) === f => g => x => f(x, g(x));
Jack Leigh
@leighman
Sep 27 2017 11:17
@svozza magic. Thanks.
Jack Leigh
@leighman
Sep 27 2017 11:23
@svozza how would I write a similar thing with ap on a function say appending head and last?
Stefano Vozza
@svozza
Sep 27 2017 11:24
the exact same
@ram-bot
R.ap(R.append, R.head)([1, 2, 3]);
ram-bot
@ram-bot
Sep 27 2017 11:25
[ [ 1, 2, 3 ] ]
Stefano Vozza
@svozza
Sep 27 2017 11:25
oooh
maybe not lol
@ram-bot
R.ap(R.equals, R.reverse)('abba')
ram-bot
@ram-bot
Sep 27 2017 11:28
true
Stefano Vozza
@svozza
Sep 27 2017 11:28
@ram-bot
R.chain(R.equals, R.reverse)('abba')
ram-bot
@ram-bot
Sep 27 2017 11:28
true
Stefano Vozza
@svozza
Sep 27 2017 11:28
hmmm
ah yes, my mistake.
chain(f, g) === f => g => x => f(g(x), x);
Kurt Milam
@kurtmilam
Sep 27 2017 13:25
@That-David-Guy My example assumes that elmentType is a fn that takes an element and returns a string indicating the type of the element, which string can also be passed to elementLenses to return the correct lens.
Unfortunately, it's not super clear from the various names in your examples what each thing does or is, so I'm sort of winging it :)
David Langford
@That-David-Guy
Sep 27 2017 21:04
Thanks @kurtmilam , that is correct! Though I'm thinking I don't need that step, I could just return the elementLens instead of the the elementType. As the only thing I use the elementType for is to get the elementLens
Vasili Sviridov
@vsviridov
Sep 27 2017 21:58
What’s a good way to user ramda and ramda-fantasy together?
like combining this const findUserById = id => find(propEq("id", id), users); with Maybe type easily
since Maybe.of(undefined) === Just(undefined)
but i’d rather have Maybe.of(undefined) === Nothing(), is there a shortcut for this?
Lucas Schejtman
@lucasschejtman
Sep 27 2017 22:02
either you (or look into other Maybe implementations)
1) result ? Just(result) : Nothing()
2) extend Maybe to have a fromNullable method
Vasili Sviridov
@vsviridov
Sep 27 2017 22:03
i’ve looked at Sanctuary
but the docs are just painful unless you have all the previous experiene
not even sure what is the proper way of getting the value out of the S.Maybe
ramda-fantasy has a ::getOrElse at least
Lucas Schejtman
@lucasschejtman
Sep 27 2017 22:04
Vasili Sviridov
@vsviridov
Sep 27 2017 22:04
yeah, i guess i was hoping that rf has that, but I could have my own wrapper
also, what would be a good read to figure out how to do a monadic transform for fluture + ramda-fantasy so I don’t have to map/map all the things?
looks like one can use Maybe(…) that would behave similar to toMaybe
Lucas Schejtman
@lucasschejtman
Sep 27 2017 22:10
I personally don't use ramda-fantasy (previously folktale now sanctuary) and I'm not sure how well maintained it is
Vasili Sviridov
@vsviridov
Sep 27 2017 22:12
i’m only using it for the Maybe currently, just getting into that in general
Lucas Schejtman
@lucasschejtman
Sep 27 2017 22:12
For your other question, I'm assuming you're talking about monad transformers so you might want to read on that topic
Vasili Sviridov
@vsviridov
Sep 27 2017 22:12
would you recommend sanctuary over it? I know it’s getting deprecated, I just want something fairly simple to play around with this..
I guess what I want is following, if I have a Future<Maybe<T>> when I map over it or whatever, i don’t have to compose two maps, one to get out the maybe value, and another to map over the future value...
Lucas Schejtman
@lucasschejtman
Sep 27 2017 22:19
gotta jump into a meeting, I'll try to be back later. But this is a good read for what you're after https://stackoverflow.com/questions/42783479/monad-transformers-explained-in-javascript
Vasili Sviridov
@vsviridov
Sep 27 2017 22:19
thanks