Talk:Partial function application: Difference between revisions

m
(→‎Is D correct?: strict vs. liberal)
 
(21 intermediate revisions by 6 users not shown)
Line 144:
 
I think I will have to mark this as incorrect. --[[User:Paddy3118|Paddy3118]] 23:45, 14 April 2011 (UTC)
 
: I tried Scala. The _ seems to be a "partial application underscore". In ''fs(f1,_:List[Int])'', the _ has no value. So ''fs(f1,_:List[Int])'' returns a function that takes the missing value. The interpreter seems to think that ''fsf1'' is a variable of type ''(List[Int]) => List[Int]''. I have not found the documentation for the "partial application underscore", so I am not sure how it works. I am not the author of the Scala solution. --[[User:Kernigh|Kernigh]] 03:47, 20 April 2011 (UTC)
 
:: Hi Kernigh, if fs were defined as taking 3 arguments and currying would still refer to fs(f1,_) and not fs(f1,_,_) then I would be inclined to accept it as the '_' would stand for "any other arguments" rather than "any one argument" and would retain most of the insensitivity to the number of arguments of the Haskel-type implementations.
 
: <lang scala>scala> def rot(x: Int, y: Int, z: Int) = (y, z, x)
rot: (x: Int,y: Int,z: Int)(Int, Int, Int)
 
scala> rot(2, 3, 7)
res0: (Int, Int, Int) = (3,7,2)
 
scala> def a(y: Int) = rot(_: Int, y, _: Int)
a: (y: Int)(Int, Int) => (Int, Int, Int)
 
scala> a(3)(2, 7)
res1: (Int, Int, Int) = (3,7,2)</lang>
 
: It seems that _ is any one parameter. So, the Scala "partial application underscore" fails the task requirement that "other parameters are not explicitely mentioned". --[[User:Kernigh|Kernigh]] 02:17, 21 April 2011 (UTC)
 
I hope I have fixed this by clearly stating up front that Scala doesn't follow the description and where. This means that there is no doubt as to where the Scala moves away from the task description. The alternative is to delete the example and omit the language from the task. --[[User:Paddy3118|Paddy3118]] 05:35, 21 April 2011 (UTC)
 
: I've never written any Scala code and only seen a few samples, but this does look like partial application to me (quite similar to Perl 6's Whatever-Star). The fact that you have to mention a type signature might just be a limitation of Scala's type inferencer. The key question is: can you use this to pass an arity 3 function to map without using any intermediate definitions or lambda's? &mdash;''[[User:Ruud Koot|Ruud]]'' 07:05, 21 April 2011 (UTC)
 
:: <lang scala>scala> def f(a: Int, x: Int, b: Int) = a * x + b
f: (a: Int,x: Int,b: Int)Int
 
scala> List(1, 2, 3).map(f(10, _, 1))
res4: List[Int] = List(11, 21, 31)</lang>
 
:: Yes, you can pass arity 3 function to map. The _ has no type signature. A _ without a type signature can be an error, so I am not sure why it worked here. (I am new to Scala, and not the author of the Scala solution.) --[[User:Kernigh|Kernigh]] 19:00, 21 April 2011 (UTC)
 
==Is Lisp correct?==
Line 181 ⟶ 211:
: would be OK by me. What do others think? --[[User:Paddy3118|Paddy3118]] 21:03, 15 April 2011 (UTC)
:: I think it's the call of the primary task author. One way to write a task is to make very specific requirements that a certain technique be used. Languages that can't do it get marked omit, and the result is a clean comparison of that technique in different languages, without the clutter of similar but not-the-same techniques. A different way to write a task is to explain "here's a technique that achieves some goal. Demonstrate the technique in your language, or, if the technique is missing in your language, show the idiomatic way of achieving the same goal." Both are valid ways to write a task, but I really like it when the task description makes it clear one way or the other. For an example, Go doesn't do named or optional parameters. The named parameter task was very specific and I marked it omit. The optional parameter task was worded the second way, even putting in bold "whatever way is most natural to your language." So I enjoyed coding up an alternative way to achieve a similar effect. &mdash;[[User:Sonia|Sonia]] 10:16, 16 April 2011 (UTC)
::: I have added an extra note on not explicitely mentioning other parameters. It's now in twice so I hope the task now matches your first style, although I still thinks it is fine to state that it cannot be done, then give a laguages idiomatic way too. --[[User:Paddy3118|Paddy3118]] 15:52, 16 April 2011 (UTC)
 
Modified the D version. The Task doesn't specify that f has to be a run-time function. In this D implementation f has to be known at compile-time.
 
:Hi, The task description begins ''"Create a function fs( f, s ) that takes a '''function''', f( n ), of one value "''.
:So it is ''required'' that f be a function. Why not just say it is not possible in D if it is not, then explain why before giving the D code? --[[User:Paddy3118|Paddy3118]] 18:26, 16 April 2011 (UTC)
:: Partial application is mainly useful if it can be applied to idiomatically defined functions (in particular functions from the standard library). Perhaps the languages can be subdivided into two categories. One where this is possible and one where this is not? &mdash;''[[User:Ruud Koot|Ruud]]'' 09:34, 17 April 2011 (UTC)
 
