Hi, my name is Seth Ladd, and welcome to this episode of
"Dart Tips." This is part one in a series about functions,
the stalwart and trusty building blocks of any app.
Dart supports top-level functions, optional
parameters, nested functions, passing functions as arguments
to other functions, and more.
It's not uncommon to build an entire
app using only functions.
If you think Dart is only classes and libraries, you're
in for a treat.
This episode will focus on
defining and calling functions.
Let's get started.
[MUSIC PLAYING]
Functions are reusable bundles of logic.
They can take zero or more arguments, perform some work,
and optionally return a value.
Here's a very simple function named meaning0fLife().
The empty parentheses means this function does not take
any parameters.
Use the return statement to return a value--
in this case, 42.
If no return statement is specified, the function
returns null.
Here's how you call this function.
So far, so good.
But Dart likes to be a terse language, so we can simplify
the definition of this function into a single line.
This fat arrow syntax is syntactic sugar for a more
terse way to return the resulting value of the
expression on the right-hand side of the fat arrow.
Functions can, of course, accept parameters.
Here's an example.
This code works just fine, but this is Dart.
We have optional type annotation, so we can annotate
this method's parameters and return type.
We strongly recommend using type annotations on the
surface area of your code.
Any code that another user will interact with, functions
being a perfect example, should annotate what types it
expects and what type it returns.
Your fellow developers will thank you, and your tools will
give you even better feedback.
Functions can take multiple parameters.
Here's an example.
This function has two required parameters-- a string for the
message and an integer for the number of exclamation points
to add at the end.
Exclamation points are loud, no doubt about it.
But sometimes, you may not want to shout so loud.
Of course, one option is to pass 0 at the end as a second
parameter, like this code shows.
However, it is hard to read this line of code.
A casual observer may not know what this magic 0 is.
Also, wouldn't it be better to simply leave off the second
parameter if you don't want to use it?
Luckily, Dart has a way to make this better.
Wrap one or more parameters with square brackets to make
them optional.
Here's an example.
Notice how the function now checks if exclamations is
null, which is the value of the parameter if it was not
provided by the caller.
Now that the second parameter is optional, you can
optionally omit it when you call the function.
Here's an example.
We made this function more flexible and easier to use.
However, there is still another problem here.
The second parameter, if it is provided, still looks a bit
like a magic number.
That is, the casual observer would not know what this magic
number 5 means.
Luckily, Dart has a solution for this, too.
You can make methods even easier to read by using
optional named parameters.
Here's an example.
I think adding a simple name to the parameter makes it
obvious what is going on.
To define optional named parameters, wrap the
parameters in curly braces.
To briefly recap, there are two ways to define optional
parameters--
square brackets for optional positional parameters and
curly braces for optional named parameters.
There's yet another benefit from the use of optional
parameters.
But first, the setup.
Sometimes there's an obvious or default
answer for a parameter.
Only on occasion does it make sense to pass in something
more unique.
For example, here's a function that opens an HTTP connection.
The first parameter IP address could be
anything, so it's required.
However, almost all HTTP connections use port 80, so
the second parameter can be optional.
The function is easier to use now, because the user doesn't
have to specify the obvious.
However, the code inside the function is a bit verbose.
Plus, there's no way to express to the user what the
port's value is if it is not provided.
Luckily, Dart lets us specify a default value for a
parameter if that parameter is optional.
Here's an example.
This code is simpler, the semantics are more clear, and
it is self-documenting.
You can use any compiled time constants, such as integer
literals, as shown here, for default values.
Here are some examples of using this function.
However, here is an example that might
not be totally clear.
Notice how I am passing null as the second parameter.
Null is a perfectly valid value.
So in this case, port will be set to null, even though it
has a default value.
The lesson here is that default values are only
applied if the caller does not supply any
value for the parameter.
This means, to really cover your bases, you should check
for null even when you use default values.
This brings up a good question.
In the case of an optional parameter without a default
value, can you tell the difference between a user
passing in null and not passing in anything at all?
The parameter will be null either way.
It turns out that Dart does indeed have a way to ask if an
optional parameter was provided when
the method was called.
Just use the question mark parameter syntax.
Here's an example.
Like the optional named parameters, you can use
default values with optional positional parameters.
There is a syntax difference, though.
You must use equals with the positional
params instead of colon.
Here's an example of defining an optional positional
parameter with a default value.
Moving on, you can define functions simply at the top
level of your code.
Here's an example.
I love this, because it means I don't need to wrap functions
assigned [? to ?] classes.
Writing a simple script with Dart is easy because of
top-level functions.
Now you know that functions can capitalize on type
annotations, have both optional positional and
optional named parameters, have default values for their
optional parameters, and more.
There's a lot more to functions in Dart.
And we'll cover nested functions, functions as
objects, and more in a future episode.
Thanks for watching.
I'm Seth Ladd.
And as we say here on "Dart Tips," stay sharp.
Click here to subscribe to our channel for more episodes of
"Dart Tips." We appreciate any thoughts you might have for
this series.
Please leave them in the comments below.
And if you have any additional questions about Dart, please
drop by Stack Overflow where Dart experts are standing by
to help you out.
See you next time.