Block.st
branchjv
changeset 20727 fb8c5591428b
parent 20579 9add81aadb7a
parent 20623 1f54b9dbfea2
child 21024 8734987eb5c7
--- a/Block.st	Wed Oct 12 07:05:13 2016 +0200
+++ b/Block.st	Tue Oct 25 12:31:42 2016 +0100
@@ -49,22 +49,52 @@
     is done by the compilers, when some sourceCode is compiled to either
     machine or byteCode.
 
+    In the code, blocks are written as:
+        [
+            expression1. 
+            ...
+            expressionN 
+        ]
+    It represents the computation inside the brackets,
+    and can be passed around as argument, assigned to variables or returned from a block or method.
+    Creation of a block does NOT evaluate its expressions. You have to give the block to someone,
+    who asks it to evaluate itself. This is done by sending #value to the block.
+    i.e.
+        foo := [ Transcript showCR:'Hello World'].
+        ...
+        foo value
+
+    Blocks are used in many many ways; one particular use is as callback:
+        |b|
+        
+        b := Button label:'Press me'.
+        b action:[ Transcript showCR:'Hello'].
+        b open.
+
     Blocks with arguments need a message of type ''value:arg1 ... value:argn''
     for evaluation; the number of arguments passed when evaluating must match
     the number of arguments the block was declared with otherwise an error is
-    raised. Blocks without args need a ''value'' message for evaluation.
-
-    Blocks keep a reference to the context where the block was declared -
+    raised. 
+    Blocks without args need a ''value'' message for evaluation.
+
+    another use of blocks is in the enumeration protocols:
+        |coll|
+
+        coll := #( 'one' 'two' 'three').
+        coll do:[:eachElement | Transcript showCR:eachElement ].
+    
+    Blocks keep a reference to the context where it was declared -
     this allows blocks to access the methods arguments and/or variables.
     This is still true after the method has returned - since the
     block keeps this reference, the methods context will NOT die in this case.
-    (i.e. Blocks are closures in Smalltalk/X)
+    (for experts: Smalltalk blocks are technically lambdas/closures)
 
     A return (via ^-statement) out of a block will force a return from the
-    blocks method context (if it is still living) - this make the implementation
-    of long-jumps and control structures possible.
-    (If the method is not alive (i.e. has already returned), a return out of the
-     block will trigger an error)
+    block's method context (if it is still living).
+    This is effectively a kind of long-jumps out of the method which declared the block
+    and makes control structures and loops possible.
+    If the method is not alive (i.e. has already returned), a return out of the
+    block will trigger an error.
 
     Long-jump is done by defining a catchBlock as ''[^ self]''
     somewhere up in the calling-tree. Then, to do the long-jump from out of some
@@ -73,30 +103,30 @@
     [Instance variables:]
 
       home        <Context>         the context where this block was created (i.e. defined)
-				    this may be a blockContext or a methodContext
+                                    this may be a blockContext or a methodContext
       nargs       <SmallInteger>    the number of arguments the block expects
       sourcePos   <SmallInteger>    the character position of its source, in chars
-				    relative to methods source beginning
+                                    relative to methods source beginning
       initialPC   <SmallInteger>    the start position within the byteCode
-				    for compiled blocks, this is nil.
+                                    for compiled blocks, this is nil.
 
 
     [Class variables:]
 
       InvalidNewSignal              raised if a Block is tried to be created
-				    with new (which is not allowed).
-				    Only the VM is allowed to create Blocks.
+                                    with new (which is not allowed).
+                                    Only the VM is allowed to create Blocks.
 
 
     NOTICE: layout known by runtime system and compiler - do not change
 
     [author:]
-	Claus Gittinger
+        Claus Gittinger
 
     [see also:]
-	Process Context
-	Collection
-	( contexts. blocks & unwinding : programming/contexts.html)
+        Process Context
+        Collection
+        ( contexts. blocks & unwinding : programming/contexts.html)
 "
 !
 
@@ -678,7 +708,6 @@
     "Created: / 28-08-2010 / 14:41:15 / cg"
 ! !
 
-
 !Block methodsFor:'accessing'!
 
 home
@@ -1042,6 +1071,105 @@
     "
 !
 
