Typed arguments

We know that our implementation of the move functions comes with some implicit design assumptions:

  • The value of v should be a numerical value, as implied by the + or - operator.
  • The widget has to be a Widget object, or at least something that contains a Position object, as implied by the access of the position field.

For these reasons, it's generally safer to define functions with some type information. Having said that, the move_up! function can be redefined as follows:

move_up!(widget::Widget, v::Int) = widget.position.y -= v

If we just define all move functions the same way, then debugging becomes easier. Suppose that we make the same mistake as we did in the preceding code by passing an integer as the first argument: we will now receive a more sensible error message:

So instead of trying to run the function and failing miserably with an unknown effect, the Julia compiler will now tell us that the method does not exist for the argument types that we pass into the function.

Before we move on to the next topic, let's at least play a little bit of the game. In order to display these objects more nicely in the Julia REPL, we can define some show functions, as follows:

# Define pretty print functions
Base.show(io::IO, p::Position) = print(io, "(", p.x, ",", p.y, ")")
Base.show(io::IO, s::Size) = print(io, s.width, " x ", s.height)
Base.show(io::IO, w::Widget) = print(io, w.name, " at ", w.position, " size ", w.size)

These Base.show functions provide the implementation that is used when Position, Size, or Widget objects need to be shown at the specific I/O device, such as the REPL. By defining these functions, we get a much nicer output. 

Note that the show function for the Widget type prints the name, position, and size of the widget. The respective show functions for the Position and Size types are going to be called from the print function. 

The show function comes with another form, show(io, mime, x), so that the value x can be displayed in different formats for different MIME types. 

MIME stands for Multipurpose Internet Mail Extensions. It is also called Media Type. It is a standard that is used to specify the type of a data stream. For example, text/plain represents a plain text stream and text/html represents a text stream that has HTML content.

The default MIME type for a show function is text/plain, which is essentially the type we use in a Julia REPL environment. If we use Julia in a notebook environment, such as Jupyter, then we can provide a show function that provides additional formatting in HTML using the MIME type of text/html.

Finally, let's give it a test drive. We can move around an asteroid game piece by calling various move functions, as follows:

# let's test these functions
w = Widget("asteroid", Position(0, 0), Size(10, 20))
move_up!(w, 10)
move_down!(w, 10)
move_left!(w, 20)
move_right!(w, 20)

# should be back to position (0,0)
print(w)

The result is as follows. Note that the output of the asteroid widget is formatted exactly as how we coded it:

Defining functions with typed arguments is generally considered a good practice because the function can only work with the specific data types of the arguments. Also, from a client usage perspective, you can clearly see what is required by the function just by looking at the function definition.

Sometimes it is more beneficial to define a function with untyped arguments. The standard print function, for instance, has a function signature that looks like print(io::IO, x). The intention is that the print function is guaranteed to work with all possible data types. 

Generally speaking, this should be an exception rather than the norm. In most situations, it makes more sense to use typed arguments.

Next, we will discuss how to provide default values for the arguments. 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.47.221