Version 2 (modified by Austin_Hastings, 5 years ago)

--

Creating Closures with NQP-rx

The following code works as of Parrot 2.1 to create and store closures from NQP-rx. If you need this, please note that the newclosure op is necessary to clone the enclosed context. Also, you need to re-enter the containing lexical scope to reset the lex vars you want unshared. Otherwise, as shown (see shared vs. not_shared) they won't be shared.

#! /usr/bin/env parrot-nqp

MAIN();

sub MAIN() {
	my @closures;
	my @names := <fred wilma barney betty>;
	{
		my $shared := 1;

		my $count := 1;
		for @names -> $name {
			my $not_shared := 1;
			
			my &sub := {
				say("$name\twas called $not_shared times. Any sub was called $shared times.");
				$shared++;
				$not_shared++;
			};
			
			@closures.push: pir::newclosure__PP( &sub );
			$count++;
		}
	}

	my $count := 0;
	while $count < 3 {
		for @closures {
			$_();
		}
		
		$count++;
	}
}

Entering Scope

It is the act of _entering_ the lexical block that performs the allocation of a new lexpad and the other housekeeping associated with a new lexical environment (for you to enclose). You can get that effect in a number of ways:

  • Calling a sub, obviously, enters its lexical scope when you call it.
  • Recursion, naturally, qualifies as entering a new lexical scope.
  • Executing a for or while/until loop, because these are implemented as subs.
  • Executing an if or unless statement that contains lexical variable declarations. (Caution! If the block has no lexical vars, it will be 'in-lined' and not a separate sub.)