Jensen's Device: Difference between revisions

From Rosetta Code
Content added Content deleted
(Jensen's Device en Yabasic)
(Added Dart)
 
(43 intermediate revisions by 23 users not shown)
Line 32: Line 32:
[[wp:Donald_Knuth|Donald Knuth]] later proposed the [[Man or boy test|Man or Boy Test]] as a more rigorous exercise.
[[wp:Donald_Knuth|Donald Knuth]] later proposed the [[Man or boy test|Man or Boy Test]] as a more rigorous exercise.
<br><br>
<br><br>

=={{header|11l}}==
{{trans|C#}}

<syntaxhighlight lang="11l">F sum(&i, lo, hi, term)
V temp = 0.0
i = lo
L i <= hi
temp += term()
i++
R temp

F main()
Int i
print(sum(&i, 1, 100, () -> 1 / @i))

main()</syntaxhighlight>

{{out}}
<pre>
5.18738
</pre>


=={{header|Ada}}==
=={{header|Ada}}==
<lang ada>with Ada.Text_IO; use Ada.Text_IO;
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO;


procedure Jensen_Device is
procedure Jensen_Device is
Line 59: 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;</lang>
end Jensen_Device;</syntaxhighlight>
<pre>
<pre>
5.18738E+00
5.18738E+00
Line 86: Line 108:
=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==
{{trans|ALGOL 60}}
{{trans|ALGOL 60}}
<lang algol68>BEGIN
<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 101: 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</lang>
END</syntaxhighlight>
Output: +5.18737751763962e +0
Output: +5.18737751763962e +0

=={{header|ALGOL W}}==
{{Trans|ALGOL 68}}
Algol W retained Algol 60's call by name but also offered additional parameter passing modes.
<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.
<syntaxhighlight lang="algolw">begin
integer i;
real procedure sum ( integer %name% i; integer value lo, hi; real procedure term );
% i is passed by-name, term is passed as a procedure which makes it effectively passed by-name %
begin
real temp;
temp := 0;
i := lo;
while i <= hi do begin % The Algol W "for" loop (as in Algol 68) creates a distinct %
temp := temp + term; % variable which would not be shared with the passed "i" %
i := i + 1 % Here the actual passed "i" is incremented. %
end while_i_le_temp;
temp
end;
% note the correspondence between the mathematical notation and the call to sum %
write( sum( i, 1, 100, 1/i ) )
end.</syntaxhighlight>
{{out}}
<pre>
</pre>


=={{header|AppleScript}}==
=={{header|AppleScript}}==
<lang AppleScript>set i to 0
<syntaxhighlight lang="applescript">set i to 0


on jsum(i, lo, hi, term)
on jsum(i, lo, hi, term)
Line 121: Line 169:
end script
end script


return jsum(a reference to i, 1, 100, term_func)</lang>
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 211: Line 259:
fUn: .float 1
fUn: .float 1


</syntaxhighlight>
</lang>

=={{header|Arturo}}==
{{trans|Ruby}}
<syntaxhighlight lang="rebol">harmonicSum: function [variable, lo, hi, term][
result: new 0.0
loop lo..hi 'n ->
'result + do ~"|variable|: |n| |term|"
result
]
print ["harmonicSum 1->100:" harmonicSum 'i 1 100 {1.0 / i}]</syntaxhighlight>
{{out}}
<pre>harmonicSum 1->100: 5.187377517639621</pre>

=={{header|Asymptote}}==
{{trans|FreeBASIC}}
<syntaxhighlight lang="Asymptote">real temp = 0;
for(int i = 1; i <= 100; ++i) {
temp += 1/i;
}
write(temp);</syntaxhighlight>
{{out}}
<pre>5.18737751763962</pre>

=={{header|AWK}}==
<syntaxhighlight lang="awk">
# syntax: GAWK -f JENSENS_DEVICE.AWK
# converted from FreeBASIC
BEGIN {
evaluation()
exit(0)
}
function evaluation( hi,i,lo,tmp) {
lo = 1
hi = 100
for (i=lo; i<=hi; i++) {
tmp += (1/i)
}
printf("%.15f\n",tmp)
}
</syntaxhighlight>
{{out}}
<pre>
5.187377517639621
</pre>

=={{header|BASIC}}==
==={{header|Applesoft BASIC}}===
Same code as [[#GW-BASIC|GW-BASIC]]

==={{header|BASIC256}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="basic256">
call Evaluation()
end

subroutine Evaluation()
lo = 1 : hi = 100 : temp = 0
for i = lo to hi
temp += (1/i) ##r(i)
next i
print temp
end subroutine</syntaxhighlight>
{{out}}
<pre>5.18737751764</pre>


=={{header|BBC BASIC}}==
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
{{works with|BBC BASIC for Windows}}
<lang bbcbasic> PRINT FNsum(j, 1, 100, FNreciprocal)
<syntaxhighlight lang="bbcbasic"> PRINT FNsum(j, 1, 100, FNreciprocal)
END
END
Line 225: Line 337:
= temp
= temp
DEF FNreciprocal = 1/i</lang>
DEF FNreciprocal = 1/i</syntaxhighlight>
Output:
Output:
<pre>
<pre>5.18737752</pre>

5.18737752
==={{header|Chipmunk Basic}}===
</pre>
{{trans|QBasic}}
{{works with|Chipmunk Basic|3.6.4}}
<syntaxhighlight lang="vbnet">100 call evaluation
110 end
120 sub evaluation()
130 lo = 1
140 hi = 100
150 temp = 0
160 for i = lo to hi
170 temp = temp+(1/i)
180 next i
190 print temp
200 end sub</syntaxhighlight>

==={{header|Craft Basic}}===
<syntaxhighlight lang="basic">precision 4

define lo = 1, hi = 100, temp = 0

for i = lo to hi

let temp = temp + (1 / i)
wait

next i

print temp</syntaxhighlight>
{{out| Output}}<pre>5.1873</pre>

==={{header|FreeBASIC}}===
<syntaxhighlight lang="vbnet">Sub Evaluation
Dim As Integer i, lo = 1, hi = 100
Dim As Double temp = 0
For i = lo To hi
temp += (1/i) ''r(i)
Next i
Print temp
End Sub

Evaluation
Sleep</syntaxhighlight>
{{out}}
<pre>5.187377517639621</pre>

==={{header|FutureBasic}}===
<syntaxhighlight lang="futurebasic">local fn JensensDevice( lo as long, hi as long ) as double
double i, temp = 0.0
for i = lo to hi
temp = temp + (1/i)
next
end fn = temp

print fn JensensDevice( 1, 100 )

HandleEvents</syntaxhighlight>
{{output}}
<pre>5.187377517639621</pre>

==={{header|Gambas}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="vbnet">Sub Evaluation()

Dim i As Integer, lo As Integer = 1, hi As Integer = 100
Dim tmp As Float = 0

For i = lo To hi
tmp += (1 / i)
Next
Print tmp

End Sub

Public Sub Main()

Evaluation

End </syntaxhighlight>

==={{header|GW-BASIC}}===
{{works with|PC-BASIC|any}}
{{works with|BASICA}}
{{works with|Applesoft BASIC}}
{{works with|Chipmunk Basic}}
{{works with|QBasic}}
{{works with|QB64}}
{{works with|Quite BASIC}}
{{works with|MSX BASIC}}
<syntaxhighlight lang="qbasic">100 GOSUB 120
110 END
120 REM Evaluation
130 LET A = 1
140 LET B = 100
150 LET T = 0
160 FOR I = A TO B
170 LET T = T + (1/I)
180 NEXT I
190 PRINT T
200 RETURN</syntaxhighlight>

==={{header|Minimal BASIC}}===
<syntaxhighlight lang="qbasic">100 GOSUB 120
110 GOTO 210
120 REM Evaluation
130 LET A = 1
140 LET B = 100
150 LET T = 0
160 FOR I = A TO B
170 LET T = T+(1/I)
180 NEXT I
190 PRINT T
200 RETURN
210 END</syntaxhighlight>

==={{header|MSX Basic}}===
{{works with|MSX BASIC|any}}
Same code as [[#GW-BASIC|GW-BASIC]]

==={{header|PureBasic}}===
{{trans|C}}
<syntaxhighlight lang="purebasic">Prototype.d func()

Global i

Procedure.d Sum(*i.Integer, lo, hi, *term.func)
Protected Temp.d
For i=lo To hi
temp + *term()
Next
ProcedureReturn Temp
EndProcedure

Procedure.d term_func()
ProcedureReturn 1/i
EndProcedure

Answer.d = Sum(@i, 1, 100, @term_func())</syntaxhighlight>

==={{header|QBasic}}===
{{works with|QBasic|1.1}}
{{works with|QuickBasic|4.5}}
{{works with|Run BASIC}}
{{works with|Just BASIC}}
{{works with|Liberty BASIC}}
{{works with|True BASIC}}
<syntaxhighlight lang="qbasic">CALL EVALUATION
END

SUB Evaluation
LET lo = 1
LET hi = 100
LET temp = 0
FOR i = lo TO hi
LET temp = temp + (1 / i)
NEXT i
PRINT temp
END SUB</syntaxhighlight>

==={{header|QB64}}===
Same code as [[#QBasic|QBasic]]

==={{header|Quite BASIC}}===
Same code as [[#GW-BASIC|GW-BASIC]]

==={{header|Run BASIC}}===
Same code as [[#QBasic|QBasic]]

==={{header|True BASIC}}===
Same code as [[#QBasic|QBasic]]

==={{header|uBasic/4tH}}===
Since uBasic/4tH does not support floating point numbers, fixed point has to be used. Of course, precision suffers significantly.
<syntaxhighlight lang="qbasic">' ** NOTE: it requires a 64-bit uBasic; number ranges are limited. **

If Info("wordsize") < 64 Then Print "This program requires a 64-bit uBasic" : End

Dim @i(1)
i = 0 ' fake something that resembles a pointer

Print Using "+?.####";FUNC(_Ftoi(FUNC(_Sum(i, 1, 100, _Term))))
End

_Sum
Param (4)
Local (1)

e@ = 0
For @i(a@) = b@ To c@ : e@ = e@ + FUNC(d@) : Next

Return (e@)

_Term Return (FUNC(_Fdiv(1, @i(i))))
_Fdiv Param (2) : Return ((a@*16384)/b@)
_Ftoi Param (1) : Return ((10000*a@)/16384)</syntaxhighlight>
{{Out}}
<pre>5.1850

0 OK, 0:313 </pre>

==={{header|Yabasic}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="yabasic">Evaluation()
end

sub Evaluation()
lo = 1 : hi = 100 : temp = 0
for i = lo to hi
temp = temp + (1/i) //r(i)
next i
print temp
end sub</syntaxhighlight>
{{out}}
<pre>5.18738</pre>

==={{header|ZX Spectrum Basic}}===
<syntaxhighlight lang="qbasic">10 DEF FN r(x)=1/x
20 LET f$="FN r(i)"
30 LET lo=1: LET hi=100
40 GO SUB 1000
50 PRINT temp
60 STOP
1000 REM Evaluation
1010 LET temp=0
1020 FOR i=lo TO hi
1030 LET temp=temp+VAL f$
1040 NEXT i
1050 RETURN </syntaxhighlight>
{{out}}
<pre>5.1873775</pre>


=={{header|Bracmat}}==
=={{header|Bracmat}}==
<lang bracmat>( ( sum
<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 245: Line 585:
)
)
& sum$((=i),1,100,(=!i^-1))
& sum$((=i),1,100,(=!i^-1))
);</lang>
);</syntaxhighlight>
Output:
Output:
<pre>14466636279520351160221518043104131447711/2788815009188499086581352357412492142272</pre>
<pre>14466636279520351160221518043104131447711/2788815009188499086581352357412492142272</pre>


=={{header|C}}==
=={{header|C}}==
<lang c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>


int i;
int i;
Line 265: Line 605:
printf("%f\n", sum(&i, 1, 100, term_func));
printf("%f\n", sum(&i, 1, 100, term_func));
return 0;
return 0;
}</lang>
}</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:
<lang c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>
int i;
int i;
Line 288: Line 628:
printf("%f\n", sum(i, 1, 100, 1.0 / i));
printf("%f\n", sum(i, 1, 100, 1.0 / i));
return 0;
return 0;
}</lang>
}</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:
<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;


class JensensDevice
class JensensDevice
Line 312: Line 652:
Console.WriteLine(Sum(ref i, 1, 100, () => 1.0 / i));
Console.WriteLine(Sum(ref i, 1, 100, () => 1.0 / i));
}
}
}</lang>
}</syntaxhighlight>


=={{header|C++}}==
=={{header|C++}}==
<lang cpp>
<syntaxhighlight lang="cpp">
#include <iostream>
#include <iostream>


Line 338: Line 678:
std::cout << SUM(i,1,100,1.0/i) << "\n";
std::cout << SUM(i,1,100,1.0/i) << "\n";
return 0;
return 0;
}</lang>
}</syntaxhighlight>
Output: 5.18738
Output: 5.18738
5.18738
5.18738
Line 344: Line 684:
=={{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.
<lang Clipper>// Jensen's device in Clipper (or Harbour)
<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 364: Line 704:
next i
next i
return temp
return temp
</syntaxhighlight>
</lang>


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==
Line 370: Line 710:
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.


<lang lisp>(declaim (inline %sum))
<syntaxhighlight lang="lisp">(declaim (inline %sum))


(defun %sum (lo hi func)
(defun %sum (lo hi func)
Line 376: Line 716:


(defmacro sum (i lo hi term)
(defmacro sum (i lo hi term)
`(%sum ,lo ,hi (lambda (,i) ,term)))</lang>
`(%sum ,lo ,hi (lambda (,i) ,term)))</syntaxhighlight>


<lang lisp>CL-USER> (sum i 1 100 (/ 1 i))
<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</lang>
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:
<lang d>double sum(ref int i, in int lo, in int hi, lazy double term)
<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 398: Line 738:
int i;
int i;
sum(i, 1, 100, 1.0/i).writeln;
sum(i, 1, 100, 1.0/i).writeln;
}</lang>
}</syntaxhighlight>
{{out}}
<pre>5.18738</pre>

=={{header|Dart}}==
{{trans|C++}}
<syntaxhighlight lang="dart">double i = 0;
double sum(int lo, int hi, double Function() term) {
double temp = 0;
for (i = lo.toDouble(); i <= hi; i++) temp += term();
return temp;
}

double termFunc() {
return 1.0 / i;
}

void main() {
print(sum(1, 100, termFunc));
}</syntaxhighlight>
{{out}}
<pre>5.187377517639621</pre>

=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}


<syntaxhighlight lang="Delphi">


type TTerm = function(i: integer): real;

function Term(I: integer): double;
begin
Term := 1 / I;
end;


function Sum(var I: integer; Lo, Hi: integer; Term: TTerm): double;
begin
Result := 0;
I := Lo;
while I <= Hi do
begin
Result := Result + Term(I);
Inc(I);
end;
end;


procedure ShowJensenDevice(Memo: TMemo);
var I: LongInt;
begin
Memo.Lines.Add(FloatToStrF(Sum(I, 1, 100, @Term), ffFixed,18,15));
end;




</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
5.187377517639621
5.18738</pre>

Elapsed Time: 1.037 ms.

</pre>



=={{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.
<lang delphi>function sum(var i : Integer; lo, hi : Integer; lazy term : Float) : Float;
<syntaxhighlight lang="delphi">function sum(var i : Integer; lo, hi : Integer; lazy term : Float) : Float;
begin
begin
i:=lo;
i:=lo;
Line 416: Line 821:
var i : Integer;
var i : Integer;


PrintLn(sum(i, 1, 100, 1.0/i));</lang>
PrintLn(sum(i, 1, 100, 1.0/i));</syntaxhighlight>
Output: 5.187...
Output: 5.187...


Line 425: Line 830:
(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>.)


<lang e>pragma.enable("one-method-object") # "def _.get" is experimental shorthand
<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 438: Line 843:
var i := null
var i := null
sum(&i, 1, 100, def _.get() { return 1/i })
sum(&i, 1, 100, def _.get() { return 1/i })
}</lang>
}</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 446: Line 851:
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:


<lang e>def sum(lo, hi, f) {
<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 })</lang>
sum(1, 100, fn i { 1/i })</syntaxhighlight>


=={{header|Elixir}}==
=={{header|Elixir}}==
{{trans|Erlang}}
{{trans|Erlang}}
<lang elixir>defmodule JensenDevice do
<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 465: Line 870:
end
end


IO.puts JensenDevice.task</lang>
IO.puts JensenDevice.task</syntaxhighlight>


{{out}}
{{out}}
<pre>
<pre>
5.1873775176396215
5.1873775176396215
</pre>

=={{header|EMal}}==
<syntaxhighlight lang="emal">
fun sum = real by int lo, int hi, fun term
real temp = 0.0
for int i = lo; i <= hi; ++i do temp += term(i) end
return temp
end
writeLine(sum(1, 100, real by int i do return 1.0/i end))
</syntaxhighlight>
{{out}}
<pre>
5.1873775176396202608051176755
</pre>
</pre>


Line 475: Line 894:
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 487: Line 906:
Temp = Term( I ),
Temp = Term( I ),
Temp + sum( I + 1, High, Term ).
Temp + sum( I + 1, High, Term ).
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 493: Line 912:
4> jensens_device:task().
4> jensens_device:task().
5.1873775176396215
5.1873775176396215
</pre>

=={{header|Euler}}==
{{Trans|ALGOL 60}}
'''begin'''
'''new''' i; '''new''' sum;
sum &lt;- ` '''formal''' i; '''formal''' lo; '''formal''' hi; '''formal''' term;
'''begin'''
'''new''' temp; '''label''' loop;
temp &lt;- 0;
i &lt;- lo;
loop: '''begin'''
temp &lt;- temp + term;
'''if''' [ i &lt;- i + 1 ] &lt;= hi '''then''' '''goto''' loop '''else''' 0
'''end''';
temp
'''end'''
&apos;;
'''out''' sum( @i, 1, 100, `1/i&apos; )
'''end''' $
{{out}}
<pre>
NUMBER 5.1873775176
</pre>
</pre>


=={{header|F_Sharp|F#}}==
=={{header|F_Sharp|F#}}==
<lang fsharp>
<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>
5.18737751763962
5.18737751763962
</pre>
</pre>

=={{header|Factor}}==
=={{header|Factor}}==
Similar to the Java and Kotlin examples:
Similar to the Java and Kotlin examples:
<lang factor>: sum ( lo hi term -- x ) [ [a,b] ] dip map-sum ; inline
<syntaxhighlight lang="factor">: sum ( lo hi term -- x ) [ [a,b] ] dip map-sum ; inline


1 100 [ recip ] sum .</lang>
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.
<lang factor>SYMBOL: i
<syntaxhighlight lang="factor">SYMBOL: i


: sum ( i lo hi term -- x )
: sum ( i lo hi term -- x )
Line 516: Line 960:
inline
inline


i 1 100 [ recip ] sum .</lang>
i 1 100 [ recip ] sum .</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 525: Line 969:
This version passes i on the stack:
This version passes i on the stack:


<lang forth>: sum 0 s>f 1+ swap ?do i over execute f+ loop drop ;
<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.</lang>
: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:


<lang forth>fvariable ii \ i is a Forth word that we need
<syntaxhighlight lang="forth">: sum ( i-xt lo hi term-xt -- r )
: sum ( xt1 lo hi xt2 -- r )
\ stack effects: i-xt ( -- addr ); term-xt ( -- r1 )
0e swap 1+ rot ?do ( addr xt r1 )
0e swap 1+ rot ?do ( r1 xt1 xt2 )
i s>f over execute f! dup execute f+
i 2 pick execute ! dup execute f+
loop 2drop ;
loop 2drop ;

' ii 1 100 :noname 1e ii f@ f/ ; sum f.</lang>
variable i1 \ avoid conflict with Forth word I
' i1 1 100 :noname 1e i1 @ s>f f/ ; sum f.</syntaxhighlight>

Inspired by the macro-based versions here's a more idiomatic approach that is closer to the original than the first version above (Forth-2012 code):

<syntaxhighlight lang="forth">: sum< ( run-time: hi+1 lo -- 0e )
0e0 postpone fliteral postpone ?do ; immediate

: >sum ( run-time: r1 r2 -- r3 )
postpone f+ postpone loop ; immediate

: main ( -- )
101 1 sum< 1e0 i s>f f/ >sum f. ;
main</syntaxhighlight>

This splits <code>sum</code> in two macros: <code>sum&lt;</code> and <code>&gt;sum</code>; in <code>main</code> these two words surround the code corresponding to <code>1/i</code> in the Algol 60 version. The loop limits are <code>101 1</code>, passed on the stack to <code>sum&lt;</code> in the order and semantics (upper bound is excluded) idiomatic in Forth.

Concerning the <code>i</code> parameter of the Algol 60 version, that is an artifact of the role of variables for storing data and passing it around in Algol-family languages. Forth's counted loops can access the current loop counter of the innermost loop with <code>i</code> (which is not a variable) without setting a variable, and that is also what one uses inside <code>sum&lt;</code> ... <code>&gt;sum</code>, as shown in <code>main</code>.


=={{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<lang Fortran> FUNCTION SUM(I,LO,HI,TERM)
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 546: Line 1,008:
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</lang>
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: <lang Fortran> FUNCTION SUMJ(I,LO,HI,TERM) !Attempt to follow Jensen's Device...
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 569: Line 1,031:


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</lang>
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.


Incidentally, a subroutine such as TEST(A,B) invoked as TEST(X,X) enables the discovery of copy-in, copy-out parameter passing. Within the routine, modify the value of A and look to see if B suddenly has a new value also.
Incidentally, a subroutine such as TEST(A,B) invoked as TEST(X,X) enables the discovery of copy-in, copy-out parameter passing. Within the routine, modify the value of A and look to see if B suddenly has a new value also.


=={{header|FreeBASIC}}==
<lang freebasic>Sub Evaluation
Dim As Integer i, lo = 1, hi = 100
Dim As Double temp = 0
For i = lo To hi
temp += (1/i) ''r(i)
Next i
Print temp
End Sub

Evaluation
Sleep</lang>
{{out}}
<pre>
5.187377517639621
</pre>



=={{header|Go}}==
=={{header|Go}}==
<lang go>package main
<syntaxhighlight lang="go">package main


import "fmt"
import "fmt"
Line 610: Line 1,053:
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) }))
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 620: Line 1,063:
{{trans|JavaScript}}
{{trans|JavaScript}}
Solution:
Solution:
<lang groovy>def sum = { i, lo, hi, term ->
<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 }))</lang>
println (sum(obj, 1, 100, { 1 / obj.value }))</syntaxhighlight>


Output:
Output:
Line 630: Line 1,073:


=={{header|Haskell}}==
=={{header|Haskell}}==
<lang haskell>import Control.Monad.ST
<syntaxhighlight lang="haskell">import Control.Monad.ST
import Data.STRef
import Data.STRef


sum_ :: STRef s Double -> Double -> Double -> ST s Double -> ST s Double
sum_ :: STRef s Double -> Double -> Double
-> ST s Double -> ST s Double
sum_ ref_i lo hi term = sum <$> mapM ((>> term) . writeSTRef ref_i) [lo .. hi]
sum_ ref lo hi term =
do
vs <- forM [lo .. hi]
(\k -> do { writeSTRef ref k
; term } )
return $ sum vs


foo :: Double
foo :: Double
foo =
foo =
runST $
runST $
do i <- newSTRef undefined -- initial value doesn't matter
do ref <- newSTRef undefined
sum_ i 1 100 $ recip <$> readSTRef i
-- initial value doesn't matter
sum_ ref 1 100 $
do
k <- readSTRef ref
return $ recip k


main :: IO ()
main :: IO ()
main = print foo</lang>
main = print foo</syntaxhighlight>
{{Out}}
{{Out}}
<pre>5.187377517639621</pre>
<pre>5.187377517639621</pre>


=={{header|Huginn}}==
=={{header|Huginn}}==
<lang huginn>harmonic_sum( i, lo, hi, term ) {
<syntaxhighlight lang="huginn">harmonic_sum( i, lo, hi, term ) {
temp = 0.0;
temp = 0.0;
i *= 0.0;
i *= 0.0;
Line 662: Line 1,115:
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; } ) ) );
}</lang>
}</syntaxhighlight>
{{Output}}<pre>5.18737751764</pre>
{{Output}}<pre>5.18737751764</pre>


Line 668: Line 1,121:
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.


<lang Icon>record mutable(value) # record wrapper to provide mutable access to immutable types
<syntaxhighlight lang="icon">record mutable(value) # record wrapper to provide mutable access to immutable types


procedure main()
procedure main()
Line 680: Line 1,133:
temp +:= @^term
temp +:= @^term
return temp
return temp
end</lang>
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.
<lang Icon> write( sum(A, 1, 100, create |1.0/A.value) )
<syntaxhighlight lang="icon"> write( sum(A, 1, 100, create |1.0/A.value) )
...
...
temp +:= @term</lang>
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.
<lang Icon> write( sum{A.value, 1, 100, 1.0/A.value} )
<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]</lang>
temp +:= @^X[4]</syntaxhighlight>


=={{header|J}}==
=={{header|J}}==
'''Solution:'''
'''Solution:'''
<lang j>jensen=: monad define
<syntaxhighlight lang="j">jensen=: monad define
'name lo hi expression'=. y
'name lo hi expression'=. y
temp=. 0
temp=. 0
Line 704: Line 1,157:
temp=. temp + ".expression
temp=. temp + ".expression
end.
end.
)</lang>
)</syntaxhighlight>
'''Example:'''
'''Example:'''
<lang j> jensen 'i';1;100;'1%i'
<syntaxhighlight lang="j"> jensen 'i';1;100;'1%i'
5.18738</lang>
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 716: Line 1,169:
This is Java 8.
This is Java 8.


