Just wanted to mention that Ruby was highly inspired by Perl, particularly its regular expressions and it has a variety of perlisms. Kind of surprised you went to python and not ruby.
I just wish ruby had the same quality of scoping and OO that perl5 has, but it ended up with the same "variables magically pop into existence for the entire function" footgun as python and a horribly restrictive OO that also requires me to repeat myself (accessor/constructor etc.) in a way that after about an hour sends me screaming back to perl
Edit: Look, this is a genuine opinion, I've chatted to ruby core devs about this and they couldn't find ways to achieve the same things I do with perl5 as elegantly in ruby (Steve Klabnik and I have an open conversation about how to find a kata where we can compare this stuff properly), I'm 100% happy to discuss this but blindly downvoting because you disagree is depressing - tell me why you think I'm wrong instead and I'll do my best to reply constructively
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.
Also, 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.
You 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.
Just wanted to mention that Ruby was highly inspired by Perl, particularly its regular expressions and it has a variety of perlisms. Kind of surprised you went to python and not ruby.
Your lisp mention reminds me of this: http://www.randomhacks.net/2005/12/03/why-ruby-is-an-accepta...