== Proposal for new task description ==
Line 199 ⟶ 236:
:::Hi again Ruud. I was sure that there would be languages with first-class functions that would not be able to curry/partially-apply. What is new to me is that there may well be languages that are OK with currying, but have problems with partial application as they can't apply a subset of arguments without ''explicitely'' mentioning all arguments in the call to partial. Some manidestly, statically typed languages - i.e. those that require a type signature for everything, would need different and explicit type signatures dependant on how many arguments were being partially applied for example; Haskel works it out for itself.
:::Somehow, I do notice the similarity between currying and PFA, but unlike you, I see it as a strong reason to have two, contrasting tasks. What to do? --[[User:Paddy3118|Paddy3118]] 03:28, 16 April 2011 (UTC)
:::: I think it's somewhat more than a similarity: in the Haskell example we have that <code>papply2</code> = <code>curry</code> and <code>papply3</code> &approx; <code>curry3</code>. In the Ruby partial application and currying are both implemented by <code>Prox#curry</code>. It would be fun to see how a <code>curry</code> function in Python looks that works for functions of any arity like <code>partial</code> does (if this is possible) and how similar their definitions would be. Their currently isn't a task on [[Currying]]. Would it be a problem to create a new task [[Currying and partial application]] or does Rosetta Code strive to avoid duplicated and overlapping entries? &mdash;''[[User:Ruud Koot|Ruud]]'' 09:40, 17 April 2011 (UTC)
 
Here are samples in Haskell and Python:
 
Line 286 ⟶ 325:
 
: I prefer a new task, not a change to this task. --[[User:Kernigh|Kernigh]] 00:25, 16 April 2011 (UTC)
 
=== Current task description is a bit odd ===
Reading over the current task description, I think it is somewhat odd. It asks you to define a function ''f'' taking a single argument, and a higher-order function ''fs'' (essential ''map'') and to partially apply ''f'' to ''fs''. The most common use case of partial application, however, would be, given a function ''f'' of arity at least 2, partially apply arguments until it has remaining arity 1 and then pass this partially applied function to ''fs'' (i.e. ''map''). Even if we do not want to adopt my proposal above, I believe the current task description should still be modified. I would in this case advise ''f'' to be of arity 3, as this makes the task slightly more challenging and interesting for statically-typed languages. &mdash;''[[User:Ruud Koot|Ruud]]'' 10:29, 17 April 2011 (UTC)
 
: My suggested task description would read:
:* Define the linear function ''f''(''a'', ''b'', ''x'') ↦ ''ax'' + ''b''. This function should preferably by defined in an idiomatic form, but if this is not possible other solutions are acceptable.
:* Define the function ''[[map]]''(''f'', ''xs'') which applies its first argument, a function expecting a single argument, to each element of the sequence ''xs''. Preferably use the implementation from the standard library, if available.
:* Perform the following operations: partially apply ''a'' = 7 and ''b'' = 9 to ''f'', and apply this partially applied function to each element of a sequence using ''map''.
: &mdash;''[[User:Ruud Koot|Ruud]]'' 12:46, 20 April 2011 (UTC)
 
:: But how to ensure ''[http://www.haskell.org/haskellwiki/Partial_application partial application]'' is what a Haskel, or other functional programming language programmer would think is partial application? The temptation is for folks to just concentrate on getting the right numerical answer and ignore or miss attempts to constrain ''how'' the result is computed. --[[User:Paddy3118|Paddy3118]] 14:10, 20 April 2011 (UTC)
 
::: This is beginning to sound like a Haskell-specific concept, rather than an algorithmic concept. --[[User:Rdm|Rdm]] 17:52, 20 April 2011 (UTC)
 
:::: Well yes, partial application is a programming language concept, not an algorithm or design pattern. But it can be "done" a number of languages. &mdash;''[[User:Ruud Koot|Ruud]]'' 17:54, 20 April 2011 (UTC)
 
::: Using common sense and discussion? I don't think the task should be overspecified either. For example, specifying that you have to define a function similar to Python's <code>partial</code> would rule out ML's and Haskell's implicit partial application or perhaps a clever, but reasonable, trick involving C's preprocessor or C++'s templates. On the other hand, the current Java implementation might follow the the task to the letter, but certainly violates the spirit as it's not applicable to idiomatically defined functions from the standard library. &mdash;''[[User:Ruud Koot|Ruud]]'' 17:54, 20 April 2011 (UTC)
 
== What is partial application? ==
 
It occurred to me that when one speaks of "partial application" one can refer to several distinct things:
# The ''syntactic sugar'' that allows one to write <code>map (f 7 9) [1..9]</code> or <code>map(f(7,_,9),{1,...,9})</code> instead of <code>map (lambda x: f 7 9 x) [1..9]</code> or <code>def g(x): return f(7,9,x); end def in map(g,(1..9))</code>.
# The ''higher-order function'' <code>functools.partial</code>.
# The ''compilation technique'' that allows function thunks or closures to be "partially applied" instead of only unapplied or fully applied.
The task here should probably be about the first, perhaps also the second. &mdash;''[[User:Ruud Koot|Ruud]]'' 15:35, 21 April 2011 (UTC)
 
== Suggested changes to the task description ==
 
1) There is no need to require functions to be named <code>f1</code>, <code>f2</code>, <code>fsf1</code> or <code>fsf2</code>, and doing so excludes solutions in languages that don't allow digits to be used in identifiers.
 
2) The wording "partially apply <code>f1</code> to <code>fs</code>" should be changed to "partially apply <code>fs</code> to <code>f1</code>" because it's more conventional to speak of functions being applied to arguments than vice versa, and in this case <code>f1</code> is the argument.
 
3) Please be consistent about distinguishing between functions themselves and expressions in which they are applied to an argument. The wording "create a function <code>fs(f,s)</code> that takes a function <code>f(n)</code> ..." should be changed to "create a function <code>fs</code> that takes a function <code>f</code> ...". The expression <math>f(n)</math> refers conventionally not to the whole function <math>f</math> but to the single output associated with the argument <math>n</math> (unless you're an economist, in which case you'll infer an implied universal quantification with respect to the variable <math>n</math>, except when you don't).
 
--[[User:Sluggo|Sluggo]] 18:09, 14 June 2011 (UTC)
Anonymous user