+value:arg1 optionalArgument:arg2 and:arg3 and:arg4
+    "evaluate the receiver.
+     Optionally pass up one, two, three or four arguments 
+     (if the receiver is a 1/2/3/4-arg block)."
+
+    nargs == 4 ifTrue:[
+        ^ self value:arg1 value:arg2 value:arg3 value:arg4
+    ].
+    nargs == 3 ifTrue:[
+        ^ self value:arg1 value:arg2 value:arg3
+    ].
+    nargs == 2 ifTrue:[
+        ^ self value:arg1 value:arg2
+    ].
+    ^ self value:arg1
+
+    "
+     |block|
+
+     block := [:arg | Transcript showCR:arg ].
+     block value:1 optionalArgument:2 and:3 and:4.
+
+     block := [:arg1 :arg2 | Transcript show:arg1; space; showCR:arg2 ].
+     block value:1 optionalArgument:2 and:3 and:4.
+
+     block := [:arg1 :arg2 :arg3 :arg4 | Transcript showCR:{arg1 . arg2 . arg3 . arg4}].
+     block value:1 optionalArgument:2 and:3 and:4.
+    "
+!
+
+value:arg1 optionalArgument:arg2 and:arg3 and:arg4 and:arg5
+    "evaluate the receiver.
+     Optionally pass up five arguments 
+     (if the receiver is a 1..5-arg block)."
+
+    nargs == 5 ifTrue:[
+        ^ self value:arg1 value:arg2 value:arg3 value:arg4 value:arg5
+    ].
+    nargs == 4 ifTrue:[
+        ^ self value:arg1 value:arg2 value:arg3 value:arg4
+    ].
+    nargs == 3 ifTrue:[
+        ^ self value:arg1 value:arg2 value:arg3
+    ].
+    nargs == 2 ifTrue:[
+        ^ self value:arg1 value:arg2
+    ].
+    ^ self value:arg1
+
+    "
+     |block|
+
+     block := [:arg | Transcript showCR:arg ].
+     block value:1 optionalArgument:2 and:3 and:4 and:5.
+
+     block := [:arg1 :arg2 | Transcript show:arg1; space; showCR:arg2 ].
+     block value:1 optionalArgument:2 and:3 and:4 and:5.
+
+     block := [:arg1 :arg2 :arg3 :arg4 :arg5 | Transcript showCR:{arg1 . arg2 . arg3 . arg4 . arg5}].
+     block value:1 optionalArgument:2 and:3 and:4 and:5.
+    "
+!
+
+value:arg1 optionalArgument:arg2 and:arg3 and:arg4 and:arg5 and:arg6
+    "evaluate the receiver.
+     Optionally pass up six arguments 
+     (if the receiver is a 1..6-arg block)."
+
+    nargs == 6 ifTrue:[
+        ^ self value:arg1 value:arg2 value:arg3 value:arg4 value:arg5 value:arg6
+    ].
+    nargs == 5 ifTrue:[
+        ^ self value:arg1 value:arg2 value:arg3 value:arg4 value:arg5
+    ].
+    nargs == 4 ifTrue:[
+        ^ self value:arg1 value:arg2 value:arg3 value:arg4
+    ].
+    nargs == 3 ifTrue:[
+        ^ self value:arg1 value:arg2 value:arg3
+    ].
+    nargs == 2 ifTrue:[
+        ^ self value:arg1 value:arg2
+    ].
+    ^ self value:arg1
+
+    "
+     |block|
+
+     block := [:arg | Transcript showCR:arg ].
+     block value:1 optionalArgument:2 and:3 and:4 and:5 and:6.
+
+     block := [:arg1 :arg2 | Transcript show:arg1; space; showCR:arg2 ].
+     block value:1 optionalArgument:2 and:3 and:4 and:5 and:6.
+
+     block := [:arg1 :arg2 :arg3 :arg4 :arg5 :arg6 | Transcript showCR:{arg1 . arg2 . arg3 . arg4 . arg5 . arg6}].
+     block value:1 optionalArgument:2 and:3 and:4 and:5 and:6.
+    "
+!
+
 value:arg1 value:arg2
     "evaluate the receiver with two arguments.
      The receiver must be a 2-arg block."
@@ -1142,6 +1270,16 @@
     ^ self wrongNumberOfArguments:3
 !
 
+value:arg1 value:arg2 value:arg3 optionalArgument:arg4
+    "evaluate the receiver.
+     Optionally pass three or four arguments (if the receiver is a 3/4-arg block)."
+
+    nargs == 4 ifTrue:[
+        ^ self value:arg1 value:arg2 value:arg3 value:arg4
+    ].
+    ^ self value:arg1 value:arg2 value:arg3
+!
+
 value:arg1 value:arg2 value:arg3 value:arg4
     "evaluate the receiver with four arguments.
      The receiver must be a 4-arg block."