When calling into Java, the message is the name of a method or field that
belongs to the object. Arguments are converted to Java types as necessary,
and some conversions are automatic. Nearly anything will convert to a string.
However, a string will not convert to an int. Casting is possible, but I
don't cover that topic here.

Now that you know a little about the Sleep language, it helps to see it in
action. Next, I present several scenarios and Sleep-based solutions to
them.

Filesystem Fun (the Biggest File)

My home directory has many files. I'm a digital packrat, and I'm always low
on disk space. I really have no idea what is on my disk. To help, I wrote a
script to find the largest files within a directory and its subdirectories:

global('$size $file @files %sizes');
sub processFile
{

This script creates a data structure of files and their sizes, sorts it,
and presents the results to the user. The &processFile function does most of
the work, and it expects a file as an argument:

if (-isDir $1)
{
filter(&processFile, ls($1));
}

If the argument is a directory, the &ls function will provide the contents
of the directory as an array. &filter expects a function and an array as
arguments. &filter calls the function on each item in the array. I use
&filter to call &processFile on the argument's subdirectories and
files:

else if (lof($1) > (1024 * 1024))
{
%sizes[$1] = lof($1);
}
}

The hash %sizes stores each filename and size. The key is the filename, and
the size is the value. The &lof function returns the length of a file in
bytes. I ignore files smaller than 1MB in size. I have so many files that
this script exhausts the memory of Java before finishing. I could set Java
to use a larger heap size with java -Xmx1024M -jar
sleep.jar. Below, I chose
to fix my script:

processFile(@ARGV[0]);

I call &processFile on the first command-line argument to kick off the
script. When this function returns, the %sizes hash will contain an entry
for each file in the specified directory and its subdirectories:

@files = sort({ return %sizes[$2] <=> %sizes[$1]; },
keys(%sizes));

The &sort function processes the keys of %sizes and places them in order
from largest to smallest size. Much like Perl, Sleep's &sort can use any
criteria given by an anonymous function:

This script ends with a foreach loop to print out the 50 largest files.

And, lo and behold! I solved my problem. I found four copies of a Christmas
movie I made on my Macintosh three years ago. Thanks to the script, I
recovered several gigabytes of disk space.

Local Processes (PS. I Love You)

Recently, I had to watch this movie about a guy who sent letters to his
wife after he passed away. I'm not really into the romantic-morbid genre;
however, I thought I could show the people in my life how much I care about
them. Here is a script that sends a random fortune to someone every 24
hours:

I use `fortune` to execute the fortune command and collect its output into
an array. Then, I combine this with the rest of the message body to make a
thoughtful message. This script uses the $variable => value syntax to pass
named arguments to &sendemail.

Backticks are one way to execute a process. I show the other way in the
sendemail.sl code.

Sending E-Mail

I use the sendmail program to send e-mail. The sendemail.sl file contents
are:

Sleep executes processes with the &exec function. Scripts interact with
processes as if they were files. As an aside, you can pass arguments with
spaces to &exec. Use an array instead of a string. For example,
exec(@("/usr/sbin/sendmail", "-t", $to)) would work
in this example:

println($handle,
"TO: $to
FROM: $from
SUBJECT: $subject
$message");

Here, I send the e-mail message to the sendmail process over STDIN. Later in
this article, I cover how to use Sleep for distributed tasks.
Don't
combine this e-mail example with that—I don't like spammers:

closef($handle);
}

The last step is to close the handle. Having successfully automated my
personal life, let's turn our attention to work matters.