block closures
Author Message
block closures

Quote:
>From what I have read, Smalltalk inherited his blocks from LISP. So, if
>somebody is out there with a knowledge of both Smalltalk and LISP:
>- Is there an equivalent to a Smalltalk expression like:
>  (a < 0) ifTrue: [a := 0].
>- If yes, what would this LISP equivalent look like ?

I'm not really an expert on Smalltalk, but that expression looks pretty
obvious to me and I think the Lisp equivalent is:

(if (< a 0) (setq a 0))
--
Barry Margolin
BBN Corporation, Cambridge, MA

(BBN customers, call (800) 632-7638 option 1 for support)

Sun, 19 Sep 1999 03:00:00 GMT
block closures

Quote:

> From what I have read, Smalltalk inherited his blocks from LISP. So, if
> somebody is out there with a knowledge of both Smalltalk and LISP:
> - Is there an equivalent to a Smalltalk expression like:
>   (a < 0) ifTrue: [a := 0].

Yes and no. The above code is a contortion ST is forced into by its
commitment to 'all-objects-all-the-time'. Thru CLOS we could in Lisp do
the same (see below), but would normally write:

(when (< a 0) (setf a 0))

No need for a closure (ST block). You need the block in ST so you can
send it along for execution to the boolean (a<0) with the message
#iftrue:.

Quote:
> - If yes, what would this LISP equivalent look like ?

God my Lisp has gotten rusty after five months of VAX Basic! :( Anyway,
roughly:

(defclass boolean ()
((value :accessor value :initarg value))))

(defmethod ifTrue ((aBool boolean) justDoIt)
(when (value aBool) (funcall justDoIt)))

...then...

