Giter Site home page Giter Site logo

Default value about idx HOT 3 CLOSED

facebook avatar facebook commented on April 28, 2024 5
Default value

from idx.

Comments (3)

yungsters avatar yungsters commented on April 28, 2024 1

I actually originally supported an optional third argument, defaultValue. However, I abandoned it because the expected behavior of such an argument turned out to be slightly more complicated than it seems, and I thought it might lead to surprises.

Here are the different potential behaviors for defaultValue (each with different nuances, none of which are obviously correct):

  • Return defaultValue only if the final member expression is null or undefined. (This is what you have proposed.)
  • Return defaultValue only if we attempt to access a property on null or undefined.
  • Return defaultValue if any of the member expressions are null or undefined.

Then, there's the question of whether or not we should return defaultValue if the final value is null or undefined.

The difference between these are pretty subtle and easy to get mixed up. In order to avoid confusion, it would be better for callers to explicitly expand the defaulting logic inline.

Also, we should think of idx as a temporary workaround until we have the real existential operator. A real existential operator will not support default values, so we should not either.

Happy to discuss further, but closing this for now. Thanks for the proposal, though!

from idx.

xareelee avatar xareelee commented on April 28, 2024

In @ppoliani 's example:

const DEFAULT_FRIENDS = [{ name: "Pavlos" }]
idx(props, _ => _.user.friends[0].friends, DEFAULT_FRIENDS)

There are five chances to get undefined:

props == undefined
props.user == undefined 
props.user.friends == undefined 
props.user.friends[0] == undefined 
props.user.friends[0].friends == undefined

We can pass the fourth argument about how to handle undefined. There are 3 values for strategies:

  • 'LOOKUP'
  • 'EXACTLY'
  • 'ANY'

LOOKUP

We can define default values for levels:

const DEFAULT_FRIENDS = [{ name: "Pavlos" }]
const defaultValues = {
  0: [],    // for level 0 to level 3
  4: DEFAULT_FRIENDS  // for level 4
}
const result = idx(props, _ => _.user.friends[0].friends, defaultValues, 'LOOKUP')

So we can get different default values for different undefined levels:

props == null
  ? []  // level 0 default value
  : props.user == null 
    ? []  // level 1 default value
    : props.user.friends == null 
      ? []  // level 2 default value
      : props.user.friends[0] == null 
        ? [] // level 3 default value
        : props.user.friends[0].friends == null
          ? [{ name: "Pavlos" }]  // level 4 default value
          : props.user.friends[0].friends

The 'LOOKUP' strategy uses inheritance, which means that if you did not provide the default value for that level, it will look up the previous level iteratively until finding a default value. If no default value is provided in the inheritance, it will use undefined.

// now we only provide level 4 default value
const defaultValues = {
  4: DEFAULT_FRIENDS
}
const result = idx(props, _ => _.user.friends[0].friends, defaultValues, 'LOOKUP')

// results
props == null
  ? undefined  // level 0 default value
  : props.user == null 
    ? undefined  // level 1 default value
    : props.user.friends == null 
      ? undefined  // level 2 default value
      : props.user.friends[0] == null 
        ? undefined // level 3 default value
        : props.user.friends[0].friends == null
          ? [{ name: "Pavlos" }]  // level 4 default value
          : props.user.friends[0].friends

EXACTLY

When we use 'EXACTLY', it will only use the default value in the exact level:

const DEFAULT_FRIENDS = [{ name: "Pavlos" }]
const defaultValues = {
  0: [],    // only for level 0
  4: DEFAULT_FRIENDS  // only for level 4
}
const result = idx(props, _ => _.user.friends[0].friends, defaultValues, 'EXACTLY')
props == null
  ? []  // level 0 default value
  : props.user == null 
    ? undefined  // level 1 default value
    : props.user.friends == null 
      ? undefined  // level 2 default value
      : props.user.friends[0] == null 
        ? undefined // level 3 default value
        : props.user.friends[0].friends == null
          ? [{ name: "Pavlos" }]  // level 4 default value
          : props.user.friends[0].friends

It won't look up the default value in other levels.

ANY

We provide only a default value for all undefined levels:

const DEFAULT_FRIENDS = [{ name: "Pavlos" }]
const result = idx(props, _ => _.user.friends[0].friends, DEFAULT_FRIENDS, 'ANY')
props == null
  ? [{ name: "Pavlos" }]  // level 0 default value
  : props.user == null 
    ? [{ name: "Pavlos" }]  // level 1 default value
    : props.user.friends == null 
      ? [{ name: "Pavlos" }]  // level 2 default value
      : props.user.friends[0] == null 
        ? [{ name: "Pavlos" }] // level 3 default value
        : props.user.friends[0].friends == null
          ? [{ name: "Pavlos" }]  // level 4 default value
          : props.user.friends[0].friends

If you don't pass the fourth argument to idx(), the default strategy would be 'ANY;, which means that we'll get DEFAULT_FRIENDS for any undefined value.

const DEFAULT_FRIENDS = [{ name: "Pavlos" }]
const result = idx(props, _ => _.user.friends[0].friends, DEFAULT_FRIENDS) // Use 'ANY' strategy

How about this proposal?

from idx.

yungsters avatar yungsters commented on April 28, 2024

@xareelee Thanks for the detailed proposal here and in claudepache/es-optional-chaining#16. However, I personally think it overcomplicates the problem that the optional chaining / existential operator seeks to solve.

Since idx is meant to be a polyfill for the ES proposal, I'll defer discussion there. If it gets incorporated into the proposal and makes reasonable progress in review, we can bring it into idx.

from idx.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.