⚠️ Warning: This is a draft ⚠️
This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.
If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.
==Limitation of First-class functions== Is this task subject to the "limitation" of [[First-class functions]], ruling out C (or Fortran, or...), or we can accomplish the task implementing just a function that returns f(g(x)), having as argument f, g and x? --[[User:ShinTakezou|ShinTakezou]] 15:17, 3 March 2009 (UTC) :Hi, the limit is you have to create a function of f and g that returns another function. It is that other function, when applied to x would be the same as doing f(g(x)). If you look at the Python example, function compose returns function sin_cos. it is then sin_cos(x) that is equivalent to sin(cos(x)). In short, you need to create function compose. Thanks. --[[User:Paddy3118|Paddy3118]] 02:54, 4 March 2009 (UTC) ::I.e. this is possible only for languages that have [[First-class functions]] (by the way, it seems like this task is already covered by showing that the language has first class functions in [[First-class functions]] task page) --[[User:ShinTakezou|ShinTakezou]] 11:27, 4 March 2009 (UTC) :::Thats right, it is another aspect of first class functions but there is no need to show functions as members of other collection types. Some languages may be able to do this and not First Class Functions. --[[User:Paddy3118|Paddy3118]] 15:48, 4 March 2009 (UTC) ::Let me show another doubt of mine. What a function ''is'' for a language, is definible inside the same language; C can deal naturally with pointers, and we pass ''function'' to e.g. other functions by pointer (reference?); so foo(bar) call foo with argument bar (by the way, "calling a subroutine" for compiled languages means always to know its address, even at the end of the games a run-time, such the one of Objective-C when "finding" the code for a selector, ''compute'' the address of other compiled code...), and "foo" ''is'' the function (which C handles by pointer). So this task, if the right constraint of [[First-class functions]] is dropped (exactly the first: "New functions can be created from others at run time"), can be implemented in C. If it is not droppable, languages can accomplish this task iff they "have" first class functions. Am I reasonably right? --[[User:ShinTakezou|ShinTakezou]] 16:23, 4 March 2009 (UTC)
::IF you can create a version of compose that works for function pointers when you have an arbitrary set of two functions to compose then why not put it down? I add the extra restriction because if you had n sets of f and g functions to compose, i.e. composeN = compose(fN, gN) for N in 0..N-1 ::Then any of the composeN should be able to be used after all have been created. I can think of a naive implementation using function pointers where the last call to compose would reset the actions of all the composeN - this is not what is meant. My C is a little rusty but I guess if you could do something like:
fg = compose(&f, &g) (*fg)(x) /* Where (*fg)(x) == f(g(x)) and another call to compose would leave this one alone */
::--[[User:Paddy3118|Paddy3118]] 19:27, 4 March 2009 (UTC)
:::Hm, I was thinking about other (not portable...) methods; I will try... ;) --[[User:ShinTakezou|ShinTakezou]] 22:15, 4 March 2009 (UTC) ::: Spoon! I think you beated me:D At the beginning I was following a method similar to yours (except that I called ''function capsule'' something similar to what you called functor). But I was dissatisfied since this works only for function with double arg and returning double; I was thinking about a way of composing functions not dependently by the type of the value passed/returned, I thought to ''encapsulate'' the function in a function (!) which wants void * as input and ret value, and then it can be "dereferenced" and casted properly by the programmer (and a macro facility)... I was experimenting different methods (also using inline assembly:D) ... at the moment, failing:(... so I calm down unless your solution is marked as not ok for the task :D. Interesting. --[[User:ShinTakezou|ShinTakezou]] 23:26, 4 March 2009 (UTC)
::::Yea, void *
would work. I didn't use it because then I would have to allocate and de-allocate doubles all over the place. But feel free to change it. --[[User:Spoon!|Spoon!]] 00:01, 5 March 2009 (UTC)
Spoon, Shintakezou; I think the C solution should stay, as it does show the kind of hoops you would have to go through to implement this task in C. It also helps to explain the second paragraph in [[wp:First-class_function#Availability|First-class function: Availability]], on why they don't normally include C in the list of FP languages and mention the limitations of function pointers. --[[User:Paddy3118|Paddy3118]] 23:53, 4 March 2009 (UTC)
==J== Function composition is fundamental in J. J has a rich set of composition primitives and syntax to combine functions in multiple, interesting ways.
In the following examples, '''f''' and '''g''' are functions, ''x'' and ''y'' are variables (data). The syntax '''f''' ''y'' means the function '''f''' applied to one argument, ''y'' (unary), whereas ''x'' '''f''' ''y'' means the function '''f''' applied to (between) two arguments, ''x'' and ''y'' (binary).
Here's a selection of J's composition options:
{| class="wikitable" |- ! Composition: ∘ ! Unary interpretation: '''f'''∘'''g''' y ! Binary interpretation: x '''f'''∘'''g''' y ! Notes |- |@ |'''f'''('''g''' ''y'') |'''f'''(''x'' '''g''' ''y'') |'''f''' applied to each output of '''g''' independently |- |@. | | | To be discussed |- |@: |'''f'''('''g''' ''y'') |'''f'''(''x'' '''g''' ''y'') |'''f''' applied to all outputs of '''g''' simultaneously |- |& |'''f'''('''g''' ''y'') |('''g''' ''x'')'''f'''('''g''' ''y'') |'''f''' applied between each output of '''g''' on ''x'' and ''y'' pairwise |- |&. | | | To be discussed |- |&.: | | | To be discussed |- |&: |'''f'''('''g''' ''y'') |('''g''' ''x'')'''f'''('''g''' ''y'') |'''f''' applied between all outputs of '''g''' on ''x'' and ''y'' ''in toto'' |- |. | | | To be discussed |- |.. |(('''f''' y) + '''f'''('''g''' ''y''))/2 |((x '''f''' y) + ('''g''' ''x'')'''f'''('''g''' ''y''))/2 |Given '''h'''←'''f'''..'''g''', the resulting function, '''h''', is ''even'' in the sense that ('''h''' ''y'') = ('''h''' -''y'') for any ''y'' ; its graph is reflected in the vertical axis. |- |.: |(('''f''' y) - '''f'''('''g''' ''y''))/2 |((x '''f''' y) - ('''g''' ''x'')'''f'''('''g''' ''y''))/2 |Given '''h'''←'''f'''.:'''g''', the resulting function, '''h''', is ''odd'' in the sense that ('''h''' ''y'') = (-'''h''' -''y'') for any ''y'' ; its graph is reflected in the origin. |- |: |'''f''' ''y'' |''x'' '''g''' ''y'' | Allows the unary and binary definitions of a function to be specified independently. |- |:. | | | To be discussed |- |:: |try { '''f''' ''y'' } catch { '''g''' ''y'' } |try { ''x'' '''f''' ''y'' } catch { ''x'' '''g''' ''y'' } | Given '''h'''←'''f'''::'''g''', if '''f''' returns a valid value without error, then the result of '''h''' is the result of '''f'''; else, the result of '''h''' is the result of '''g'''. These succinct, functional exception handlers can be chained. |- |''hook'' | | | To be discussed |- |''fork'' | | | To be discussed |- |}
Still to discuss
::@. = functional selection ('''f'''`'''g'''@.'''h''')
::&. = ''under'', f&.g is (g_obverse@f)&g where g_obverse is the inverse of g if one has been defined.
::&.: = &.: is to &. as &: is to &.
::. = '''f'''.'''g''' is defined in terms of a recursive expansion by minors along the first column when unary, and as a generalized inner product when binary.
:::. = related to &. -- g :. G defines a new verb that behaves like g except that its obverse (defined inverse) is G.
::hook = an implicit composition of 2 functions -- in contexts which take only one argument it's structurally similar to the S combinator in much the way [ is similar to the K combinator and ([ [) y is y. ((u v) y) in J is equivalent to (y u v y) in J if u and v are verbs and y is a noun. Here, u is a combining verb (which takes a left and right argument and v gets only a single argument. For example (* -) 3 is 3 * - 3 or negative nine. Meanwhile x (u v) y is simply x u v y. For example 4 (* -) 3 is negative 12.
::fork = an implicit composition of 3 functions. (u v w) y is (u y) v (w y) for example (! * -) 4 is (!4) * (-4) or 24 * _4 or _96. Similarly x (u v w) y is (x u y) v (x w y) so for example 5 (* - +) 4 is (5*4) - (5+4) which is 20-9 which is 11. Trains of verbs longer than 3 are organized by grouping the rightmost three verbs as a fork which in turn is a single verb.
==VBScript problem== I think their should be a note added to the VBScript example stating that it takes two strings which are the names of functions which is not the same as VBScript functions, which the task description requires. With that stipulation up-front it would look OK. --[[User:Paddy3118|Paddy3118]] 05:48, 20 February 2010 (UTC)
== Wrong hint ==
The hint about using a closure is incorrect. Take javascript:
function compose(f, g) { var r = function(x) { return f(g(x)); } return r; }
returns an existing function ref with a closure containing function definition f
and g
at the time of invocation, while using eval and function names:
function compose2(f, g) { var r = new Function("x", "return " + f + "(" + g + "(x))"); //var r = eval("function(x) { return " + f + "(" + g + "(x));}"); return r; }
returns a function that calls g then f by names as passed in. The eval mathod creates a new, full fledged function, freshly compiled, and has nothing to do with closures. Either way, a function that's equivalent to f(g(x))
is returned, with the difference being that if f()
or g()
is modified later, the first method will not change, while the eval'd result will notice and call the new definitions. Which is more "true" of a function composition is a matter of intepretation. --[[User:Ledrug|Ledrug]] 07:25, 16 July 2011 (UTC)
:I have fixed the hint. --[[User:Rdm|Rdm]] 11:05, 16 July 2011 (UTC)
==Multiple Function Composition== I believe that quite a few languages have succeeded in performing this task simply because composing two numeric functions with a single parameter is (probably) the easiest possible example of function composition. In several cases, these solutions appear to violate the "spirit" of function composition. In my opinion, the definition of a function used to composes functions should look and behave like [http://reference.wolfram.com/mathematica/ref/Composition.html Mathematica's Composition function]. Common sense would suggest that if a developer needs to write greater than 80 SLOC just to compose two functions w/ one parameter, the likelihood of someone using this language feature in practice is pretty low. Therefore, I think we should discuss either modifying this task, or possibly creating a more difficult sub-task, to better reflect the practical use of this language feature.
As a starter, I would suggest that the compose function must be able to accept two or more functions as parameters. I would also like to see a concrete example for what should be composed then computed. I haven't come up with anything interesting, but I do like the following example because it uses multiple functions, a couple of different data types, and has an easily verifiable answer.
CL-USER> (compose model #'ceiling #'1+ #'sin #'square)
MODEL
CL-USER> (model pi)
1
-0.43030121700009226697L0
CL-USER>
--[[User:Lhignight|Larry Hignight]] 06:18, 14 June 2012 (UTC)
: Hi Larry, some might say that the comparison of LOC (Lines Of Code) to do this task is a good way of comparing the languages, and a new task to accept a list/array of functions, compose them in some order, then show the results of applying the composition to a number might be a good task to create. --[[User:Paddy3118|Paddy3118]] 07:04, 14 June 2012 (UTC)
: It's probably sufficient here to show that the composition of two functions is a function which can be composed like any other function? --[[User:Rdm|Rdm]] 13:11, 14 June 2012 (UTC)
:: Brilliant. No need for another task. --[[User:Paddy3118|Paddy3118]] 19:18, 14 June 2012 (UTC)
:: Agreed. Although it is less elegant than composing multiple functions with a single call, it does demonstrate that a language supports function composition without having to resort to additional functional programming language features. I would still prefer to see the task defined more precisely because I'm afraid we'll end up with several (sin (asin (sin x))) implementations. I haven't come up with a good example (yet), but I think that changing the task description to include the following output should separate most of the wheat from the chaff.
;;Example Usage:
;CL-USER> (compose f #'ceiling #'sin #'sqrt)
;F
CL-USER> (compose g #'1+ #'abs #'cos)
G
CL-USER> (compose h #'f #'g)
H
CL-USER> (values (f pi) (g pi) (h pi))
1
2.0L0
1
CL-USER>
--[[User:Lhignight|Larry Hignight]] 23:00, 20 June 2012 (UTC)
::: Not sure I agree with you about elegance -- the syntax you have in your illustration here favors composing lists of functions but that's an implementation detail, it's not universal. For example, in J, composing f g and h looks like f@g@h and composing them as a list looks like :6)@(y
:6)'''''/f
gh)
:6