[comp.lang.smalltalk] Block variables

franka@mmintl.UUCP (04/03/87)

[Not food]

What is the proper scope for the name of a variable which is a block
argument?  I had assumed it was the block only, but Smalltalk/V treats it as
the entire method.  Is this a bug?

As an example of what I mean, consider the following:

In UndefinedObject, define:

test
    | x |
    x := 3.
    ^Array with: [ :x | x + 1] with: [x]

Now evaluate:

| temp |
temp := nil test.
(temp at: 1) value: 7.
(temp at: 2) value

Should the result be 3 or 7?

(I am using ":=" as the assignment operator, as Smalltalk/V does.)

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Ashton-Tate          52 Oakland Ave North         E. Hartford, CT 06108

rentsch@unc.UUCP (04/05/87)

In article <2084@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes:
> What is the proper scope for the name of a variable which is a block
> argument?  I had assumed it was the block only, but Smalltalk/V treats it as
> the entire method.  Is this a bug?

The Smalltalk/V treatment is the same as that used by Smalltalk-80
(i.e., block argument is really a local variable in the containing
method).  The semantics of Smalltalk/V agrees with Smalltalk-80 (and
thus is arguably not a "bug").



> In UndefinedObject, define:
> 
> test
>     | x |
>     x := 3.
>     ^Array with: [ :x | x + 1] with: [x]
> 
> Now evaluate:
> 
> | temp |
> temp := nil test.
> (temp at: 1) value: 7.
> (temp at: 2) value
> 
> Should the result be 3 or 7?
> 
> (I am using ":=" as the assignment operator, as Smalltalk/V does.)

The result should be 7 by Smalltalk-80 semantics.  Here is an
equivalent, but simpler, version of the same test:

	| x |
	x := 3.
	[ :x | nil ] value: 7.
	x

(select and choose 'print it' [or is it 'show it' in Smalltalk/V?].)
Result will be 7, not 3.  (Note the "nil" returned from the block is
ignored, and the block could have been written "[ :x ]" with
equivalent effect.)

I agree, by the way, that these semantics are neither intuitive nor
particularly desireable.  This problem is magnified for nested
blocks;  consider for example

	1 to: thing xDimension do: [ :i |
		1 to: thing yDimension do: [ :j |
			(thing at: i@j) whatever: i@j ] ].

If the body of the inner loop is thought to be expensive and worth a
new process for every j (e.g., "1 to: thing yDimension parallelDo:",
etc.), the various processes will interact deleteriously because
there is really only ONE j.  (For that matter, the same comments
apply to the outer loop and i;  for some reason, I see the
non-block-structureness as a clearer example of the problem in the
inner block.)

In spite of the name, blocks in Smalltalk (either -80 or /V) do not
have block structure (either in terms of scope or in terms of
variable lifetime) as Algol-60 defines it.  It would be nice if this
deficiency could be remedied, but it is difficult given the current
Smalltalk-80 virtual machine architecture (which puts block locals
in the home context).

cheers, and Happy Smalltalking,

txr

johnson@uiucdcsp.UUCP (04/06/87)

Smalltalk-80 defines block arguments the same way.  A block argument
is really just a temporary variable. In fact, the following method

foo
    [:t| 3] value: 4.
    ^t

not only compiles, it returns 4.  This is not a bug in the compiler,
though it may well be considered to be a bug in the language.  The
language was defined this way for performance reasons (evaluating a block
does not have to create a new context) but it is definitely counterintuitive.
It will probably be changed someday.