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

Apply is not a function #38

Closed
agentultra opened this Issue Sep 7, 2016 · 3 comments

Comments

Projects
None yet
2 participants
@agentultra

agentultra commented Sep 7, 2016

In trying to run a simple example of using core.operator I'm getting a TypeError from core.lambda, it dependency.

Steps to reproduce

const op = require('core.operators')

const users = [
    {name: 'Bob', email: 'bob@burgers.com', age: 43},
    {name: 'Linda', email: 'linda@burgers.com', age: 42},
    {name: 'Louise', email: 'louise@burgers.com', age: 9},
    {name: 'Tina', email: 'zombielove@burgers.com', age: 14},
    {name: 'Gene', email: 'gene@burgers.com', age: 12}
]

console.log(users.map(op.get('name')))
> npm install core.operator
> node test.js

Expected behaviour

It should print

['Bob', 'Linda', 'Louise', 'Tina', 'Gene']

Observed behaviour

/home/user/tmp/node_modules/core.lambda/lib/index.js:133
                               .apply(null, allArgs.slice(n)) }}
                                ^

TypeError: f.apply(...).apply is not a function
    at /home/user/tmp/node_modules/core.lambda/lib/index.js:133:33
    at Array.map (native)
    at Object.<anonymous> (/home/user/tmp/fp.js:13:19)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.runMain (module.js:575:10)
    at run (bootstrap_node.js:352:7)

Environment

  • Darwin Kernel Version 15.6.0
  • Node v6.3.0
  • core.operator@1.0.0
    • core.lambda@1.0.0
      )

@agentultra agentultra closed this Sep 7, 2016

@robotlolita

This comment has been minimized.

Show comment
Hide comment
@robotlolita

robotlolita Sep 7, 2016

Member

Ah, this is because core.operators has all functions curried, and Folktale's curry behaviour tries to unroll the function application.

const users = [a, b, c];
users.map(op.get('name'));

What you'd expect:

[op.get('name')(a), op.get('name')(b), op.get('name')(c)]

But Array.prototype.map doesn't pass one argument to that function, it passes three: the element, the index, and the array itself, so you get this instead:

[op.get('name')(a)(0, users), op.get('name')(b)(1, users), op.get('name')(c)(2, users)]

But because op.get('name') returns a String, rather than a function, the program fails :(

Solutions

There are two possible solutions here. One is not using core.operators for non-fantasy-land data structures. Since it looks like you're using ES6, your code could use this instead:

const users = [
    {name: 'Bob', email: 'bob@burgers.com', age: 43},
    {name: 'Linda', email: 'linda@burgers.com', age: 42},
    {name: 'Louise', email: 'louise@burgers.com', age: 9},
    {name: 'Tina', email: 'zombielove@burgers.com', age: 14},
    {name: 'Gene', email: 'gene@burgers.com', age: 12}
]

console.log(users.map(user => user.name))

This is the recommended solution as of Folktale 2.0. The new documentation for curry explains this in details.


Another option is using the core.arity library to restrict the number of arguments passed to your function:

const op = require('core.operators')
const unary = require('core.arity').unary

const users = [
    {name: 'Bob', email: 'bob@burgers.com', age: 43},
    {name: 'Linda', email: 'linda@burgers.com', age: 42},
    {name: 'Louise', email: 'louise@burgers.com', age: 9},
    {name: 'Tina', email: 'zombielove@burgers.com', age: 14},
    {name: 'Gene', email: 'gene@burgers.com', age: 12}
]

console.log(users.map(unary(op.get('name'))))

The unary function takes a function and makes sure that function only gets one argument, discarding all the others.

Do note that both core.operator and core.arity are deprecated in Folktale 2, in favour of the new ES6 arrow functions, which are simpler to understand and easier to read.

Member

robotlolita commented Sep 7, 2016

Ah, this is because core.operators has all functions curried, and Folktale's curry behaviour tries to unroll the function application.

const users = [a, b, c];
users.map(op.get('name'));

What you'd expect:

[op.get('name')(a), op.get('name')(b), op.get('name')(c)]

But Array.prototype.map doesn't pass one argument to that function, it passes three: the element, the index, and the array itself, so you get this instead:

[op.get('name')(a)(0, users), op.get('name')(b)(1, users), op.get('name')(c)(2, users)]

But because op.get('name') returns a String, rather than a function, the program fails :(

Solutions

There are two possible solutions here. One is not using core.operators for non-fantasy-land data structures. Since it looks like you're using ES6, your code could use this instead:

const users = [
    {name: 'Bob', email: 'bob@burgers.com', age: 43},
    {name: 'Linda', email: 'linda@burgers.com', age: 42},
    {name: 'Louise', email: 'louise@burgers.com', age: 9},
    {name: 'Tina', email: 'zombielove@burgers.com', age: 14},
    {name: 'Gene', email: 'gene@burgers.com', age: 12}
]

console.log(users.map(user => user.name))

This is the recommended solution as of Folktale 2.0. The new documentation for curry explains this in details.


Another option is using the core.arity library to restrict the number of arguments passed to your function:

const op = require('core.operators')
const unary = require('core.arity').unary

const users = [
    {name: 'Bob', email: 'bob@burgers.com', age: 43},
    {name: 'Linda', email: 'linda@burgers.com', age: 42},
    {name: 'Louise', email: 'louise@burgers.com', age: 9},
    {name: 'Tina', email: 'zombielove@burgers.com', age: 14},
    {name: 'Gene', email: 'gene@burgers.com', age: 12}
]

console.log(users.map(unary(op.get('name'))))

The unary function takes a function and makes sure that function only gets one argument, discarding all the others.

Do note that both core.operator and core.arity are deprecated in Folktale 2, in favour of the new ES6 arrow functions, which are simpler to understand and easier to read.

@agentultra

This comment has been minimized.

Show comment
Hide comment
@agentultra

agentultra Sep 7, 2016

Thanks for the detailed reply. I was just about to reply that I had figured it out and you beat me to it. 👍

agentultra commented Sep 7, 2016

Thanks for the detailed reply. I was just about to reply that I had figured it out and you beat me to it. 👍

@robotlolita

This comment has been minimized.

Show comment
Hide comment
@robotlolita

robotlolita Sep 7, 2016

Member

Np :)

Member

robotlolita commented Sep 7, 2016

Np :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment