Jensen's Device owes its name to Kathleen Jensen, co-author with Niklaus Wirth of the Pascal User Manual and Report.

Jensen's Device came about through a creative interpretation of the Algol 60 programming language standard as it was being defined.

The standard set about defining calling conventions for procedures. In this, there were two parameter passing mechanisms:

  • By value
    Expressions are evaluated, and the values are assigned to the formal parameter variables. You are permitted to change the formal parameters inside the procedure, but this has no effect on the caller's environment.
  • By name
    The parameter is evaluated in the context where it is used in the calling code. The variable may be referred to inside the procedure as an lvalue or rvalue.

The subtleties of pass by name were overlooked by early language implementers, and it was only when Jensen's device was published, that they realised that extra effort was required to implement the Algol 60 standard as written. The subsequent implementations usually involved passing a parse tree, with extra semantics for when this is interpreted as lvalue and rvalue. A more tidy way of achieving the same thing is to use a "thunk" or closure.

Jensen's Device fell into disrepute, being slated as obfuscation and leading to misunderstandings and buggy code. None of the successor languages of Algol 60, apart from Algol W, had pass by name. They adopted pass by reference, which was in widespread use in Fortran. However, the Ruby language has full scale calling by name, and implements Jensen's Device (but calls this an iterator).

Jensen's Device example


begin
    comment This is a simple example of Jensen's device;

    comment This takes the sum of expr from lo to hi, inclusive.
        The variable index is incremented through the range.;

    real procedure sum(lo, hi, index, expr);
        value lo, hi;
        integer lo, hi, index;
        real expr;
        begin
            real accum;

            comment initialize accum to zero and add the terms.;
            accum := 0.0;
            for index := lo step 1 until hi do begin
                accum := accum + expr
            end;

            sum := accum
        end;

    begin
        comment Sum of integers, 1 to 20.;
        integer i;
        outreal(1, sum(1, 20, i, i));
        outstring(1, "\n");
    end;

    begin
        comment sum of 10 die rolls;
        integer i;
        outreal(1, sum(1, 10, i, rand MOD 6));
        outstring(1, "\n");
    end;
	
    begin
        comment mean and variance;
        real array data[10];
        integer i;
        real mean, sumd, sumsq;
        for i:=1 step 1 until 10 do
            readreal(2, data[i]);
        sumd = sum(1, 10, i, data[i]);
        sumsq = sum(1, 10, i, data[i]*data[i]);
        outstring(1, "Mean is: ");
        mean = sumd / 10.0;
        outreal(1, mean );
        outstring(1, "Variance is :");
        outreal(1, sumsq / 10.0 - mean * mean);
    end
end

Log in or register to write something here or to contact authors.