2 ms·
Scoping - 'my' is lexical/block scoping, same as javascript's 'let' (thank you! steal more things please!) so use feature 'say'; use strict; use warnings
by mst 8y ago
Scoping - 'my' is lexical/block scoping, same as javascript's 'let' (thank you! steal more things please!) so
use feature 'say';
use strict;
use warnings;
my $code = do {
my $count = 0;
sub { ++$count }
};
say $code->(); # 1
say $code->(); # 2
and note that if I e.g. typoed $count inside the subroutine I'd get a compile time error (and it goes out of scope at the end of the 'do { ... }' block). Note that the 'state' keyword provides an easier way to do this, but it's the easiest demo of closures I can think of, though also there's fun to be had with methods:
my $method = sub ($self, @args) { $self->foo(3, @args) };
$object->$method(1, 2); # same as $object->foo(3, 1, 2);
Constructor/accessor wise:
package MyClass;
use Moo;
has foo => (is => 'ro', required => 1);
has bar => (is => 'rw');
has baz => (is => 'lazy', builder => sub { expensive_default() });
then means that
MyClass->new
will throw an exception telling you foo is required
MyClass->new(foo => 1);
will work fine,
$obj->foo; # returns the value of foo
$obj->foo(3); # throws an exception - foo is ro
$obj->bar; # returns the value of bar is any
$obj->bar(26); # sets bar
and (if you didn't pass a value for it to the constructor)
$obj->baz; # runs expensive_default() once and then retains the value
Hopefully that's a start, this is all typed off the top of my head on my first post-9am pint of coffee so my apologies for any omissions and/or errors.
- CydeWeys 8y agoAlso, in languages like Java, C++, or C#, you can use bare braces to define a new scope, no keyword necessary. It's not done so much anymore because modern coding standards tend to favor shorter functions for clarity and unit testability, but it's always still an option.
- mst 8y agoYou can do bare braces in perl5 too, I used the 'do { ... }' block because that's an expression rather than a statement so I could return the subroutine - my $code; { my $count = 0; $code = sub { ++$count }; } would've been equivalent but I always try and do assign-once-at-declaration-time where possible because mutable state is my mortal enemy.
- fouc 8y agowhat's the js equivalent to your example? let code = () => { let count = 0; return ++count } doesn't do the trick
- mst 8y agoJS doesn't have the do {} expression form so let code; { let count = 0; code = () => ++count; } or let-over-lambda it and let code = (() => { let count = 0; return () => ++count; })();