(ifTrue (make-instance 'boolean :value (< a 0)) #'(lambda() (setf a 0)))

Pretty silly, but again, ST uses a block to achieve the classic "if"
statement out of religious fervor (IMHO), as in its all-objects policy.

I think many a good idea has failed becuase the inventor got e{*filter*}d and
said, Hey, let's use this for /everything/.

Let the flames begin. <G>

ken

Sun, 19 Sep 1999 03:00:00 GMT
block closures

Quote:

> >From what I have read, Smalltalk inherited his blocks from LISP. So, if
> >somebody is out there with a knowledge of both Smalltalk and LISP:
> >- Is there an equivalent to a Smalltalk expression like:
> >  (a < 0) ifTrue: [a := 0].
> >- If yes, what would this LISP equivalent look like ?

> I'm not really an expert on Smalltalk, but that expression looks pretty
> obvious to me and I think the Lisp equivalent is:

> (if (< a 0) (setq a 0))

Yes and no.  In practice, it is equivalent. However, the
block following the ifTrue: is (in principle) a closure
that gets passed as an argument to the ifTrue: method,
which is a difference.  Smalltalk compilers often inline
the ifTrue:, though, so even that difference means little.

~~~~~~~~~~~~~~~~~~~~~~

Texas liaison for the International Programmers Guild
For information on IPG, see http://www.ipgnet.com/ipghome.htm

Sun, 19 Sep 1999 03:00:00 GMT
block closures

From what I have read, Smalltalk inherited his blocks from LISP. So, if
somebody is out there with a knowledge of both Smalltalk and LISP:
- Is there an equivalent to a Smalltalk expression like:
(a < 0) ifTrue: [a := 0].
- If yes, what would this LISP equivalent look like ?
- What are the differences in the semantics ?

**********************************************************************

* Bahnhofstr.7                                     using OS/2 Warp 4 *
* D-52064 Aachen                             - standard disclaimer - *
**********************************************************************

Sun, 19 Sep 1999 03:00:00 GMT
block closures

Quote:

> Pretty silly, but again, ST uses a block to achieve the classic "if"
> statement out of religious fervor (IMHO), as in its all-objects policy.

> I think many a good idea has failed becuase the inventor got e{*filter*}d and
> said, Hey, let's use this for /everything/.

What do you think is the downside of an 'all-objects policy'?

....Mike

Mon, 20 Sep 1999 03:00:00 GMT
block closures

: From what I have read, Smalltalk inherited his blocks from LISP. So, if
: somebody is out there with a knowledge of both Smalltalk and LISP:
: - Is there an equivalent to a Smalltalk expression like:
:   (a < 0) ifTrue: [a := 0].
: - If yes, what would this LISP equivalent look like ?

Yet speaking of Smalltalk, I prefer to write such things as

a := 0 max: a.

--Vassili

Mon, 20 Sep 1999 03:00:00 GMT
block closures

Quote:

> > Pretty silly, but again, ST uses a block to achieve the classic "if"
> > statement out of religious fervor (IMHO), as in its all-objects policy.

> > I think many a good idea has failed becuase the inventor got e{*filter*}d and
> > said, Hey, let's use this for /everything/.

> What do you think is the downside of an 'all-objects policy'?

It allowed C++ and Java to proliferate by people who can't handle the fact
that everything IS an object.

(Oh yes, I forgot the little ----> :-)

: Bytesmiths < http://www.*-*-*.com/ >
: Java, the elegant simplicity of C++ and the blazing speed of Smalltalk.

Mon, 20 Sep 1999 03:00:00 GMT
block closures

Quote:
>From what I have read, Smalltalk inherited his blocks from LISP. So, if
>somebody is out there with a knowledge of both Smalltalk and LISP:
>- Is there an equivalent to a Smalltalk expression like:
>  (a < 0) ifTrue: [a := 0].
>- If yes, what would this LISP equivalent look like ?

(if (< a 0) (setq a 0))

However, neither Smalltalk nor Lisp use real block closures here. Smalltalk
optimizes the ifTrue: method inside the compiler (but has still the same
semantic). Lisp uses a special form "if" which prevents the evaluation of
the "then" argument, if the condition isn't true. A better equivalent would
be (if I remember the definition of CLOS methods right)

(defmethod ifTrue ((condition nil) block)
(block))

(defmethod ifTrue ((condition T) block)
nil)

(ifTrue (< a 0) (lambda () (setq a 0))

This has exactly the same semantic.

Quote:
>- What are the differences in the semantics ?

Lisp's if expression is a special form and doesn't use method sending.
Otherwise, Lisp's lambda expressions (using only lexically bound variables)
have the same semantic as Smalltalk block closures as provided by most
Smalltalk implementations.

bye

Mon, 20 Sep 1999 03:00:00 GMT
block closures

Quote:

> From what I have read, Smalltalk inherited his blocks from LISP. So, if
> somebody is out there with a knowledge of both Smalltalk and LISP:
> - Is there an equivalent to a Smalltalk expression like:
>   (a < 0) ifTrue: [a := 0].
> - If yes, what would this LISP equivalent look like ?
> - What are the differences in the semantics ?

With a little macrology you can do things like:

? (define-modify-macro maxf (&optional (arg 0)) max)

Use it:

? (maxf a)

What it does:

? (macroexpand '(maxf a))
(SETQ A (MAX A 0))

;-)

--
http://www.lavielle.com/~joswig/

Mon, 20 Sep 1999 03:00:00 GMT
block closures

Quote:

> ....
> Lisp's if expression is a special form and doesn't use method sending.
> Otherwise, Lisp's lambda expressions (using only lexically bound variables)
> have the same semantic as Smalltalk block closures as provided by most
> Smalltalk implementations.

Not exactly.  In particular, an explicit return from a
Smalltalk block is defined as a return from the defining
method of the block, whereas a (return) in a Common Lisp
closure is a return from the closure itself.  (Common Lisp
also provides a mechanism to specify a return from specific
enclosing contexts by name, which Smalltalk lacks.)  This
difference has nothing much to do with the ifTrue:/(if ...)
example, but it does reflect a limitation of Smalltalk in
dealing with a block which may be invoked outside of the
context of the method in which it is defined.

In this sense, Smalltalk blocks do not behave as first-class
objects.

--

Icon Computing               http://www.iconcomp.com
Texas liaison for the International Programmers Guild
For IPG info, see http://www.ipgnet.com/ipghome.htm

Tue, 21 Sep 1999 03:00:00 GMT
block closures

Quote:

> > ....
> > Lisp's if expression is a special form and doesn't use method sending.
> > Otherwise, Lisp's lambda expressions (using only lexically bound variables)
> > have the same semantic as Smalltalk block closures as provided by most
> > Smalltalk implementations.

> Not exactly.  In particular, an explicit return from a
> Smalltalk block is defined as a return from the defining
> method of the block, whereas a (return) in a Common Lisp
> closure is a return from the closure itself.  (Common Lisp
> also provides a mechanism to specify a return from specific
> enclosing contexts by name, which Smalltalk lacks.)  This
> difference has nothing much to do with the ifTrue:/(if ...)
> example, but it does reflect a limitation of Smalltalk in
> dealing with a block which may be invoked outside of the
> context of the method in which it is defined.

> In this sense, Smalltalk blocks do not behave as first-class
> objects.

Nonsense! ( :) ) Smalltalk blocks _can_ return from a block
as well as return from a block's enclosing method.  How does
the following work otherwise:

(1 to: 10) select: [:n| n even]

i.e. [:n| n even] is returning to the select method after each
activation.

its enclosing method.  But there's lots of mechanism around to
do it.

e.g.

someMethod: someCollection
| exitSignal result |
exitSignal := Signal new.
. . .
result := exitSignal
handle: [:ex| ex returnWith: #negative]
do: [someCollection select:
[:elem|
elem isInfinite ifTrue: [^#infinte].
elem negative ifTrue: [exitSignal raise].
elem even].
. . .

which returns #infinite to the sender of someMethod: when an
infinite element is encountered before a negative one in someCollection,
and assigns #negative to result when a negative value is encountered
before an infinite one in someCollecion, and otherwise assigns the
even elements in someCollection to result.

There are also numerous ways of writing the following style:

BlockClosure methods for evaluating
valueWithExit
^self value: [:exitValue| ^exitValue]

someMethod: someCollection
| exitSignal result |
exitSignal := Signal new.
. . .
result := [:exit| someCollection select:
[:elem|
elem isInfinite ifTrue: [^#infinte].
elem negative ifTrue: [exit value: #negative].
elem even]] valueWithExit.
. . .

which has the same effect as the above.

And in what sense do these behaviours imply that Smalltalk closures
are not first class objects?  First-class refers to the ability to
a) pass closures around as freely as any other objects
b) the ability to define methods on closures as any other objects
Smalltalk provides both of these.

Which begs the question are closures in CLOS objects?  I don't know,
but CLOS, being an impure language (unlike Smalltalk and Dylan), may
not make closures objects.  If so, it is CLOS which lacks first-class
closures and not Smalltalk.
_______________,,,^..^,,,_______________
Eliot Miranda, ObjectEngine technical lead, ParcPlace-Digitalk

Tue, 21 Sep 1999 03:00:00 GMT
block closures

and I forgot to say that the use of raise and return in

Quote:
> someMethod: someCollection
>     | exitSignal result |
>     exitSignal := Signal new.
>     . . .
>     result := exitSignal
>                 handle: [:ex| ex returnWith: #negative]
>                 do: [someCollection select:
>                         [:elem|
>                         elem isInfinite ifTrue: [^#infinte].
>                         elem negative ifTrue: [exitSignal raise].
>                         elem even].
>     . . .

is exactly analogous to Lisp's catch and throw (which pre-dates CLOS).

and I also forgot to include

Quote:
> And in what sense do these behaviours imply that Smalltalk closures
> are not first class objects?  First-class refers to the ability to
> a) pass closures around as freely as any other objects
> b) the ability to define methods on closures as any other objects

c) define new subclasses of closures that define additonal
state/new methods etc

Quote:
> Smalltalk provides both of these.

Some Smalltalks (e.g. VW) provide all three, even if c) requires
creating a vanilla closure first.

_______________,,,^..^,,,_______________
Eliot Miranda, ObjectEngine technical lead, ParcPlace-Digitalk

Tue, 21 Sep 1999 03:00:00 GMT
block closures

Quote:

> > Not exactly.  In particular, an explicit return from a
> > Smalltalk block is defined as a return from the defining
> > method of the block, whereas a (return) in a Common Lisp
> > closure is a return from the closure itself.  (Common Lisp
> > also provides a mechanism to specify a return from specific
> > enclosing contexts by name, which Smalltalk lacks.)  This
> > difference has nothing much to do with the ifTrue:/(if ...)
> > example, but it does reflect a limitation of Smalltalk in
> > dealing with a block which may be invoked outside of the
> > context of the method in which it is defined.

> > In this sense, Smalltalk blocks do not behave as first-class
> > objects.

> Nonsense! ( :) ) Smalltalk blocks _can_ return from a block
> as well as return from a block's enclosing method.

Not via an explicit ^ return, as far as I know.  If
they can, none of your examples demonstrate this -
they all exhibit blocks which either complete without
doing an explicit return, or return directly from the
defining method.

Quote:
>  How does the following work otherwise:

>         (1 to: 10) select: [:n| n even]

This has no explicit return, nor is it an example of
a block which may be invoked outside the context of
the method in which it is defined (aka a block with
indefinite, as opposed to dynamic, extent).

Quote:
> ... Smalltalk provides no default syntax for a block to return to
> its enclosing method.  But there's lots of mechanism around to
> do it.

There is one mechanism that I know of: the block
completes without executing an explicit return, thus
returning the value of the last statement evaluated.
This is the *only* return mechanism that is valid in
a block which is executed outside the context of its
defining method, since any explicit return in that
case results in a runtime exception (due to trying to
return from a method context for a method which is
no longer on the execution stack).

Quote:
> ....
> someMethod: someCollection
>     | exitSignal result |
>     exitSignal := Signal new.
>     . . .
>     result := exitSignal
>                 handle: [:ex| ex returnWith: #negative]
>                 do: [someCollection select:
>                         [:elem|
>                         elem isInfinite ifTrue: [^#infinte].
>                         elem negative ifTrue: [exitSignal raise].
>                         elem even].
>     . . .

Again, this example does not show a block which is
executed outside of the context of its defining method,
and the explicit return of #infinte is a return from the
defining method, and not from the select: block.

Quote:
> There are also numerous ways of writing the following style:
>     . . .

> which has the same effect as the above.

Fine, whatever.  Try the following, which illustrates
my point:

defineBlock
^[ :arg | arg == #broken
ifTrue: [^#veryBroken]
ifFalse: [#allRightyThen] ].

testIt
| block result1 result2 |
block := self defineBlock.
result1 := block value: #fine.
result2 := block value: #broken.
^OrderedCollection with: result1 with: result2.

When you invoke #testIt, you'll get a walkback.

Quote:
> And in what sense do these behaviours imply that Smalltalk closures
> are not first class objects?  First-class refers to the ability to
> a) pass closures around as freely as any other objects
> b) the ability to define methods on closures as any other objects
> Smalltalk provides both of these.

True, although (a) entails the limitation (demonstrated
in the above example) that blocks which can be invoked
outside the context of their definition cannot use the
full Smalltalk syntax and behavior.  They are constrained
because they implicitly depend on the context of their
defining method, which they do not encapsulate.

Quote:
> Which begs the question are closures in CLOS objects?  I don't know,
> but CLOS, being an impure language (unlike Smalltalk and Dylan), may
> not make closures objects.  If so, it is CLOS which lacks first-class
> closures and not Smalltalk.

CLOS makes no pretense of "purity."  I could be wrong,
but I don't believe the standard requires that closures
be first-class CLOS objects.  However, CLOS implementa-
tions can make closures first-class without violating
the standard, and I believe that at least some implemen-
tations do so.

In any case, CL closures in any implementation of the
standard are far more powerful and flexible than Smalltalk
blocks.

Are we having fun yet?

--

Icon Computing               http://www.iconcomp.com
Texas liaison for the International Programmers Guild
For IPG info, see http://www.ipgnet.com/ipghome.htm

Tue, 21 Sep 1999 03:00:00 GMT
block closures

Quote:

> > ....
> > Lisp's if expression is a special form and doesn't use method sending.
> > Otherwise, Lisp's lambda expressions (using only lexically bound variables)
> > have the same semantic as Smalltalk block closures as provided by most
> > Smalltalk implementations.

> Not exactly.  In particular, an explicit return from a
> Smalltalk block is defined as a return from the defining
> method of the block, whereas a (return) in a Common Lisp
> closure is a return from the closure itself.  (Common Lisp
> also provides a mechanism to specify a return from specific
> enclosing contexts by name, which Smalltalk lacks.)  This
> difference has nothing much to do with the ifTrue:/(if ...)
> example, but it does reflect a limitation of Smalltalk in
> dealing with a block which may be invoked outside of the
> context of the method in which it is defined.

> In this sense, Smalltalk blocks do not behave as first-class
> objects.

Perhaps you mean that Smalltalk blocks are not first class **functions**
(or methods).  Because there can be no question that they are first
class **objects** (they have all the same capabilities and privileges
of any other object).

--
Alan L. Lovejoy         | Why Smalltalk?
Smalltalk Consultant    | Because I don't want to follow the crowd,

Tue, 21 Sep 1999 03:00:00 GMT
block closures

Quote:

> > > Not exactly.  In particular, an explicit return from a
> > > Smalltalk block is defined as a return from the defining
> > > method of the block, whereas a (return) in a Common Lisp
> > > closure is a return from the closure itself.  (Common Lisp
> > > also provides a mechanism to specify a return from specific
> > > enclosing contexts by name, which Smalltalk lacks.)  This
> > > difference has nothing much to do with the ifTrue:/(if ...)
> > > example, but it does reflect a limitation of Smalltalk in
> > > dealing with a block which may be invoked outside of the
> > > context of the method in which it is defined.

> > > In this sense, Smalltalk blocks do not behave as first-class
> > > objects.

> > Nonsense! ( :) ) Smalltalk blocks _can_ return from a block
> > as well as return from a block's enclosing method.

> Not via an explicit ^ return, as far as I know.  If
> they can, none of your examples demonstrate this -
> they all exhibit blocks which either complete without
> doing an explicit return, or return directly from the
> defining method.

^-return is defined to mean "return to the sender of the current method"
whether the point of execution is at the first level within the method,
or nested within the activation of some closure.  This is more
convenient
than have it mean "return to caller" for the majority of cases.  It is
also considered more consistent, since within any method ^-return means

My examples demonstrated how one can construct a mechanism which does
(including nesting).

You're confusing the restriction on the use of ^-return with an
non-existent restriction on being able to return to the caller of a
block.
^-return must be executed within the dynamic extent of the enclosing
method
for there to be a sender of the method to return to.  There is no such
restriction on returning to caller.

Appologies for not including an example that demonstrated a block
being used outside the dynamic extent of its enclosing method.
But you know that its possible; your example below illustrates it:

[snip]

- Show quoted text -

Quote:
> Fine, whatever.  Try the following, which illustrates
> my point:

> defineBlock
>  ^[ :arg | arg == #broken
>                ifTrue: [^#veryBroken]
>                ifFalse: [#allRightyThen] ].

> testIt
>  | block result1 result2 |
>  block := self defineBlock.
>  result1 := block value: #fine.
>  result2 := block value: #broken.
>  ^OrderedCollection with: result1 with: result2.

> When you invoke #testIt, you'll get a walkback.

Right.  Try doing the same thing in CLOS and you'll also get a
walk-back.
Of course, its harder to writem since CLOS provides no convenient syntax
for ^.  But then Smalltalk provides no convenient syntax for returning
to a caller from an arbitrary point in a block.  But this illustrates
a merely syntactic difference.

There's nothing to stop you doing

defineBlock
^[ :arg | arg == #broken
ifTrue: [#notBroken]
ifFalse: [#allRightyThen]].

testIt
| block result1 result2 |
block := self defineBlock.
result1 := block value: #fine.
result2 := block value: #broken.
^OrderedCollection with: result1 with: result2.

just as there's nothing to stop you writing

defineBlock
^[:arg|
[:exit|
arg == #broken ifTrue: [exit value: #notBroken].
#allRightyThen] valueWithExit]

its syntactically ugly, but it does what your CLOS closure can.

Quote:
> > And in what sense do these behaviours imply that Smalltalk closures
> > are not first class objects?  First-class refers to the ability to
> > a) pass closures around as freely as any other objects
> > b) the ability to define methods on closures as any other objects
> > Smalltalk provides both of these.

> True, although (a) entails the limitation (demonstrated
> in the above example) that blocks which can be invoked
> outside the context of their definition cannot use the
> full Smalltalk syntax and behavior.  They are constrained
> because they implicitly depend on the context of their
> defining method, which they do not encapsulate.

Wrong.

Quote:
> > Which begs the question are closures in CLOS objects?  I don't know,
> > but CLOS, being an impure language (unlike Smalltalk and Dylan), may
> > not make closures objects.  If so, it is CLOS which lacks first-class
> > closures and not Smalltalk.

> CLOS makes no pretense of "purity."  I could be wrong,
> but I don't believe the standard requires that closures
> be first-class CLOS objects.  However, CLOS implementa-
> tions can make closures first-class without violating
> the standard, and I believe that at least some implemen-
> tations do so.

> In any case, CL closures in any implementation of the
> standard are far more powerful and flexible than Smalltalk
> blocks.

How?  (they're not.  One can implement Lisp atop Smalltalk directly
mapping Lisp closures to Smalltalk blocks just as one can easily
do the converse.) They have the same semantic power.  CLOS lacks
syntax for Smalltalk-style ^-return.   Smalltalk lacks syntax
for CLOS's explicit return.  But both provide mechanism for
implementing the other.

Quote:
> Are we having fun yet?

Very much so.

P.S. The original Smalltalk-80 as described by Goldberg and Robson
also had indefinite extent blocks, but these were not full closures,
and were not re-entrant.  This limitation has been absent from all
major commercial implementations for some time.
_______________,,,^..^,,,_______________
Eliot Miranda, ObjectEngine technical lead, ParcPlace-Digitalk

Tue, 21 Sep 1999 03:00:00 GMT

 Page 1 of 2 [ 25 post ] Go to page: [1] [2]

Relevant Pages