3

I am learning function currying in JavaScript by reading online and writing some simple code. I got following example in online article

    function toArray(obj) {
        return Array.prototype.slice.call(obj);
    }

    Function.prototype.curry = function() {
        if (arguments.length<1) {
            return this; //nothing to curry with - return function
        }
        var __method = this;
        var args = toArray(arguments);
        return function() {
            return __method.apply(this, args.concat(toArray(arguments)));
        }
    }

    var add = function(a,b) {
        return a + b;
    }

    var addTen = add.curry(10); //create function that returns 10 + argument
    alert(addTen(20)); //alerts 30 correctly

Then I tried to try it on the method of an instantiated function. So I tried following. But it gave me error "Unable to get property 'prototype' of undefined or null reference" on the second last line. I know this error is nothing to do with currying but I am messing up with some basics of JS functions concept. So where I am going wrong.

    function Person()
    {
        this.age = 15;
    }

    Person.ageAfter = function (years) {
        return this.age + years;
    }

    var personObj = new Person();
    var ageAfterFiveYears = personObj.ageAfter.prototype.curry(5);  //**Error**
    alert(ageAfterFiveYears());
5
  • 2
    personObj does not have a property ageAfter. Only Person has. I think you meant to assign ageAfter to Person.prototype.ageAfter, so that each Person instance inherits that function. Commented Mar 24, 2013 at 20:20
  • @FelixKling I read that as a transcription error but you may be right that that's the immediate problem. Commented Mar 24, 2013 at 20:22
  • @Pointy: It's one of the problems I presume. The mentioned error message ""Unable to get property 'prototype' of undefined or null reference" supports this. Commented Mar 24, 2013 at 20:29
  • It's one of the problems I mentioned. Commented Mar 24, 2013 at 20:32
  • 2
    I'd just like to mention, that's not proper currying; it's partial application. See: stackoverflow.com/questions/218025/… Commented Mar 24, 2013 at 21:05

3 Answers 3

4

You have two issues:

  1. The ageAfter function is not an instance method - you've added it to the "class" (i.e. it's kind of like a static method). It should be added to the prototype.

  2. When you curry the function you lose your object's context, so you either need to rebind the context

e.g:

var ageAfterFiveYears = Person.prototype.ageAfter.curry(5).bind(personObj);

giving you a function that only works on the current instance, or better yet, as @Pointy suggests in the comments, you should just put the curried function back onto the prototype:

Person.prototype.ageAfterFiveYears = Person.prototype.ageAfter.curry(5);

which then adds the .ageAfterFiveYears method to every Person object.

Sign up to request clarification or add additional context in comments.

1 Comment

Alternatively, the result of calling "curry" could be added as a property of the instance or the "Person" prototype, and then called via the instance just like "ageAfter" is called.
4

You shouldn't include the prototype in your call:

var ageAfterFiveYears = personObj.ageAfter.curry(5);

The "ageAfter" property has a function for its value, so that function will have access to your "curry" function just like the function in your first example.

When you call it on the prototype, the value of this inside your function will be the prototype object, not the "ageAfter" function.

Also as a comment points out, you need to put "ageAfter" on the prototype:

Person.prototype.ageAfter = function(years) { ... }

edit — the binding issue that Alnitak points out is also important. (When I say "important", what I mean is "necessary to make your code work".)

1 Comment

@Mahesha999 without fixing the binding problem this remains incomplete.
1

Curry will not work for your use case. You need to bind the context so this is your personObj.

function Person() {
    this.age = 15;
}

Person.prototype.ageAfter = function (years) {
    return this.age + years;
}

var personObj = new Person();
var ageAfterFiveYears = personObj.ageAfter.bind(personObj, 5);
alert(ageAfterFiveYears());

2 Comments

note that although this works, it's probably no use to the OP since it doesn't actually use his .curry function.
yeah I know this bind() approach is also function currying, I tried this earlier and it worked but just wanted to explore other ways

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.