In this issue, we’ll talk about the built-in wrap
routine and its possible applications.
Example 1. wrap
The wrap
routine — as you may guess from its name — wraps another function. Let us go straight to the example.
sub greet($name) { say "Hello, $name!"; } &greet.wrap({ callwith($^arg.uc) }); greet('Venusians'); # Hello, VENUSIANS!
First, we’ve got a regular function that takes a string and prints the message with it. In the end, the function is called as usual.
In-between, we see that the function is wrapped into another function, which is actually called when you call greet
instead of it. In this example, the wrapping function calls the original function with the modified argument: callwith($^arg.uc)
. Here, $^arg
is a placeholder variable that the wrapper gets when the original function is called in the last line of the program.
Example 2. unwrap
Let us extend the previous program and remove the wrapper after some time. To do that, you need to save the wrapper object in a variable, which you can later pass to the unwrap
routine.
sub greet($name) { say "Hello, $name!"; } my $x = &greet.wrap({ callwith($^arg.uc) }); greet('Venusians'); # Hello, VENUSIANS! &greet.unwrap($x); greet('Venusians'); # Hello, Venusians!
Example 3. Execution time
One of the useful examples of wrappers can be measuring time of execution of a slow function. Here is how you can do it:
sub slow { sleep(1); } sub timer { my $t0 = now; callsame; say now - $t0; } &slow.wrap(&timer); slow();
This time, the wrapper uses callsame
to call the original function with the same arguments. In this example, I am using a bit different syntax of calling the wrap
method. This option is more suitable for bigger wrapping functions.
Example 4. Logging
Another example — a logger that you can place around a function that visits the sites, for example.
use HTTP::UserAgent; sub browse($url) { my $ua = HTTP::UserAgent.new; my $response = $ua.get($url); say $response.status-line; } &browse.wrap(-> $url { note "{DateTime.now} $url"; callsame; }); browse('https://google.com/'); browse('https://raku.org/');
Again, just for the sake of diversity, I used a pointy block here. You do not need to change the browser
function to start logging. Just create a wrapper which does the job:
$ raku wrap-log.raku > /dev/null 2020-09-17T23:04:32.383453+02:00 https://google.com/ 2020-09-17T23:04:32.807365+02:00 https://raku.org/
And that’s it for now!
* * *
Find the code of this issue on GitHub and browse for more Raku Pearls.