NAME
PerlSub - Encapsulate a perl CODE reference in JavaScript
DESCRIPTION
Perl subroutines that you pass to javascript will be wrapped into instances of PerlSub
.
More generally, any perl CODE reference that enters javascript land will become a PerlSub
instance.
...
$ctx->bind_function(perl_rand => sub { rand });
$ctx->bind_function(add => sub {
my($a, $b) = @_;
return $a + $b;
});
...
$ctx->eval(q{
val = add(10, 20); // val now 30
say("10 + 20 = " + val); // 'say' itself is defined in the
// stock context
v1 = perl_rand();
v2 = perl_rand();
say(v1 + " + " + v2 + " = " + add(v1, v2));
});
JAVASCRIPT INTERFACE
When you send a subroutine from perl to javascript, you'll get an instance of PerlSub
. PerlSub
s behave pretty much like native javascript Functions.
Like Function instances, instances of PerlSub are invoked with a parenthesized list of arguments.
var foo = perl_rand(); // invoke perl_rand, foo now random number
var bar = perl_rand; // now 'bar' is another reference to perl_rand
var baz = bar(); // invoke it, baz now a random number
And as with any other object, you can manipulate properties and call methods of instances of PerlSub
.
perl_rand.attr = 'This is a function imported from perl';
add.toString(); // Please try this ;-)
add.toSource(); // Or this!
Instance methods
PerlSub.prototype
implements methods analogous to Function.prototype
's.
- call(thisArg, ARGLIST)
-
Analogous to
Function.prototype.call
. - apply(thisArg, somerray)
-
Analogous to
Function.prototype.apply
. - toSource( )
-
Analogous to
Function.protype.toSource
. Tries to uncompile and returns the perl code associated, depends on B::Deparse. - toString( )
-
Returns the literal string
"sub {\n\t[perl code]\n}"
Instance properties
- name string
-
Store the name on the original perl subroutine if named or the string "(anonymous)".
- prototype object
-
Remember that any Function instance has a property
prototype
, and PerlSub instances have one also. Please read your javascript documentation for details. - $wantarray boolean
-
Determines the perl's context,
false
-> 'scalar',true
-> 'list', to use when the subrotine is called. Defaults totrue
!!. See "Perl contexts".
Constructor
You can construct new perl functions from inside javascript.
- new PerlSub(PERLCODE)
-
var padd = new PerlSub("\ my($a, $b) = @_;\ return $a +$b\ ");
Returns a new instance of
PerlSub
, that can be called in the normal way:padd(5, 6); // 11
PERLCODE, a string, is the body of your new perl subroutine, it's passed verbatim to perl for compilation. Syntax errors will throw exceptions at construction time.
If you ever pass to perl instances constructed by PerlSub you'll see normal CODE references indistinguishable from anonymous subs.
Calling semantics
When you invoke a PerlSub
from javascript, in most cases JSPL does the right thing. But there are differences in the way than javascript and perl behave respect to function calling that you should be aware of. Mainly when you export to javascript arbitrary perl functions or expose perl namespaces to javascript.
Read this section for the gory details.
Perl contexts
In perl you call a subroutine in either scalar or list context. Perl determines this context automatically using the form of the expression in which the function is called. And perl lets your subroutine know which context is being used (via "wantarray" in perlfunc). Some subroutines behave differently depending on which context they where called. In javascript this concept doesn't exists.
To make the problem of calling perl subroutines from javascript even more interesting, perl subroutines can return list of values where javascript functions always return a single value.
To solve the first problem, the context in which the perl subroutine call will be made is taken from the $wantarray
property of the instances of PerlSub
. $wantarray
defaults to true
, which is the correct value to use in the vast majority of the cases. We explain why and when to use a false
value below.
For the return value of a PerlSub
call you will get either a single value or a PerlArray
. You'll get a single value when $wantarray
is false
or when the list returned has a single element, otherwise you'll get a PerlArray
.
You'll never receive arrays with a single element in them. This behaviour may be unfortunate but it makes the rest of the cases much more simpler. Besides, you can check trivially for that condition as follows:
res = perl_sub_that_returns_a_list();
if(res instanceof PerlArray) {
...
} else {
...
}
Having $wantarray
default to true is the best thing to do because, on one side, perl subroutines returning single values are not affected, and on the other side it's the correct value to use for subroutines returning lists.
You'll need to set $wantarray
to false
when: you need to call a perl subroutine that uses wantarray and/or you need to force 'scalar' context for the call.
$wantarray
usage example:
// Asuming that 'perlfunc' is a PerlSub
perlfunc.$wantarray = true; // this is the default
listres = perlfunc(); // Called in 'list' context
perlfunc.$wantarray = false;
scalres = perlfunc(); // Called in 'scalar' context
this
In javascript every call to a function is a method call and a reference to the caller is visible inside the function as this
. The function author decides if behave as a method, using this
or as a simple function ignoring this
.
In perl method calls use a syntax different from regular calls. A subroutine called as a method sees its caller in front of the other arguments.
When the caller to a PerlSub
is either a PerlObject
or a Stash
, JSPL's engine will push it in the arguments. The call will use perl's method call semantics.
In every other case, JSPL's engine assumes that you are creating or extending regular JavaScript objects with PerlSub
-based methods and you need a way to get the value of this
in a transparent way. Thats the purpose of the magical variable "$This" in JSPL.
Perl code not aware of being called from JavaScript will see its arguments unmodified. Perl code that needs JavaScript's this
gets it in $JSPL::This
. And everyone is happy.