Block type literals

Block literals are a form of type literal. Use a block literal to reference a specific block type. The block literal specifies the kinds of arguments that the block takes and the type of the return value.

Block types BNF notation

The formal BNF notation of a block literal is:

blockliteral -> block_literal_1 | block_literal_2
block_literal_1 -> block ( type_list ) : type
block_literal_2 -> parameter_name ( type_list ) : return_type
type_list -> type | type_list , | null

Block types in declarations

To declare a variable to contain a block, the preferred syntax is:

var variableName( list_of_argument_types ) : return_type

For example, to declare that strBlock is a variable that can contain a block that takes a single String argument and returns a String value, use this code:

var strBlock( String ) : String

In declarations, you can also optionally use the block keyword, although this is discouraged in declarations:

var variableName : block( list_of_types ) : return_type

For example, this code declares the same block type as described earlier:

var x : block( String ) : String

Usage of block types not in declarations

For a block type literal that is not part of a declaration, the block keyword is strictly required:

block( list_of_types ) : return_type

For example:

return b as block( String ) : int

The b variable is assigned a value that is a block type. Because the block type literal is not directly part of the declaration, Gosu requires the block keyword.

Block types in argument lists

A function definition can specify a function argument as a block. As you define the block argument, provide a name for that block parameter so that you can use the block within the function. Use the following syntax for block types in argument lists:

parameter_variable_name( list_of_types ) : return_type

For example, suppose you want to declare a function that takes one argument, which is a block. Suppose the block takes a single String argument and returns no value. To refer to this block by name as myCallback, define the argument using the syntax:

myCallBack( String ) : void

Example of a block type in an argument list

The following Gosu class includes a function that takes a callback block. The argument is called myCallBack, which is a block that takes a single string argument and returns no value. The outer function calls that callback function with a String argument.

package mytest

class test1 {
  function myMethod( myCallBack( String ) : void ) {

    // Call your callback block and pass it a String argument
    myCallBack("Hello World")
  }
}

After creating the class, you can test the following code in the Gosu Scratchpad:

var a = new mytest.test1()
a.myMethod( \ s : String -> print("<contents>" + s + "</contents>") )

For more concise code, you can omit the argument type “: String” in the in-line block. The block is defined in-line as an argument to a method whose argument types are already defined. In other words, you can use the following code:

var a = new mytest.test1()
a.myMethod( \ s -> print("<contents>" + s + "</contents>") )

Both versions print the following:

<contents>Hello World</contents>

Usage of block types for recursion

Gosu blocks support recursion, in which the block calls itself until reaching an end condition. To use recursion in blocks, you must name and define the block signature before you define the block code. For example, the following code defines a block that returns the factorial of an integer:

var bFactorial: block(int): int
bFactorial = \ x -> x > 12 or x < 1 ? -1 : (x == 1 ? 1 : x * bFactorial(x-1))

This code has two end conditions. The first end condition ensures that the block terminates if the result would be greater than Integer.MAX_VALUE or if the parameter value is less than 1. The second end condition terminates the recursion when the argument value is 1. To test this block, use code like the following:

print(bFactorial(6))

This code prints:

720