4 kyu
Currying vs. Partial Application
2,408 of 2,835surtich
Loading description...
Functional Programming
View
This comment has been reported as {{ abuseKindText }}.
Show
This comment has been hidden. You can view it now .
This comment can not be viewed.
- |
- Reply
- Edit
- View Solution
- Expand 1 Reply Expand {{ comments?.length }} replies
- Collapse
- Spoiler
- Remove
- Remove comment & replies
- Report
{{ fetchSolutionsError }}
-
-
Your rendered github-flavored markdown will appear here.
-
Label this discussion...
-
No Label
Keep the comment unlabeled if none of the below applies.
-
Issue
Use the issue label when reporting problems with the kata.
Be sure to explain the problem clearly and include the steps to reproduce. -
Suggestion
Use the suggestion label if you have feedback on how this kata can be improved.
-
Question
Use the question label if you have questions and/or need help solving the kata.
Don't forget to mention the language you're using, and mark as having spoiler if you include your solution.
-
No Label
- Cancel
Commenting is not allowed on this discussion
You cannot view this solution
There is no solution to show
Please sign in or sign up to leave a comment.
This comment has been hidden.
This comment has been hidden.
This comment has been hidden.
For dynamic languages with varargs support and high-order functions this is a very simple one liner. It was like 7kyu for me
Wouldn't go as far as saying 7kyu. It's ~6kyu-ish for JS, and maybe ~5-kyu-ish for Python. Doing it in Python was nowhere near as trivial as JS; the tests were a lot more exhaustive and the language isn't as lenient.
Weird flex.
My code passes all test cases except the very last 'tree of calls'. I wish there was a simpler test that did the same thing that was understandable enough to debug. The way that is written I have no idea how it expects to get a count from zero to 7. I keep returning 8 function calls instead. This criteria should be explained as part of the question prompt.
I've stored args in a scoped array. Different wrappings start to reference the same array. A test case not working with my "shared state" solution:
A pure solution may be even shorter/easier than an impure one
There really should be some random tests with functions of higher arity. I plugged in a lazy solution that actually relies on the fact that there is 0 to 4 arguments in test functions and it worked. Now I am not satisfied with myself but too lazy to change the solution.
Can't you just use arbitrary numbers of args?
Exactly. A real solution should work with an arbitrary number of args. Mine does not. But it passed the tests. That is why I think that there should be more tricky tests.
Newer versions of JavaScript should be enabled.
Node 12.x
enabled without updating all tests. Hopefully it's futureproof.Python 3 should be enabled.
Could this Kata possible be easier to solve in Javascript than in PHP? I only did the PHP version, but I found it to be more difficult than other level 4 Kayas.
All 12 current PHP solutions, including mine, use stuff from the PHP manual where it says in a big red box: "Warning: This function is currently not documented; only its argument list is available.". In other words: "Who knows what this does? Use at your own peril.". This is clearly not something you would ever want use on a daily basis.
Katas always seem have the same difficulty level, regardless of language, but perhaps that is not always right?
This comment has been hidden.
I added an unrandomized version of the test fixture to the example tests. This should help a lot ;-)
Thanks, can you check this other issue too please? ;-)
I don't think I'm familiar with currying/partial application in Python to figure it out quickly, unfortunately :(
This comment has been hidden.
Python: only one solution passes this test (a.k.a. composing (
partial
applying) a function that has already enough parameters to be evaluated) This is unconsistent with the fact you have to ignore additional parameters when currying a function.You should add this test or remove handling of additional arguments from your spec.
Done.
Impressive edit, also ensuring that local state is preserved is a clever requirement
That requirement had been there all along ;-)
This doesn't make sense though. The kata description says that first argument of
curryPartial
is a function.double
is a function, so iscurryPartial(double)
double
is a function without parameters, socurryPartial(double)
should beresult
Then you have to ignore additional parameters when currying: several tests use this fact and they must be consistent, otherwise it is a weird requirement to stop composition right in the middle.
See previous issue below
But it's still not consistent.
If I understand you correctly you say that
curryPartial(curryPartial(double), redundant_parameter) == result
is a valid test case becausecurryPartial(double, redundant_parameter) == result
is a valid test case.But with the same reasoning
curryPartial(double)(redundant_parameter) == result
should also be a valid test case. And that's something most current solutions couldn't cope with.I agree with robkal. There is a discrepancy between the JS and Python versions: my - submitted - JS solution would not pass the test
curryPartial(curryPartial(double), redundant_parameter) == result
because it yieldsresult
forcurryPartial(double)
, sincedouble()
has an arity of0
.Tough kata, but a very nice one. After completion, it was fascinating to see how other users solved it. Apparently there are many ways to do it.
May I suggest editing the tags on this kata? I would definitely add the tag: "metaprogramming". Also "advanced language features" seems a bit more appropriate than "fundamentals".
This are no metaprogramming required in this kata compared to another kata, Default Arguments. Standard JS usage is enough to finish this kata.
Looks like there's a bad spec, according to the examples you provided. Spec provides ultimately 4 arguments, but the function
add
being passed in only handles 3. My implementation takes those arguments without a problem and passes them all toadd
, but the expected result is 10 when it should be 6 - again, according to the examples.Which language are you encountering this problem in? I completed both the JavaScript and PHP versions myself without encountering any issues (except for following convention in PHP).
I encountered this same problem in JavaScript. It's the second test spec in the 'State isn't preserved' suite of tests.
There are no problems with the last set of tests. Since state is not preserved:
JS: Needs example tests
I added an unrandomized version of the test fixture to the example tests. This should help a lot ;-)
[PHP] Although there is no official documentation on the type of casing that user-defined function names should adopt, the fact that most, if not all, built-in PHP functions are in
snake_case
suggests that that should be the convention adopted. Please change the name of the function in PHP fromcurryPartial()
tocurry_partial()
.My bad for approving this Kata without checking the Python and PHP versions of this Kata beforehand (I only completed this Kata in JavaScript at the time of approval), but ...
Codewars Forums - Kata Best Practices - Follow Conventions
[Python] Function names should always be in
snake_case
and notcamelCase
(source: PEP 8) so please change the name of the user function fromcurryPartial
tocurry_partial
.Fixed
This comment has been hidden.
That is no longer the case - fortunately, all 4 Issues raised on this Kata were merely opinions and did not reflect any major flaws within the Kata itself so I resolved them all and approved it :D
Wait ... I just found a genuine Issue with the Python version of this Kata but I can't throw it back into Beta QAQ
Well, you approved the kata so you can edit the kata yourself to fix it.
It also means you're responsible for future kata issues ;-)
In my opinion, your tests don't cover all cases, for example, I found that a lot of solutions which don't take care of such case: var fn = curryPartial((a,b,c)=>a+b+c) var fn1 = fn(1) fn1(4,5) // returns 10 fn1(6,7) // returns 10, but must returns 14
Could you fix this problem? Or I can add such tests for your kata if you want
That means that this comment shouldn't be marked as an Issue - it should be marked as a Suggestion instead. Issues are for obvious problems with the Kata itself that need to be fixed to be of acceptable quality.
Personally, I found the test cases quite comprehensive. Even when it was hard to add random assertions to this Kata (due to the nature of the problem itself), the Kata author still went with it and made the greatest effort to introduce randomness to the test fixture to prevent hardcoded solutions from passing. As for the edge cases you mentioned, I think it's fair to allow a bit of wiggle room in the user solution so solvers can exercise their creativity and come up with different approaches.
Marking this as resolved for approval (if the other Issues on this Kata can be resolved as well).
Just because someone has an opinion doesn't mean it's debatable.
1 + 6 + 7
is14
. There is no room for people expressing their "creativity and come up with different approaches."I never worked with "functions within functions" (is it officially called "Closure"?) Is there any kata envolving this specific theme and easier to understand/solve?
Interesting kata. Getting my head around what it was asking for was a bit difficult, but once done it wasn't too hard. ES6 enables some pretty elegant solutions.
If you can you should make this for Lisp or Racket. Lambda calc is the core of Racket.
I think it's good to add a hint about specific Python features which help to solve a kata. At least it's a Python's kata, and it should help to learn a language, not just functional programming concepts.
P.S.: Also I think the difficulty of kata is not of "fundamentals": this is fundamental for any functional language, but not as excersise for Python.
This comment has been hidden.
I don't think
curryPartial(add)()(1)()()(2)(3, 4, 5, 6)
should be interpreted at all. You should throw a TypeError, because you gave it to many arguments. It would also be nice to have the examples as testcases.
Maybe you should add to the description, that kwargs (and arguments with defaults in general) are ignored.
Other than that, I really enjoyed solving this kata.
That is a personal opinion. JavaScript does not throw an error with the following code:
... so I think it's fair for the Kata author to define the task such that excess arguments do not cause a problem.
Marking this as resolved for approval (as long as other Issues on this Kata can be resolved as well).
It would've been nice if the tests given in the instructions were also given in the tests window. Not nice to have to write the tests out yourself if they could already have been given.
Excercise could be clearer. I was unsure of where to start. more examples would probably be good.
Personally I'm having issues accessing the data. I've tried console.log(fn); and it doesn't return anything ... am I missing something?
I think for clarity there should be a section that clearly outlines how to access the given data to avoid having to log. Blind pigs can find an occasional truffel, but it helps to know they grow in an oak forest ... give us an oak forest :P
I don't know if the Kata Description has been updated since you made this comment but right now the Description looks very clear to me with an abundance of examples.
Marking this as resolved for approval.
This comment has been hidden.
Them sounds like Haskell programmer words.
This was a port from a Javascript exercise. Actually, I ported the Python myself from the Hy source code, the lisp that compiles to python AST, because I thought it was cute. I modified it so that it fit Surtich's original exercise spec, since I didn't want to change his wording.
Javscript isn't beautiful. Software engineering isn't beautiful (not that this exercise is good engineering). Computers weren't invented by mathematicians. Babbage never finished his. They were invented to do the US Census, to crack Enigma code using a series of hacks, and to account for air resistance for World War II gunners. Actually, we might not have bothered with the air resistance calculations except that all of the hair dressers we had employed doing the arithmetic with adding machines were making too many errors (if you think Python can be ugly, I encourage you to program hairdressers for an exercise).
Historically, sometimes computer engineering was beautiful, but most of the time it was mountains of hacks on hacks. You should check out Goldstein's The Computer from Pascal to Von Neumann if haven't already. The truth about engineering is that things haven't changed much.
If you want a beautiful exercise, check out the Finally Tagless Interpreter kata. This, IMO, the most elegant exercise we have on Codewars.
True words. So we are happy that we aren't in software engineering here but on code wars. Alas, that FTI only is available in Haskell yet :-(
I find it peculiar that superfluous arguments are to be ignored. That is no good coding style, I'd say. Errors will go unnoticed, and taken strictly, things like
cur(add)(1)(2)(3)(4)
should be evaluated asadd(1,2,3)(4)
which would mean to call6(4)
and ints aren't callable. So this breaks the pattern.It's probably a good idea to drop the discussion of types in the description.
For one thing, in Haskell we have:
\ f -> curry ( curry f ) ≠ \ f -> curry f
(sincecurry . curry
has a different type thancurry
)However, in this kata we have
lambda f: curryPartial(curryPartial(f)) ≣ lambda f: curryPartial(f)
In fact
curryPartial
is not typeable in the simply typed or polymorphically typed λ-calculus. Given that both Javascript and Python are dynamically typed, talking about types doesn't really make a lot of sense for them.It's not obvious the function should handle any number of arguments, i.e. the number of arguments the passed funtion accepts.
This should be automatically implied from the Kata Task itself, what is the fun of this Kata if all functions passed in ever only receive exactly three arguments?
Marking this as resolved for approval.
Needs some polish to make it out of beta for Python IMHO
There are some typos in example code (eg. curriedAdd(add)), and no unit tests. I realised the typo because I used the inline examples. Codewars is printing functions as empty strings, so found this particular mistake annoying and took me a while to debug.
The repeated application of the function converter (
curryParial(curryPartial(fn))
), I found that tricky because of losing an easy way to read the original arity. Thought of setting some kind of property on function, but new to Python and wasn't sure how. See how now from other answers, but also quite a few people got lazy like me and just used exception handling instead. Not sure the value of handling this contingency anyway, since currying + variadic doesn't make much sense, and double application of currying would be a no-op and something to avoid.My bad; fixed.
Not really sure how to help here. Do you think the description text should contain hints that link to places in the documentation where you can learn these things?
Looking at latest answers, see how varied the solutions to get around the issue were. Eg. dudymas' use of a callable Class, or peatey using the function's internal name. Think finding a solution to the repeated application case is just "part of the fun" in the end.
Perhaps a small paragraph about ambiguity when calling on variadic functions would be useful.
This should be ranked as a pretty difficult kata, the description alone suggests architecture level, in my opinion borders on self gratification for the kata author,especially since there are only two people involved in the discussion of this kata. The explanation is rather abstract and would only make sense to those who operate at that level. Perhaps a more verbose and structured description could encourage us lesser mortals to attmpt the kata?
Sorry but it is not as difficult as you think. In fact it is relatively easy if you know something about functional programming. What I wanted with this kata is to explain the difference between currying and partial application. Since they are very similar things that are sometimes confused.
I'm bothered because your judgments. I am teacher and this kata I'm going to use in class with my students.
Well, despite your 'being a teacher' you missed the point, I was commenting on the description (instructions on the task) not on the complexity of the task itself. As you know being a teacher means ensuring the students understand the task at hand, which also means knowing the range of abilities your students can have). Since this is a Beta task, I was under the impression, all critiques were welcome, surely you are able to take contuctive critisism without being bothered, it certainly is no 'judgement'!
I myself am a developer, and have taught in the past, I know what functional programming is, however, your instructions still remain to me rather complex.
quote: 'in my opinion borders on self gratification for the kata author' -> In my opinion it is a judgment.
In the kata, I link this source. You could get more info there as the explanation of the kata is an adaptation of that article.
Yes, in my opinion, ? Are you suggesting I can't offer an opinion without you feeling its judgemental? This is a silly discussion, I will stop now as it 'appears' you are a little too sensitive to critisism.
I was wondering... doesn't this just amount to a simple partial? Allowing any number of args in, until they meet the signature of the function, then running the function?
Not in python, it doesn't. Give it a shot,
functools.partial
won't pass the test framework.Oh, I see. So a partial takes a load of arguments, then on the second call, adds the additional args and runs the original function. So you can only do
partial(func, arg1)(arg2)
, but no more?What do I look like, a python interpreter? •॒̀ ູ॒•́
But yeah, that's how
functools.partial
works.Sorry-- I don't use python or partials myself, so I'm just getting to understand this stuff. Sorry if my questions are dumb.
Could be an idea to add a note to the partials explanation so that it's clear what the difference between the curry/partial functionality is vs a regular partial.
I don't know, I think if it's set to level four then some hand holding can be eschewed...
Yeah, I see what you mean. To me though, there are two options: assume the coder knows what you are talking about, due to the kata's level, and not explain the given-topics; or explain them anyway, so that people that don't know can learn.
You can go either way I guess, but I'd lean toward the later.
Very nicely done.
Thought the pseudo-code snippets could use some work. Unless you understand that kind of Math-like way of showing things, this could be quite confusing for coders.
Well... I didn't have any problem, but then again I am a recovering mathematician.
Maybe you can post the edits you think should be made to the description here?
I think maybe if you just had the examples and make them clearer:
And then the partial:
Then say we want to write a method that will allow currying or partialing.
Sounds good to me.
Can you do the python code listings too or do you need help?
(Also, you should wait for surtich's okay, although I did make quite a few changes myself... I hope porting this to python was okay)
I'll let him do it, if he sees this (which I guess he will do at some point). And I'm only a JS guy, I'm afraid.
Eh, python is really easy... once there are a few more kata on this website you can pick it up in no time.
Yeah, that's cool. For now though, could you put in the python stuff?
I thought I did. What do you want me to do?
I was talking about tweaking the examples and explanations. You said
Can you do the python code listings too or do you need help?
-- not sure what you were referring to?I was offering to help you translate the listings in this message: http://www.codewars.com/kata/53cf7e37e9876c35a60002c9/discuss#53d53709c2c77223b70008ef
But since you aren't updating the kata, I think it's a bit premature for me to do anything.
Oh, I see. Yeah, go for it. ^^
Port to python?
Sorry. I do not enough know Python to do it.
@xcthulu You can actually edit other people's katas, so perhaps you could write the python tests?
Done.
...To bad the Clojure test runner is still in alpha, this is a great exercise in Clojure too...
It seems you've overwritten the JS description as well. Is there a way to write the descriptions separately for each language?
I did write seperate code listings for everything, and ordinarily this works (I've done in the past successfully for coffeescript/javascript/ruby listings).
Anyway, I fixed it now so it looks okay for javascript, but python is still screwed up.
I'll go file an issue for the Codewars devs.
Yeah-- had a go myself, and looks like it's not working correctly.