Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R.prop and R.path inconsistency #1522

Closed
lo1tuma opened this issue Nov 16, 2015 · 7 comments
Closed

R.prop and R.path inconsistency #1522

lo1tuma opened this issue Nov 16, 2015 · 7 comments

Comments

@lo1tuma
Copy link
Member

lo1tuma commented Nov 16, 2015

As mentioned in gitter, I’ve found a scenario where the behavior of R.path differs from R.prop:

R.prop('foo', undefined); // throws 
R.path(['foo'], undefined); // -> undefined

IMHO if the path array of R.path contains only one element the function should be equivalent to R.prop.

@CrossEye
Copy link
Member

I'd forgotten that this was mentioned on Gitter. I was going to respond there, but some other conversation intervened. I believe someone there suggested that both should throw. I'm going to disagree. Functions that throw do not compose. While I have no problem leaving unspecified behavior fairly inconsistent, I think we should not throw here, and have prop take its cue from path.

module.exports = _curry2(function prop(p, obj) {
  if (obj == null) {
    return;
  }
  return obj[p];
});

What do others think?

@gilligan
Copy link
Contributor

👍 for having both functions return undefined in that scenario.

@lo1tuma
Copy link
Member Author

lo1tuma commented Nov 16, 2015

Agreed, I would also prefer to return undefined in both cases.

@davidchambers
Copy link
Member

Functions that throw do not compose.

In this case we're talking about a type mismatch – an error that would be caught at compile-time in a statically typed language. It's important not to conflate type mismatches with correctly typed operations which may fail. Types such as Maybe a and Either a b allow us to encode the possibility of failure. Type mismatches, though, should (in my view) crash the program. How can we continue if we receive a value of an unexpected type?

Looked at another way, how should R.compose(R.toUpper, R.negate)(42) behave? The types don't line up. If R.prop('foo', undefined) were to evaluate to undefined, should R.toUpper(-42) evaluate to undefined also? Is there some reason that R.prop should accept arguments of the wrong types but other functions (such as R.toUpper) should not?

@gilligan
Copy link
Contributor

@davidchambers Hm, well I suppose your line of argumentation is sound. I was looking at it from a more pragmatic perspective where a function returning undefined is more convenient to handle.

An aside: You mention that we can encode failures in sum types. I would however assume that the majority of ramda users do not use it in combination with fantasyspec adhering Maybe/Either sum types.

@davidchambers
Copy link
Member

You mention that we can encode failures in sum types. I would however assume that the majority of ramda users do not use it in combination with fantasyspec adhering Maybe/Either sum types.

You're no doubt correct. I worry, though, about null tolerance permeating the library due to the unavailability of suitable types. We could find ourselves in a position where all Ramda functions have a != null guard, which would make locating the source of a type error quite challenging.

@buzzdecafe
Copy link
Member

We could find ourselves in a position where all Ramda functions have a != null guard

i'll be dead then

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants