Skip to main content
Engineering LibreTexts

13.1: Basics

  • Page ID
    43736
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    What is a block? A block is a lambda expression that captures (or closes over) its environment at creation-time. We will see later what it means exactly. For now, imagine a block as an anonymous function or method. A block is a piece of code whose execution is frozen and can be kicked in using messages. Blocks are defined by square brackets.

    If you execute and print the result of the following code, you will not get 3, but a block. Indeed, you did not ask for the block value, but just for the block itself, and you got it.

    [1+2]
        → [1+2]
    

    A block is evaluated by sending the value message to it. More precisely, blocks can be evaluated using value (when no argument is mandatory), value: (when the block requires one argument), value:value: (for two arguments), value:value:value: (for three) and valueWithArguments: anArray (for more arguments). These messages are the basic and historical API for block evaluation. They were presented in the Pharo by Example book.

    [ 1 + 2 ] value
        → 3
    
    [ :x | x + 2 ] value: 5
        → 7
    

    Some handy extensions

    Beyond the value messages, Pharo includes some handy messages such as cull: and friends to support the evaluation of blocks even in the presence of more values than necessary. cull: will raise an error if the receiver requires more arguments than provided. The valueWithPossibleArgs: message is similar to cull: but takes an array of parameters to pass to a block as argument. If the block requires more arguments than provided, valueWithPossibleArgs: will fill them with nil.

    [ 1 + 2 ] cull: 5                         → 3
    [ 1 + 2 ] cull: 5 cull: 6                 → 3
    [ :x | 2 + x ] cull: 5                    → 7
    [ :x | 2 + x ] cull: 5 cull: 3            → 7
    [ :x :y | 1 + x + y ] cull: 5 cull: 2     → 8
    [ :x :y | 1 + x + y ] cull: 5             → error because the block needs 2 arguments.
    [ :x :y | 1 + x + y ] valueWithPossibleArgs: #(5)
                        → error because 'y' is nil and '+' does not accept nil as a parameter.
    

    Other messages. Some messages are useful to profile evaluation (more information in the Chapter 17):

    • bench. Return how many times the receiver block can be evaluated in 5 seconds.
    • durationToRun. Answer the duration (instance of class Duration) taken to evaluate the receiver block.
    • timeToRun. Answer the number of milliseconds taken to evaluate this block.

    Some messages are related to error handling (as explained in the Chapter 13).

    • ensure: terminationBlock. Evaluate the termination block after evaluating the receiver, regardless of whether the receiver’s evaluation completes.
    • ifCurtailed: onErrorBlock. Evaluate the receiver, and, if the evaluation does not complete, evaluate the error block. If evaluation of the receiver finishes normally, the error block is not evaluated.
    • on: exception do: catchBlock. Evaluate the receiver. If an exception exception is raised, evaluate the catch block.
    • on: exception fork: catchBlock. Evaluate the receiver. If an exception exception is raised, fork a new process, which will handle the error. The original process will continue running as if the receiver evaluation finished and answered nil, i.e., an expression like: [ self error: ’some error’] on: Error fork: [:ex | 123 ] will always answer nil to the original process. The context stack, starting from the context which sent this message to the receiver and up to the top of the stack will be transferred to the forked process, with the catch block on top. Eventually, the catch block will be evaluated in the forked process.

    Some messages are related to process scheduling. We list the most important ones. Since this Chapter is not about concurrent programming in Pharo, we will not go deep into them.

    • fork. Create and schedule a Process evaluating the receiver.
    • forkAt: aPriority. Create and schedule a Process evaluating the receiver at the given priority. Answer the newly created process.
    • newProcess. Answer a Process evaluating the receiver. The process is not scheduled.

    This page titled 13.1: Basics is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by Alexandre Bergel, Damien Cassou, Stéphane Ducasse, Jannik Laval (Square Bracket Associates) via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.