First-class functions/Use numbers analogously: Difference between revisions

Added FreeBASIC
m (syntax highlighting fixup automation)
(Added FreeBASIC)
 
(9 intermediate revisions by 7 users not shown)
Line 108:
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.
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="arturo">x: 2.0
xi: 0.5
y: 4.0
yi: 0.25
z: x + y
zi: 1 / z
 
multiplier: function [m n][
function [a] with [m n][
a*m*n
]
]
 
couple @[x y z] @[xi yi zi]
| map 'p -> multiplier p\0 p\1
| map => [call & -> 0.5]
| print</syntaxhighlight>
 
{{out}}
 
<pre>0.5 0.5 0.5</pre>
 
=={{header|Axiom}}==
Line 413 ⟶ 437:
=={{header|Elena}}==
{{trans|C#}}
ELENA 56.0x :
<syntaxhighlight lang="elena">import system'routines;
import extensions;
Line 431 ⟶ 455:
var multiplied := numlist.zipBy(numlisti, (n1,n2 => (m => n1 * n2 * m) )).toArray();
multiplied.forEach::(multiplier){ console.printLine(multiplier(0.5r)) }
}</syntaxhighlight>
{{out}}
Line 541 ⟶ 565:
}
</syntaxhighlight>
 
=={{header|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.
<syntaxhighlight lang="vbnet">Dim As Double x = 2.0, xi = 0.5
Dim As Double y = 4.0, yi = 0.25
Dim As Double z = x + y, zi = 1.0 / (x + y)
Dim As Double values(2) = {x, y, z}
Dim As Double inverses(2) = {xi, yi, zi}
 
Dim Shared As Double m = 0.5
 
Function multiplier(a As Double, d As Double) As Double
Return a * d * m
End Function
 
For i As Byte = 0 To Ubound(values)
Dim As Double new_function = multiplier(values(i), inverses(i))
Print values(i); " *"; inverses(i); " *"; m; " ="; new_function
Next i
 
Sleep</syntaxhighlight>
{{out}}
<pre> 2 * 0.5 * 0.5 = 0.5
4 * 0.25 * 0.5 = 0.5
6 * 0.1666666666666667 * 0.5 = 0.5</pre>
 
=={{header|Go}}==
Line 810 ⟶ 861:
 
Please refer to [http://rosettacode.org/wiki/First-class_functions#Tacit_.28unorthodox.29_version First-class functions tacit (unorthodox) version] for the definitions of the functions train, an and of.
 
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
 
public class FirstClassFunctionsUseNumbersAnalogously {
 
public static void main(String[] args) {
final double x = 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 ( int i = 0; i < list.size(); i++ ) {
Function<Double, Double> multiply = multiplier.apply(list.get(i), inverseList.get(i));
final double argument = (double) ( i + 1 );
System.out.println(multiply.apply(argument));
}
}
 
}
</syntaxhighlight>
{{ out }}
<pre>
1.0
2.0
3.0
</pre>
 
=={{header|jq}}==
Line 815 ⟶ 900:
<syntaxhighlight lang="jq"># Infrastructure:
# zip this and that
def zip(that): [., that] | transpose;
. as $this | reduce range(0;length) as $i ([]; . + [ [$this[$i], that[$i]] ]);
 
# The task:
Line 833 ⟶ 917:
def multiplier(j): .[0] * .[1] * j;
 
numlist | zip(invlist) | map( multiplier(0.5) )</syntaxhighlight>
{{out}}
$ jq -n -c -f First_class_functions_Use_numbers_analogously.jq
[0.5,0.5,0.5]
 
As of this writing, there is no entry for jq at<!-- [[First-class functions#jq]]. -->
 
=={{header|JavaScript}}==
Line 1,205 ⟶ 1,289:
};</syntaxhighlight>
The two are very similar, though as requested the test numbers are in 6 variables instead of two vectors.
 
=={{header|Pascal}}==
Works with FPC (currently only version 3.3.1).
<syntaxhighlight lang="pascal">
program FunTest;
{$mode objfpc}
{$modeswitch functionreferences}
{$modeswitch anonymousfunctions}
uses
SysUtils;
 
type
TMultiplier = reference to function(n: Double): Double;
 
function GetMultiplier(a, b: Double): TMultiplier;
var
prod: Double;
begin
prod := a * b;
Result := function(n: Double): Double begin Result := prod * n end;
end;
 
var
Multiplier: TMultiplier;
I: Integer;
x, xi, y, yi: Double;
Numbers, Inverses: array of Double;
begin
x := 2.0;
xi := 0.5;
y := 4.0;
yi := 0.25;
Numbers := [x, y, x + y];
Inverses := [xi, yi, 1.0 / (x + y)];
for I := 0 to High(Numbers) do begin
Multiplier := GetMultiplier(Numbers[I], Inverses[I]);
WriteLn(Multiplier(0.5));
end;
end.
</syntaxhighlight>
{{out}}
<pre>
5.0000000000000000E-001
5.0000000000000000E-001
5.0000000000000000E-001
</pre>
 
=={{header|Perl}}==
Line 1,636 ⟶ 1,766:
4 * 0.25 * 0.5 = 0.5
6 * 0.166667 * 0.5 = 0.5</pre>
 
=={{header|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 called <code>binop</code> 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. The <code>binop</code> 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.
 
<syntaxhighlight lang="txrlisp">(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])</syntaxhighlight>
 
With this, the following sort of thing is possible:
 
<pre>1> [f* 6 4] ;; ordinary arithmetic.
24
2> [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)
900
4> [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))
60
6> [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
</pre>
 
So with these definitions, we can solve the task like this, which demonstrates that numbers and functions are handled by the same operations:
 
<syntaxhighlight lang="txrlisp">(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]))))</syntaxhighlight>
 
{{out}}
 
<pre>42.0
42.0
42.0</pre>
 
=={{header|Ursala}}==
Line 1,666 ⟶ 1,888:
=={{header|Wren}}==
{{libheader|Wren-fmt}}
<syntaxhighlight lang="ecmascriptwren">import "./fmt" for Fmt
 
var multiplier = Fn.new { |n1, n2| Fn.new { |m| n1 * n2 * m } }
2,130

edits