<lang java>import java.util.function.*;
<syntaxhighlight lang="java">import java.util.function.*;
import java.util.stream.*;
import java.util.stream.*;


Line 728: Line 1,181:
}
}
}
}
</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:


<lang java>public class Jensen2 {
<syntaxhighlight lang="java">public class Jensen2 {


interface IntToDoubleFunction {
interface IntToDoubleFunction {
Line 754: Line 1,207:
}
}
}
}
</syntaxhighlight>
</lang>


=={{header|JavaScript}}==
=={{header|JavaScript}}==
Line 761: Line 1,214:
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.


<lang javascript>var obj;
<syntaxhighlight lang="javascript">var obj;


function sum(o, lo, hi, term) {
function sum(o, lo, hi, term) {
Line 771: Line 1,224:


obj = {val: 0};
obj = {val: 0};
alert(sum(obj, 1, 100, function() {return 1 / obj.val}));</lang>
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}}==
<lang Joy>100 [0] [[1.0 swap /] dip +] primrec.</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 781: Line 1,234:
=={{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.
<lang jq>def sum(lo; hi; term):
<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/.)</lang>
sum(1;100;1/.)</syntaxhighlight>
{{Out}}
{{Out}}
$ jq -n -f jensen.jq
$ jq -n -f jensen.jq
Line 794: Line 1,247:
{{trans|C}}
{{trans|C}}


<lang julia>macro sum(i, loname, hiname, term)
<syntaxhighlight lang="julia">macro sum(i, loname, hiname, term)
return quote
return quote
lo = $loname
lo = $loname
Line 807: Line 1,260:


i = 0
i = 0
@sum(i, 1, 100, 1.0 / i)</lang>
@sum(i, 1, 100, 1.0 / i)</syntaxhighlight>


=={{header|Kotlin}}==
=={{header|Kotlin}}==
<lang scala>fun sum(lo: Int, hi: Int, f: (Int) -> Double) = (lo..hi).sumByDouble(f)
<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 }))</lang>
fun main(args: Array<String>) = println(sum(1, 100, { 1.0 / it }))</syntaxhighlight>

=={{header|Lambdatalk}}==
<syntaxhighlight lang="scheme">
{def jensen
{lambda {:n}
{+ {S.map {lambda {:i} {/ 1 :i}}
{S.serie 1 :n}} }}}
-> jensen

{jensen 100}
-> 5.187377517639621
</syntaxhighlight>
I probably didn't understand this task, what's going on ...


=={{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 825: Line 1,291:
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 845: Line 1,311:
}
}
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 862: Line 1,328:
}
}
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 879: Line 1,345:
}
}
Jensen`s_Device
Jensen`s_Device
</syntaxhighlight>
</lang>


=={{header|M4}}==
=={{header|M4}}==
<lang M4>define(`for',
<syntaxhighlight lang="m4">define(`for',
`ifelse($#,0,``$0'',
`ifelse($#,0,``$0'',
`ifelse(eval($2<=$3),1,
`ifelse(eval($2<=$3),1,
Line 889: Line 1,355:
`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')</lang>
sum(`i',1,100,`1000/i')</syntaxhighlight>


Output:
Output:
Line 898: Line 1,364:
=={{header|Mathematica}} / {{header|Wolfram Language}}==
=={{header|Mathematica}} / {{header|Wolfram Language}}==


<lang Mathematica>sum[term_, i_, lo_, hi_] := Block[{temp = 0},
<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];</lang>
SetAttributes[sum, HoldFirst];</syntaxhighlight>


Output:
Output:
Line 912: Line 1,378:


=={{header|Maxima}}==
=={{header|Maxima}}==
<lang maxima>mysum(e, v, lo, hi) := block([s: 0], for i from lo thru hi do s: s + subst(v=i, e), s)$
<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 926: Line 1,392:
/* still works */
/* still works */
mysum(1/n, n, 1, 10);
mysum(1/n, n, 1, 10);
7381/2520</lang>
7381/2520</syntaxhighlight>


=={{header|NetRexx}}==
=={{header|NetRexx}}==
<lang netrexx>
<syntaxhighlight lang="netrexx">
import COM.ibm.netrexx.process.
import COM.ibm.netrexx.process.


Line 967: Line 1,433:
return Rexx termMethod.invoke(null,[iv])
return Rexx termMethod.invoke(null,[iv])
</syntaxhighlight>
</lang>


=={{header|Nim}}==
=={{header|Nim}}==
<lang nim>var i: int
<syntaxhighlight lang="nim">var i: int


proc harmonicSum(i: var int, lo, hi, term): float =
proc harmonicSum(i: var int; lo, hi: int; term: proc: float): float =
i = lo
i = lo
while i <= hi:
while i <= hi:
Line 978: Line 1,444:
inc i
inc i


echo harmonicSum(i, 1, 100, proc: float = 1.0 / float(i))</lang>
echo harmonicSum(i, 1, 100, proc: float = 1 / i)</syntaxhighlight>

Output:
{{out}}
<pre>5.1873775176396206e+00</pre>
<pre>5.5.187377517639621</pre>


=={{header|Objeck}}==
=={{header|Objeck}}==
<lang objeck>
<syntaxhighlight lang="objeck">
bundle Default {
bundle Default {
class Jensens {
class Jensens {
Line 1,007: Line 1,474:
}
}
}
}
</syntaxhighlight>
</lang>


Output: 5.18738
Output: 5.18738


=={{header|OCaml}}==
=={{header|OCaml}}==
<lang ocaml>let i = ref 42 (* initial value doesn't matter *)
<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,024: Line 1,491:


let () =
let () =
Printf.printf "%f\n" (sum' i 1 100 (fun () -> 1. /. float !i))</lang>
Printf.printf "%f\n" (sum' i 1 100 (fun () -> 1. /. float !i))</syntaxhighlight>
Output: 5.187378
Output: 5.187378


=={{header|Oforth}}==
=={{header|Oforth}}==


<lang Oforth>: mysum(lo, hi, term) | i | 0 lo hi for: i [ i term perform + ] ;</lang>
<syntaxhighlight lang="oforth">: mysum(lo, hi, term) | i | 0 lo hi for: i [ i term perform + ] ;</syntaxhighlight>


{{out}}
{{out}}
Line 1,042: Line 1,509:
=={{header|Oz}}==
=={{header|Oz}}==
Translation using mutable references and an anonymous function:
Translation using mutable references and an anonymous function:
<lang oz>declare
<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,055: Line 1,522:
I = {NewCell unit}
I = {NewCell unit}
in
in
{Show {Sum I 1 100 fun {$} 1.0 / {Int.toFloat @I} end}}</lang>
{Show {Sum I 1 100 fun {$} 1.0 / {Int.toFloat @I} end}}</syntaxhighlight>


Idiomatic code:
Idiomatic code:
<lang oz>declare
<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}}</lang>
{Show {Sum 1 100 fun {$ I} 1.0/{Int.toFloat I} end}}</syntaxhighlight>


=={{header|PARI/GP}}==
=={{header|PARI/GP}}==
Line 1,069: Line 1,536:


=={{header|Pascal}}==
=={{header|Pascal}}==
<syntaxhighlight lang="pascal">program Jensens_Device;
<lang pascal>{$MODE objFPC}

{$IFDEF FPC}
{$MODE objFPC}
{$ENDIF}

type
type
tTerm = function(i: integer):real;
tTerm = function(i: integer): real;

function term(i:integer):real;
function term(i: integer): real;
begin
Begin
term := 1/i;
term := 1 / i;
end;
end;


function sum(var i: LongInt;
function sum(var i: LongInt; lo, hi: integer; term: tTerm): real;
begin
lo,hi: integer;
term:tTerm):real;
Begin
result := 0;
result := 0;
i := lo;
i := lo;
while i<=hi do begin
while i <= hi do
begin
result := result+term(i);
result := result + term(i);
inc(i);
inc(i);
end;
end;
end;
end;


var
var
i : LongInt;
i: LongInt;

Begin
begin
writeln(sum(i,1,100,@term));
writeln(sum(i, 1, 100, @term));
end.
{$IFNDEF UNIX} readln; {$ENDIF}
</lang>
end.</syntaxhighlight>
Out
Out
<pre> 5.1873775176396206E+000</pre>
<pre> 5.1873775176396206E+000</pre>


=={{header|Perl}}==
=={{header|Perl}}==
<lang perl>my $i;
<syntaxhighlight lang="perl">my $i;
sub sum {
sub sum {
my ($i, $lo, $hi, $term) = @_;
my ($i, $lo, $hi, $term) = @_;
Line 1,111: Line 1,582:
}
}


print sum(\$i, 1, 100, sub { 1 / $i }), "\n";</lang>
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:
<lang perl>my $i;
<syntaxhighlight lang="perl">my $i;
sub sum {
sub sum {
my (undef, $lo, $hi, $term) = @_;
my (undef, $lo, $hi, $term) = @_;
Line 1,125: Line 1,596:
}
}


print sum($i, 1, 100, sub { 1 / $i }), "\n";</lang>
print sum($i, 1, 100, sub { 1 / $i }), "\n";</syntaxhighlight>
Output: 5.18737751763962
Output: 5.18737751763962


Line 1,132: Line 1,603:
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)-->
<lang Phix>function sumr(integer lo, hi, rid)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
atom res = 0
<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>
for i=lo to hi do
<span style="color: #004080;">atom</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
res += call_func(rid,{i})
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">lo</span> <span style="color: #008080;">to</span> <span style="color: #000000;">hi</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">res</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">rid</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
return res
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function reciprocal(atom i) return 1/i end function
<span style="color: #008080;">function</span> <span style="color: #000000;">reciprocal</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">i</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
?sumr(1, 100, routine_id("reciprocal"))</lang>
<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,149: Line 1,623:


=={{header|PHP}}==
=={{header|PHP}}==
<lang php>$i;
<syntaxhighlight lang="php">$i;
function sum (&$i, $lo, $hi, $term) {
function sum (&$i, $lo, $hi, $term) {
$temp = 0;
$temp = 0;
Line 1,173: Line 1,647:


//Output: 5.1873775176396
//Output: 5.1873775176396
</syntaxhighlight>
</lang>


=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
<lang PicoLisp>(scl 6)
<syntaxhighlight lang="picolisp">(scl 6)


(de jensen (I Lo Hi Term)
(de jensen (I Lo Hi Term)
Line 1,189: Line 1,663:
(format
(format
(jensen I 1 100 '(() (*/ 1.0 (val I))))
(jensen I 1 100 '(() (*/ 1.0 (val I))))
*Scl ) )</lang>
*Scl ) )</syntaxhighlight>
Output:
Output:
<pre>-> "5.187383"</pre>
<pre>-> "5.187383"</pre>

=={{header|PureBasic}}==
{{trans|C}}
<lang PureBasic>Prototype.d func()

Global i

Procedure.d Sum(*i.Integer, lo, hi, *term.func)
Protected Temp.d
For i=lo To hi
temp + *term()
Next
ProcedureReturn Temp
EndProcedure

Procedure.d term_func()
ProcedureReturn 1/i
EndProcedure

Answer.d = Sum(@i, 1, 100, @term_func())</lang>


=={{header|Python}}==
=={{header|Python}}==
<lang python>class Ref(object):
<syntaxhighlight lang="python">class Ref(object):
def __init__(self, value=None):
def __init__(self, value=None):
self.value = value
self.value = value
Line 1,231: Line 1,685:
# 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)</lang>
print harmonic_sum(i, 1, 100, lambda: 1.0/i.value)</syntaxhighlight>


or
or


<lang python>
<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,241: Line 1,695:
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


<lang python>
<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,251: Line 1,705:
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,261: Line 1,715:
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.


<lang R>sum <- function(var, lo, hi, term)
<syntaxhighlight lang="r">sum <- function(var, lo, hi, term)
eval(substitute({
eval(substitute({
.temp <- 0;
.temp <- 0;
Line 1,275: Line 1,729:
##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</lang>
sum(i, 1, 100, i^x) #5.187378</syntaxhighlight>


=={{header|Racket}}==
=={{header|Racket}}==
Line 1,281: Line 1,735:
be written just as Jørn Jensen did at Regnecentralen.
be written just as Jørn Jensen did at Regnecentralen.


<lang racket>
<syntaxhighlight lang="racket">
#lang algol60
#lang algol60
begin
begin
Line 1,300: Line 1,754:
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:


<lang racket>
<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,315: Line 1,769:


Rather than playing tricks like Perl&nbsp;5 does, the declarations of the formal parameters are quite straightforward in Raku:
Rather than playing tricks like Perl&nbsp;5 does, the declarations of the formal parameters are quite straightforward in Raku:
<lang perl6>sub sum($i is rw, $lo, $hi, &term) {
<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,324: Line 1,778:


my $i;
my $i;
say sum $i, 1, 100, { 1 / $i };</lang>
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}}==
<lang rascal>public num Jenssen(int lo, int hi, num (int i) term){
<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,334: Line 1,788:
lo += 1;}
lo += 1;}
return temp;
return temp;
}</lang>
}</syntaxhighlight>


With as output:
With as output:


<lang rascal>rascal>Jenssen(1, 100, num(int i){return 1.0/i;})
<syntaxhighlight lang="rascal">rascal>Jenssen(1, 100, num(int i){return 1.0/i;})
num: 5.18737751763962026080511767565825315790897212670845165317653395662</lang>
num: 5.18737751763962026080511767565825315790897212670845165317653395662</syntaxhighlight>


=={{header|REXX}}==
=={{header|REXX}}==
<lang rexx>/*REXX program demonstrates Jensen's device (via call subroutine, and args by name). */
<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,358: Line 1,812:
/*comment lit var lit var lit var literal var literal */
/*comment lit var lit var lit var literal var literal */


return $</lang>
return $</syntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
{{out|output|text=&nbsp; when using the default input:}}
<pre>
<pre>
Line 1,379: Line 1,833:


=={{header|Ring}}==
=={{header|Ring}}==
<lang ring>
<syntaxhighlight lang="ring">
# Project : Jensen's Device
# Project : Jensen's Device


Line 1,393: Line 1,847:
next
next
return temp
return temp
</syntaxhighlight>
</lang>
Output:
Output:
<pre>
<pre>
5.18737751763962
5.18737751763962
</pre>

=={{header|RPL}}==
{{works with|Halcyon Calc|4.2.7}}
≪ → idx lo hi term
≪ lo idx STO 0
DO
term EVAL +
1 idx STO+
UNTIL idx EVAL hi > END
idx PURGE
‘SUM’ STO
'K' 1 100 '1/K' SUM
'N' 0 100 '1/FACT(N)' SUM
{{out}}
<pre>
2: 5.18737751764
1: 2.71828182846
</pre>
</pre>


=={{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:
<lang ruby>def sum(var, lo, hi, term, 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,408: Line 1,883:
sum
sum
end
end
p sum "i", 1, 100, "1.0 / i", binding # => 5.18737751763962</lang>
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:
<lang ruby>def sum2(lo, hi)
<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</lang>
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)
<lang ruby>
<syntaxhighlight lang="ruby">
def sum lo, hi, &term
def sum lo, hi, &term
(lo..hi).sum(&term)
(lo..hi).sum(&term)
Line 1,424: Line 1,899:
# 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}}==
<syntaxhighlight lang="rust">
use std::f32;

fn harmonic_sum<F>(lo: usize, hi: usize, term: F) -> f32
where
F: Fn(f32) -> f32,
{
(lo..hi + 1).fold(0.0, |acc, item| acc + term(item as f32))
}

fn main() {
println!("{}", harmonic_sum(1, 100, |i| 1.0 / i));
}

</syntaxhighlight>
{{out}}
<pre>
5.187378
</pre>


=={{header|Scala}}==
=={{header|Scala}}==
Line 1,433: Line 1,929:
class, which is effectively the same as passing by reference.
class, which is effectively the same as passing by reference.


<lang scala>class MyInt { var i: Int = _ }
<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,444: Line 1,940:
temp
temp
}
}
sum(i, 1, 100, 1.0 / i.i)</lang>
sum(i, 1, 100, 1.0 / i.i)</syntaxhighlight>


Result:
Result:
Line 1,455: Line 1,951:
Scheme procedures do not support call-by-name. Scheme macros, however, do:
Scheme procedures do not support call-by-name. Scheme macros, however, do:


<lang scheme>
<syntaxhighlight lang="scheme">
(define-syntax sum
(define-syntax sum
(syntax-rules ()
(syntax-rules ()
Line 1,465: Line 1,961:
(loop (+ var 1)
(loop (+ var 1)
(+ result . body)))))))
(+ result . body)))))))
</syntaxhighlight>
</lang>


<pre>
<pre>
Line 1,475: Line 1,971:
Seed7 supports call-by-name with function parameters:
Seed7 supports call-by-name with function parameters:


<lang seed7>
<syntaxhighlight lang="seed7">
$ include "seed7_05.s7i";
$ include "seed7_05.s7i";
include "float.s7i";
include "float.s7i";
Line 1,495: Line 1,991:
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,503: Line 1,999:


=={{header|Sidef}}==
=={{header|Sidef}}==
<lang ruby>var i;
<syntaxhighlight lang="ruby">var i
func sum (i, lo, hi, term) {
func sum (i, lo, hi, term) {
var temp = 0;
var temp = 0
for (*i = lo; *i <= hi; (*i)++) {
for (*i = lo; *i <= hi; (*i)++) {
temp += term.run;
temp += term.run
};
}
return temp;
return temp
};
}
say sum(\i, 1, 100, { 1 / i });</lang>
say sum(\i, 1, 100, { 1 / i })</syntaxhighlight>
{{out}}
{{out}}
<pre>5.18737751763962026080511767565825315790899</pre>
<pre>5.18737751763962026080511767565825315790897212671</pre>


=={{header|Simula}}==
=={{header|Simula}}==
{{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.<lang simula>comment Jensen's Device;
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,540: Line 2,036:
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</lang>
end</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,547: Line 2,043:


=={{header|Standard ML}}==
=={{header|Standard ML}}==
<lang sml>val i = ref 42 (* initial value doesn't matter *)
<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,561: Line 2,057:


val () =
val () =
print (Real.toString (sum' (i, 1, 100, fn () => 1.0 / real (!i))) ^ "\n")</lang>
print (Real.toString (sum' (i, 1, 100, fn () => 1.0 / real (!i))) ^ "\n")</syntaxhighlight>
Output: 5.18737751764
Output: 5.18737751764


=={{header|Swift}}==
=={{header|Swift}}==
<lang swift>var i = 42 // initial value doesn't matter
<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,575: Line 2,071:
}
}


println(sum(&i, 1, 100, 1 / Double(i)))</lang>
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,582: Line 2,078:
=={{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.
<lang tcl>proc sum {var lo hi term} {
<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,590: Line 2,086:
return $sum
return $sum
}
}
puts [sum i 1 100 {1.0/$i}] ;# 5.177377517639621</lang>
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
<lang tcl>proc sum2 {lo hi lambda} {
<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,599: Line 2,095:
return $sum
return $sum
}
}
puts [sum2 1 100 {i {expr {1.0/$i}}}] ;# 5.177377517639621</lang>
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,615: Line 2,111:
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,625: Line 2,121:
=={{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.
<lang ecmascript>class Box {
<syntaxhighlight lang="wren">class Box {
construct new(v) { _v = v }
construct new(v) { _v = v }
v { _v }
v { _v }
Line 1,644: Line 2,140:


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)</lang>
System.print(s)</syntaxhighlight>


{{out}}
{{out}}
Line 1,650: Line 2,146:
5.1873775176396
5.1873775176396
</pre>
</pre>


=={{header|Yabasic}}==
{{trans|FreeBASIC}}
<lang Yabasic>sub Evaluation()
lo = 1 : hi = 100 : temp = 0
for i = lo to hi
temp = temp + (1/i) //r(i)
next i
print temp
end sub

Evaluation()</lang>
{{out}}
<pre>
5.18738
</pre>



=={{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:
<lang zkl>fcn sum(ri, lo,hi, 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();</lang>
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):
<lang zkl>fcn sum2(ri, lo,hi, term){
<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,684: Line 2,162:
}
}
ri:=Ref(0);
ri:=Ref(0);
sum2(ri, 1,100, 'wrap(){ 1.0/ri.value }).println();</lang>
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:
<lang zkl>fcn sum3(lo,hi, term){ [lo..hi].reduce('wrap(sum,i){ sum + term(i) },0.0) }
<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();</lang>
sum3(1,100, fcn(i){ 1.0/i }).println();</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,695: Line 2,173:
5.187378
5.187378
5.187378
5.187378
</pre>

=={{header|ZX Spectrum Basic}}==
<lang zxbasic>10 DEF FN r(x)=1/x
20 LET f$="FN r(i)"
30 LET lo=1: LET hi=100
40 GO SUB 1000
50 PRINT temp
60 STOP
1000 REM Evaluation
1010 LET temp=0
1020 FOR i=lo TO hi
1030 LET temp=temp+VAL f$
1040 NEXT i
1050 RETURN
</lang>
{{out}}
<pre>
5.1873775
</pre>
</pre>



Latest revision as of 13:15, 28 April 2024

This page uses content from Wikipedia. The original article was at Jensen's Device. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance)
Task
Jensen's Device
You are encouraged to solve this task according to the task description, using any language you may know.

This task is an exercise in call by name.

Jensen's Device is a computer programming technique devised by Danish computer scientist Jørn Jensen after studying the ALGOL 60 Report.

The following program was proposed to illustrate the technique. It computes the 100th harmonic number:

begin
   integer i;
   real procedure sum (i, lo, hi, term);
      value lo, hi;
      integer i, lo, hi;
      real term;
      comment term is passed by-name, and so is i;
   begin
      real temp;
      temp := 0;
      for i := lo step 1 until hi do
         temp := temp + term;
      sum := temp
   end;
   comment note the correspondence between the mathematical notation and the call to sum;
   print (sum (i, 1, 100, 1/i))
end

The above exploits call by name to produce the correct answer (5.187...). It depends on the assumption that an expression passed as an actual parameter to a procedure would be re-evaluated in the caller's context every time the corresponding formal parameter's value was required. If the last parameter to sum had been passed by value, and assuming the initial value of i were 1, the result would have been 100 × 1/1 = 100.

Moreover, the first parameter to sum, representing the "bound" variable of the summation, must also be passed by name (or at least by reference), otherwise changes to it (made within sum) would not be visible in the caller's context when computing each of the values to be added. (On the other hand, the global variable does not have to use the same identifier, in this case i, as the formal parameter.)

Donald Knuth later proposed the Man or Boy Test as a more rigorous exercise.

11l

Translation of: C#
F sum(&i, lo, hi, term)
   V temp = 0.0
   i = lo
   L i <= hi
      temp += term()
      i++
   R temp

F main()
   Int i
   print(sum(&i, 1, 100, () -> 1 / @i))

main()
Output:
5.18738

Ada

with Ada.Text_IO;  use Ada.Text_IO;

procedure Jensen_Device is
   function Sum
            (  I : not null access Float;
               Lo, Hi : Float;
               F : access function return Float
            )  return Float is
      Temp : Float := 0.0;
   begin
      I.all := Lo;
      while I.all <= Hi loop
         Temp := Temp + F.all;
         I.all := I.all + 1.0;
      end loop;
      return Temp;
   end Sum;

   I : aliased Float;
   function Inv_I return Float is
   begin
      return 1.0 / I;
   end Inv_I;
begin
   Put_Line (Float'Image (Sum (I'Access, 1.0, 100.0, Inv_I'Access)));
end Jensen_Device;
 5.18738E+00

ALGOL 60

Honor given where honor is due. In Algol 60, 'call by name' is the default argument evaluation.

begin
   integer i;
   real procedure sum (i, lo, hi, term);
      value lo, hi;
      integer i, lo, hi;
      real term;
      comment term is passed by-name, and so is i;
   begin
      real temp;
      temp := 0;
      for i := lo step 1 until hi do
         temp := temp + term;
      sum := temp
   end;
   comment note the correspondence between the mathematical notation and the call to sum;
   print (sum (i, 1, 100, 1/i))
end

ALGOL 68

Translation of: ALGOL 60
BEGIN
   INT i;
   PROC sum  = (REF INT i, INT lo, hi, PROC REAL term)REAL:
      COMMENT term is passed by-name, and so is i COMMENT
   BEGIN
      REAL temp := 0;
      i := lo;
      WHILE i <= hi DO           # ALGOL 68 has a "for" loop but it creates a distinct #
         temp +:= term;          # variable which would not be shared with the passed "i" #
         i +:= 1                 # Here the actual passed "i" is incremented. #
      OD;
      temp
   END;
   COMMENT note the correspondence between the mathematical notation and the call to sum COMMENT
   print (sum (i, 1, 100, REAL: 1/i))
END

Output: +5.18737751763962e +0

ALGOL W

Translation of: ALGOL 68

Algol W retained Algol 60's call by name but also offered additional parameter passing modes.
This version uses call by name for the i parameter but uses a procedure parameter for the summed expression.
The expression supplied in the call is automatically converted to a procedure by the compiler.

begin
   integer i;
   real procedure sum  ( integer %name% i; integer value lo, hi; real procedure term );
      % i is passed by-name, term is passed as a procedure which makes it effectively passed by-name %
   begin
       real temp;
       temp := 0;
       i := lo;
       while i <= hi do begin      % The Algol W "for" loop (as in Algol 68) creates a distinct %
           temp := temp + term;    % variable which would not be shared with the passed "i" %
           i := i + 1              % Here the actual passed "i" is incremented. %
       end while_i_le_temp;
       temp
   end;
   % note the correspondence between the mathematical notation and the call to sum %
   write( sum( i, 1, 100, 1/i ) )
end.
Output:

AppleScript

set i to 0

on jsum(i, lo, hi, term)
    set {temp, i's contents} to {0, lo}
    repeat while i's contents  hi
        set {temp, i's contents} to {temp + (term's f(i)), (i's contents) + 1}
    end repeat
    return temp
end jsum

script term_func
    on f(i)
        return 1 / i
    end f
end script

return jsum(a reference to i, 1, 100, term_func)

Output: 5.18737751764

ARM Assembly

Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program jensen.s   */
/* compil as with option  -mcpu=<processor> -mfpu=vfpv4 -mfloat-abi=hard  */
/* link with gcc          */

/* Constantes    */
.equ EXIT,   1                           @ Linux syscall
/* Initialized data */
.data

szFormat: .asciz "Result = %.8f \n" 
.align 4

/* UnInitialized data */
.bss 

/*  code section */
.text
.global main 
main: 
    mov r0,#1                                   @ first indice
    mov r1,#100                                 @ last indice
    adr r2,funcdiv                              @ address function
    bl funcSum
    vcvt.f64.f32  d1, s0                        @ conversion double float for print by C
    ldr r0,iAdrszFormat                         @ display format
    vmov r2,r3,d1                               @ parameter function printf for float double
    bl printf                                   @ display float double

100:                                            @ standard end of the program
    mov r0, #0                                  @ return code
    mov r7, #EXIT                               @ request to exit program
    svc 0                                       @ perform system call

iAdrszFormat:             .int szFormat
/******************************************************************/
/*     function sum                                               */ 
/******************************************************************/
/* r0 contains begin  */
/* r1 contains end */
/* r2 contains address function */

/* r0 return result                      */
funcSum:
    push {r0,r3,lr}                       @ save  registers 
    mov r3,r0
    mov r0,#0                             @ init r0
    vmov s3,r0                            @ and s3
    vcvt.f32.s32 s3, s3                   @ convert in float single précision (32bits)
1:                                        @ begin loop
    mov r0,r3                             @ loop indice -> parameter function
    blx r2                                @ call function address in r2
    vadd.f32 s3,s0                        @ addition float
    add r3,#1                             @ increment indice
    cmp r3,r1                             @ end ?
    ble 1b                                @ no loop
    vmov s0,s3                            @ return float result in s0

100:
    pop {r0,r3,lr}                        @ restaur registers
    bx lr                                 @ return
/******************************************************************/
/*     compute 1/r0                                               */ 
/******************************************************************/
/* r0 contains the value                 */
/* r0 return result                      */
funcdiv:
    push {r1,lr}                       @ save  registers 
    vpush {s1}                         @ save float registers
    cmp r0,#0                          @ division by zero -> end
    beq 100f
    ldr r1,fUn                         @ load float constant 1.0
    vmov s0,r1                         @ in float register s3
    vmov s1,r0                         @ 
    vcvt.f32.s32 s1, s1                @conversion in float single précision (32 bits)
    vdiv.f32 s0,s0,s1                  @ division 1/r0
                                       @ and return result in s0
100:
    vpop {s1}                          @ restaur float registers
    pop {r1,lr}                        @ restaur registers
    bx lr                              @ return
fUn:                .float 1

Arturo

Translation of: Ruby
harmonicSum: function [variable, lo, hi, term][
    result: new 0.0
    loop lo..hi 'n ->
        'result + do ~"|variable|: |n| |term|"
    result
]
print ["harmonicSum 1->100:" harmonicSum 'i 1 100 {1.0 / i}]
Output:
harmonicSum 1->100: 5.187377517639621

Asymptote

Translation of: FreeBASIC
real temp = 0;
for(int i = 1; i <= 100; ++i) {
    temp += 1/i;
}
write(temp);
Output:
5.18737751763962

AWK

# syntax: GAWK -f JENSENS_DEVICE.AWK
# converted from FreeBASIC
BEGIN {
    evaluation()
    exit(0)
}
function evaluation(  hi,i,lo,tmp) {
    lo = 1
    hi = 100
    for (i=lo; i<=hi; i++) {
      tmp += (1/i)
    }
    printf("%.15f\n",tmp)
}
Output:
5.187377517639621

BASIC

Applesoft BASIC

Same code as GW-BASIC

BASIC256

Translation of: FreeBASIC
call Evaluation()
end

subroutine Evaluation()
	lo = 1 : hi = 100 : temp = 0
	for i = lo to hi
		temp += (1/i)  ##r(i)
	next i
	print temp
end subroutine
Output:
5.18737751764

BBC BASIC

      PRINT FNsum(j, 1, 100, FNreciprocal)
      END
      
      DEF FNsum(RETURN i, lo, hi, RETURN func)
      LOCAL temp
      FOR i = lo TO hi
        temp += FN(^func)
      NEXT
      = temp
      
      DEF FNreciprocal = 1/i

Output:

5.18737752

Chipmunk Basic

Translation of: QBasic
Works with: Chipmunk Basic version 3.6.4
100 call evaluation
110 end
120 sub evaluation()
130   lo = 1
140   hi = 100
150   temp = 0
160   for i = lo to hi
170     temp = temp+(1/i)
180   next i
190   print temp
200 end sub

Craft Basic

precision 4

define lo = 1, hi = 100, temp = 0

for i = lo to hi

	let temp = temp + (1 / i)
	wait

next i

print temp
Output:
5.1873

FreeBASIC

Sub Evaluation
    Dim As Integer i, lo = 1, hi = 100
    Dim As Double temp = 0
    For i = lo To hi
        temp += (1/i)  ''r(i)
    Next i
    Print temp
End Sub

Evaluation
Sleep
Output:
5.187377517639621

FutureBasic

local fn JensensDevice( lo as long, hi as long ) as double
  double i, temp = 0.0
  for i = lo to hi
    temp = temp + (1/i)
  next
end fn = temp

print fn JensensDevice( 1, 100 )

HandleEvents
Output:
5.187377517639621

Gambas

Translation of: FreeBASIC
Sub Evaluation()

  Dim i As Integer, lo As Integer = 1, hi As Integer = 100 
  Dim tmp As Float = 0 

  For i = lo To hi 
    tmp += (1 / i)
  Next 
  Print tmp 

End Sub

Public Sub Main() 

  Evaluation 

End

GW-BASIC

Works with: PC-BASIC version any
Works with: BASICA
Works with: Applesoft BASIC
Works with: Chipmunk Basic
Works with: QBasic
Works with: QB64
Works with: Quite BASIC
Works with: MSX BASIC
100 GOSUB 120
110 END
120 REM Evaluation
130   LET A = 1
140   LET B = 100
150   LET T = 0
160   FOR I = A TO B
170     LET T = T + (1/I)
180   NEXT I
190   PRINT T
200 RETURN

Minimal BASIC

100 GOSUB 120
110 GOTO 210
120 REM Evaluation
130   LET A = 1
140   LET B = 100
150   LET T = 0
160   FOR I = A TO B
170     LET T = T+(1/I)
180   NEXT I
190   PRINT T
200 RETURN
210 END

MSX Basic

Works with: MSX BASIC version any

Same code as GW-BASIC

PureBasic

Translation of: C
Prototype.d func()

Global i

Procedure.d Sum(*i.Integer, lo, hi, *term.func)
  Protected Temp.d
  For i=lo To hi
    temp + *term()
  Next
  ProcedureReturn Temp
EndProcedure

Procedure.d term_func()
  ProcedureReturn 1/i
EndProcedure

Answer.d = Sum(@i, 1, 100, @term_func())

QBasic

Works with: QBasic version 1.1
Works with: QuickBasic version 4.5
Works with: Run BASIC
Works with: Just BASIC
Works with: Liberty BASIC
Works with: True BASIC
CALL EVALUATION
END

SUB Evaluation
    LET lo = 1
    LET hi = 100
    LET temp = 0
    FOR i = lo TO hi
        LET temp = temp + (1 / i)
    NEXT i
    PRINT temp
END SUB

QB64

Same code as QBasic

Quite BASIC

Same code as GW-BASIC

Run BASIC

Same code as QBasic

True BASIC

Same code as QBasic

uBasic/4tH

Since uBasic/4tH does not support floating point numbers, fixed point has to be used. Of course, precision suffers significantly.

' ** NOTE: it requires a 64-bit uBasic; number ranges are limited. **

If Info("wordsize") < 64 Then Print "This program requires a 64-bit uBasic" : End

Dim @i(1)
i = 0                                  ' fake something that resembles a pointer

Print Using "+?.####";FUNC(_Ftoi(FUNC(_Sum(i, 1, 100, _Term))))
End

_Sum
  Param (4)
  Local (1)

  e@ = 0
  For @i(a@) = b@ To c@ : e@ = e@ + FUNC(d@) : Next

Return (e@)

_Term Return (FUNC(_Fdiv(1, @i(i))))
_Fdiv Param (2) : Return ((a@*16384)/b@)
_Ftoi Param (1) : Return ((10000*a@)/16384)
Output:
5.1850

0 OK, 0:313 

Yabasic

Translation of: FreeBASIC
Evaluation()
end

sub Evaluation()
    lo = 1 : hi = 100 : temp = 0
    for i = lo to hi
        temp = temp + (1/i)  //r(i)
    next i
    print temp
end sub
Output:
5.18738

ZX Spectrum Basic

10 DEF FN r(x)=1/x
20 LET f$="FN r(i)"
30 LET lo=1: LET hi=100
40 GO SUB 1000
50 PRINT temp
60 STOP 
1000 REM Evaluation
1010 LET temp=0
1020 FOR i=lo TO hi
1030 LET temp=temp+VAL f$
1040 NEXT i
1050 RETURN
Output:
5.1873775

Bracmat

( ( sum
  =   I lo hi Term temp
    .   !arg:((=?I),?lo,?hi,(=?Term))
      & 0:?temp
      & !lo:?!I
      &   whl
        ' ( !!I:~>!hi
          & !temp+!Term:?temp
          & 1+!!I:?!I
          )
      & !temp
  )
& sum$((=i),1,100,(=!i^-1))
);

Output:

14466636279520351160221518043104131447711/2788815009188499086581352357412492142272

C

#include <stdio.h>

int i;
double sum(int *i, int lo, int hi, double (*term)()) {
    double temp = 0;
    for (*i = lo; *i <= hi; (*i)++)
        temp += term();
    return temp;
}

double term_func() { return 1.0 / i; }

int main () {
    printf("%f\n", sum(&i, 1, 100, term_func));
    return 0;
}

Output: 5.18738

Works with: gcc

Alternatively, C's macros provide a closer imitation of ALGOL's call-by-name semantics:

#include <stdio.h>
 
int i;

#define sum(i, lo_byname, hi_byname, term)      \
  ({                                            \
  int lo = lo_byname;                           \
  int hi = hi_byname;                           \
                                                \
  double temp = 0;                              \
  for (i = lo; i <= hi; ++i)                    \
    temp += term;                               \
  temp;                                         \
  })

int main () {
    printf("%f\n", sum(i, 1, 100, 1.0 / i));
    return 0;
}

Output: 5.187378

C#

Can be simulated via lambda expressions:

using System;

class JensensDevice
{    
    public static double Sum(ref int i, int lo, int hi, Func<double> term)
    {
        double temp = 0.0;
        for (i = lo; i <= hi; i++)
        {
            temp += term();
        }
        return temp;
    }

    static void Main()
    {
        int i = 0;
        Console.WriteLine(Sum(ref i, 1, 100, () => 1.0 / i));
    }
}

C++

#include <iostream>

#define SUM(i,lo,hi,term)\
[&](const int _lo,const int _hi){\
  decltype(+(term)) sum{};\
  for (i = _lo; i <= _hi; ++i) sum += (term);\
  return sum;\
}((lo),(hi))

int i;
double sum(int &i, int lo, int hi, double (*term)()) {
    double temp = 0;
    for (i = lo; i <= hi; i++)
        temp += term();
    return temp;
}
double term_func() { return 1.0 / i; }

int main () {
    std::cout << sum(i, 1, 100, term_func) << std::endl;
    std::cout << SUM(i,1,100,1.0/i) << "\n";
    return 0;
}

Output: 5.18738 5.18738

Clipper

With hindsight Algol60 provided this feature in a way that is terrible for program maintenance, because the calling code looks innocuous.

// Jensen's device in Clipper (or Harbour)
//    A fairly direct translation of the Algol 60
// John M Skelton 11-Feb-2012

function main()
local i
? transform(sum(@i, 1, 100, {|| 1 / i}), "##.###############")
   // @ is the quite rarely used pass by ref, {|| ...} is a
   // code block (an anonymous function, here without arguments)
   // The @i makes it clear that something unusual is occurring;
   // a called function which modifies a parameter is commonly
   // poor design!
return 0

function sum(i, lo, hi, bFunc)
local temp := 0
for i = lo to hi
   temp += eval(bFunc)
next i
return temp

Common Lisp

Common Lisp does not have call-by-name for functions; however, it can be directly simulated by a macro wrapping selected parameters in lambdas.

(declaim (inline %sum))

(defun %sum (lo hi func)
  (loop for i from lo to hi sum (funcall func i)))

(defmacro sum (i lo hi term)
  `(%sum ,lo ,hi (lambda (,i) ,term)))
CL-USER> (sum i 1 100 (/ 1 i))
14466636279520351160221518043104131447711/2788815009188499086581352357412492142272
CL-USER> (float (sum i 1 100 (/ 1 i)))
5.1873775

D

There are better ways to do this in D, but this is closer to the original Algol version:

double sum(ref int i, in int lo, in int hi, lazy double term)
pure @safe /*nothrow @nogc*/ {
    double result = 0.0;
    for (i = lo; i <= hi; i++)
        result += term();
    return result;
}

void main() {
    import std.stdio;

    int i;
    sum(i, 1, 100, 1.0/i).writeln;
}
Output:
5.18738

Dart

Translation of: C++
double i = 0;
double sum(int lo, int hi, double Function() term) {
  double temp = 0;
  for (i = lo.toDouble(); i <= hi; i++) temp += term();
  return temp;
}

double termFunc() {
  return 1.0 / i;
}

void main() {
  print(sum(1, 100, termFunc));
}
Output:
5.187377517639621

Delphi

Works with: Delphi version 6.0


type TTerm = function(i: integer): real;

function Term(I: integer): double;
begin
Term := 1 / I;
end;


function Sum(var I: integer; Lo, Hi: integer; Term: TTerm): double;
begin
Result := 0;
I := Lo;
while I <= Hi do
	begin
	Result := Result + Term(I);
	Inc(I);
	end;
end;


procedure ShowJensenDevice(Memo: TMemo);
var I: LongInt;
begin
Memo.Lines.Add(FloatToStrF(Sum(I, 1, 100, @Term), ffFixed,18,15));
end;
Output:
5.187377517639621

Elapsed Time: 1.037 ms.


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.

function sum(var i : Integer; lo, hi : Integer; lazy term : Float) : Float;
begin
   i:=lo;
   while i<=hi do begin
      Result += term;
      Inc(i);
   end;
end;

var i : Integer;

PrintLn(sum(i, 1, 100, 1.0/i));

Output: 5.187...

E

In E, the distinct mutable locations behind assignable variables can be reified as Slot objects. The E language allows a variable name (noun) to be bound to a particular slot, and the slot of an already-bound noun to be extracted, using the & operator.

(The definition of the outer i has been moved down to emphasize that it is unrelated to the i inside of sum.)

pragma.enable("one-method-object") # "def _.get" is experimental shorthand
def sum(&i, lo, hi, &term) {   # bind i and term to passed slots
    var temp := 0
    i := lo
    while (i <= hi) {          # E has numeric-range iteration but it creates a distinct
        temp += term           # variable which would not be shared with the passed i
        i += 1
    }
    return temp
}
{ 
    var i := null
    sum(&i, 1, 100, def _.get() { return 1/i })
}

1/i is not a noun, so there is no slot associated with it; so we use def _.get() { return 1/i } to define a slot object which does the computation when it is read as a slot.

The value returned by the above program (expression) is 5.187377517639621.

This emulation of the original call-by-name is of course unidiomatic; a natural version of the same computation would be:

def sum(lo, hi, f) {
    var temp := 0
    for i in lo..hi { temp += f(i) }
    return temp
}
sum(1, 100, fn i { 1/i })

Elixir

Translation of: Erlang
defmodule JensenDevice do
  def task, do: sum( 1, 100, fn i -> 1 / i end )
  
  defp sum( i, high, _term ) when i > high, do: 0
  defp sum( i, high, term ) do
    temp = term.( i )
    temp + sum( i + 1, high, term )
  end
end

IO.puts JensenDevice.task
Output:
5.1873775176396215

EMal

fun sum = real by int lo, int hi, fun term
  real temp = 0.0
  for int i = lo; i <= hi; ++i do temp += term(i) end
  return temp
end
writeLine(sum(1, 100, real by int i do return 1.0/i end))
Output:
5.1873775176396202608051176755

Erlang

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.

-module( jensens_device ).

-export( [task/0] ).

task() ->
    sum( 1, 100, fun (I) -> 1 / I end ).

sum( I, High, _Term ) when I > High -> 0;
sum( I, High, Term ) ->
    Temp = Term( I ),
    Temp + sum( I + 1, High, Term ).
Output:
4> jensens_device:task().
5.1873775176396215

Euler

Translation of: ALGOL 60
begin
   new i; new sum;
   sum <- ` formal i; formal lo; formal hi; formal term;
            begin
                new temp; label loop;
                temp <- 0;
                i    <- lo;
loop:           begin
                    temp <- temp + term;
                    if [ i <- i + 1 ] <= hi then goto loop else 0
                end;
                temp
            end
          ';

   out sum( @i, 1, 100, `1/i' )
end $
Output:
    NUMBER        5.1873775176

F#

printfn "%.14f" (List.fold(fun n g->n+1.0/g) 0.0 [1.0..100.0]);;
Output:
5.18737751763962

Factor

Similar to the Java and Kotlin examples:

: sum ( lo hi term -- x ) [ [a,b] ] dip map-sum ; inline

1 100 [ recip ] sum .

This version is a bit closer to the original, as it increments i in the caller's namespace.

SYMBOL: i

: sum ( i lo hi term -- x )
    [ [a,b] ] dip pick [ inc ] curry compose map-sum nip ;
    inline

i 1 100 [ recip ] sum .
Output:
5+522561233577855727314756256041670736351/2788815009188499086581352357412492142272

Forth

This version passes i on the stack:

: 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.

Output: 5.18737751763962

The following version passes i and 1/i as execution tokens and is thus closer to the original, but less idiomatic:

: sum ( i-xt lo hi term-xt -- r )
  \ stack effects: i-xt ( -- addr ); term-xt ( -- r1 )
  0e swap 1+ rot ?do ( r1 xt1 xt2 )
    i 2 pick execute ! dup execute f+
  loop 2drop ;

variable i1 \ avoid conflict with Forth word I
' i1 1 100 :noname 1e i1 @ s>f f/ ; sum f.

Inspired by the macro-based versions here's a more idiomatic approach that is closer to the original than the first version above (Forth-2012 code):

: sum< ( run-time: hi+1 lo -- 0e )
    0e0 postpone fliteral postpone ?do ; immediate

: >sum ( run-time: r1 r2 -- r3 )
    postpone f+ postpone loop ; immediate

: main ( -- )
    101 1 sum< 1e0 i s>f f/ >sum f. ;
main

This splits sum in two macros: sum< and >sum; in main these two words surround the code corresponding to 1/i in the Algol 60 version. The loop limits are 101 1, passed on the stack to sum< in the order and semantics (upper bound is excluded) idiomatic in Forth.

Concerning the i parameter of the Algol 60 version, that is an artifact of the role of variables for storing data and passing it around in Algol-family languages. Forth's counted loops can access the current loop counter of the innermost loop with i (which is not a variable) without setting a variable, and that is also what one uses inside sum< ... >sum, as shown in main.

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

      FUNCTION SUM(I,LO,HI,TERM)
        SUM = 0
        DO I = LO,HI
          SUM = SUM + TERM
        END DO
      END FUNCTION SUM
      WRITE (6,*) SUM(I,1,100,1.0/I)
      END

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 I 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 I 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:

      FUNCTION SUMJ(I,LO,HI,TERM)	!Attempt to follow Jensen's Device...
       INTEGER I	!Being by reference is workable.
       INTEGER LO,HI	!Just as any other parameters.
       EXTERNAL TERM	!Thus, not a variable, but a function.
        SUMJ = 0
        DO I = LO,HI	!The specified span.
          SUMJ = SUMJ + TERM(I)	!Number and type of parameters now apparent.
        END DO		!TERM will be evaluated afresh, each time.
      END FUNCTION SUMJ	!So, almost there.

      FUNCTION THIS(I)	!A function of an integer.
       INTEGER I
        THIS = 1.0/I	!Convert to floating-point.
      END		!Since 1/i will mostly give zero.

      PROGRAM JENSEN	!Aspiration.
      EXTERNAL THIS	!Thus, not a variable, but a function.
      INTEGER I		!But this is a variable, not a function.

      WRITE (6,*) SUMJ(I,1,100,THIS)	!No statement as to the parameters of THIS.
      END

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 I is a parameter to SUM is an irrelevance, and might as well be omitted from SUMJ.

Incidentally, a subroutine such as TEST(A,B) invoked as TEST(X,X) enables the discovery of copy-in, copy-out parameter passing. Within the routine, modify the value of A and look to see if B suddenly has a new value also.

Go

package main

import "fmt"

var i int

func sum(i *int, lo, hi int, term func() float64) float64 {
    temp := 0.0
    for *i = lo; *i <= hi; (*i)++ {
        temp += term()
    }
    return temp
}

func main() {
    fmt.Printf("%f\n", sum(&i, 1, 100, func() float64 { return 1.0 / float64(i) }))
}
Output:
5.187378

Groovy

Translation of: JavaScript

Solution:

def sum = { i, lo, hi, term ->
    (lo..hi).sum { i.value = it; term() }
}
def obj = [:]
println (sum(obj, 1, 100, { 1 / obj.value }))

Output:

5.1873775176

Haskell

import Control.Monad.ST
import Data.STRef

sum_ :: STRef s Double -> Double -> Double 
     -> ST s Double -> ST s Double
sum_ ref lo hi term = 
   do
     vs <- forM [lo .. hi] 
            (\k -> do { writeSTRef ref k
                      ; term } )
     return $ sum vs

foo :: Double
foo =
  runST $
  do ref <- newSTRef undefined
          -- initial value doesn't matter
     sum_ ref 1 100 $
       do
         k <- readSTRef ref
         return $ recip k

main :: IO ()
main = print foo
Output:
5.187377517639621

Huginn

harmonic_sum( i, lo, hi, term ) {
        temp = 0.0;
        i *= 0.0;
        i += lo;
        while ( i <= hi ) {
                temp += term();
                i += 1.0;
        }
        return ( temp );
}

main() {
        i = 0.0;
        print( "{}\n".format( harmonic_sum( i, 1.0, 100.0, @[i](){ 1.0 / i; } ) ) );
}
Output:
5.18737751764

Icon and Unicon

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.

record mutable(value)   # record wrapper to provide mutable access to immutable types

procedure main()
    A := mutable()      
    write( sum(A, 1, 100, create 1.0/A.value) )
end

procedure sum(A, lo, hi, term)
    temp := 0
    every A.value := lo to hi do
        temp +:= @^term
    return temp
end

Refreshing the co-expression above is more expensive to process but to avoid it requires unary alternation in the call.

    write( sum(A, 1, 100, create |1.0/A.value) )
...
        temp +:= @term

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.

    write( sum{A.value, 1, 100, 1.0/A.value} )
...
procedure sum(X)
...
    every @X[1] := @X[2] to @X[3] do
        temp +:= @^X[4]

J

Solution:

jensen=: monad define
  'name lo hi expression'=. y
  temp=. 0
  for_n. lo+i.1+hi-lo do.
    (name)=. n
    temp=. temp + ".expression
  end.
)

Example:

   jensen 'i';1;100;'1%i'
 5.18738

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.

And another obvious variation here would be turning the expression into a named entity (if it has some lasting usefulness).

Java

This is Java 8.

import java.util.function.*;
import java.util.stream.*;

public class Jensen {
    static double sum(int lo, int hi, IntToDoubleFunction f) {
        return IntStream.rangeClosed(lo, hi).mapToDouble(f).sum();
    }
        
    public static void main(String args[]) {
        System.out.println(sum(1, 100, (i -> 1.0/i)));
    }
}

The program prints '5.187377517639621'.

Java 7 is more verbose, but under the hood does essentially the same thing:

public class Jensen2 {

    interface IntToDoubleFunction {
        double apply(int n);
    }

    static double sum(int lo, int hi, IntToDoubleFunction f) {
        double res = 0;
        for (int i = lo; i <= hi; i++)
            res += f.apply(i);
        return res;

    }
    public static void main(String args[]) {
        System.out.println(
            sum(1, 100,
                new IntToDoubleFunction() {
                    public double apply(int i) { return 1.0/i;}
                }));
    }
}

JavaScript

Translation of: C

Uses an object o instead of integer pointer i, as the C example does.

var obj;

function sum(o, lo, hi, term) {
  var tmp = 0;
  for (o.val = lo; o.val <= hi; o.val++)
    tmp += term();
  return tmp;
}

obj = {val: 0};
alert(sum(obj, 1, 100, function() {return 1 / obj.val}));

The alert shows us '5.187377517639621'.

Joy

100 [0] [[1.0 swap /] dip +] primrec.

Joy does not have named parameters. Neither i nor 1/i are visible in the program.

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.

def sum(lo; hi; term):
  reduce range(lo; hi+1) as $i (0; . + ($i|term));

# The task:
sum(1;100;1/.)
Output:
$ jq -n -f jensen.jq
5.187377517639621

Julia

Works with: Julia version 0.6
Translation of: C
macro sum(i, loname, hiname, term)
    return quote
        lo = $loname
        hi = $hiname
        tmp = 0.0
        for i in lo:hi
            tmp += $term
        end
        return tmp
    end
end

i = 0
@sum(i, 1, 100, 1.0 / i)

Kotlin

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 }))

Lambdatalk

{def jensen
 {lambda {:n}
  {+ {S.map {lambda {:i} {/ 1 :i}}
            {S.serie 1 :n}} }}}
-> jensen

{jensen 100}
-> 5.187377517639621

I probably didn't understand this task, what's going on ...

Lua

function sum(var, a, b, str)
  local ret = 0
  for i = a, b do
    ret = ret + setfenv(loadstring("return "..str), {[var] = i})()
  end
  return ret
end
print(sum("i", 1, 100, "1/i"))

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.

Module Jensen`s_Device {
      Def double i
      Report Lazy$(1/i)  ' display the definition of the lazy function
      Function Sum (&i, lo, hi, &f()) {
            def double temp
            For i= lo to hi {
                  temp+=f()
            }
            =temp
      }
      Print Sum(&i, 1, 100, Lazy$(1/i))==5.1873775176392  ' true
      Print i=101 ' true
}
Jensen`s_Device

Using Decimal for better accuracy. change &i to &any to show that: when any change, change i, so f() use this i.

Module Jensen`s_Device {
      Def decimal i
      Function Sum (&any, lo, hi, &f()) {
            def decimal temp
            For any= lo to hi {
                  temp+=f()
            }
            =temp
      }
      Print Sum(&i, 1, 100, Lazy$(1/i))=5.1873775176396202608051176755@  ' true
      Print i=101 ' true
}
Jensen`s_Device

Many other examples use single float. So this is one for single.

Module Jensen`s_Device {
      Def single i
      Function Sum (&any, lo, hi, &f()) {
            def single temp
            For any= lo to hi {
                  temp+=f()
            }
            =temp
      }
      Print Sum(&i, 1, 100, Lazy$(1/i))=5.187378~  ' true
      Print i=101 ' true
}
Jensen`s_Device

M4

define(`for',
   `ifelse($#,0,``$0'',
   `ifelse(eval($2<=$3),1,
   `pushdef(`$1',$2)$4`'popdef(`$1')$0(`$1',incr($2),$3,`$4')')')')
define(`sum',
   `pushdef(`temp',0)`'for(`$1',$2,$3,
      `define(`temp',eval(temp+$4))')`'temp`'popdef(`temp')')
sum(`i',1,100,`1000/i')

Output:

5142

Mathematica / Wolfram Language

sum[term_, i_, lo_, hi_] := Block[{temp = 0},
   				Do[temp = temp + term, {i, lo, hi}];
   				temp];
SetAttributes[sum, HoldFirst];

Output:

In[2]:= sum[1/i, i, 1, 100]
Out[2]= 14466636279520351160221518043104131447711/2788815009188499086581352357412492142272

In[3]:=N[sum[1/i, i, 1, 100]]
Out[3]:=5.18738

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);
7381/2520

/* compare with builtin sum */
sum(1/n, n, 1, 10);
7381/2520

/* what if n is assigned a value ? */
n: 200$

/* still works */
mysum(1/n, n, 1, 10);
7381/2520

NetRexx

import COM.ibm.netrexx.process.

class JensensDevice
  
  properties static
  interpreter=NetRexxA
  exp=Rexx ""    
  termMethod=Method
  
  method main(x=String[]) static
    say sum('i',1,100,'1/i')
    
  method sum(i,lo,hi,term) static SIGNALS IOException,NoSuchMethodException,IllegalAccessException,InvocationTargetException
    sum=0
    loop iv=lo to hi
      sum=sum+termeval(i,iv,term)
    end
    return sum
    
  method termeval(i,iv,e) static returns Rexx SIGNALS IOException,NoSuchMethodException,IllegalAccessException,InvocationTargetException 
    if e\=exp then interpreter=null
    exp=e
    
    if interpreter=null then do
      termpgm='method term('i'=Rexx) static returns rexx;return' e
      fw=FileWriter("termpgm.nrx")
      fw.write(termpgm,0,termpgm.length)
      fw.close
      interpreter=NetRexxA()
      interpreter.parse([String 'termpgm.nrx'],[String 'nocrossref'])
      termClass=interpreter.getClassObject(null,'termpgm')
      classes=[interpreter.getClassObject('netrexx.lang', 'Rexx', 0)]
      termMethod=termClass.getMethod('term', classes)
    end
    
    return Rexx termMethod.invoke(null,[iv])

Nim

var i: int

proc harmonicSum(i: var int; lo, hi: int; term: proc: float): float =
  i = lo
  while i <= hi:
    result += term()
    inc i

echo harmonicSum(i, 1, 100, proc: float = 1 / i)
Output:
5.5.187377517639621

Objeck

bundle Default {
  class Jensens {
    i : static : Int;

    function : Sum(lo : Int, hi : Int, term : () ~ Float) ~ Float {
      temp := 0.0;

      for(i := lo; i <= hi; i += 1;) {
        temp += term();
      };

      return temp;
    }

    function : term() ~ Float {
      return 1.0 / i;
    }

    function : Main(args : String[]) ~ Nil {
      Sum(1, 100, term() ~ Float)->PrintLine();
    }
  }
}

Output: 5.18738

OCaml

let i = ref 42 (* initial value doesn't matter *)

let sum' i lo hi term =
  let result = ref 0. in
    i := lo;
    while !i <= hi do
      result := !result +. term ();
      incr i
    done;
    !result

let () =
  Printf.printf "%f\n" (sum' i 1 100 (fun () -> 1. /. float !i))

Output: 5.187378

Oforth

: mysum(lo, hi, term)  | i | 0 lo hi for: i [ i term perform + ] ;
Output:
mysum(1, 100, #inv) println
5.18737751763962

mysum(1, 100, #[ sq inv ]) println
1.63498390018489

Oz

Translation using mutable references and an anonymous function:

declare
  fun {Sum I Lo Hi Term}
     Temp = {NewCell 0.0}
  in
     I := Lo
     for while:@I =< Hi do
        Temp := @Temp + {Term}
        I := @I + 1
     end
     @Temp
  end
  I = {NewCell unit}
in
  {Show {Sum I 1 100 fun {$} 1.0 / {Int.toFloat @I} end}}

Idiomatic code:

declare
  fun {Sum Lo Hi F}
     {FoldL {Map {List.number Lo Hi 1} F} Number.'+' 0.0}
  end
in
  {Show {Sum 1 100 fun {$ I} 1.0/{Int.toFloat I} end}}

PARI/GP

GP does not have pass-by-reference semantics for user-generated functions, though some predefined functions do. PARI programming allows this, though such a solution would essentially be identical to the C solution above.

Pascal

program Jensens_Device;

{$IFDEF FPC}
  {$MODE objFPC}
{$ENDIF}

type
  tTerm = function(i: integer): real;

function term(i: integer): real;
begin
  term := 1 / i;
end;

function sum(var i: LongInt; lo, hi: integer; term: tTerm): real;
begin
  result := 0;
  i := lo;
  while i <= hi do
  begin
    result := result + term(i);
    inc(i);
  end;
end;

var
  i: LongInt;

begin
  writeln(sum(i, 1, 100, @term));
  {$IFNDEF UNIX}  readln; {$ENDIF}
end.

Out

 5.1873775176396206E+000

Perl

my $i;
sub sum {
    my ($i, $lo, $hi, $term) = @_; 
    my $temp = 0;
    for ($$i = $lo; $$i <= $hi; $$i++) {
        $temp += $term->();
    }
    return $temp;
}

print sum(\$i, 1, 100, sub { 1 / $i }), "\n";

Output: 5.18737751763962

Or you can take advantage of the fact that elements of the @_ are aliases of the original:

my $i;
sub sum {
    my (undef, $lo, $hi, $term) = @_; 
    my $temp = 0;
    for ($_[0] = $lo; $_[0] <= $hi; $_[0]++) {
        $temp += $term->();
    }
    return $temp;
}

print sum($i, 1, 100, sub { 1 / $i }), "\n";

Output: 5.18737751763962

Phix

Not really as asked for (implicit assumption replaced with explicit parameter) but this gives the required result.
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.
I wholeheartedly agree with the comment on the Clipper example.

with javascript_semantics
function sumr(integer lo, hi, rid)
    atom res = 0
    for i=lo to hi do
        res += rid(i)
    end for
    return res
end function
 
function reciprocal(atom i) return 1/i end function
 
?sumr(1, 100, reciprocal)
Output:
5.187377518

PHP

$i;
function sum (&$i, $lo, $hi, $term) {
    $temp = 0;
    for ($i = $lo; $i <= $hi; $i++) {
        $temp += $term();
    }
    return $temp;
}

echo sum($i, 1, 100, create_function('', 'global $i; return 1 / $i;')), "\n";
//Output: 5.18737751764 (5.1873775176396)

function sum ($lo,$hi)
{
 $temp = 0;
 for ($i = $lo; $i <= $hi; $i++)
 {
  $temp += (1 / $i);
 }
 return $temp;
}
echo sum(1,100);

//Output: 5.1873775176396

PicoLisp

(scl 6)

(de jensen (I Lo Hi Term)
   (let Temp 0
      (set I Lo)
      (while (>= Hi (val I))
         (inc 'Temp (Term))
         (inc I) )
      Temp ) )

(let I (box)  # Create indirect reference
   (format
      (jensen I 1 100 '(() (*/ 1.0 (val I))))
      *Scl ) )

Output:

-> "5.187383"

Python

class Ref(object):
    def __init__(self, value=None):
        self.value = value

def harmonic_sum(i, lo, hi, term):
    # term is passed by-name, and so is i
    temp = 0
    i.value = lo
    while i.value <= hi:  # Python "for" loop creates a distinct which
        temp += term() # would not be shared with the passed "i"
        i.value += 1   # Here the actual passed "i" is incremented.
    return temp

i = Ref()

# 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))
print harmonic_sum(i, 1, 100, lambda: 1.0/i.value)

or

def harmonic_sum(i, lo, hi, term):
    return sum(term() for i[0] in range(lo, hi + 1))
 
i = [0]
print(harmonic_sum(i, 1, 100, lambda: 1.0 / i[0]))

or

def harmonic_sum(i, lo, hi, term):
    return sum(eval(term) for i[0] in range(lo, hi + 1))
 
i = [0]
print(harmonic_sum(i, 1, 100, "1.0 / i[0]"))

Output: 5.18737751764

R

R uses a call by need evaluation strategy where function inputs are evaluated on demand and then cached; functions can bypass the normal argument evaluation by using functions substitute and match.call to access the parse tree of the as-yet-unevaluated arguments, and using parent.frame to access the scope of the caller. There are some proposed conventions to do this in a way that is less confusing to the user of a function; however, ignoring conventions we can come disturbingly close to the ALGOL call-by-name semantics.

sum <- function(var, lo, hi, term)
  eval(substitute({
    .temp <- 0;
    for (var in lo:hi) {
      .temp <- .temp + term
    }
    .temp
  }, as.list(match.call()[-1])),
  enclos=parent.frame())

sum(i, 1, 100, 1/i) #prints 5.187378

##and because of enclos=parent.frame(), the term can involve variables in the caller's scope:
x <- -1
sum(i, 1, 100, i^x) #5.187378

Racket

Racket happens to have an Algol 60-language, so Jensen's Device can be written just as Jørn Jensen did at Regnecentralen.

#lang algol60
begin
   integer i;
   real procedure sum (i, lo, hi, term);
      value lo, hi;
      integer i, lo, hi;
      real term;
      comment term is passed by-name, and so is i;
   begin
      real temp;
      temp := 0;
      for i := lo step 1 until hi do
         temp := temp + term;
      sum := temp
   end;
   comment note the correspondence between the mathematical notation and the call to sum;
   printnln (sum (i, 1, 100, 1/i))
end

But of course you can also use the more boring popular alternative of first class functions:

#lang racket/base
(define (sum lo hi f)
  (for/sum ([i (in-range lo (add1 hi))]) (f i)))
(sum 1 100 (λ(i) (/ 1.0 i)))

Raku

(formerly Perl 6)

Rather than playing tricks like Perl 5 does, the declarations of the formal parameters are quite straightforward in Raku:

sub sum($i is rw, $lo, $hi, &term) {
    my $temp = 0;
    loop ($i = $lo; $i <= $hi; $i++) {
        $temp += term;
    }
    return $temp;
}

my $i;
say sum $i, 1, 100, { 1 / $i };

Note that the C-style "for" loop is pronounced "loop" in Raku, and is the only loop statement that actually requires parens.

Rascal

public num Jenssen(int lo, int hi, num (int i) term){
	temp = 0;
	while (lo <= hi){
		temp += term(lo);
		lo += 1;}
	return temp;
}

With as output:

rascal>Jenssen(1, 100, num(int i){return 1.0/i;})
num: 5.18737751763962026080511767565825315790897212670845165317653395662

REXX

/*REXX program demonstrates  Jensen's device  (via call subroutine,  and args by name). */
parse arg d .                                    /*obtain optional argument from the CL.*/
if d=='' | d==","  then d= 100                   /*Not specified?  Then use the default.*/
numeric digits d                                 /*use  D  decimal digits (9 is default)*/
say 'using '    d    " decimal digits:"          /*display what's being used for digits.*/
say
say  sum( i,  1,  100,  "1/i" )                  /*invoke  SUM  (100th harmonic number).*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
sum: procedure;   parse arg j,start,finish,exp;               $= 0

     interpret  'do'   j   "="   start   'to'   finish   ";   $=$+"   exp   ';   end'

 /*comment      ────   ═   ───   ═════   ────   ══════   ──────────   ═══   ─────────   */
 /*comment       lit  var  lit    var     lit     var      literal    var    literal    */

     return $
output   when using the default input:
using  100  decimal digits:

5.187377517639620260805117675658253157908972126708451653176533956587219557532550496605687768923120415
output   when using the input:   1000


(Shown at three-quarter size   and   with   200   characters per line.)

using  1000  decimal digits:

5.187377517639620260805117675658253157908972126708451653176533956587219557532550496605687768923120413552951372900080959485764334902003859251284547479399606488677719356437701034351417501628003612133813
93634033610397170258150385609229760925775852490242015786454123413833660918987060275907253504512582948807527866739590394714709377905509971663909084580816222756304901297019081913723833776150679344482592
19985786828216280140988475651174867766685160764730429716983310052063466701008405663630740646670436720827975050329078640945579952223172461998152578702106818073281191723171032278163615245743308956980821
10786794204451169328900410057940565163334352244388766863157323818250401277131246550164879348955299573048040410736739783727083287179928615106959660501145265658411572959372901925824344377263363761945330
17905075097606740175205276891748232922334187250177881689092871712673549165589217457070884105311065936887252732260150280756519586504475363590572034459636088593436136141078274322996362525543164325745468
2

Ring

# Project : Jensen's Device

decimals(14)
i = 100
see sum(i,1,100,"1/n") + nl

func sum(i,lo,hi,term)
        temp = 0
        for n = lo to hi step 1
             eval("num = " + term)
             temp = temp + num
        next
        return temp

Output:

5.18737751763962

RPL

Works with: Halcyon Calc version 4.2.7
≪ → idx lo hi term
  ≪ lo idx STO 0
    DO
       term EVAL +
       1 idx STO+
    UNTIL idx EVAL hi > END
    idx PURGE
  ≫ 
≫
‘SUM’ STO

'K' 1 100 '1/K' SUM
'N' 0 100 '1/FACT(N)' SUM
Output:
2: 5.18737751764
1: 2.71828182846

Ruby

Here, setting the variable and evaluating the term are truly executed in the "outer" context:

def sum(var, lo, hi, term, context)
  sum = 0.0
  lo.upto(hi) do |n|
    sum += eval "#{var} = #{n}; #{term}", context
  end
  sum
end
p sum "i", 1, 100, "1.0 / i", binding   # => 5.18737751763962

But here is the Ruby way to do it:

def sum2(lo, hi)
  lo.upto(hi).inject(0.0) {|sum, n| sum += yield n}
end
p sum2(1, 100) {|i| 1.0/i}  # => 5.18737751763962

Even more concise: (requires ruby >= 2.4)

def sum lo, hi, &term
  (lo..hi).sum(&term)
end
p sum(1,100){|i| 1.0/i}   # => 5.187377517639621
# or using Rational:
p sum(1,100){|i| Rational(1,i)}  # => 14466636279520351160221518043104131447711 / 2788815009188499086581352357412492142272

Rust

use std::f32;

fn harmonic_sum<F>(lo: usize, hi: usize, term: F) -> f32
where
    F: Fn(f32) -> f32,
{
    (lo..hi + 1).fold(0.0, |acc, item| acc + term(item as f32))
}

fn main() {
    println!("{}", harmonic_sum(1, 100, |i| 1.0 / i));
}
Output:
5.187378

Scala

Actually, the i parameter needs to be passed by reference, as done in so many examples here, so that changes made to it reflect on the parameter that was passed. Scala supports passing parameters by name, but not by reference, which means it can't change the value of any parameter passed. The code below gets around that by creating a mutable integer class, which is effectively the same as passing by reference.

class MyInt { var i: Int = _ }
val i = new MyInt
def sum(i: MyInt, lo: Int, hi: Int, term: => Double) = {
  var temp = 0.0
  i.i = lo
  while(i.i <= hi) {
    temp = temp + term
    i.i += 1
  }
  temp
}
sum(i, 1, 100, 1.0 / i.i)

Result:

res2: Double = 5.187377517639621

Scheme

Scheme procedures do not support call-by-name. Scheme macros, however, do:

(define-syntax sum
  (syntax-rules ()
    ((sum var low high . body)
     (let loop ((var low)
                (result 0))
       (if (> var high)
           result
           (loop (+ var 1)
                 (+ result . body)))))))
(exact->inexact (sum i 1 100 (/ 1 i)))
5.18737751763962

Seed7

Seed7 supports call-by-name with function parameters:

$ include "seed7_05.s7i";
  include "float.s7i";

var integer: i is 0;

const func float: sum (inout integer: i, in integer: lo, in integer: hi,
    ref func float: term) is func
  result
    var float: sum is 0.0
  begin
    for i range lo to hi do
      sum +:= term;
    end for;
  end func;

const proc: main is func
  begin
   writeln(sum(i, 1, 100, 1.0/flt(i)) digits 6);
  end func;

Output:

5.187378

Sidef

var i
func sum (i, lo, hi, term) {
    var temp = 0
    for (*i = lo; *i <= hi; (*i)++) {
        temp += term.run
    }
    return temp
}
say sum(\i, 1, 100, { 1 / i })
Output:
5.18737751763962026080511767565825315790897212671

Simula

Translation of: algol60
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.

comment Jensen's Device;
begin
   integer i;
   real procedure sum (i, lo, hi, term);
      name i, term;
      value lo, hi;
      integer i, lo, hi;
      real term;
      comment term is passed by-name, and so is i;
   begin
      integer j;
      real temp;
      temp := 0;
      for j := lo step 1 until hi do
      begin
         i := j;
         temp := temp + term
      end;
      sum := temp
   end;
   comment note the correspondence between the mathematical notation and the call to sum;
   outreal (sum (i, 1, 100, 1/i), 7, 14)
end
Output:
 5.187378&+000  

Standard ML

val i = ref 42 (* initial value doesn't matter *)

fun sum' (i, lo, hi, term) = let
  val result = ref 0.0
in
  i := lo;
  while !i <= hi do (
    result := !result + term ();
    i := !i + 1
  );
  !result
end

val () =
  print (Real.toString (sum' (i, 1, 100, fn () => 1.0 / real (!i))) ^ "\n")

Output: 5.18737751764

Swift

var i = 42 // initial value doesn't matter

func sum(inout i: Int, lo: Int, hi: Int, @autoclosure term: () -> Double) -> Double {
  var result = 0.0
  for i = lo; i <= hi; i++ {
    result += term()
  }
  return result
}

println(sum(&i, 1, 100, 1 / Double(i)))

(Prior to Swift 1.2, replace @autoclosure term: () -> Double with term: @autoclosure () -> Double.)

Output:
5.187378

Tcl

Here, we set the value of the passed variable in the caller's frame. We then evaluate the passed term there too.

proc sum {var lo hi term} {
    upvar 1 $var x
    set sum 0.0
    for {set x $lo} {$x < $hi} {incr x} {
        set sum [expr {$sum + [uplevel 1 [list expr $term]]}]
    }
    return $sum
}
puts [sum i 1 100 {1.0/$i}] ;# 5.177377517639621

However, the solution is expressed more simply like this

proc sum2 {lo hi lambda} {
    set sum 0.0
    for {set n $lo} {$n < $hi} {incr n} {
        set sum [expr {$sum + [apply $lambda $n]}]
    }
    return $sum
}
puts [sum2 1 100 {i {expr {1.0/$i}}}] ;# 5.177377517639621

VBA

Private Function sum(i As String, ByVal lo As Integer, ByVal hi As Integer, term As String) As Double
    Dim temp As Double
    For k = lo To hi
        temp = temp + Evaluate(Replace(term, i, k))
    Next k
    sum = temp
End Function
Sub Jensen_Device()
    Debug.Print sum("i", 1, 100, "1/i")
    Debug.Print sum("i", 1, 100, "i*i")
    Debug.Print sum("j", 1, 100, "sin(j)")
End Sub
Output:
 5,18737751763962 
 338350 
-0,12717101366042

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.

class Box {
    construct new(v) { _v = v }
    v { _v }
    v=(value) { _v = value }
}

var i = Box.new(0)  // any initial value will do here

var sum = Fn.new { |i, lo, hi, term|
    var temp = 0
    i.v = lo
    while (i.v <= hi) {
        temp = temp + term.call()
        i.v = i.v + 1
    }
    return temp
}

var s = sum.call(i, 1, 100, Fn.new { 1/i.v })
System.print(s)
Output:
5.1873775176396

zkl

zkl doesn't support call by name/address but does have reference objects. Using an explicit call to term:

fcn sum(ri, lo,hi, term){
   temp:=0.0; ri.set(lo);
   do{ temp+=term(ri); } while(ri.inc()<hi); // inc return previous value
   return(temp);
}
sum(Ref(0), 1,100, fcn(ri){ 1.0/ri.value }).println();

Using function application/deferred(lazy) objects, we can make the function call implicit (addition forces evaluation of the LHS):

fcn sum2(ri, lo,hi, term){
   temp:=0.0; ri.set(lo);
   do{ temp=term + temp; } while(ri.inc()<hi); // inc return previous value
   return(temp);
}
ri:=Ref(0);
sum2(ri, 1,100, 'wrap(){ 1.0/ri.value }).println();

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:

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();
Output:
5.187378
5.187378
5.187378