Jensen's Device: Difference between revisions
Content added Content deleted
m (→{{header|Joy}}) |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 36: | Line 36: | ||
{{trans|C#}} |
{{trans|C#}} |
||
< |
<syntaxhighlight lang="11l">F sum(&i, lo, hi, term) |
||
V temp = 0.0 |
V temp = 0.0 |
||
i = lo |
i = lo |
||
Line 48: | Line 48: | ||
print(sum(&i, 1, 100, () -> 1 / @i)) |
print(sum(&i, 1, 100, () -> 1 / @i)) |
||
main()</ |
main()</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 56: | Line 56: | ||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
< |
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO; |
||
procedure Jensen_Device is |
procedure Jensen_Device is |
||
Line 81: | Line 81: | ||
begin |
begin |
||
Put_Line (Float'Image (Sum (I'Access, 1.0, 100.0, Inv_I'Access))); |
Put_Line (Float'Image (Sum (I'Access, 1.0, 100.0, Inv_I'Access))); |
||
end Jensen_Device;</ |
end Jensen_Device;</syntaxhighlight> |
||
<pre> |
<pre> |
||
5.18738E+00 |
5.18738E+00 |
||
Line 108: | Line 108: | ||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
{{trans|ALGOL 60}} |
{{trans|ALGOL 60}} |
||
< |
<syntaxhighlight lang="algol68">BEGIN |
||
INT i; |
INT i; |
||
PROC sum = (REF INT i, INT lo, hi, PROC REAL term)REAL: |
PROC sum = (REF INT i, INT lo, hi, PROC REAL term)REAL: |
||
Line 123: | Line 123: | ||
COMMENT note the correspondence between the mathematical notation and the call to sum COMMENT |
COMMENT note the correspondence between the mathematical notation and the call to sum COMMENT |
||
print (sum (i, 1, 100, REAL: 1/i)) |
print (sum (i, 1, 100, REAL: 1/i)) |
||
END</ |
END</syntaxhighlight> |
||
Output: +5.18737751763962e +0 |
Output: +5.18737751763962e +0 |
||
Line 131: | Line 131: | ||
<br>This version uses call by name for the i parameter but uses a procedure parameter for the summed expression. |
<br>This version uses call by name for the i parameter but uses a procedure parameter for the summed expression. |
||
<br>The expression supplied in the call is automatically converted to a procedure by the compiler. |
<br>The expression supplied in the call is automatically converted to a procedure by the compiler. |
||
< |
<syntaxhighlight lang="algolw">begin |
||
integer i; |
integer i; |
||
real procedure sum ( integer %name% i; integer value lo, hi; real procedure term ); |
real procedure sum ( integer %name% i; integer value lo, hi; real procedure term ); |
||
Line 147: | Line 147: | ||
% note the correspondence between the mathematical notation and the call to sum % |
% note the correspondence between the mathematical notation and the call to sum % |
||
write( sum( i, 1, 100, 1/i ) ) |
write( sum( i, 1, 100, 1/i ) ) |
||
end.</ |
end.</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 153: | Line 153: | ||
=={{header|AppleScript}}== |
=={{header|AppleScript}}== |
||
< |
<syntaxhighlight lang="applescript">set i to 0 |
||
on jsum(i, lo, hi, term) |
on jsum(i, lo, hi, term) |
||
Line 169: | Line 169: | ||
end script |
end script |
||
return jsum(a reference to i, 1, 100, term_func)</ |
return jsum(a reference to i, 1, 100, term_func)</syntaxhighlight> |
||
Output: 5.18737751764 |
Output: 5.18737751764 |
||
=={{header|ARM Assembly}}== |
=={{header|ARM Assembly}}== |
||
{{works with|as|Raspberry Pi}} |
{{works with|as|Raspberry Pi}} |
||
<syntaxhighlight lang="arm assembly"> |
|||
<lang ARM Assembly> |
|||
/* ARM assembly Raspberry PI */ |
/* ARM assembly Raspberry PI */ |
||
Line 259: | Line 259: | ||
fUn: .float 1 |
fUn: .float 1 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Arturo}}== |
=={{header|Arturo}}== |
||
{{trans|Ruby}} |
{{trans|Ruby}} |
||
< |
<syntaxhighlight lang="rebol">harmonicSum: function [variable, lo, hi, term][ |
||
result: new 0.0 |
result: new 0.0 |
||
loop lo..hi 'n -> |
loop lo..hi 'n -> |
||
Line 268: | Line 268: | ||
result |
result |
||
] |
] |
||
print ["harmonicSum 1->100:" harmonicSum 'i 1 100 {1.0 / i}]</ |
print ["harmonicSum 1->100:" harmonicSum 'i 1 100 {1.0 / i}]</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 275: | Line 275: | ||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
<syntaxhighlight lang="awk"> |
|||
<lang AWK> |
|||
# syntax: GAWK -f JENSENS_DEVICE.AWK |
# syntax: GAWK -f JENSENS_DEVICE.AWK |
||
# converted from FreeBASIC |
# converted from FreeBASIC |
||
Line 290: | Line 290: | ||
printf("%.15f\n",tmp) |
printf("%.15f\n",tmp) |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 298: | Line 298: | ||
=={{header|BASIC256}}== |
=={{header|BASIC256}}== |
||
{{trans|FreeBASIC}} |
{{trans|FreeBASIC}} |
||
< |
<syntaxhighlight lang="basic256">subroutine Evaluation() |
||
lo = 1 : hi = 100 : temp = 0 |
lo = 1 : hi = 100 : temp = 0 |
||
for i = lo to hi |
for i = lo to hi |
||
Line 307: | Line 307: | ||
call Evaluation() |
call Evaluation() |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 316: | Line 316: | ||
=={{header|BBC BASIC}}== |
=={{header|BBC BASIC}}== |
||
{{works with|BBC BASIC for Windows}} |
{{works with|BBC BASIC for Windows}} |
||
< |
<syntaxhighlight lang="bbcbasic"> PRINT FNsum(j, 1, 100, FNreciprocal) |
||
END |
END |
||
Line 326: | Line 326: | ||
= temp |
= temp |
||
DEF FNreciprocal = 1/i</ |
DEF FNreciprocal = 1/i</syntaxhighlight> |
||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 333: | Line 333: | ||
=={{header|Bracmat}}== |
=={{header|Bracmat}}== |
||
< |
<syntaxhighlight lang="bracmat">( ( sum |
||
= I lo hi Term temp |
= I lo hi Term temp |
||
. !arg:((=?I),?lo,?hi,(=?Term)) |
. !arg:((=?I),?lo,?hi,(=?Term)) |
||
Line 346: | Line 346: | ||
) |
) |
||
& sum$((=i),1,100,(=!i^-1)) |
& sum$((=i),1,100,(=!i^-1)) |
||
);</ |
);</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>14466636279520351160221518043104131447711/2788815009188499086581352357412492142272</pre> |
<pre>14466636279520351160221518043104131447711/2788815009188499086581352357412492142272</pre> |
||
=={{header|C}}== |
=={{header|C}}== |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
int i; |
int i; |
||
Line 366: | Line 366: | ||
printf("%f\n", sum(&i, 1, 100, term_func)); |
printf("%f\n", sum(&i, 1, 100, term_func)); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
Output: 5.18738 |
Output: 5.18738 |
||
{{works with|gcc}} |
{{works with|gcc}} |
||
Alternatively, C's macros provide a closer imitation of ALGOL's call-by-name semantics: |
Alternatively, C's macros provide a closer imitation of ALGOL's call-by-name semantics: |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
int i; |
int i; |
||
Line 389: | Line 389: | ||
printf("%f\n", sum(i, 1, 100, 1.0 / i)); |
printf("%f\n", sum(i, 1, 100, 1.0 / i)); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
Output: 5.187378 |
Output: 5.187378 |
||
=={{header|C sharp}}== |
=={{header|C sharp}}== |
||
Can be simulated via lambda expressions: |
Can be simulated via lambda expressions: |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
class JensensDevice |
class JensensDevice |
||
Line 413: | Line 413: | ||
Console.WriteLine(Sum(ref i, 1, 100, () => 1.0 / i)); |
Console.WriteLine(Sum(ref i, 1, 100, () => 1.0 / i)); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|C++}}== |
=={{header|C++}}== |
||
< |
<syntaxhighlight lang="cpp"> |
||
#include <iostream> |
#include <iostream> |
||
Line 439: | Line 439: | ||
std::cout << SUM(i,1,100,1.0/i) << "\n"; |
std::cout << SUM(i,1,100,1.0/i) << "\n"; |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
Output: 5.18738 |
Output: 5.18738 |
||
5.18738 |
5.18738 |
||
Line 445: | Line 445: | ||
=={{header|Clipper}}== |
=={{header|Clipper}}== |
||
With hindsight Algol60 provided this feature in a way that is terrible for program maintenance, because the calling code looks innocuous. |
With hindsight Algol60 provided this feature in a way that is terrible for program maintenance, because the calling code looks innocuous. |
||
< |
<syntaxhighlight lang="clipper">// Jensen's device in Clipper (or Harbour) |
||
// A fairly direct translation of the Algol 60 |
// A fairly direct translation of the Algol 60 |
||
// John M Skelton 11-Feb-2012 |
// John M Skelton 11-Feb-2012 |
||
Line 465: | Line 465: | ||
next i |
next i |
||
return temp |
return temp |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
Line 471: | Line 471: | ||
Common Lisp does not have call-by-name for functions; however, it can be directly simulated by a macro wrapping selected parameters in lambdas. |
Common Lisp does not have call-by-name for functions; however, it can be directly simulated by a macro wrapping selected parameters in lambdas. |
||
< |
<syntaxhighlight lang="lisp">(declaim (inline %sum)) |
||
(defun %sum (lo hi func) |
(defun %sum (lo hi func) |
||
Line 477: | Line 477: | ||
(defmacro sum (i lo hi term) |
(defmacro sum (i lo hi term) |
||
`(%sum ,lo ,hi (lambda (,i) ,term)))</ |
`(%sum ,lo ,hi (lambda (,i) ,term)))</syntaxhighlight> |
||
< |
<syntaxhighlight lang="lisp">CL-USER> (sum i 1 100 (/ 1 i)) |
||
14466636279520351160221518043104131447711/2788815009188499086581352357412492142272 |
14466636279520351160221518043104131447711/2788815009188499086581352357412492142272 |
||
CL-USER> (float (sum i 1 100 (/ 1 i))) |
CL-USER> (float (sum i 1 100 (/ 1 i))) |
||
5.1873775</ |
5.1873775</syntaxhighlight> |
||
=={{header|D}}== |
=={{header|D}}== |
||
There are better ways to do this in D, but this is closer to the original Algol version: |
There are better ways to do this in D, but this is closer to the original Algol version: |
||
< |
<syntaxhighlight lang="d">double sum(ref int i, in int lo, in int hi, lazy double term) |
||
pure @safe /*nothrow @nogc*/ { |
pure @safe /*nothrow @nogc*/ { |
||
double result = 0.0; |
double result = 0.0; |
||
Line 499: | Line 499: | ||
int i; |
int i; |
||
sum(i, 1, 100, 1.0/i).writeln; |
sum(i, 1, 100, 1.0/i).writeln; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 506: | Line 506: | ||
=={{header|DWScript}}== |
=={{header|DWScript}}== |
||
Must use a "while" loop, as "for" loop variables are restricted to local variable for code clarity, and this indeed a case where any kind of extra clarity helps. |
Must use a "while" loop, as "for" loop variables are restricted to local variable for code clarity, and this indeed a case where any kind of extra clarity helps. |
||
< |
<syntaxhighlight lang="delphi">function sum(var i : Integer; lo, hi : Integer; lazy term : Float) : Float; |
||
begin |
begin |
||
i:=lo; |
i:=lo; |
||
Line 517: | Line 517: | ||
var i : Integer; |
var i : Integer; |
||
PrintLn(sum(i, 1, 100, 1.0/i));</ |
PrintLn(sum(i, 1, 100, 1.0/i));</syntaxhighlight> |
||
Output: 5.187... |
Output: 5.187... |
||
Line 526: | Line 526: | ||
(The definition of the outer <var>i</var> has been moved down to emphasize that it is unrelated to the <var>i</var> inside of <var>sum</var>.) |
(The definition of the outer <var>i</var> has been moved down to emphasize that it is unrelated to the <var>i</var> inside of <var>sum</var>.) |
||
< |
<syntaxhighlight lang="e">pragma.enable("one-method-object") # "def _.get" is experimental shorthand |
||
def sum(&i, lo, hi, &term) { # bind i and term to passed slots |
def sum(&i, lo, hi, &term) { # bind i and term to passed slots |
||
var temp := 0 |
var temp := 0 |
||
Line 539: | Line 539: | ||
var i := null |
var i := null |
||
sum(&i, 1, 100, def _.get() { return 1/i }) |
sum(&i, 1, 100, def _.get() { return 1/i }) |
||
}</ |
}</syntaxhighlight> |
||
<tt>1/i</tt> is not a noun, so there is no slot associated with it; so we use <tt>def _.get() { return 1/i }</tt> to define a slot object which does the computation when it is read as a slot. |
<tt>1/i</tt> is not a noun, so there is no slot associated with it; so we use <tt>def _.get() { return 1/i }</tt> to define a slot object which does the computation when it is read as a slot. |
||
Line 547: | Line 547: | ||
This emulation of the original call-by-name is of course unidiomatic; a natural version of the same computation would be: |
This emulation of the original call-by-name is of course unidiomatic; a natural version of the same computation would be: |
||
< |
<syntaxhighlight lang="e">def sum(lo, hi, f) { |
||
var temp := 0 |
var temp := 0 |
||
for i in lo..hi { temp += f(i) } |
for i in lo..hi { temp += f(i) } |
||
return temp |
return temp |
||
} |
} |
||
sum(1, 100, fn i { 1/i })</ |
sum(1, 100, fn i { 1/i })</syntaxhighlight> |
||
=={{header|Elixir}}== |
=={{header|Elixir}}== |
||
{{trans|Erlang}} |
{{trans|Erlang}} |
||
< |
<syntaxhighlight lang="elixir">defmodule JensenDevice do |
||
def task, do: sum( 1, 100, fn i -> 1 / i end ) |
def task, do: sum( 1, 100, fn i -> 1 / i end ) |
||
Line 566: | Line 566: | ||
end |
end |
||
IO.puts JensenDevice.task</ |
IO.puts JensenDevice.task</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 576: | Line 576: | ||
No call by name, no macros, so I use a fun(ction). Actually, the the macro part is a lie. Somebody else, that knows how, could do a parse transform. |
No call by name, no macros, so I use a fun(ction). Actually, the the macro part is a lie. Somebody else, that knows how, could do a parse transform. |
||
<syntaxhighlight lang="erlang"> |
|||
<lang Erlang> |
|||
-module( jensens_device ). |
-module( jensens_device ). |
||
Line 588: | Line 588: | ||
Temp = Term( I ), |
Temp = Term( I ), |
||
Temp + sum( I + 1, High, Term ). |
Temp + sum( I + 1, High, Term ). |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 597: | Line 597: | ||
=={{header|F_Sharp|F#}}== |
=={{header|F_Sharp|F#}}== |
||
< |
<syntaxhighlight lang="fsharp"> |
||
printfn "%.14f" (List.fold(fun n g->n+1.0/g) 0.0 [1.0..100.0]);; |
printfn "%.14f" (List.fold(fun n g->n+1.0/g) 0.0 [1.0..100.0]);; |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 606: | Line 606: | ||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
Similar to the Java and Kotlin examples: |
Similar to the Java and Kotlin examples: |
||
< |
<syntaxhighlight lang="factor">: sum ( lo hi term -- x ) [ [a,b] ] dip map-sum ; inline |
||
1 100 [ recip ] sum .</ |
1 100 [ recip ] sum .</syntaxhighlight> |
||
This version is a bit closer to the original, as it increments <code>i</code> in the caller's namespace. |
This version is a bit closer to the original, as it increments <code>i</code> in the caller's namespace. |
||
< |
<syntaxhighlight lang="factor">SYMBOL: i |
||
: sum ( i lo hi term -- x ) |
: sum ( i lo hi term -- x ) |
||
Line 617: | Line 617: | ||
inline |
inline |
||
i 1 100 [ recip ] sum .</ |
i 1 100 [ recip ] sum .</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 626: | Line 626: | ||
This version passes i on the stack: |
This version passes i on the stack: |
||
< |
<syntaxhighlight lang="forth">: sum 0 s>f 1+ swap ?do i over execute f+ loop drop ; |
||
:noname s>f 1 s>f fswap f/ ; 1 100 sum f.</ |
:noname s>f 1 s>f fswap f/ ; 1 100 sum f.</syntaxhighlight> |
||
Output: 5.18737751763962 |
Output: 5.18737751763962 |
||
The following version passes i and 1/i as execution tokens and is thus closer to the original, but less idiomatic: |
The following version passes i and 1/i as execution tokens and is thus closer to the original, but less idiomatic: |
||
< |
<syntaxhighlight lang="forth">fvariable ii \ i is a Forth word that we need |
||
: sum ( xt1 lo hi xt2 -- r ) |
: sum ( xt1 lo hi xt2 -- r ) |
||
0e swap 1+ rot ?do ( addr xt r1 ) |
0e swap 1+ rot ?do ( addr xt r1 ) |
||
i s>f over execute f! dup execute f+ |
i s>f over execute f! dup execute f+ |
||
loop 2drop ; |
loop 2drop ; |
||
' ii 1 100 :noname 1e ii f@ f/ ; sum f.</ |
' ii 1 100 :noname 1e ii f@ f/ ; sum f.</syntaxhighlight> |
||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
Fortran does not offer call-by-name in the manner of the Algol language. It passes parameters by reference (i.e. by passing the storage address) and alternatively uses copy-in, copy-out to give the same effect, approximately, as by reference. If a parameter is an arithmetic expression, it will be evaluated and its value stored in a temporary storage area, whose address will be passed to the routine. This evaluation is done once only for each call, thus vitiating the repeated re-evaluation required by Jensen's device every time within the routine that the parameter is accessed. So, this will ''not'' work< |
Fortran does not offer call-by-name in the manner of the Algol language. It passes parameters by reference (i.e. by passing the storage address) and alternatively uses copy-in, copy-out to give the same effect, approximately, as by reference. If a parameter is an arithmetic expression, it will be evaluated and its value stored in a temporary storage area, whose address will be passed to the routine. This evaluation is done once only for each call, thus vitiating the repeated re-evaluation required by Jensen's device every time within the routine that the parameter is accessed. So, this will ''not'' work<syntaxhighlight lang="fortran"> FUNCTION SUM(I,LO,HI,TERM) |
||
SUM = 0 |
SUM = 0 |
||
DO I = LO,HI |
DO I = LO,HI |
||
Line 647: | Line 647: | ||
END FUNCTION SUM |
END FUNCTION SUM |
||
WRITE (6,*) SUM(I,1,100,1.0/I) |
WRITE (6,*) SUM(I,1,100,1.0/I) |
||
END</ |
END</syntaxhighlight> |
||
Here, type declarations have been omitted to save space because they won't help - until there appears a "BY NAME" or some such phrasing. Although variable <code>I</code> in the calling routine will have its value adjusted as the DO-loop in SUM proceeds (the parameter being passed by reference), this won't affect the evaluation of 1.0/I, which will be performed once using whatever value is in the caller's variable (it is uninitialised, indeed, undeclared also and so by default an integer) then the function is invoked with the address of the location containing that result. The function will make many references to that result, obtaining the same value each time. The fact that the caller's <code>I</code> will be changed each time doesn't matter. |
Here, type declarations have been omitted to save space because they won't help - until there appears a "BY NAME" or some such phrasing. Although variable <code>I</code> in the calling routine will have its value adjusted as the DO-loop in SUM proceeds (the parameter being passed by reference), this won't affect the evaluation of 1.0/I, which will be performed once using whatever value is in the caller's variable (it is uninitialised, indeed, undeclared also and so by default an integer) then the function is invoked with the address of the location containing that result. The function will make many references to that result, obtaining the same value each time. The fact that the caller's <code>I</code> will be changed each time doesn't matter. |
||
Fortran does offer a facility to pass a function as a parameter using the EXTERNAL declaration, as follows - SUM is a F90 library function, so a name change to SUMJ: < |
Fortran does offer a facility to pass a function as a parameter using the EXTERNAL declaration, as follows - SUM is a F90 library function, so a name change to SUMJ: <syntaxhighlight lang="fortran"> FUNCTION SUMJ(I,LO,HI,TERM) !Attempt to follow Jensen's Device... |
||
INTEGER I !Being by reference is workable. |
INTEGER I !Being by reference is workable. |
||
INTEGER LO,HI !Just as any other parameters. |
INTEGER LO,HI !Just as any other parameters. |
||
Line 670: | Line 670: | ||
WRITE (6,*) SUMJ(I,1,100,THIS) !No statement as to the parameters of THIS. |
WRITE (6,*) SUMJ(I,1,100,THIS) !No statement as to the parameters of THIS. |
||
END</ |
END</syntaxhighlight> |
||
The result of this is 5.187378, however it does not follow the formalism of Jensen's Device. The invocation statement SUMJ(I,1,100,THIS) does not contain the form of the function but only its name, and the function itself is defined separately. This means that the convenience of different functions via the likes of SUM(I,1,100,1.0/I**2) is unavailable, a separately-defined function with its own name must be defined for each such function. Further, the SUM routine must invoke TERM(I) itself, explicitly supplying the appropriate parameter. And the fact that variable <code>I</code> is a parameter to SUM is an irrelevance, and might as well be omitted from SUMJ. |
The result of this is 5.187378, however it does not follow the formalism of Jensen's Device. The invocation statement SUMJ(I,1,100,THIS) does not contain the form of the function but only its name, and the function itself is defined separately. This means that the convenience of different functions via the likes of SUM(I,1,100,1.0/I**2) is unavailable, a separately-defined function with its own name must be defined for each such function. Further, the SUM routine must invoke TERM(I) itself, explicitly supplying the appropriate parameter. And the fact that variable <code>I</code> is a parameter to SUM is an irrelevance, and might as well be omitted from SUMJ. |
||
Line 677: | Line 677: | ||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
< |
<syntaxhighlight lang="freebasic">Sub Evaluation |
||
Dim As Integer i, lo = 1, hi = 100 |
Dim As Integer i, lo = 1, hi = 100 |
||
Dim As Double temp = 0 |
Dim As Double temp = 0 |
||
Line 687: | Line 687: | ||
Evaluation |
Evaluation |
||
Sleep</ |
Sleep</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 695: | Line 695: | ||
=={{header|Go}}== |
=={{header|Go}}== |
||
< |
<syntaxhighlight lang="go">package main |
||
import "fmt" |
import "fmt" |
||
Line 711: | Line 711: | ||
func main() { |
func main() { |
||
fmt.Printf("%f\n", sum(&i, 1, 100, func() float64 { return 1.0 / float64(i) })) |
fmt.Printf("%f\n", sum(&i, 1, 100, func() float64 { return 1.0 / float64(i) })) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 721: | Line 721: | ||
{{trans|JavaScript}} |
{{trans|JavaScript}} |
||
Solution: |
Solution: |
||
< |
<syntaxhighlight lang="groovy">def sum = { i, lo, hi, term -> |
||
(lo..hi).sum { i.value = it; term() } |
(lo..hi).sum { i.value = it; term() } |
||
} |
} |
||
def obj = [:] |
def obj = [:] |
||
println (sum(obj, 1, 100, { 1 / obj.value }))</ |
println (sum(obj, 1, 100, { 1 / obj.value }))</syntaxhighlight> |
||
Output: |
Output: |
||
Line 731: | Line 731: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
< |
<syntaxhighlight lang="haskell">import Control.Monad.ST |
||
import Data.STRef |
import Data.STRef |
||
Line 744: | Line 744: | ||
main :: IO () |
main :: IO () |
||
main = print foo</ |
main = print foo</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>5.187377517639621</pre> |
<pre>5.187377517639621</pre> |
||
=={{header|Huginn}}== |
=={{header|Huginn}}== |
||
< |
<syntaxhighlight lang="huginn">harmonic_sum( i, lo, hi, term ) { |
||
temp = 0.0; |
temp = 0.0; |
||
i *= 0.0; |
i *= 0.0; |
||
Line 763: | Line 763: | ||
i = 0.0; |
i = 0.0; |
||
print( "{}\n".format( harmonic_sum( i, 1.0, 100.0, @[i](){ 1.0 / i; } ) ) ); |
print( "{}\n".format( harmonic_sum( i, 1.0, 100.0, @[i](){ 1.0 / i; } ) ) ); |
||
}</ |
}</syntaxhighlight> |
||
{{Output}}<pre>5.18737751764</pre> |
{{Output}}<pre>5.18737751764</pre> |
||
Line 769: | Line 769: | ||
Traditional call by name and reference are not features of Icon/Unicon. Procedures parameters are passed by value (immutable types) and reference (mutable types). However, a similar effect may be accomplished by means of co-expressions. The example below was selected for cleanliness of calling. |
Traditional call by name and reference are not features of Icon/Unicon. Procedures parameters are passed by value (immutable types) and reference (mutable types). However, a similar effect may be accomplished by means of co-expressions. The example below was selected for cleanliness of calling. |
||
< |
<syntaxhighlight lang="icon">record mutable(value) # record wrapper to provide mutable access to immutable types |
||
procedure main() |
procedure main() |
||
Line 781: | Line 781: | ||
temp +:= @^term |
temp +:= @^term |
||
return temp |
return temp |
||
end</ |
end</syntaxhighlight> |
||
Refreshing the co-expression above is more expensive to process but to avoid it requires unary alternation in the call. |
Refreshing the co-expression above is more expensive to process but to avoid it requires unary alternation in the call. |
||
< |
<syntaxhighlight lang="icon"> write( sum(A, 1, 100, create |1.0/A.value) ) |
||
... |
... |
||
temp +:= @term</ |
temp +:= @term</syntaxhighlight> |
||
Alternately, we can use a programmer defined control operator (PDCO) approach that passes every argument as a co-expression. Again the refresh co-expression/unary iteration trade-off can be made. The call is cleaner looking but the procedure code is less clear. Additionally all the parameters are passed as individual co-expressions. |
Alternately, we can use a programmer defined control operator (PDCO) approach that passes every argument as a co-expression. Again the refresh co-expression/unary iteration trade-off can be made. The call is cleaner looking but the procedure code is less clear. Additionally all the parameters are passed as individual co-expressions. |
||
< |
<syntaxhighlight lang="icon"> write( sum{A.value, 1, 100, 1.0/A.value} ) |
||
... |
... |
||
procedure sum(X) |
procedure sum(X) |
||
... |
... |
||
every @X[1] := @X[2] to @X[3] do |
every @X[1] := @X[2] to @X[3] do |
||
temp +:= @^X[4]</ |
temp +:= @^X[4]</syntaxhighlight> |
||
=={{header|J}}== |
=={{header|J}}== |
||
'''Solution:''' |
'''Solution:''' |
||
< |
<syntaxhighlight lang="j">jensen=: monad define |
||
'name lo hi expression'=. y |
'name lo hi expression'=. y |
||
temp=. 0 |
temp=. 0 |
||
Line 805: | Line 805: | ||
temp=. temp + ".expression |
temp=. temp + ".expression |
||
end. |
end. |
||
)</ |
)</syntaxhighlight> |
||
'''Example:''' |
'''Example:''' |
||
< |
<syntaxhighlight lang="j"> jensen 'i';1;100;'1%i' |
||
5.18738</ |
5.18738</syntaxhighlight> |
||
Note, however, that in J it is reasonably likely that the expression (or an obvious variation on the expression) can deal with the looping itself. And in typical use this often simplifies to entering the expression and data directly on the command line. |
Note, however, that in J it is reasonably likely that the expression (or an obvious variation on the expression) can deal with the looping itself. And in typical use this often simplifies to entering the expression and data directly on the command line. |
||
Line 817: | Line 817: | ||
This is Java 8. |
This is Java 8. |
||
< |
<syntaxhighlight lang="java">import java.util.function.*; |
||
import java.util.stream.*; |
import java.util.stream.*; |
||
Line 829: | Line 829: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
The program prints '5.187377517639621'. |
The program prints '5.187377517639621'. |
||
Java 7 is more verbose, but under the hood does essentially the same thing: |
Java 7 is more verbose, but under the hood does essentially the same thing: |
||
< |
<syntaxhighlight lang="java">public class Jensen2 { |
||
interface IntToDoubleFunction { |
interface IntToDoubleFunction { |
||
Line 855: | Line 855: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
Line 862: | Line 862: | ||
Uses an object ''o'' instead of integer pointer ''i'', as the C example does. |
Uses an object ''o'' instead of integer pointer ''i'', as the C example does. |
||
< |
<syntaxhighlight lang="javascript">var obj; |
||
function sum(o, lo, hi, term) { |
function sum(o, lo, hi, term) { |
||
Line 872: | Line 872: | ||
obj = {val: 0}; |
obj = {val: 0}; |
||
alert(sum(obj, 1, 100, function() {return 1 / obj.val}));</ |
alert(sum(obj, 1, 100, function() {return 1 / obj.val}));</syntaxhighlight> |
||
The alert shows us '5.187377517639621'. |
The alert shows us '5.187377517639621'. |
||
=={{header|Joy}}== |
=={{header|Joy}}== |
||
<syntaxhighlight lang= |
<syntaxhighlight lang="joy">100 [0] [[1.0 swap /] dip +] primrec.</syntaxhighlight> |
||
Joy does not have named parameters. |
Joy does not have named parameters. |
||
Neither i nor 1/i are visible in the program. |
Neither i nor 1/i are visible in the program. |
||
Line 882: | Line 882: | ||
=={{header|jq}}== |
=={{header|jq}}== |
||
The technique used in the Javascript example can also be used in jq, but in jq it is more idiomatic to use "." to refer to the current term. For example, using sum/3 defined below, we can write: sum(1; 100; 1/.) to perform the task. |
The technique used in the Javascript example can also be used in jq, but in jq it is more idiomatic to use "." to refer to the current term. For example, using sum/3 defined below, we can write: sum(1; 100; 1/.) to perform the task. |
||
< |
<syntaxhighlight lang="jq">def sum(lo; hi; term): |
||
reduce range(lo; hi+1) as $i (0; . + ($i|term)); |
reduce range(lo; hi+1) as $i (0; . + ($i|term)); |
||
# The task: |
# The task: |
||
sum(1;100;1/.)</ |
sum(1;100;1/.)</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
$ jq -n -f jensen.jq |
$ jq -n -f jensen.jq |
||
Line 895: | Line 895: | ||
{{trans|C}} |
{{trans|C}} |
||
< |
<syntaxhighlight lang="julia">macro sum(i, loname, hiname, term) |
||
return quote |
return quote |
||
lo = $loname |
lo = $loname |
||
Line 908: | Line 908: | ||
i = 0 |
i = 0 |
||
@sum(i, 1, 100, 1.0 / i)</ |
@sum(i, 1, 100, 1.0 / i)</syntaxhighlight> |
||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
< |
<syntaxhighlight lang="scala">fun sum(lo: Int, hi: Int, f: (Int) -> Double) = (lo..hi).sumByDouble(f) |
||
fun main(args: Array<String>) = println(sum(1, 100, { 1.0 / it }))</ |
fun main(args: Array<String>) = println(sum(1, 100, { 1.0 / it }))</syntaxhighlight> |
||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
<syntaxhighlight lang="lua"> |
|||
<lang Lua> |
|||
function sum(var, a, b, str) |
function sum(var, a, b, str) |
||
local ret = 0 |
local ret = 0 |
||
Line 926: | Line 926: | ||
end |
end |
||
print(sum("i", 1, 100, "1/i")) |
print(sum("i", 1, 100, "1/i")) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|M2000 Interpreter}}== |
=={{header|M2000 Interpreter}}== |
||
The definition of the lazy function has two statements. First statement is a Module with one argument, the actual name of Jensen`s_Device, which make the function to get the same scope as module Jensen`s_Device, and the second statement is =1/i which return the expression. |
The definition of the lazy function has two statements. First statement is a Module with one argument, the actual name of Jensen`s_Device, which make the function to get the same scope as module Jensen`s_Device, and the second statement is =1/i which return the expression. |
||
<syntaxhighlight lang="m2000 interpreter"> |
|||
<lang M2000 Interpreter> |
|||
Module Jensen`s_Device { |
Module Jensen`s_Device { |
||
Def double i |
Def double i |
||
Line 946: | Line 946: | ||
} |
} |
||
Jensen`s_Device |
Jensen`s_Device |
||
</syntaxhighlight> |
|||
</lang> |
|||
Using Decimal for better accuracy. change &i to &any to show that: when any change, change i, so f() use this i. |
Using Decimal for better accuracy. change &i to &any to show that: when any change, change i, so f() use this i. |
||
<syntaxhighlight lang="m2000 interpreter"> |
|||
<lang M2000 Interpreter> |
|||
Module Jensen`s_Device { |
Module Jensen`s_Device { |
||
Def decimal i |
Def decimal i |
||
Line 963: | Line 963: | ||
} |
} |
||
Jensen`s_Device |
Jensen`s_Device |
||
</syntaxhighlight> |
|||
</lang> |
|||
Many other examples use single float. So this is one for single. |
Many other examples use single float. So this is one for single. |
||
<syntaxhighlight lang="m2000 interpreter"> |
|||
<lang M2000 Interpreter> |
|||
Module Jensen`s_Device { |
Module Jensen`s_Device { |
||
Def single i |
Def single i |
||
Line 980: | Line 980: | ||
} |
} |
||
Jensen`s_Device |
Jensen`s_Device |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|M4}}== |
=={{header|M4}}== |
||
< |
<syntaxhighlight lang="m4">define(`for', |
||
`ifelse($#,0,``$0'', |
`ifelse($#,0,``$0'', |
||
`ifelse(eval($2<=$3),1, |
`ifelse(eval($2<=$3),1, |
||
Line 990: | Line 990: | ||
`pushdef(`temp',0)`'for(`$1',$2,$3, |
`pushdef(`temp',0)`'for(`$1',$2,$3, |
||
`define(`temp',eval(temp+$4))')`'temp`'popdef(`temp')') |
`define(`temp',eval(temp+$4))')`'temp`'popdef(`temp')') |
||
sum(`i',1,100,`1000/i')</ |
sum(`i',1,100,`1000/i')</syntaxhighlight> |
||
Output: |
Output: |
||
Line 999: | Line 999: | ||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
||
< |
<syntaxhighlight lang="mathematica">sum[term_, i_, lo_, hi_] := Block[{temp = 0}, |
||
Do[temp = temp + term, {i, lo, hi}]; |
Do[temp = temp + term, {i, lo, hi}]; |
||
temp]; |
temp]; |
||
SetAttributes[sum, HoldFirst];</ |
SetAttributes[sum, HoldFirst];</syntaxhighlight> |
||
Output: |
Output: |
||
Line 1,013: | Line 1,013: | ||
=={{header|Maxima}}== |
=={{header|Maxima}}== |
||
< |
<syntaxhighlight lang="maxima">mysum(e, v, lo, hi) := block([s: 0], for i from lo thru hi do s: s + subst(v=i, e), s)$ |
||
mysum(1/n, n, 1, 10); |
mysum(1/n, n, 1, 10); |
||
Line 1,027: | Line 1,027: | ||
/* still works */ |
/* still works */ |
||
mysum(1/n, n, 1, 10); |
mysum(1/n, n, 1, 10); |
||
7381/2520</ |
7381/2520</syntaxhighlight> |
||
=={{header|NetRexx}}== |
=={{header|NetRexx}}== |
||
< |
<syntaxhighlight lang="netrexx"> |
||
import COM.ibm.netrexx.process. |
import COM.ibm.netrexx.process. |
||
Line 1,068: | Line 1,068: | ||
return Rexx termMethod.invoke(null,[iv]) |
return Rexx termMethod.invoke(null,[iv]) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
< |
<syntaxhighlight lang="nim">var i: int |
||
proc harmonicSum(i: var int; lo, hi: int; term: proc: float): float = |
proc harmonicSum(i: var int; lo, hi: int; term: proc: float): float = |
||
Line 1,079: | Line 1,079: | ||
inc i |
inc i |
||
echo harmonicSum(i, 1, 100, proc: float = 1 / i)</ |
echo harmonicSum(i, 1, 100, proc: float = 1 / i)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,085: | Line 1,085: | ||
=={{header|Objeck}}== |
=={{header|Objeck}}== |
||
< |
<syntaxhighlight lang="objeck"> |
||
bundle Default { |
bundle Default { |
||
class Jensens { |
class Jensens { |
||
Line 1,109: | Line 1,109: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: 5.18738 |
Output: 5.18738 |
||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
< |
<syntaxhighlight lang="ocaml">let i = ref 42 (* initial value doesn't matter *) |
||
let sum' i lo hi term = |
let sum' i lo hi term = |
||
Line 1,126: | Line 1,126: | ||
let () = |
let () = |
||
Printf.printf "%f\n" (sum' i 1 100 (fun () -> 1. /. float !i))</ |
Printf.printf "%f\n" (sum' i 1 100 (fun () -> 1. /. float !i))</syntaxhighlight> |
||
Output: 5.187378 |
Output: 5.187378 |
||
=={{header|Oforth}}== |
=={{header|Oforth}}== |
||
< |
<syntaxhighlight lang="oforth">: mysum(lo, hi, term) | i | 0 lo hi for: i [ i term perform + ] ;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,144: | Line 1,144: | ||
=={{header|Oz}}== |
=={{header|Oz}}== |
||
Translation using mutable references and an anonymous function: |
Translation using mutable references and an anonymous function: |
||
< |
<syntaxhighlight lang="oz">declare |
||
fun {Sum I Lo Hi Term} |
fun {Sum I Lo Hi Term} |
||
Temp = {NewCell 0.0} |
Temp = {NewCell 0.0} |
||
Line 1,157: | Line 1,157: | ||
I = {NewCell unit} |
I = {NewCell unit} |
||
in |
in |
||
{Show {Sum I 1 100 fun {$} 1.0 / {Int.toFloat @I} end}}</ |
{Show {Sum I 1 100 fun {$} 1.0 / {Int.toFloat @I} end}}</syntaxhighlight> |
||
Idiomatic code: |
Idiomatic code: |
||
< |
<syntaxhighlight lang="oz">declare |
||
fun {Sum Lo Hi F} |
fun {Sum Lo Hi F} |
||
{FoldL {Map {List.number Lo Hi 1} F} Number.'+' 0.0} |
{FoldL {Map {List.number Lo Hi 1} F} Number.'+' 0.0} |
||
end |
end |
||
in |
in |
||
{Show {Sum 1 100 fun {$ I} 1.0/{Int.toFloat I} end}}</ |
{Show {Sum 1 100 fun {$ I} 1.0/{Int.toFloat I} end}}</syntaxhighlight> |
||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
Line 1,171: | Line 1,171: | ||
=={{header|Pascal}}== |
=={{header|Pascal}}== |
||
< |
<syntaxhighlight lang="pascal">program Jensens_Device; |
||
{$IFDEF FPC} |
{$IFDEF FPC} |
||
Line 1,202: | Line 1,202: | ||
writeln(sum(i, 1, 100, @term)); |
writeln(sum(i, 1, 100, @term)); |
||
{$IFNDEF UNIX} readln; {$ENDIF} |
{$IFNDEF UNIX} readln; {$ENDIF} |
||
end.</ |
end.</syntaxhighlight> |
||
Out |
Out |
||
<pre> 5.1873775176396206E+000</pre> |
<pre> 5.1873775176396206E+000</pre> |
||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
< |
<syntaxhighlight lang="perl">my $i; |
||
sub sum { |
sub sum { |
||
my ($i, $lo, $hi, $term) = @_; |
my ($i, $lo, $hi, $term) = @_; |
||
Line 1,217: | Line 1,217: | ||
} |
} |
||
print sum(\$i, 1, 100, sub { 1 / $i }), "\n";</ |
print sum(\$i, 1, 100, sub { 1 / $i }), "\n";</syntaxhighlight> |
||
Output: 5.18737751763962 |
Output: 5.18737751763962 |
||
Or you can take advantage of the fact that elements of the @_ are aliases of the original: |
Or you can take advantage of the fact that elements of the @_ are aliases of the original: |
||
< |
<syntaxhighlight lang="perl">my $i; |
||
sub sum { |
sub sum { |
||
my (undef, $lo, $hi, $term) = @_; |
my (undef, $lo, $hi, $term) = @_; |
||
Line 1,231: | Line 1,231: | ||
} |
} |
||
print sum($i, 1, 100, sub { 1 / $i }), "\n";</ |
print sum($i, 1, 100, sub { 1 / $i }), "\n";</syntaxhighlight> |
||
Output: 5.18737751763962 |
Output: 5.18737751763962 |
||
Line 1,238: | Line 1,238: | ||
I could also have done what C and PHP are doing, though in Phix I'd have to explicitly assign the static var within the loop.<br> |
I could also have done what C and PHP are doing, though in Phix I'd have to explicitly assign the static var within the loop.<br> |
||
I wholeheartedly agree with the comment on the Clipper example. |
I wholeheartedly agree with the comment on the Clipper example. |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
||
<span style="color: #008080;">function</span> <span style="color: #000000;">sumr</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">lo</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hi</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rid</span><span style="color: #0000FF;">)</span> |
<span style="color: #008080;">function</span> <span style="color: #000000;">sumr</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">lo</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hi</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rid</span><span style="color: #0000FF;">)</span> |
||
Line 1,251: | Line 1,251: | ||
<span style="color: #0000FF;">?</span><span style="color: #000000;">sumr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">100</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">reciprocal</span><span style="color: #0000FF;">)</span> |
<span style="color: #0000FF;">?</span><span style="color: #000000;">sumr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">100</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">reciprocal</span><span style="color: #0000FF;">)</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,258: | Line 1,258: | ||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
< |
<syntaxhighlight lang="php">$i; |
||
function sum (&$i, $lo, $hi, $term) { |
function sum (&$i, $lo, $hi, $term) { |
||
$temp = 0; |
$temp = 0; |
||
Line 1,282: | Line 1,282: | ||
//Output: 5.1873775176396 |
//Output: 5.1873775176396 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
< |
<syntaxhighlight lang="picolisp">(scl 6) |
||
(de jensen (I Lo Hi Term) |
(de jensen (I Lo Hi Term) |
||
Line 1,298: | Line 1,298: | ||
(format |
(format |
||
(jensen I 1 100 '(() (*/ 1.0 (val I)))) |
(jensen I 1 100 '(() (*/ 1.0 (val I)))) |
||
*Scl ) )</ |
*Scl ) )</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>-> "5.187383"</pre> |
<pre>-> "5.187383"</pre> |
||
Line 1,304: | Line 1,304: | ||
=={{header|PureBasic}}== |
=={{header|PureBasic}}== |
||
{{trans|C}} |
{{trans|C}} |
||
< |
<syntaxhighlight lang="purebasic">Prototype.d func() |
||
Global i |
Global i |
||
Line 1,320: | Line 1,320: | ||
EndProcedure |
EndProcedure |
||
Answer.d = Sum(@i, 1, 100, @term_func())</ |
Answer.d = Sum(@i, 1, 100, @term_func())</syntaxhighlight> |
||
=={{header|Python}}== |
=={{header|Python}}== |
||
< |
<syntaxhighlight lang="python">class Ref(object): |
||
def __init__(self, value=None): |
def __init__(self, value=None): |
||
self.value = value |
self.value = value |
||
Line 1,340: | Line 1,340: | ||
# note the correspondence between the mathematical notation and the |
# note the correspondence between the mathematical notation and the |
||
# call to sum it's almost as good as sum(1/i for i in range(1,101)) |
# call to sum it's almost as good as sum(1/i for i in range(1,101)) |
||
print harmonic_sum(i, 1, 100, lambda: 1.0/i.value)</ |
print harmonic_sum(i, 1, 100, lambda: 1.0/i.value)</syntaxhighlight> |
||
or |
or |
||
< |
<syntaxhighlight lang="python"> |
||
def harmonic_sum(i, lo, hi, term): |
def harmonic_sum(i, lo, hi, term): |
||
return sum(term() for i[0] in range(lo, hi + 1)) |
return sum(term() for i[0] in range(lo, hi + 1)) |
||
Line 1,350: | Line 1,350: | ||
i = [0] |
i = [0] |
||
print(harmonic_sum(i, 1, 100, lambda: 1.0 / i[0])) |
print(harmonic_sum(i, 1, 100, lambda: 1.0 / i[0])) |
||
</syntaxhighlight> |
|||
</lang> |
|||
or |
or |
||
< |
<syntaxhighlight lang="python"> |
||
def harmonic_sum(i, lo, hi, term): |
def harmonic_sum(i, lo, hi, term): |
||
return sum(eval(term) for i[0] in range(lo, hi + 1)) |
return sum(eval(term) for i[0] in range(lo, hi + 1)) |
||
Line 1,360: | Line 1,360: | ||
i = [0] |
i = [0] |
||
print(harmonic_sum(i, 1, 100, "1.0 / i[0]")) |
print(harmonic_sum(i, 1, 100, "1.0 / i[0]")) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: 5.18737751764 |
Output: 5.18737751764 |
||
Line 1,370: | Line 1,370: | ||
of a function; however, ignoring conventions we can come disturbingly close to the ALGOL call-by-name semantics. |
of a function; however, ignoring conventions we can come disturbingly close to the ALGOL call-by-name semantics. |
||
< |
<syntaxhighlight lang="r">sum <- function(var, lo, hi, term) |
||
eval(substitute({ |
eval(substitute({ |
||
.temp <- 0; |
.temp <- 0; |
||
Line 1,384: | Line 1,384: | ||
##and because of enclos=parent.frame(), the term can involve variables in the caller's scope: |
##and because of enclos=parent.frame(), the term can involve variables in the caller's scope: |
||
x <- -1 |
x <- -1 |
||
sum(i, 1, 100, i^x) #5.187378</ |
sum(i, 1, 100, i^x) #5.187378</syntaxhighlight> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
Line 1,390: | Line 1,390: | ||
be written just as Jørn Jensen did at Regnecentralen. |
be written just as Jørn Jensen did at Regnecentralen. |
||
< |
<syntaxhighlight lang="racket"> |
||
#lang algol60 |
#lang algol60 |
||
begin |
begin |
||
Line 1,409: | Line 1,409: | ||
printnln (sum (i, 1, 100, 1/i)) |
printnln (sum (i, 1, 100, 1/i)) |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
But of course you can also use the more boring popular alternative of first class functions: |
But of course you can also use the more boring popular alternative of first class functions: |
||
< |
<syntaxhighlight lang="racket"> |
||
#lang racket/base |
#lang racket/base |
||
(define (sum lo hi f) |
(define (sum lo hi f) |
||
(for/sum ([i (in-range lo (add1 hi))]) (f i))) |
(for/sum ([i (in-range lo (add1 hi))]) (f i))) |
||
(sum 1 100 (λ(i) (/ 1.0 i))) |
(sum 1 100 (λ(i) (/ 1.0 i))) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
Line 1,424: | Line 1,424: | ||
Rather than playing tricks like Perl 5 does, the declarations of the formal parameters are quite straightforward in Raku: |
Rather than playing tricks like Perl 5 does, the declarations of the formal parameters are quite straightforward in Raku: |
||
<lang |
<syntaxhighlight lang="raku" line>sub sum($i is rw, $lo, $hi, &term) { |
||
my $temp = 0; |
my $temp = 0; |
||
loop ($i = $lo; $i <= $hi; $i++) { |
loop ($i = $lo; $i <= $hi; $i++) { |
||
Line 1,433: | Line 1,433: | ||
my $i; |
my $i; |
||
say sum $i, 1, 100, { 1 / $i };</ |
say sum $i, 1, 100, { 1 / $i };</syntaxhighlight> |
||
Note that the C-style "for" loop is pronounced "loop" in Raku, and is the only loop statement that actually requires parens. |
Note that the C-style "for" loop is pronounced "loop" in Raku, and is the only loop statement that actually requires parens. |
||
=={{header|Rascal}}== |
=={{header|Rascal}}== |
||
< |
<syntaxhighlight lang="rascal">public num Jenssen(int lo, int hi, num (int i) term){ |
||
temp = 0; |
temp = 0; |
||
while (lo <= hi){ |
while (lo <= hi){ |
||
Line 1,443: | Line 1,443: | ||
lo += 1;} |
lo += 1;} |
||
return temp; |
return temp; |
||
}</ |
}</syntaxhighlight> |
||
With as output: |
With as output: |
||
< |
<syntaxhighlight lang="rascal">rascal>Jenssen(1, 100, num(int i){return 1.0/i;}) |
||
num: 5.18737751763962026080511767565825315790897212670845165317653395662</ |
num: 5.18737751763962026080511767565825315790897212670845165317653395662</syntaxhighlight> |
||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
< |
<syntaxhighlight lang="rexx">/*REXX program demonstrates Jensen's device (via call subroutine, and args by name). */ |
||
parse arg d . /*obtain optional argument from the CL.*/ |
parse arg d . /*obtain optional argument from the CL.*/ |
||
if d=='' | d=="," then d= 100 /*Not specified? Then use the default.*/ |
if d=='' | d=="," then d= 100 /*Not specified? Then use the default.*/ |
||
Line 1,467: | Line 1,467: | ||
/*comment lit var lit var lit var literal var literal */ |
/*comment lit var lit var lit var literal var literal */ |
||
return $</ |
return $</syntaxhighlight> |
||
{{out|output|text= when using the default input:}} |
{{out|output|text= when using the default input:}} |
||
<pre> |
<pre> |
||
Line 1,488: | Line 1,488: | ||
=={{header|Ring}}== |
=={{header|Ring}}== |
||
< |
<syntaxhighlight lang="ring"> |
||
# Project : Jensen's Device |
# Project : Jensen's Device |
||
Line 1,502: | Line 1,502: | ||
next |
next |
||
return temp |
return temp |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 1,510: | Line 1,510: | ||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
Here, setting the variable and evaluating the term are truly executed in the "outer" context: |
Here, setting the variable and evaluating the term are truly executed in the "outer" context: |
||
< |
<syntaxhighlight lang="ruby">def sum(var, lo, hi, term, context) |
||
sum = 0.0 |
sum = 0.0 |
||
lo.upto(hi) do |n| |
lo.upto(hi) do |n| |
||
Line 1,517: | Line 1,517: | ||
sum |
sum |
||
end |
end |
||
p sum "i", 1, 100, "1.0 / i", binding # => 5.18737751763962</ |
p sum "i", 1, 100, "1.0 / i", binding # => 5.18737751763962</syntaxhighlight> |
||
But here is the Ruby way to do it: |
But here is the Ruby way to do it: |
||
< |
<syntaxhighlight lang="ruby">def sum2(lo, hi) |
||
lo.upto(hi).inject(0.0) {|sum, n| sum += yield n} |
lo.upto(hi).inject(0.0) {|sum, n| sum += yield n} |
||
end |
end |
||
p sum2(1, 100) {|i| 1.0/i} # => 5.18737751763962</ |
p sum2(1, 100) {|i| 1.0/i} # => 5.18737751763962</syntaxhighlight> |
||
Even more concise: (requires ruby >= 2.4) |
Even more concise: (requires ruby >= 2.4) |
||
< |
<syntaxhighlight lang="ruby"> |
||
def sum lo, hi, &term |
def sum lo, hi, &term |
||
(lo..hi).sum(&term) |
(lo..hi).sum(&term) |
||
Line 1,533: | Line 1,533: | ||
# or using Rational: |
# or using Rational: |
||
p sum(1,100){|i| Rational(1,i)} # => 14466636279520351160221518043104131447711 / 2788815009188499086581352357412492142272 |
p sum(1,100){|i| Rational(1,i)} # => 14466636279520351160221518043104131447711 / 2788815009188499086581352357412492142272 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Rust}}== |
=={{header|Rust}}== |
||
< |
<syntaxhighlight lang="rust"> |
||
use std::f32; |
use std::f32; |
||
Line 1,550: | Line 1,550: | ||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,563: | Line 1,563: | ||
class, which is effectively the same as passing by reference. |
class, which is effectively the same as passing by reference. |
||
< |
<syntaxhighlight lang="scala">class MyInt { var i: Int = _ } |
||
val i = new MyInt |
val i = new MyInt |
||
def sum(i: MyInt, lo: Int, hi: Int, term: => Double) = { |
def sum(i: MyInt, lo: Int, hi: Int, term: => Double) = { |
||
Line 1,574: | Line 1,574: | ||
temp |
temp |
||
} |
} |
||
sum(i, 1, 100, 1.0 / i.i)</ |
sum(i, 1, 100, 1.0 / i.i)</syntaxhighlight> |
||
Result: |
Result: |
||
Line 1,585: | Line 1,585: | ||
Scheme procedures do not support call-by-name. Scheme macros, however, do: |
Scheme procedures do not support call-by-name. Scheme macros, however, do: |
||
< |
<syntaxhighlight lang="scheme"> |
||
(define-syntax sum |
(define-syntax sum |
||
(syntax-rules () |
(syntax-rules () |
||
Line 1,595: | Line 1,595: | ||
(loop (+ var 1) |
(loop (+ var 1) |
||
(+ result . body))))))) |
(+ result . body))))))) |
||
</syntaxhighlight> |
|||
</lang> |
|||
<pre> |
<pre> |
||
Line 1,605: | Line 1,605: | ||
Seed7 supports call-by-name with function parameters: |
Seed7 supports call-by-name with function parameters: |
||
< |
<syntaxhighlight lang="seed7"> |
||
$ include "seed7_05.s7i"; |
$ include "seed7_05.s7i"; |
||
include "float.s7i"; |
include "float.s7i"; |
||
Line 1,625: | Line 1,625: | ||
writeln(sum(i, 1, 100, 1.0/flt(i)) digits 6); |
writeln(sum(i, 1, 100, 1.0/flt(i)) digits 6); |
||
end func; |
end func; |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
Line 1,633: | Line 1,633: | ||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
< |
<syntaxhighlight lang="ruby">var i; |
||
func sum (i, lo, hi, term) { |
func sum (i, lo, hi, term) { |
||
var temp = 0; |
var temp = 0; |
||
Line 1,641: | Line 1,641: | ||
return temp; |
return temp; |
||
}; |
}; |
||
say sum(\i, 1, 100, { 1 / i });</ |
say sum(\i, 1, 100, { 1 / i });</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>5.18737751763962026080511767565825315790899</pre> |
<pre>5.18737751763962026080511767565825315790899</pre> |
||
Line 1,648: | Line 1,648: | ||
{{trans|algol60}} |
{{trans|algol60}} |
||
{{works with|SIMULA-67}} |
{{works with|SIMULA-67}} |
||
Compare with Algol 60, in Simula 67 'call by name' is specified with '''name'''. It is a true 'call by name' evaluation not a 'procedure parameter' emulation.< |
Compare with Algol 60, in Simula 67 'call by name' is specified with '''name'''. It is a true 'call by name' evaluation not a 'procedure parameter' emulation.<syntaxhighlight lang="simula">comment Jensen's Device; |
||
begin |
begin |
||
integer i; |
integer i; |
||
Line 1,670: | Line 1,670: | ||
comment note the correspondence between the mathematical notation and the call to sum; |
comment note the correspondence between the mathematical notation and the call to sum; |
||
outreal (sum (i, 1, 100, 1/i), 7, 14) |
outreal (sum (i, 1, 100, 1/i), 7, 14) |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,677: | Line 1,677: | ||
=={{header|Standard ML}}== |
=={{header|Standard ML}}== |
||
< |
<syntaxhighlight lang="sml">val i = ref 42 (* initial value doesn't matter *) |
||
fun sum' (i, lo, hi, term) = let |
fun sum' (i, lo, hi, term) = let |
||
Line 1,691: | Line 1,691: | ||
val () = |
val () = |
||
print (Real.toString (sum' (i, 1, 100, fn () => 1.0 / real (!i))) ^ "\n")</ |
print (Real.toString (sum' (i, 1, 100, fn () => 1.0 / real (!i))) ^ "\n")</syntaxhighlight> |
||
Output: 5.18737751764 |
Output: 5.18737751764 |
||
=={{header|Swift}}== |
=={{header|Swift}}== |
||
< |
<syntaxhighlight lang="swift">var i = 42 // initial value doesn't matter |
||
func sum(inout i: Int, lo: Int, hi: Int, @autoclosure term: () -> Double) -> Double { |
func sum(inout i: Int, lo: Int, hi: Int, @autoclosure term: () -> Double) -> Double { |
||
Line 1,705: | Line 1,705: | ||
} |
} |
||
println(sum(&i, 1, 100, 1 / Double(i)))</ |
println(sum(&i, 1, 100, 1 / Double(i)))</syntaxhighlight> |
||
(Prior to Swift 1.2, replace <code>@autoclosure term: () -> Double</code> with <code>term: @autoclosure () -> Double</code>.) |
(Prior to Swift 1.2, replace <code>@autoclosure term: () -> Double</code> with <code>term: @autoclosure () -> Double</code>.) |
||
{{out}} |
{{out}} |
||
Line 1,712: | Line 1,712: | ||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
Here, we set the value of the passed variable in the caller's frame. We then evaluate the passed term there too. |
Here, we set the value of the passed variable in the caller's frame. We then evaluate the passed term there too. |
||
< |
<syntaxhighlight lang="tcl">proc sum {var lo hi term} { |
||
upvar 1 $var x |
upvar 1 $var x |
||
set sum 0.0 |
set sum 0.0 |
||
Line 1,720: | Line 1,720: | ||
return $sum |
return $sum |
||
} |
} |
||
puts [sum i 1 100 {1.0/$i}] ;# 5.177377517639621</ |
puts [sum i 1 100 {1.0/$i}] ;# 5.177377517639621</syntaxhighlight> |
||
However, the solution is expressed more simply like this |
However, the solution is expressed more simply like this |
||
< |
<syntaxhighlight lang="tcl">proc sum2 {lo hi lambda} { |
||
set sum 0.0 |
set sum 0.0 |
||
for {set n $lo} {$n < $hi} {incr n} { |
for {set n $lo} {$n < $hi} {incr n} { |
||
Line 1,729: | Line 1,729: | ||
return $sum |
return $sum |
||
} |
} |
||
puts [sum2 1 100 {i {expr {1.0/$i}}}] ;# 5.177377517639621</ |
puts [sum2 1 100 {i {expr {1.0/$i}}}] ;# 5.177377517639621</syntaxhighlight> |
||
=={{header|VBA}}== |
=={{header|VBA}}== |
||
<syntaxhighlight lang="vb"> |
|||
<lang vb> |
|||
Private Function sum(i As String, ByVal lo As Integer, ByVal hi As Integer, term As String) As Double |
Private Function sum(i As String, ByVal lo As Integer, ByVal hi As Integer, term As String) As Double |
||
Dim temp As Double |
Dim temp As Double |
||
Line 1,745: | Line 1,745: | ||
Debug.Print sum("j", 1, 100, "sin(j)") |
Debug.Print sum("j", 1, 100, "sin(j)") |
||
End Sub |
End Sub |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,755: | Line 1,755: | ||
=={{header|Wren}}== |
=={{header|Wren}}== |
||
As Wren doesn't support call by name, call by reference nor pointers we need to 'box' the global numeric variable 'i' and use a function for 'term' to simulate Jensen's device. This works because all user defined types are reference types and functions can capture external variables. |
As Wren doesn't support call by name, call by reference nor pointers we need to 'box' the global numeric variable 'i' and use a function for 'term' to simulate Jensen's device. This works because all user defined types are reference types and functions can capture external variables. |
||
< |
<syntaxhighlight lang="ecmascript">class Box { |
||
construct new(v) { _v = v } |
construct new(v) { _v = v } |
||
v { _v } |
v { _v } |
||
Line 1,774: | Line 1,774: | ||
var s = sum.call(i, 1, 100, Fn.new { 1/i.v }) |
var s = sum.call(i, 1, 100, Fn.new { 1/i.v }) |
||
System.print(s)</ |
System.print(s)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,784: | Line 1,784: | ||
=={{header|Yabasic}}== |
=={{header|Yabasic}}== |
||
{{trans|FreeBASIC}} |
{{trans|FreeBASIC}} |
||
< |
<syntaxhighlight lang="yabasic">sub Evaluation() |
||
lo = 1 : hi = 100 : temp = 0 |
lo = 1 : hi = 100 : temp = 0 |
||
for i = lo to hi |
for i = lo to hi |
||
Line 1,792: | Line 1,792: | ||
end sub |
end sub |
||
Evaluation()</ |
Evaluation()</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,801: | Line 1,801: | ||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
zkl doesn't support call by name/address but does have reference objects. Using an explicit call to term: |
zkl doesn't support call by name/address but does have reference objects. Using an explicit call to term: |
||
< |
<syntaxhighlight lang="zkl">fcn sum(ri, lo,hi, term){ |
||
temp:=0.0; ri.set(lo); |
temp:=0.0; ri.set(lo); |
||
do{ temp+=term(ri); } while(ri.inc()<hi); // inc return previous value |
do{ temp+=term(ri); } while(ri.inc()<hi); // inc return previous value |
||
return(temp); |
return(temp); |
||
} |
} |
||
sum(Ref(0), 1,100, fcn(ri){ 1.0/ri.value }).println();</ |
sum(Ref(0), 1,100, fcn(ri){ 1.0/ri.value }).println();</syntaxhighlight> |
||
Using function application/deferred(lazy) objects, we can make the function call implicit (addition forces evaluation of the LHS): |
Using function application/deferred(lazy) objects, we can make the function call implicit (addition forces evaluation of the LHS): |
||
< |
<syntaxhighlight lang="zkl">fcn sum2(ri, lo,hi, term){ |
||
temp:=0.0; ri.set(lo); |
temp:=0.0; ri.set(lo); |
||
do{ temp=term + temp; } while(ri.inc()<hi); // inc return previous value |
do{ temp=term + temp; } while(ri.inc()<hi); // inc return previous value |
||
Line 1,814: | Line 1,814: | ||
} |
} |
||
ri:=Ref(0); |
ri:=Ref(0); |
||
sum2(ri, 1,100, 'wrap(){ 1.0/ri.value }).println();</ |
sum2(ri, 1,100, 'wrap(){ 1.0/ri.value }).println();</syntaxhighlight> |
||
In this case, we can call sum or sum2 and it does the same thing (the ri parameter will be ignored). |
In this case, we can call sum or sum2 and it does the same thing (the ri parameter will be ignored). |
||
Of course, as others have pointed out, this can be expressed very simply: |
Of course, as others have pointed out, this can be expressed very simply: |
||
< |
<syntaxhighlight lang="zkl">fcn sum3(lo,hi, term){ [lo..hi].reduce('wrap(sum,i){ sum + term(i) },0.0) } |
||
sum3(1,100, fcn(i){ 1.0/i }).println();</ |
sum3(1,100, fcn(i){ 1.0/i }).println();</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,828: | Line 1,828: | ||
=={{header|ZX Spectrum Basic}}== |
=={{header|ZX Spectrum Basic}}== |
||
< |
<syntaxhighlight lang="zxbasic">10 DEF FN r(x)=1/x |
||
20 LET f$="FN r(i)" |
20 LET f$="FN r(i)" |
||
30 LET lo=1: LET hi=100 |
30 LET lo=1: LET hi=100 |
||
Line 1,840: | Line 1,840: | ||
1040 NEXT i |
1040 NEXT i |
||
1050 RETURN |
1050 RETURN |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |