Jensen's Device

Revision as of 21:11, 21 November 2008 by rosettacode>NevilleDNZ (From: [http://en.wikipedia.org/wiki/Jensen%27s_device])
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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)

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

Task
Jensen's Device
You are encouraged to solve this task according to the task description, using any language you may know.

The following program was proposed to illustrate the technique. It computes the 100th 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 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, otherwise it would not be possible to compute 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.

ALGOL 68

BEGIN
   INT i;
   PROC sum  = (REF INT ref i, INT lo, hi, PROC REAL term)REAL:
      COMMENT term is passed by-name, and so is i COMMENT
   BEGIN
      REAL temp;
      temp := 0;
      FOR i FROM lo BY 1 TO hi DO
         ref i := i;
         temp := temp + term
      OD;
      # sum := # 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

Python

<python>class Ref(object):

 def __init__(self, value=None):
   self.value=value

i = Ref() def sum(ref_i, lo, hi, term):

  # term is passed by-name, and so is i #
  temp = 0;
  for i in range(lo,hi+1):
     ref_i.value = i;
     temp = temp + term()
  return  temp
  1. note the correspondence between the mathematical notation and the call to sum #

print (sum (i, 1, 100, lambda: 1.0/i.value))</python> Output: 5.18737751764