function factory (name, dependencies, create, meta) {
  function assertAndCreate (scope) {
    // we only pass the requested dependencies to the factory function
    // to prevent functions to rely on dependencies that are not explicitly
    // requested.
    const deps = pickShallow(scope, dependencies.map(stripOptionalNotation))

    assertDependencies(name, dependencies, scope)

    return create(deps)
  }

  assertAndCreate.isFactory = true
  assertAndCreate.fn = name
  assertAndCreate.dependencies = dependencies.slice().sort()
  if (meta) {
    assertAndCreate.meta = meta
  }

  return assertAndCreate
}
Create a factory function, which can be used to inject dependencies.

The created functions are memoized, a consecutive call of the factory
with the exact same inputs will return the same function instance.
The memoized cache is exposed on `factory.cache` and can be cleared
if needed.

Example:

    const name = 'log'
    const dependencies = ['config', 'typed', 'divideScalar', 'Complex']

    export const createLog = factory(name, dependencies, ({ typed, config, divideScalar, Complex }) => {
      // ... create the function log here and return it
    }

@param {string} name           Name of the function to be created
@param {string[]} dependencies The names of all required dependencies
@param {function} create       Callback function called with an object with all dependencies
@param {Object} [meta]
    Optional object with meta information that will be attached
    to the created factory function as property `meta`. For explanation
    of what meta properties can be specified and what they mean, see
    docs/core/extension.md.
@returns {function}