user2504831
user2504831

Reputation: 157

Translate Javascript if/else to Ramda cond issue

I found some problem on the handling after if/else logic checking. Let's take an example.

Basic config

const result = {
  data: 1,
  state: {
    pass: 'N'
  }
}

For JS if/else checking, the log should not show after logic checking

function checking() {
  if(result.state.pass !== 'Y') {
    return result;
  }

  console.log("Should not appear the log")
}

checking()

Then, I tried to translate it using Ramda cond function

function checking() {
  R.cond([
    [
      R.compose(R.not, R.equals('Y'), R.prop('pass'), R.prop('state')),
      (res) => res
    ]
  ])(result)

  console.log("Should not appear the log")
}

checking()

However, the log appear in Ramda cond example. May i know

Thanks.

Upvotes: 0

Views: 5761

Answers (2)

Scott Sauyet
Scott Sauyet

Reputation: 50807

Updated: I'd originally read this backward about when the log is supposed to show.


My suggestion would look like this:

const checking = R.when(
  R.compose(R.equals('Y'), R.path(['state', 'pass'])),
  (res) => {console.log("Should not appear in the log"); return res;}
)

Here's how I got there from your code: My first pass would be to fix up the use of cond:

const result1 = {data: 1, state: {pass: 'N'}}
const result2 = {data: 2, state: {pass: 'Y'}}

const checking = R.cond([
  [
    R.compose(R.not, R.equals('Y'), R.prop('pass'), R.prop('state')),
    R.identity
  ],
  [
    R.T, 
    (res) => {console.log("Should not appear in the log"); return res;}
  ]
])

checking(result1); 
//=> {data: 1, state: {pass: 'N'}} 
checking(result2);
// logs "Should not appear in the log
//=> {data: 2, state: {pass: 'Y'}}

Note that cond is most like a switch statement: it takes a collection of condition-consequent pairs and returns a function which passes its argument to each pair until it finds one whose condition is true, then it returns the result of calling its consequent. Thus for the second condition, we just check R.T, which is a function that always returns true, and use identity to return the input.

This new function now accepts a result object and returns it unchanged, logging a message to the console if it doesn't match the initial test.


But this isn't the end. This code can be refactored.

Here's one simple fix I would apply:

const checking = R.cond([
  [
    R.compose(R.not, R.equals('Y'), R.path(['state', 'pass'])),
    R.identity
  ],
  [
    R.T, 
    (res) => {console.log("Should not appear in the log"); return res;}
  ]
])

This simply changed from compose(prop('pass'), prop('state')) to path(['state', 'pass']). It's a minor tweak, but I think this is cleaner.


The next change is more substantive.

const checking = R.ifElse(
  R.compose(R.not, R.equals('Y'), R.path(['state', 'pass'])),
  R.identity,
  (res) => {console.log("Should not appear in the log"); return res;}
)

When we have a cond statement with only two branches, and the second one tests on R.T, we can write this more clearly with ifElse. This takes a condition and two consequents, one for when the condition passes, one for when it fails.


This might be as far as you would want to go, especially if you're eventually planning on doing something different in the fail condition. But if you're not, and you really only need one consequent, then R.unless offers a further simplification on ifElse, for those cases where the second consequent is just a pass-through:

const checking = R.unless(
  R.compose(R.not, R.equals('Y'), R.path(['state', 'pass'])),
  (res) => {console.log("Should not appear in the log"); return res;}
)

unless simply checks the condition and runs the consequent if the condition is false and returns the input intact if it's true.


But we can pull out the not as well by switching from unless to when:

const checking = R.when(
  R.compose(R.equals('Y'), R.path(['state', 'pass'])),
  (res) => {console.log("Should not appear in the log"); return res;}
)

And I would probably leave it there, although I might factor out a log function for clarity.

All of this is available (including a final version with a log function) on the Ramda REPL.

Upvotes: 4

jgr0
jgr0

Reputation: 727

You forgot to add a return statement.

const result = {
  data: 1,
  state: {
    pass: 'N'
  }
}

function checking() {
  // Need to add return statement below
  return R.cond([
    [
      R.compose(
        R.not, 
        R.equals('Y'), 
        R.prop('pass'), 
        R.prop('state')),
      (res) => res
    ]
  ])(result)

  console.log("Should not appear the log")
}
  
checking() 
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.23.0/ramda.min.js"></script>

Upvotes: -1

Related Questions