Movatterモバイル変換


[0]ホーム

URL:


Jump to content
Rosetta Code
Search

First-class functions/Use numbers analogously

From Rosetta Code
<First-class functions
Task
First-class functions/Use numbers analogously
You are encouraged tosolve this task according to the task description, using any language you may know.

InFirst-class functions, a language is showing how its manipulation of functions is similar to its manipulation of other types.

This tasks aim is to compare and contrast a language's implementation of first class functions, with its normal handling of numbers.


Write a program to create an ordered collection of a mixture of literally typed and expressions producing a real number, together with another ordered collection of their multiplicative inverses. Try and use the following pseudo-code to generate the numbers for the ordered collections:

  x  = 2.0  xi = 0.5  y  = 4.0  yi = 0.25  z  = x + y  zi = 1.0 / ( x + y )

Create a functionmultiplier, that given two numbers as arguments returns a function that when called with one argument, returns the result of multiplying the two arguments to the call to multiplier that created it and the argument in the call:

 new_function = multiplier(n1,n2) # where new_function(m) returns the result of n1 * n2 * m

Applying the multiplier of a number and its inverse from the two ordered collections of numbers in pairs, show that the result in each case is one.
Compare and contrast the resultant program with the corresponding entry inFirst-class functions. They should be close.

To paraphrase the task description: Do what was done before, but with numbers rather than functions

11l

Translation of:Python
V (x, xi, y, yi) = (2.0, 0.5, 4.0, 0.25)V z = x + yV zi = 1.0 / (x + y)V multiplier = (n1, n2) -> (m -> @=n1 * @=n2 * m)V numlist = [x, y, z]V numlisti = [xi, yi, zi]print(zip(numlist, numlisti).map((n, inversen) -> multiplier(inversen, n)(.5)))
Output:
[0.5, 0.5, 0.5]

Ada

withAda.Text_IO;procedureFirstclassisgenericn1,n2:Float;functionMultiplier(m:Float)returnFloat;functionMultiplier(m:Float)returnFloatisbeginreturnn1*n2*m;endMultiplier;num,inv:array(1..3)ofFloat;beginnum:=(2.0,4.0,6.0);inv:=(1.0/2.0,1.0/4.0,1.0/6.0);foriinnum'Rangeloopdeclarefunctionnew_functionisnewMultiplier(num(i),inv(i));beginAda.Text_IO.Put_Line(Float'Image(new_function(0.5)));end;endloop;endFirstclass;
Output:
5.00000E-015.00000E-015.00000E-01

ALGOL 68

Translation of:python
Works with:ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release1.8-8d

Note: Standard ALGOL 68's scoping rules forbids exporting aproc[edure] (orformat) out of it's scope (closure). Hence this specimen will run onELLA ALGOL 68, but is non-standard. For a discussion of first-class functions in ALGOL 68 consult"The Making of Algol 68" -C.H.A. Koster (1993).

REAL  x  := 2,  xi := 0.5,  y  := 4,  yi := 0.25,  z  := x + y,  zi := 1 / ( x + y );MODE F = PROC(REAL)REAL; PROC multiplier = (REAL n1, n2)F: ((REAL m)REAL: n1 * n2 * m);# Numbers as members of collections #[]REAL num list = (x, y, z),       inv num list = (xi, yi, zi);# Apply numbers from list #FOR key TO UPB num list DO  REAL n = num list[key],       inv n = inv num list[key];  print ((multiplier(inv n, n)(.5), new line))OD

Output:

+.500000000000000e +0+.500000000000000e +0+.500000000000000e +0

Comparing and contrasting with the First Class Functions example:

As noted above, in order to do what is required by this task and the First Class Functions task, extensions to Algol 68 must be used.

The First Class Functions example uses C. H. Lindsey's partial parameterization extension to Algol 68 which implemented in Algol 68G but not in algol68toc.This example uses an alternative (technically, invalid Algol 68 as the author notes) accepted by algol68toc but not Algol 68G.

Arturo

x:2.0xi:0.5y:4.0yi:0.25z:x+yzi:1/zmultiplier:function[mn][function[a]with[mn][a*m*n]]couple@[xyz]@[xiyizi]|map'p->multiplierp\0p\1|map=>[call&->0.5]|print
Output:
0.5 0.5 0.5

Axiom

(x,xi,y,yi) := (2.0,0.5,4.0,0.25)(z,zi) := (x+y,1/(x+y))(numbers,invers) := ([x,y,z],[xi,yi,zi])multiplier(a:Float,b:Float):(Float->Float) == (m +-> a*b*m)[multiplier(number,inver) 0.5 for number in numbers for inver in invers]

Output:

  [0.5,0.5,0.5]                          Type: List(Float)

We can also curry functions, possibly with function composition, with the same output as before:

mult(n:Float):(Float->Float) == curryLeft(*$Float,n)$MAPPKG3(Float,Float,Float)[mult(number*inver) 0.5 for number in numbers for inver in invers][(mult(number)*mult(inver)) 0.5 for number in numbers for inver in invers]

Using the Spad code inFirst-class functions#Axiom, this can be done more economically using:

(map(mult,numbers)*map(mult,invers)) 0.5

For comparison,First-class functions#Axiom gave:

fns := [sin$Float, cos$Float, (x:Float):Float +-> x^3]inv := [asin$Float, acos$Float, (x:Float):Float +-> x^(1/3)][(f*g) 0.5 for f in fns for g in inv]

- which has the same output.

BBC BASIC

Works with:BBC BASIC for Windows
REM Create some numeric variables:x=2:xi=1/2y=4:yi=0.25z=x+y:zi=1/(x+y)REM Create the collections (here structures are used):DIMc{x,y,z}DIMci{x,y,z}c.x=x:c.y=y:c.z=zci.x=xi:ci.y=yi:ci.z=ziREM Create some multiplier functions:multx=FNmultiplier(c.x,ci.x)multy=FNmultiplier(c.y,ci.y)multz=FNmultiplier(c.z,ci.z)REM Test applying the compositions:x=1.234567:PRINTx" ",FN(multx)(x)x=2.345678:PRINTx" ",FN(multy)(x)x=3.456789:PRINTx" ",FN(multz)(x)ENDDEFFNmultiplier(n1,n2)LOCALf$,p%f$="(m)="+STR$n1+"*"+STR$n2+"*m"DIMp%LEN(f$)+4$(p%+4)=f$:!p%=p%+4=p%

Output:

  1.234567            1.234567  2.345678            2.345678  3.456789          3.45678901

Compare with the implementation of First-class functions:

REM Create some functions and their inverses:DEFFNsin(a)=SIN(a)DEFFNasn(a)=ASN(a)DEFFNcos(a)=COS(a)DEFFNacs(a)=ACS(a)DEFFNcube(a)=a^3DEFFNroot(a)=a^(1/3)dummy=FNsin(1)REM Create the collections (here structures are used):DIMcA{Sin%,Cos%,Cube%}DIMcB{Asn%,Acs%,Root%}cA.Sin%=^FNsin():cA.Cos%=^FNcos():cA.Cube%=^FNcube()cB.Asn%=^FNasn():cB.Acs%=^FNacs():cB.Root%=^FNroot()REM Create some function compositions:AsnSin%=FNcompose(cB.Asn%,cA.Sin%)AcsCos%=FNcompose(cB.Acs%,cA.Cos%)RootCube%=FNcompose(cB.Root%,cA.Cube%)REM Test applying the compositions:x=1.234567:PRINTx,FN(AsnSin%)(x)x=2.345678:PRINTx,FN(AcsCos%)(x)x=3.456789:PRINTx,FN(RootCube%)(x)ENDDEFFNcompose(f%,g%)LOCALf$,p%f$="(x)="+CHR$&A4+"(&"+STR$~f%+")("+\\CHR$&A4+"(&"+STR$~g%+")(x))"DIMp%LEN(f$)+4$(p%+4)=f$:!p%=p%+4=p%

C#

Works with:C# version 4.0

The structure here is exactly the same as the C# entry inFirst-class functions. The "var" keyword allows us to use the same initialization code for an array of doubles as an array of functions. Note that variable names have been changed to correspond with the new functionality.

usingSystem;usingSystem.Linq;classProgram{staticvoidMain(string[]args){doublex,xi,y,yi,z,zi;x=2.0;xi=0.5;y=4.0;yi=0.25;z=x+y;zi=1.0/(x+y);varnumlist=new[]{x,y,z};varnumlisti=new[]{xi,yi,zi};varmultiplied=numlist.Zip(numlisti,(n1,n2)=>{Func<double,double>multiplier=m=>n1*n2*m;returnmultiplier;});foreach(varmultiplierinmultiplied)Console.WriteLine(multiplier(0.5));}}

C++

#include<array>#include<iostream>intmain(){doublex=2.0;doublexi=0.5;doubley=4.0;doubleyi=0.25;doublez=x+y;doublezi=1.0/(x+y);conststd::arrayvalues{x,y,z};conststd::arrayinverses{xi,yi,zi};automultiplier=[](doublea,doubleb){return[=](doublem){returna*b*m;};};for(size_ti=0;i<values.size();++i){autonew_function=multiplier(values[i],inverses[i]);doublevalue=new_function(i+1.0);std::cout<<value<<"\n";}}
Output:
123

Clojure

(defx2.0)(defxi0.5)(defy4.0)(defyi0.25)(defz(+xy))(defzi(/1.0(+xy)))(defnumbers[xyz])(definvers[xiyizi])(defnmultiplier[ab](fn[m](*abm)))>(for[[ni](zipmapnumbersinvers)]((multiplierni)0.5))(0.50.50.5)

For comparison:

(use'clojure.contrib.math)(let[fns[#(Math/sin%)#(Math/cos%)(fn[x](*xxx))]inv[#(Math/asin%)#(Math/acos%)#(expt%1/3)]](map#(%0.5)(map#(comp%1%2)fnsinv)))

Output:

(0.5 0.4999999999999999 0.5000000000000001)

Common Lisp

(defunmultiplier(fg)#'(lambda(x)(*fgx)))(let*((x2.0)(xi0.5)(y4.0)(yi0.25)(z(+xy))(zi(/1.0(+xy)))(numbers(listxyz))(inverses(listxiyizi)))(loopwithvalue=0.5fornumberinnumbersforinverseininversesformultiplier=(multipliernumberinverse)do(formatt"~&(~A * ~A)(~A) = ~A~%"numberinversevalue(funcallmultipliervalue))))

Output:

(2.0 * 0.5)(0.5) = 0.5(4.0 * 0.25)(0.5) = 0.5(6.0 * 0.16666667)(0.5) = 0.5

The code fromFirst-class functions, for comparison:

(defuncompose(fg)(lambda(x)(funcallf(funcallgx))))(defuncube(x)(exptx3))(defuncube-root(x)(exptx(/3)))(loopwithvalue=0.5forfunctionin(list#'sin#'cos#'cube)forinversein(list#'asin#'acos#'cube-root)forcomposed=(composeinversefunction)do(formatt"~&(~A ∘ ~A)(~A) = ~A~%"inversefunctionvalue(funcallcomposedvalue)))

Output:

(#<FUNCTION ASIN> ∘ #<FUNCTION SIN>)(0.5) = 0.5(#<FUNCTION ACOS> ∘ #<FUNCTION COS>)(0.5) = 0.5(#<FUNCTION CUBE-ROOT> ∘ #<FUNCTION CUBE>)(0.5) = 0.5

D

importstd.stdio;automultiplier(doublea,doubleb){return(doublec)=>a*b*c;}voidmain(){doublex=2.0;doublexi=0.5;doubley=4.0;doubleyi=0.25;doublez=x+y;doublezi=1.0/(z);double[3]f=[x,y,z];double[3]r=[xi,yi,zi];foreach(i;0..3){automult=multiplier(f[i],r[i]);writefln("%f * %f * %f == %f",f[i],r[i],1.0,mult(1));}}

Output:

2.000000 * 0.500000 * 1.000000 == 1.0000004.000000 * 0.250000 * 1.000000 == 1.0000006.000000 * 0.166667 * 1.000000 == 1.000000

E

This is written to have identical structure toFirst-class functions#E, though the variable names are different.

def x := 2.0def xi := 0.5def y := 4.0def yi := 0.25def z := x + ydef zi := 1.0 / (x + y)def forward := [x,  y,  z ]def reverse := [xi, yi, zi]def multiplier(a, b) {    return fn x { a * b * x }}def s := 0.5for i => a in forward {    def b := reverse[i]    println(`s = $s, a = $a, b = $b, multiplier($a, $b)($s) = ${multiplier(a, b)(s)}`)}

Output:

s = 0.5, a = 2.0, b = 0.5, multiplier(2.0, 0.5)(0.5) = 0.5s = 0.5, a = 4.0, b = 0.25, multiplier(4.0, 0.25)(0.5) = 0.5s = 0.5, a = 6.0, b = 0.16666666666666666, multiplier(6.0, 0.16666666666666666)(0.5) = 0.5

Note:def g := reverse[i] is needed here because E as yet has no defined protocol for iterating over collections in parallel.Page for this issue.

Elena

Translation of:C#

ELENA 6.x :

import system'routines;import extensions; public program(){    real x := 2.0r;    real xi := 0.5r;    real y := 4.0r;    real yi := 0.25r;    real z := x + y;    real zi := 1.0r / (x + y);     var numlist := new real[]{  x, y, z };    var numlisti := new real[]{ xi, yi, zi };     var multiplied := numlist.zipBy(numlisti, (n1,n2 => (m => n1 * n2 * m) )).toArray();     multiplied.forEach::(multiplier){ console.printLine(multiplier(0.5r)) }}
Output:
0.50.50.5

Erlang

-module(first_class_functions_use_numbers).-export([task/0]).task()->X=2.0,Xi=0.5,Y=4.0,Yi=0.25,Z=X+Y,Zi=1.0/(X+Y),As=[X,Y,Z],Bs=[Xi,Yi,Zi],[io:fwrite("Value: 2.5 Result:~p~n",[(multiplier(A,B))(2.5)])||{A,B}<-lists:zip(As,Bs)].multiplier(N1,N2)->fun(M)->N1*N2*Mend.
Output:
20> first_class_functions_use_numbers:task().Value: 2.5 Result: 2.5Value: 2.5 Result: 2.5Value: 2.5 Result: 2.5

F#

Note that F# has a function that does this.

printfn "%f" ((*) 2.3 4.2) produces 9.660000.

letx=2.0letxi=0.5lety=4.0letyi=0.25letz=x+yletzi=1.0/(x+y)letmultiplier(n1,n2)=fun(m:float)->n1*n2*m[x;y;z]|>List.zip[xi;yi;zi]|>List.mapmultiplier|>List.map((|>)0.5)|>printfn"%A"
Output:
[0.5; 0.5; 0.5]

Factor

Compared tohttp://rosettacode.org/wiki/First-class_functions, the call to "compose" is replaced with the call to "mutliplier"

USING:arrayskernelliteralsmathprettyprintsequences;IN:qCONSTANT:x2.0CONSTANT:xi0.5CONSTANT:y4.0CONSTANT:yi.25CONSTANT:z$[$ x$ y+]CONSTANT:zi$[1$ x$ y+/]CONSTANT:A${xyz}CONSTANT:B${xiyizi}:multiplier(n1n2--q)[**]2curry;:create-all(seq1seq2--seq)[multiplier]2map;:example(--)0.5ABcreate-all[call(x--y)]withmap.;
Output:
{ 0.5 0.5 0.5 }

Fantom

class Main{  static |Float -> Float| combine (Float n1, Float n2)  {    return |Float m -> Float| { n1 * n2 * m }  }  public static Void main ()  {    Float x := 2f    Float xi := 0.5f    Float y := 4f    Float yi := 0.25f    Float z := x + y    Float zi := 1 / (x + y)    echo (combine(x, xi)(0.5f))    echo (combine(y, yi)(0.5f))    echo (combine(z, zi)(0.5f))  }}

Thecombine function is very similar to thecompose function in 'First-class functions'. In both cases a new function is returned:

  static |Obj -> Obj| compose (|Obj -> Obj| fn1, |Obj -> Obj| fn2)  {    return |Obj x -> Obj| { fn2 (fn1 (x)) }  }

FreeBASIC

FreeBASIC does not support first-class functions or function closures, which means that you cannot create a function that returns another function or that has a function defined inside it.

However, similar behavior can be achieved with subroutines and global variables.

DimAsDoublex=2.0,xi=0.5DimAsDoubley=4.0,yi=0.25DimAsDoublez=x+y,zi=1.0/(x+y)DimAsDoublevalues(2)={x,y,z}DimAsDoubleinverses(2)={xi,yi,zi}DimSharedAsDoublem=0.5Functionmultiplier(aAsDouble,dAsDouble)AsDoubleReturna*d*mEndFunctionForiAsByte=0ToUbound(values)DimAsDoublenew_function=multiplier(values(i),inverses(i))Printvalues(i);" *";inverses(i);" *";m;" =";new_functionNextiSleep
Output:
 2 * 0.5 * 0.5 = 0.5 4 * 0.25 * 0.5 = 0.5 6 * 0.1666666666666667 * 0.5 = 0.5

Go

"Number means value"

Task interpretation 1: "Number" means a numeric value, not any sort of reference. This is the most natural interpretation in Go.

At point A, the six variables have been assigned values, 64 bit floating point numbers, and not references to anything that is evaluated later. Again, at point B, these values have beencopied into the array elements. (The arrays being "ordered collections.") The original six variables could be changed at this point and the array values would stay the same.

Multiplier multiplies pairs of values and binds the result to the returned closure. This might be considered a difference from the First-class functions task. In that task, the functions were composed into a new function but not evaluated at the time of composition. Theycould have been, but that is not the usual meaning of function composition.

This task however, works with numbers, which are not reference types. Specifically, the closure here could could have closed on n1 an n2 individually and delayed multiplication until closure evaluation, but that might seem inconsistent with the task interpretation of working with numbers as values. Also, one would expect that a function named "multiplier" does actually multiply.

Multiplier of this task and compose of the First-class function task are similar in that they both return first class function objects, which are closed on free variables. The free variables in compose held the two (unevaluated) functions being composed. The free variable in multiplier holds theresult of multiplication.

At point C, numbers and their inverses have been multiplied and bound to first class functions. The ordered collection arrays could be modified at this point and the function objects would be unaffected.

packagemainimport"fmt"funcmain(){x:=2.xi:=.5y:=4.yi:=.25z:=x+yzi:=1/(x+y)// point Anumbers:=[]float64{x,y,z}inverses:=[]float64{xi,yi,zi}// point Bmfs:=make([]func(float64)float64,len(numbers))fori:=rangemfs{mfs[i]=multiplier(numbers[i],inverses[i])}// point Cfor_,mf:=rangemfs{fmt.Println(mf(1))}}funcmultiplier(n1,n2float64)func(float64)float64{// compute product of n's, store in a new variablen1n2:=n1*n2// close on variable containing productreturnfunc(mfloat64)float64{returnn1n2*m}}

Output:

111

"Number means reference"

Task interpretation 2: "Number" means something abstract, evaluation of which is delayed as long as possible. This interpretation is suggested by the task wording that this program and and the corresponding First-class functions program "should be close" and "do what was done before...."

To implement this behavior, reference types are used for "numbers" and a polymorphic array is used for the ordered collection, allowing both static and computed objects to stored.

At point A, the variables z and zi are assigned function literals, first class function objects closed on x and y. Changing the values of x or y at this point will cause z and zi to return different results. The x and y in these function literals reference the same storage as the x and y assigned values 2 and 4. This is more like the the First-class functions task in that we now have functions which we can compose.

At point B, we have filled the polymorphic arrays with all reference types. References to numeric typed variables x, xi, y, and yi were created with the & operator. z and zi can already be considered reference types in that they reference x and y. Changes to any of x, xi, y, or yi at this point would still affect later results.

Multiplier, in this interpretation of the task, simply composes multiplication of three reference objects, which may be variables or functions. It does not actually multiply and does not even evaluate the three objects. This is very much like the compose function of the First-class functions task.

Pursuant to the task description, this version of multiplier "returns the result of n1 * n2 * m" in the sense that it sets up evaluation of n1, n2, and m to be done at the same time, even if that time is not quite yet.

At point C, changes to x, xi, y, and yi will still propagate through and affect the results returned by the mfs objects. This can be seen as like the First-class functions task in that nothing (nothing numberic anyway) is evaluated until the final composed objects are evaluated.

This can also be done with an interface type rather than the "empty interface" (interface{}) for better type safety and to avoid theeval function and type switch.

packagemainimport"fmt"funcmain(){x:=2.xi:=.5y:=4.yi:=.25z:=func()float64{returnx+y}zi:=func()float64{return1/(x+y)}// point Anumbers:=[]interface{}{&x,&y,z}inverses:=[]interface{}{&xi,&yi,zi}// point Bmfs:=make([]func(ninterface{})float64,len(numbers))fori:=rangemfs{mfs[i]=multiplier(numbers[i],inverses[i])}// pointCfor_,mf:=rangemfs{fmt.Println(mf(1.))}}funcmultiplier(n1,n2interface{})func(interface{})float64{returnfunc(minterface{})float64{// close on interface objects n1, n2, and mreturneval(n1)*eval(n2)*eval(m)}}// utility function for evaluating multiplier interface objectsfunceval(ninterface{})float64{switchn.(type){casefloat64:returnn.(float64)case*float64:return*n.(*float64)casefunc()float64:returnn.(func()float64)()}panic("unsupported multiplier type")return0// never reached}

Groovy

defmultiplier={n1,n2->{m->n1*n2*m}}defε=0.00000001// tolerance(epsilon): acceptable level of "wrongness" to account for rounding error[(2.0):0.5,(4.0):0.25,(6.0):(1/6.0)].each{num,inv->defnew_function=multiplier(num,inv)(1.0..5.0).each{trial->assert(new_function(trial)-trial).abs()<εprintf('%5.3f * %5.3f * %5.3f == %5.3f\n',num,inv,trial,trial)}println()}
Output:
2.000 * 0.500 * 1.000 == 1.0002.000 * 0.500 * 2.000 == 2.0002.000 * 0.500 * 3.000 == 3.0002.000 * 0.500 * 4.000 == 4.0002.000 * 0.500 * 5.000 == 5.0004.000 * 0.250 * 1.000 == 1.0004.000 * 0.250 * 2.000 == 2.0004.000 * 0.250 * 3.000 == 3.0004.000 * 0.250 * 4.000 == 4.0004.000 * 0.250 * 5.000 == 5.0006.000 * 0.167 * 1.000 == 1.0006.000 * 0.167 * 2.000 == 2.0006.000 * 0.167 * 3.000 == 3.0006.000 * 0.167 * 4.000 == 4.0006.000 * 0.167 * 5.000 == 5.000

Haskell

moduleMainwhereimportText.Printf-- Pseudo code happens to be valid Haskellx=2.0xi=0.5y=4.0yi=0.25z=x+yzi=1.0/(x+y)-- Multiplier functionmultiplier::Double->Double->Double->Doublemultiplierab=\m->a*b*mmain::IO()main=doletnumbers=[x,y,z]inverses=[xi,yi,zi]pairs=zipnumbersinversesprint_pair(number,inverse)=letnew_function=multipliernumberinverseinprintf"%f * %f * 0.5 = %f\n"numberinverse(new_function0.5)mapM_print_pairpairs

This is very close to the first-class functions example, but given as a full Haskell program rather than an interactive session.

Icon andUnicon

The following is a Unicon solution. It can be recast in Icon, but only at the costof losing the "function-call" syntax on the created "procedure". The solution usesthe same basic foundation that is buried in the "compose" procedure in theFirst-class functions task solution. The solution hereis simpler and more direct since it handles a specific function definition.

importUtilsproceduremain(A)mult:=multiplier(get(A),get(A))# first 2 args define functioneverywrite(mult(!A))# remaining are passed to new functionendproceduremultiplier(n1,n2)returnmakeProc{repeatinVal:=n1*n2*(inVal@&source)[1]}end

A sample run:

->mu 2 3 4 5 6 724303642->

J

Explicit version

This seems to satisfy the new problem statement:

x=:2.0xi=:0.5y=:4.0yi=:0.25z=:x+yzi=:1.0%(x+y)NB. / is spelled % in Jfwd=:x,y,zrev=:xi,yi,zimultiplier=:2:'m * n * ]'

An equivalent but perhaps prettier definition of multiplier would be:

multiplier=:{{m*n*]}}

Or, if J's "right bracket is the right identity function" bothers you, you might prefer the slightly more verbose but still equivalent:

multiplier=:{{m*n*{{y}}}}

Example use:

   fwd multiplier rev 0.50.5 0.5 0.5

For contrast, here are the final results fromFirst-class functions#J:

   BA unqcol 0.50.5 0.5 0.5 0.5

Tacit (unorthodox) version

Although the pseudo-code to generate the numbers can certainly be written (see aboveExplicit version ) this is not done for this version because it would destroy part of the analogy (J encourages, from the programming perspective, to process all components at once as opposed to one component at a time). In addition, this version is done in terms of boxed lists of numbers instead of plain list of numbers, again, to preserve the analogy.

   multiplier=. train@:((;:'&*') ;~ an@: *)      ]A=. 2  ; 4  ; (2 + 4)   NB. Corresponds to  ]A=. box (1&o.)`(2&o.)`(^&3)┌─┬─┬─┐│2│4│6│└─┴─┴─┘   ]B=. %&.> A              NB. Corresponds to  ]B =. inverse&.> A┌───┬────┬────────┐│0.5│0.25│0.166667│└───┴────┴────────┘   ]BA=. B multiplier&.> A  NB. Corresponds to  B compose&.> A┌───┬───┬───┐│1&*│1&*│1&*│└───┴───┴───┘   BA of &> 0.5             NB. Corresponds to  BA of &> 0.5  (exactly)0.5 0.5 0.5

Please refer toFirst-class functions tacit (unorthodox) version for the definitions of the functions train, an and of.

Java

importjava.util.List;importjava.util.function.BiFunction;importjava.util.function.Function;publicfinalclassFirstClassFunctionsUseNumbersAnalogously{publicstaticvoidmain(String[]args){finaldoublex=2.0,xi=0.5,y=4.0,yi=0.25,z=x+y,zi=1.0/(x+y);List<Double>list=List.of(x,y,z);List<Double>inverseList=List.of(xi,yi,zi);BiFunction<Double,Double,Function<Double,Double>>multiplier=(a,b)->product->a*b*product;for(inti=0;i<list.size();i++){Function<Double,Double>multiply=multiplier.apply(list.get(i),inverseList.get(i));finaldoubleargument=(double)(i+1);System.out.println(multiply.apply(argument));}}}
Output:
1.02.03.0

jq

It may be helpful to compare the following definition of "multiplier" with its Ruby counterpartbelow. Whereas the Ruby definition must name all its positional parameters, the jq equivalent is defined as a filter that obtains them implicitly from its input.

# Infrastructure:# zip this and thatdef zip(that): [., that] | transpose;# The task:def x:  2.0;def xi: 0.5;def y:  4.0;def yi: 0.25;def z:  x + y;def zi: 1.0 / (x + y);def numlist: [x,y,z];def invlist: [xi, yi, zi];# Input: [x,y]def multiplier(j): .[0] * .[1] * j;numlist | zip(invlist) | map( multiplier(0.5) )
Output:
$ jq -n -c -f First_class_functions_Use_numbers_analogously.jq[0.5,0.5,0.5]


JavaScript

constx=2.0;constxi=0.5;consty=4.0;constyi=0.25;constz=x+y;constzi=1.0/(x+y);constpairs=[[x,xi],[y,yi],[z,zi]];consttestVal=0.5;constmultiplier=(a,b)=>m=>a*b*m;consttest=()=>{returnpairs.map(([a,b])=>{constf=multiplier(a,b);constresult=f(testVal);return`${a} *${b} *${testVal} =${result}`;});}test().join('\n');
Output:
2 * 0.5 * 0.5 = 0.54 * 0.25 * 0.5 = 0.56 * 0.16666666666666666 * 0.5 = 0.5

Julia

Works with:Julia version 0.6

In Julia, like Python and R, functions can be treated as like as other Types.

x,xi=2.0,0.5y,yi=4.0,0.25z,zi=x+y,1.0/(x+y)multiplier=(n1,n2)->(m)->n1*n2*mnumlist=[x,y,z]numlisti=[xi,yi,zi]@showcollect(multiplier(n,invn)(0.5)for(n,invn)inzip(numlist,numlisti))
Output:
collect(((multiplier(n, invn))(0.5) for (n, invn) = zip(numlist, numlisti))) = [0.5, 0.5, 0.5]

Kotlin

// version 1.1.2funmultiplier(n1:Double,n2:Double)={m:Double->n1*n2*m}funmain(args:Array<String>){valx=2.0valxi=0.5valy=4.0valyi=0.25valz=x+yvalzi=1.0/(x+y)vala=doubleArrayOf(x,y,z)valai=doubleArrayOf(xi,yi,zi)valm=0.5for(iin0untila.size){println("${multiplier(a[i], ai[i])(m)} = multiplier(${a[i]}, ${ai[i]})($m)")}}
Output:
0.5 = multiplier(2.0, 0.5)(0.5)0.5 = multiplier(4.0, 0.25)(0.5)0.5 = multiplier(6.0, 0.16666666666666666)(0.5)

Lua

-- This function returns another function that-- keeps n1 and n2 in scope, ie. a closure.functionmultiplier(n1,n2)returnfunction(m)returnn1*n2*mendend-- Multiple assignment a-go-golocalx,xi,y,yi=2.0,0.5,4.0,0.25localz,zi=x+y,1.0/(x+y)localnums,invs={x,y,z},{xi,yi,zi}-- 'new_function' stores the closure and then has the 0.5 applied to it-- (this 0.5 isn't in the task description but everyone else used it)fork,vinpairs(nums)donew_function=multiplier(v,invs[k])print(v.." * "..invs[k].." * 0.5 = "..new_function(0.5))end
Output:
2 * 0.5 * 0.5 = 0.54 * 0.25 * 0.5 = 0.56 * 0.16666666666667 * 0.5 = 0.5

M2000 Interpreter

ModuleCheckIt{\\bydefaultnumbersaredoublex=2xi=0.5y=4yi=0.25z=x+yzi=1/(x+y)Composed=lambda(a,b)->{=lambdaa,b(n)->{=a*b*n}}numbers=(x,y,z)inverses=(xi,yi,zi)DimBase0,combo(3)combo(0)=Composed(x,xi),Composed(y,yi),Composed(z,zi)num=each(numbers)inv=each(inverses)fun=each(combo())Whilenum,inv,fun{Print$("0.00"),Array(num);" * ";Array(inv);" * 0.50 = ";combo(fun^)(0.5),$("")Print}}Checkit\\forfunctionswehavethisdefinitionComposed=lambda(f1,f2)->{=lambdaf1,f2(x)->{=f1(f2(x))}}
Output:
2.00 * 0.50 * 0.50 = 0.504.00 * 0.25 * 0.50 = 0.506.00 * 0.17 * 0.50 = 0.50

Mathematica /Wolfram Language

This code demonstrates the example using structure similar to function composition, however the composition function is replace with the multiplier function.

multiplier[n1_,n2_]:=n1n2#&num={2,4,2+4};numi=1/num;multiplierfuncs=multiplier@@@Transpose[{num,numi}];

The resulting functions are unity multipliers:

Table[i[0.666], {i, multiplierfuncs}]{0.666, 0.666, 0.666}

Note that unlike Composition, the above definition of multiplier only allows for exactly two arguments. The definition can be changed to allow any nonzero number of arguments:

multiplier[arg__]:=Times[arg,#]&

Nemerle

Translation of:Python
usingSystem;usingSystem.Console;usingNemerle.Collections.NCollectionsExtensions;moduleFirstClassNums{Main():void{defx=2.0;defxi=0.5;defy=4.0;defyi=0.25;defz=x+y;defzi=1.0/(x+y);defmultiplier=fun(a,b){fun(c){a*b*c}};defnums=[x,y,z];definums=[xi,yi,zi];WriteLine($[multiplier(n,m)(0.5)|(n,m)inZipLazy(nums,inums)]);}}

Never

func multiplier(a : float, b : float) -> (float) -> float {    let func(m : float) -> float { a * b * m }}func main() -> int {    var x = 2.0;    var xi = 0.5;    var y = 4.0;    var yi = 0.25;    var z = x + y;    var zi = 1.0 / z;    var f = [ x, y, z ] : float;    var i = [ xi, yi, zi ] : float;    var c = 0;    var mult = let func(m : float) -> float { 0.0 };        for (c = 0; c < 3; c = c + 1) {        mult = multiplier(f[c], i[c]);        prints(f[c] + " * " + i[c] + " * " + 1.0 + " = " + mult(1) + "\n")    };    0}
Output:
2.00 * 0.50 * 1.00 = 1.004.00 * 0.25 * 1.00 = 1.006.00 * 0.17 * 1.00 = 1.00

Nim

funcmultiplier(a,b:float):auto=letab=a*bresult=func(c:float):float=ab*cletx=2.0xi=0.5y=4.0yi=0.25z=x+yzi=1.0/(x+y)letlist=[x,y,z]letinvlist=[xi,yi,zi]foriin0..list.high:# Create a multiplier function...letf=multiplier(list[i],invlist[i])# ... and apply it.echof(0.5)
Output:
0.50.50.5

Objeck

Similar however this code does not generate a list of functions.

use Collection.Generic;class FirstClass {  function : Main(args : String[]) ~ Nil {    x := 2.0;    xi := 0.5;    y := 4.0;    yi := 0.25;    z := x + y;    zi := 1.0 / (x + y);    numlist := CompareVector->New()<FloatHolder>;    numlist->AddBack(x); numlist->AddBack(y); numlist->AddBack(z);    numlisti := Vector->New()<FloatHolder>;    numlisti->AddBack(xi); numlisti->AddBack(yi); numlisti->AddBack(zi);        each(i : numlist) {      v := numlist->Get(i); vi := numlisti->Get(i);      mult := Multiplier(v, vi);      r := mult(0.5);      "{$v} * {$vi} * 0.5 = {$r}"->PrintLine();    };  }    function : Multiplier(a : FloatHolder, b : FloatHolder) ~ (FloatHolder) ~ FloatHolder {    return \(FloatHolder) ~ FloatHolder : (c) =>  a * b * c;  }}
Output:
2 * 0.5 * 0.5 = 0.54 * 0.25 * 0.5 = 0.56 * 0.166667 * 0.5 = 0.5

OCaml

#letx=2.0;;#lety=4.0;;#letz=x+.y;;#letcoll=[x;y;z];;#letinv_coll=List.map(funx->1.0/.x)coll;;#letmultipliern1n2=(funt->n1*.n2*.t);;(* create a list of new functions *)#letfunc_list=List.map2(funninv->(multiplierninv))collinv_coll;;#List.map(funf->f0.5)func_list;;-:floatlist=[0.5;0.5;0.5](* or just apply the generated function immediately... *)#List.map2(funninv->(multiplierninv)0.5)collinv_coll;;-:floatlist=[0.5;0.5;0.5]

Oforth

: multiplier(n1, n2)  #[ n1 n2 * * ] ;: firstClassNum| x xi y yi z zi |    2.0 ->x    0.5 ->xi   4.0 ->y   0.25 ->yi   x y + ->z   x y + inv ->zi   [ x, y, z ] [ xi, yi, zi ] zipWith(#multiplier) map(#[ 0.5 swap perform ] ) . ;
Output:
[0.5, 0.5, 0.5]

Oz

declare  [X Y Z] = [2.0  4.0  Z=X+Y]  [XI YI ZI] = [0.5  0.25  1.0/(X+Y)]  fun {Multiplier A B}     fun {$ M}        A * B * M     end  endin   for     N in [X  Y  Z]     I in [XI YI ZI]  do     {Show {{Multiplier N I} 0.5}}  end

"Multiplier" is like "Compose", but with multiplication instead of function application. Otherwise the code is identical except for the argument types (numbers instead of functions).

PARI/GP

Works with:PARI/GP version 2.4.2 and above
multiplier(n1,n2)={  x -> n1 * n2 * x};test()={  my(x = 2.0, xi = 0.5, y = 4.0, yi = 0.25, z = x + y, zi = 1.0 / ( x + y ));  print(multiplier(x,xi)(0.5));  print(multiplier(y,yi)(0.5));  print(multiplier(z,zi)(0.5));};

The two are very similar, though as requested the test numbers are in 6 variables instead of two vectors.

Pascal

Works with FPC (currently only version 3.3.1).

programFunTest;{$mode objfpc}{$modeswitch functionreferences}{$modeswitch anonymousfunctions}usesSysUtils;typeTMultiplier=referencetofunction(n:Double):Double;functionGetMultiplier(a,b:Double):TMultiplier;varprod:Double;beginprod:=a*b;Result:=function(n:Double):DoublebeginResult:=prod*nend;end;varMultiplier:TMultiplier;I:Integer;x,xi,y,yi:Double;Numbers,Inverses:arrayofDouble;beginx:=2.0;xi:=0.5;y:=4.0;yi:=0.25;Numbers:=[x,y,x+y];Inverses:=[xi,yi,1.0/(x+y)];forI:=0toHigh(Numbers)dobeginMultiplier:=GetMultiplier(Numbers[I],Inverses[I]);WriteLn(Multiplier(0.5));end;end.
Output:
5.0000000000000000E-0015.0000000000000000E-0015.0000000000000000E-001

PascalABC.NET

beginvarx,xi,y,yi,z,zi:real;x:=2.0;xi:=0.5;y:=4.0;yi:=0.25;z:=x+y;zi:=1.0/(x+y);varnumlist:=newreal[](x,y,z);varnumlisti:=newreal[](xi,yi,zi);varmultiplied:=numlist.Zip(numlisti,(n1,n2)->beginvarmultiplier:real->real:=m->n1*n2*m;Result:=multiplier;end);foreachvarmultiplierinmultiplieddoPrintln(multiplier(0.5));end.
Output:
0.50.50.5

Perl

submultiplier{my($n1,$n2)=@_;sub{$n1*$n2*$_[0];};}my$x=2.0;my$xi=0.5;my$y=4.0;my$yi=0.25;my$z=$x+$y;my$zi=1.0/($x+$y);my%zip;@zip{$x,$y,$z}=($xi,$yi,$zi);while(my($number,$inverse)=each%zip){printmultiplier($number,$inverse)->(0.5),"\n";}

Output:

0.50.50.5

The entry in first-class functions uses the same technique:

subcompose{my($f,$g)=@_;sub{$f->($g->(@_));};}...compose($flist1[$_],$flist2[$_])->(0.5)

Phix

Just as there is no real support for first class functions, not much that is pertinent to this task for numbers either, but the manual way is just as trivial:

withjavascript_semanticssequencemtable={}functionmultiplier(atomn1,atomn2)mtable=append(mtable,{n1,n2})returnlength(mtable)endfunctionfunctioncall_multiplier(integerf,atomm)atom{n1,n2}=mtable[f]returnn1*n2*mendfunctionconstantx=2,xi=0.5,y=4,yi=0.25,z=x+y,zi=1/(x+y)?call_multiplier(multiplier(x,xi),0.5)?call_multiplier(multiplier(y,yi),0.5)?call_multiplier(multiplier(z,zi),0.5)
Output:
0.50.50.5

I should perhaps note that output in Phix automatically rounds to the specified precision (10 d.p. if none) so 4.9999 to two decimal places is shown as 5.00, and you can be pretty sure that sort of thing is happening on the last line.

Compared to first class functions, there are (as in my view there should be) significant differences in the treatment of numbers and functions, but as mentioned on that page tagging ctable entries should be quite sufficient.

withjavascript_semanticssequencectable={}functioncompose(integerf,g)ctable=append(ctable,{f,g})integercdx=length(ctable)returncdxendfunctionfunctioncall_composite(integercdx,atomx)integer{f,g}=ctable[cdx]returnf(g(x))endfunctionfunctionplus1(atomx)returnx+1endfunctionfunctionhalve(atomx)returnx/2endfunctionconstantm=compose(halve,plus1)?call_composite(m,1)-- displays 1?call_composite(m,4)-- displays 2.5

PicoLisp

(load "@lib/math.l")(de multiplier (N1 N2)   (curry (N1 N2) (X)      (*/ N1 N2 X `(* 1.0 1.0)) ) )(let (X 2.0  Xi 0.5  Y 4.0  Yi 0.25  Z (+ X Y)  Zi (*/ 1.0 1.0 Z))   (mapc      '((Num Inv)         (prinl (format ((multiplier Inv Num) 0.5) *Scl)) )      (list X Y Z)      (list Xi Yi Zi) ) )

Output:

0.5000000.5000000.500001

This follows the same structure asFirst-class functions#PicoLisp, justthat the function 'multiplier' above accepts two numbers, while 'compose'below accepts two functions:

(load "@lib/math.l")(de compose (F G)   (curry (F G) (X)      (F (G X)) ) )(de cube (X)   (pow X 3.0) )(de cubeRoot (X)   (pow X 0.3333333) )(mapc   '((Fun Inv)      (prinl (format ((compose Inv Fun) 0.5) *Scl)) )   '(sin  cos  cube)   '(asin acos cubeRoot) )

With a similar output:

0.5000010.4999990.500000

Python

This new task:

IDLE2.6.1>>># Number literals>>>x,xi,y,yi=2.0,0.5,4.0,0.25>>># Numbers from calculation>>>z=x+y>>>zi=1.0/(x+y)>>># The multiplier function is similar to 'compose' but with numbers>>>multiplier=lambdan1,n2:(lambdam:n1*n2*m)>>># Numbers as members of collections>>>numlist=[x,y,z]>>>numlisti=[xi,yi,zi]>>># Apply numbers from list>>>[multiplier(inversen,n)(.5)forn,inverseninzip(numlist,numlisti)][0.5,0.5,0.5]>>>

The Python solution to First-class functions for comparison:

>>># Some built in functions and their inverses>>>frommathimportsin,cos,acos,asin>>># Add a user defined function and its inverse>>>cube=lambdax:x*x*x>>>croot=lambdax:x**(1/3.0)>>># First class functions allow run-time creation of functions from functions>>># return function compose(f,g)(x) == f(g(x))>>>compose=lambdaf1,f2:(lambdax:f1(f2(x)))>>># first class functions should be able to be members of collection types>>>funclist=[sin,cos,cube]>>>funclisti=[asin,acos,croot]>>># Apply functions from lists as easily as integers>>>[compose(inversef,f)(.5)forf,inversefinzip(funclist,funclisti)][0.5,0.4999999999999999,0.5]>>>

As can be see, the treatment of functions is very close to the treatment of numbers. there are no extra wrappers, or function pointer syntax added, for example.

R

multiplier<-function(n1,n2){(function(m){n1*n2*m})}x=2.0xi=0.5y=4.0yi=0.25z=x+yzi=1.0/(x+y)num=c(x,y,z)inv=c(xi,yi,zi)multiplier(num,inv)(0.5)Output[1]0.50.50.5

sCompared to original first class functions

sapply(mapply(compose,f1,f2),do.call,list(.5))[1]0.50.50.5

Quackery

In Quackery, everything is first-class. ("Everything" being operators (corresponding to "primitives"), numbers (bigNums), and nests (dynamic arrays of operators, numbers and nests.) Evaluating ("DOing" a number returns the value of the number (puts it on the stack – it's a stack-based concatenative language.) , but then very few languages do. Mostly they support some form of approximation to the reals, typically floating point, but Quackery comes with a library of basic bignum rational arithmetical words, defined in Quackery.

In the First-class functions task we borrowed floating point functions from Python as trigonometric functions were required. In this task rational arithmetic is plenty, so we will use that.

In the First-class functions task the wordcompose was defined as[ dip nested nested join ] is compose ( x x --> [ ). That would also work here, but it is overkill; the wordjoin is sufficient.

To make what is happening less opaque, the output shows the result of applyingmultiplier to the two arguments preceding it, and then the result of applying that to x, y, or z.

  [ $ "bigrat.qky" loadfile ] now!  [ 2 1 ]                    is x          (           --> n/d )  [ 1 2 ]                    is xi         (           --> n/d )  [ 4 1 ]                    is y          (           --> n/d )  [ 1 4 ]                    is yi         (           --> n/d )  [ x y v+ ]                 is z          (   n/d n/d --> n/d )   [ x y v+ 1/v ]             is zi         (   n/d n/d --> n/d )   [  ' [ v* v* ] join join ] is multiplier ( x n/d  --> [      )' xi ' [ 1 2 ] multiplier dup echo x rot do say " applied to x gives: " vulgar$ echo$ cr' yi ' [ 1 2 ] multiplier dup echo y rot do say " applied to y gives: " vulgar$ echo$ cr' zi ' [ 1 2 ] multiplier dup echo z rot do say " applied to z gives: " vulgar$ echo$ cr
Output:
[ 1 2 1 2 v* v* ] applied to x gives: 1/2[ 1 4 1 2 v* v* ] applied to y gives: 1/2[ x y v+ 1/v 1 2 v* v* ] applied to z gives: 1/2

Racket

#langracket(definex2.0)(definexi0.5)(definey4.0)(defineyi0.25)(definez(+xy))(definezi(/1.0(+xy)))(define((multiplierxy)z)(*xyz))(definenumbers(listxyz))(defineinverses(listxiyizi))(for/list([nnumbers][iinverses])((multiplierni)0.5));; -> '(0.5 0.5 0.5)

Raku

(formerly Perl 6)

Works with:Rakudo version 2015-09-10
submultiplied ($g,$f) {return {$g *$f *$^x } }my$x  =2.0;my$xi =0.5;my$y  =4.0;my$yi =0.25;my$z  =$x +$y;my$zi =1.0 / ($x +$y );my@numbers =$x,$y,$z;my@inverses =$xi,$yi,$zi;forflat@numbersZ@inverses {saymultiplied($^g,$^f)(.5) }

Output:

0.50.50.5

The structure of this is identical to first-class function task.

REXX

The REXX language doesn't have an easy method to call functions by using a variable name,
but theinterpret instruction can be used to provide that capability.

/*REXX program to use a  first-class function  to  use numbers analogously.             */nums=2.04.06.0/*various numbers,  can have fractions.*/invs=1/2.01/4.01/6.0/*inverses of the above (real) numbers.*/m=0.5/*multiplier when invoking new function*/doj=1forwords(nums);num=word(nums,j);inv=word(invs,j)nf=multiplier(num,inv);interpretcallnfm/*sets the var RESULT.*/say'number='@(num)'inverse='@(inv)'m='@(m)'result='@(result)end/*j*/exit/*stick a fork in it,  we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/@:returnleft(arg(1)/1,15)/*format the number,  left justified.  */multiplier:procedureexposen1n2;parseargn1,n2;n1n2=n1*n2;return'a_new_func'a_new_func:returnn1n2*arg(1)
output  when using the internal default inputs:
number= 2               inverse= 0.5             m= 0.5             result= 0.5number= 4               inverse= 0.25            m= 0.5             result= 0.5number= 6               inverse= 0.166666667     m= 0.5             result= 0.5

Ruby

multiplier=proc{|n1,n2|proc{|m|n1*n2*m}}numlist=[x=2,y=4,x+y]invlist=[0.5,0.25,1.0/(x+y)]pnumlist.zip(invlist).map{|n,invn|multiplier[invn,n][0.5]}# => [0.5, 0.5, 0.5]

This structure is identical to the treatment of Ruby'sfirst-class functions -- create a Proc object that returns a Proc object (a closure). These examples show that 0.5 times numbern (or passed to functionf) times inverse ofn (or passed to inverse off) returns the original number, 0.5.

Rust

#![feature(conservative_impl_trait)]fnmain(){let(x,xi)=(2.0,0.5);let(y,yi)=(4.0,0.25);letz=x+y;letzi=1.0/z;letnumlist=[x,y,z];letinvlist=[xi,yi,zi];letresult=numlist.iter().zip(&invlist).map(|(x,y)|multiplier(*x,*y)(0.5)).collect::<Vec<_>>();println!("{:?}",result);}fnmultiplier(x:f64,y:f64)->implFn(f64)->f64{move|m|x*y*m}

This is very similar to thefirst-class functions implementation save that the type inference works a little bit better here (e.g. when declaringnumlist andinvlist) andmultiplier's declaration is substantially simpler thancompose's. Both of these boil down to the fact that closures and regular functions are actually different types in Rust so we have to be generic over them but here we are only dealing with 64-bit floats.

Scala

scala>valx=2.0x:Double=2.0scala>valxi=0.5xi:Double=0.5scala>valy=4.0y:Double=4.0scala>valyi=0.25yi:Double=0.25scala>valz=x+yz:Double=6.0scala>valzi=1.0/(x+y)zi:Double=0.16666666666666666scala>valnumbers=List(x,y,z)numbers:List[Double]=List(2.0,4.0,6.0)scala>valinverses=List(xi,yi,zi)inverses:List[Double]=List(0.5,0.25,0.16666666666666666)scala>defmultiplier=(n1:Double,n2:Double)=>(m:Double)=>n1*n2*mmultiplier:(Double,Double)=>(Double)=>Doublescala>defcomp=numberszipinversesmapmultiplier.tupledcomp:List[(Double)=>Double]scala>comp.foreach(f=>println(f(0.5)))0.50.50.5

Scheme

This implementation closely follows the Scheme implementation of theFirst-class functions problem.

(definex2.0)(definexi0.5)(definey4.0)(defineyi0.25)(definez(+xy))(definezi(/(+xy)))(definenumber(listxyz))(defineinverse(listxiyizi))(define(multipliern1n2)(lambda(m)(*n1n2m)))(definem0.5)(define(gon1n2)(for-each(lambda(n1n2)(display((multipliern1n2)m))(newline))n1n2))(gonumberinverse)

Output:

0.50.50.5

Sidef

funcmultiplier(n1,n2){func(n3){n1*n2*n3}}varx=2.0varxi=0.5vary=4.0varyi=0.25varz=(x+y)varzi=(1/(x+y))varnumbers=[x,y,z]varinverses=[xi,yi,zi]forf,g(numbers~Zinverses){saymultiplier(f,g)(0.5)}
Output:
0.50.50.5

Slate

This example isincorrect. Please fix the code and remove this message.

Details: Compare and contrast the resultant program with the corresponding entry in First-class functions.

define: #multiplier -> [| :n1 :n2 | [| :m | n1 * n2 * m]].define: #x -> 2.define: #y -> 4.define: #numlist -> {x. y. x + y}.define: #numlisti -> (numlist collect: [| :x | 1.0 / x]).numlist with: numlisti collect: [| :n1 :n2 | (multiplier applyTo: {n1. n2}) applyWith: 0.5].

Tcl

Works with:Tcl version 8.5
packagerequireTcl8.5procmultiplier{ab}{listapply{{abm}{expr{$ab*$m}}}[expr{$a*$b}]}

Note that, as with Tcl's solution forFirst-class functions, the resulting term must be expanded on application. For example, study this interactive session:

%setmult23[multiplier23]apply{{abm}{expr{$ab*$m}}}6%{*}$mult23530

Formally, for the task:

setx2.0setxi0.5sety4.0setyi0.25setz[expr{$x+$y}]setzi[expr{1.0/($x+$y)}]setnumlist[list$x$y$z]setnumlisti[list$xi$yi$zi]foreacha$numlistb$numlisti{puts[format"%g * %g * 0.5 = %g"$a$b[{*}[multiplier$a$b]0.5]]}

Which produces this output:

2 * 0.5 * 0.5 = 0.54 * 0.25 * 0.5 = 0.56 * 0.166667 * 0.5 = 0.5

TXR

This solution seeks a non-strawman interpretation of the exercise: to treat functions and literal numeric terms under the same operations. We develop a three-argument function calledbinop whose argument is an ordinary function which works on numbers, and two arithmetic arguments which are any combination of functions or numbers. The functions may have any arity from 0 to 2. Thebinop functions handles all the cases.

The basic rules are:

  • When all required arguments are given to a function, it is expected that a number will be produced.
  • Zero-argument functions are called to force a number out of them.
  • When operands are numbers or zero-argument functions, a numeric result is calculated.
  • Otherwise the operation is a functional combinator, returning a function.
(defun binop (numop x y)  (typecase x    (number (typecase y              (number [numop x y])              (fun (caseql (fun-fixparam-count y)                     (0 [numop x [y]])                     (1 (ret [numop x [y @1]]))                     (2 (ret [numop x [y @1 @2]]))                     (t (error "~s: right argument has too many params"                               %fun% y))))              (t (error "~s: right argument must be function or number"                        %fun% y))))    (fun (typecase y           (number (caseql (fun-fixparam-count x)                     (0 [numop [x] y])                     (1 (ret [numop [x @1] y]))                     (2 (ret [numop [x @1 @2] y]))                     (t (error "~s: left argument has too many params"                               %fun% x))))           (fun (macrolet ((pc (x-param-count y-param-count)                                ^(+ (* 3 ,x-param-count) ,y-param-count)))                   (caseql* (pc (fun-fixparam-count x) (fun-fixparam-count y))                     (((pc 0 0)) [numop [x] [y]])                     (((pc 0 1)) (ret [numop [x] [y @1]]))                     (((pc 0 2)) (ret [numop [x] [y @1 @2]]))                     (((pc 1 0)) (ret [numop [x @1] [y]]))                     (((pc 1 1)) (ret [numop [x @1] [y @1]]))                     (((pc 1 2)) (ret [numop [x @1] [y @1 @2]]))                     (((pc 2 0)) (ret [numop [x @1 @2] [y]]))                     (((pc 2 1)) (ret [numop [x @1 @2] [y @1]]))                     (((pc 2 2)) (ret [numop [x @1 @2] [y @1 @2]]))                     (t (error "~s: one or both arguments ~s and ~s\ \                               have excess arity" %fun% x y)))))))      (t (error "~s: left argument must be function or number"              %fun% y))))(defun f+ (x y) [binop + x y])(defun f- (x y) [binop - x y])(defun f* (x y) [binop * x y])(defun f/ (x y) [binop / x y])

With this, the following sort of thing is possible:

1> [f* 6 4]  ;; ordinary arithmetic.242> [f* f+ f+]  ;; product of additions#<interpreted fun: lambda (#:arg-1-0062 #:arg-2-0063 . #:arg-rest-0061)>3> [*2 10 20]  ;; i.e. (* (+ 10 20) (+ 10 20)) -> (* 30 30)9004> [f* 2 f+]   ;; doubled addition#<interpreted fun: lambda (#:arg-1-0017 #:arg-2-0018 . #:arg-rest-0016)>5> [*4 11 19]  ;; i.e. (* 2 (+ 11 19))606> [f* (op f+ 2 @1) (op f+ 3 @1)]#<interpreted fun: lambda (#:arg-1-0047 . #:arg-rest-0046)>7> [*6 10 10]  ;; i.e. (* (+ 2 10) (+ 3 10)) -> (* 12 13)156

So with these definitions, we can solve the task like this, which demonstrates that numbers and functions are handled by the same operations:

(let* ((x 2.0)       (xi 0.5)       (y 4.0)       (yi 0.25)       (z (lambda () (f+ x y))) ;; z is obviously function       (zi (f/ 1 z)))           ;; also a function  (flet ((multiplier (a b) (op f* @1 (f* a b))))    (each ((n (list x y z))           (v (list xi yi zi)))      (prinl [[multiplier n v] 42.0]))))
Output:
42.042.042.0

Ursala

The form is very similar to the first class functions task solutionin Ursala, except that the multiplier function takes the place of thecomposition operator (+), and is named in compliancewith the task specification.

#import std#import flonumbers  = <2.,4.,plus(2.,4.)>inverses = <0.5,0.25,div(1.,plus(2.,4.))>multiplier = //times+ times#cast %eLmain = (gang multiplier*p\numbers inverses) 0.5

The multiplier could have been written in patternmatching form like this.

multiplier("a","b") "c" = times(times("a","b"),"c")

The main program might also have been written with ananonymous function like this.

main = (gang (//times+ times)*p\numbers inverses) 0.5

output:

<5.000000e-01,5.000000e-01,5.000000e-01>

Wren

Library:Wren-fmt
import"./fmt"forFmtvarmultiplier=Fn.new{|n1,n2|Fn.new{|m|n1*n2*m}}varorderedCollection=Fn.new{varx=2.0varxi=0.5vary=4.0varyi=0.25varz=x+yvarzi=1.0/(x+y)return[[x,y,z],[xi,yi,zi]]}varoc=orderedCollection.call()for(iin0..2){varx=oc[0][i]vary=oc[1][i]varm=0.5// rather than 1 to compare with first-class functions taskFmt.print("$0.1g * $g * $0.1g = $0.1g",x,y,m,multiplier.call(x,y).call(m))}
Output:

Agreeing with results of first-class functions task:

2.0 * 0.5      * 0.5 = 0.54.0 * 0.25     * 0.5 = 0.56.0 * 0.166667 * 0.5 = 0.5

zkl

var x=2.0, y=4.0, z=(x+y), c=T(x,y,z).apply(fcn(n){ T(n,1.0/n) });  //-->L(L(2,0.5),L(4,0.25),L(6,0.166667))
fcn multiplier(n1,n2){ return('*.fp(n1,n2)) }

This is actually partial evaluation, multiplier returns n1*n2*X where X isn't known yet. So multiplier(2,3)(4) --> (2*3*)4 --> 24. Even better, multiplier(2,3)(4,5) --> 120, multiplier(2,3)(4,5,6) --> 720, multiplier(2,3)() --> 6.

Alternatively,

fcn multiplier(n1,n2){ fcn(n,X){ n*X }.fp(n1*n2) }
var ms=c.apply(fcn([(n1,n2)]){ multiplier(n1,n2) });   //-->L(Deferred,Deferred,Deferred) // lazy eval of n*(1/n)*Xms.run(True,1.0)  //-->L(1,1,1)ms.run(True,5.0)  //-->L(5,5,5)ms.run(True,0.5)  //-->L(0.5,0.5,0.5)

List.run(True,X), for each item in the list, does i(X) and collects the results into another list. Sort of an inverted map or fold.

Retrieved from "https://rosettacode.org/wiki/First-class_functions/Use_numbers_analogously?oldid=374378"
Categories:
Hidden category:
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

[8]ページ先頭

©2009-2025 Movatter.jp