matteosister / php-curry

Curried functions for PHP
61 stars 1 forks source link

argument placeholder added #5

Closed webNeat closed 8 years ago

webNeat commented 8 years ago

Hello, I added a new feature which is argument placeholder. inspired from Ramdajs. This will allow doing things like:

$minus = C\curry(function ($x, $y) { return $x - $y; });
$decrement = $minus(C\__(), 1);
$this->assertEquals(9, $decrement(10));
matteosister commented 8 years ago

Hi @webNeat, thanks for your contribution...

I'm not so sure that I want to add this, because its about partial application and not currying functions. There are many libraries that do partial application, for example this one.

I'm open to change my idea....what do you think?

webNeat commented 8 years ago

Hello,

Currying and Partial Application are very close concepts. Let's take the definitions from this article

According to these definitions and this quote from the README

Currying a function means the ability to pass a subset of arguments to a function, and receive back another function that accept the rest of the arguments.

Your library does Partial Application more then Currying. Because the result of curry() is not an unary function !

What about the Placeholder ?

Let's take this function

function add ($x, $y, $z) {
    return $x + $y + $z;
}

Which can be represented with

add :: (Number $x, Number $y, Number $z) -> Number ($x + $y + $z)

A real curried version of it would be

function curriedAdd ($x) {
    return function ($y) use ($x) {
        return function ($z) use ($x, $y) {
            return $x + $y + $z;
        }
    }
}

Which similarly can be represented with

curriedAdd :: Number $x -> (Number $y -> (Number $z -> Number ($x + $y + $z)))

We generaly get ride of ()s and simply write

curriedAdd :: Number $x -> Number $y -> Number $z -> Number ($x + $y + $z)

So doing

$addTwo = curriedAdd(2);

gives

$addTwo :: Number $y -> Number $z -> Number ($x + $y + $z)

$addTwo is a function that takes 1 argument ($y) and returns another function

We can also say that $addTwo is somehow a partial application, because we can no longer change the value of the parameter $x which was already 'applied' with the value 2.

But doing

$newCurried = curriedAdd(__())

Results something like this

$newCurried :: Number $y -> Number $z -> Number $x -> Number ($x + $y + $z)

This function has the same arity as curriedAdd, the only difference is that curriedAdd takes $x then $y then $z, while this one takes $y then $z then $x.

This proccess is not partial application because the resulting function has exactly the same arity of the input function.

Summary:

Sorry for the long comment. I hope this clarifies the things a little bit

Feel free to correct me if I am wrong :smile:

matteosister commented 8 years ago

I know all the theory, thanks anyway for the head up :smile: Currying, sticking to the theory, is simply not possible in php. It should be done at a higher level. Haskell, for example is curried by default. And that is something that feels just right.

In elixir, the language I'm using the most right now, there is no default currying, but a thing called pipeline, that, in my opinion, bring the concept of partial/currying to a higher level. Where expressiveness and terseness wins upon theory.

Back to the sad php (that funcionally speaking really sucks) you could only mimic the behaviour.

When you apply two arguments to a function with an arity of 3, you are mimicing the fact that a curried language will return a one argument function for every step. In my opinion a placeholder do not fit with this concept. In haskell there is not a thing like that. You simply supply argument in the way they are specified in the original curried function.

Having said that, I'm happy to accept your pull request! Because you are really passionate about the argument, and the PR is really well done...many thanks!

matteosister commented 8 years ago

new release out!! https://github.com/matteosister/php-curry/releases/tag/0.4.0

webNeat commented 8 years ago

Thank you for accepting my PR. The thing is that I needed this feature in a library I am building https://github.com/tarsana/functional . And by the way, feel free to give me feedbacks about this one :smile: