Wednesday, May 28, 2014

Perl6 object construction and excess arguments

When I get some JSON data in my Lacuna Expanse client they arrive as enormous hash. Sometimes I need just a few things from them.

In perl6 this may be done without any special code. This is done by Interface_Consistency that works for .new like for any other argument-less method.

IMHO this way is much more comfortable than creating big hash field and a lot of getters. See example:
use v6;

class PersonalId{
    has Int $.number;
    has Str $.full_name;
}

my Hash $p; #just because i'm afraid of pair conversions
$p{"number"} = 13123123123;
$p{"full_name"} = "John Doe";
$p{"age"}=64;
$p{"shoesize"}=44;

say PersonalId.new(|%($p)).perl;

$ perl6 sandbox.pl
PersonalId.new(number => 13123123123, full_name => "John Doe")

If you want to check arguments passed to new method instead of default behaviour Tadzik ported StrictConstructor from Moose

Wednesday, May 21, 2014

Perl6 will help you in object reuse

While using objects gathered from external source I probable don't want to recreate them. For example I have planet with buidlings on it but I don't want to get building list everytime beacause it is very slow operation and new buildings are not added often.
class Planet is LacunaSession;
constant $URL = '/body';
has $.id;
has @.buildings = self.get_buildings;
my Planet %planets;

method planet ($id = self.home_planet_id --> Planet) {
    %planets{$id} = Planet.new(id => $id) unless %planets{$id};
    %planets{$id}
}
Can be replaced with
class Planet is LacunaSession;
constant $URL = '/body';
has $.id = self.home_planet_id;
has @.buildings = self.get_buildings;

method planet ($id = self.home_planet_id --> Planet) is cached {
    Planet.new(id => $id)
}
To ensure this will work as expected I've added some code
use v6;
 
class UUU {
    has Str $.a;
}
sub x($a) is cached {
    UUU.new(a => "vvvvvvv"); 
}
 
sub y($a) {
    UUU.new(a => "vvvvvvv"); 
}
 
say "Cached first argument three times";
say x(1).WHICH;
say x(1).WHICH;
say x(1).WHICH;
 
say "Cached second argument three times";
say x(2).WHICH;
say x(2).WHICH;
say x(2).WHICH;
 
say "Not cached versions";
say y(1).WHICH;
say y(1).WHICH;
say y(1).WHICH;
say y(2).WHICH;
say y(2).WHICH;
say y(2).WHICH;
End the result was as expected
Cached first argument three times
UUU|5198114092745258178
UUU|5198114092745258178
UUU|5198114092745258178
Cached second argument three times
UUU|5198114092755151046
UUU|5198114092755151046
UUU|5198114092755151046
Not cached versions
UUU|5198114092752784585
UUU|5198114092757007311
UUU|5198114092748636120
UUU|5198114092759081941
UUU|5198114092750688723
UUU|5198114092746537667
This is experimental feaure but can be easily recreated with own trait.

Saturday, August 24, 2013

Order matters

While getting used to java i sometimes forget about order importance. Actually in java there are also moments that declaration order is important. It is class initialization but now I wanted to write about perl. I have quite not small test written in my favorite scripting language. I really spent a while to find out why my subroutine stopped working after moving to separate module:
use 5.014;


package Foo;
my $foo = 1;
sub getFoo{
    say "Will get foo";
    say $foo;
}

Foo::getFoo();
Bar::getBar();

package Bar;
our $bar = 2;
sub getBar {
    say "Will get bar";
    say $bar; 
}
Variable bar is undefined:
Will get foo
1
Will get bar

?
At first I thought it's scoping related but adding our didn't change anything. The only problem was order because subroutines and vars are available since beginning but package variable is initialized after perl parses every line above it. The are two solutions to it. First is moving package to separate file. Including it by use will initialize variable in right moment. Second one is safer and easier:
package Bar;
our $bar;
BEGIN{
 $bar = 2;
}
sub getBar {
  say "Will get bar";
  say $bar; 
}

This secret subroutine called BEGIN is run before normal subs are called so package like that will result in singleton like behavior wherever we declare it.

Tuesday, August 20, 2013

Easy way to organize Gists into sets

Gist is just quite geeky pastebin but like everybody i like to have all things in one place. That was reason why I've created my first own homepage. The differ from regular repositories with only few things. The biggest one is that you don't have to push changes and merge branches. Also changelog is automatically filled so its perfect for fast snippets.

Here are my gists (UPDATE I moved it to regular github repository)

The thing I did: Gists sorts files in single gist and displays first one. The dot symbol is used for hidden files in Unix and almost guaranties that file with . will appear before any other uploaded files. To feel really eccentric I used Plain Old Documentation but anyone can use GitHub Markdown if wants to.

Anyway it is good question whether gist is good service at all because it not differs much from normal git repository without some features.. 

Thursday, August 8, 2013

Perl SOAP::Lite rpc:literal tomcat quick start

I've lost almost half a day on trying to connect tomcat web service. I didn't want to use java for that because I wanted to this as fast as possible [in coding time not in run time :)]. After debugging I found out that problem is namespace in XML so I replaced default_ns with ns. The only problem is warning (so I run with -X) about undefined value but my services are tested now.
  use Soap::Lite;
  my $soap = SOAP::Lite->new( service=> $wsdl, proxy => $url, uri => $url);
  $soap->autotype(0)->readable(1);
  $soap->ns($namespace);
  my $som =  $soap->call('methodName', 
             SOAP::Data->name('methodArgument')->value($value));
    die $som->faultstring if ($som->fault);
Another interesting thing is that SOAP::Lite stores all definitions between services creation so creating new $soap object with same WSDL will result with subroutine redefinition warning by eval injected code.

Tuesday, August 6, 2013

Function style

Have you ever wanted to make fast subroutinte to assign result to a variable?
my $b= {
 my $a=9;
 say "Inside";
 2+5+$a
       }();
say $b

Or If you want to use perl5
my $a = &{
  sub{
    my $b=-10;
    5+$b
  }
};

print "perl", $a, "\n"

Wednesday, July 31, 2013

start-stop-daemon output redirect

I was working on startup scripts that are pretending to become state of art :). I have even used inline perl to make it more compact. While working on it I found following problem:
start-witch)

echo  "Starting Witch"
   export LD_LIBRARY_PATH=$LIB_DIR
   start-stop-daemon -v --start \
   --pidfile $PID_WITCH --make-pidfile --background  \
   --exec "$APP_DIR/Witch/Witch" -- $WITCH_OPT 2>$DIR/WitchErr.log
;;
I've tried almost everything except writing separate bash script for my application. After some time, much time to be honest, I realized that problem is that output redirect is bash feature and application runs outside the shell. The solution was changing moment that sends app into background.
start-witch)

echo  "Starting Witch"
   export LD_LIBRARY_PATH=$LIB_DIR
   start-stop-daemon -v --start \
   --pidfile $PID_WITCH --make-pidfile \
   --exec "$APP_DIR/Witch/Witch" -- $WITCH_OPT 2>$DIR/WitchErr.log
;;
I heard that newer versions of start-stop-daemon will have --no-close feature that won't need hacks like this. But even Ubuntu still uses an old version.
If interested in embedding script inside bash:
perl <<'EOF'
     use feature 'say';
     say "Your script hoes here";
     EOF