1.21 Gigawatts

1.21 Gigawatts

Lightning strikes 11 times! Almost a dozen short talks about stuff that I was thinking about in 2013.

Cec6b9b88295ead26c65f8747a76561b?s=128

Ricardo Signes

January 23, 2014
Tweet

Transcript

  1. 3.
  2. 4.
  3. 7.

    use List::Util; my $x = first { $_ > 1

    } @list; my $y = min @list;
  4. 8.

    use List::Util; my $x = first { $_ > 1

    } @list; my $y = min @list; die if any { $_ < 0 } @list;
  5. 10.
  6. 14.

    use List::MoreUtils; my ($min, $max) = minmax(@list); my @header =

    before { $_ eq ‘’ } @input; die if any { $_ < 0 } @list;
  7. 15.

    use List::MoreUtils; my ($min, $max) = minmax(@list); my @header =

    before { $_ eq ‘’ } @input; die if any { $_ < 0 } @list; @x = uniq @x;
  8. 28.

    ! ! my $fh = IO::Uncompress::Gunzip ->new("myfile.csv.gz"); ! my $fh

    = IO::Compress::Gzip ->new("output.txt.gz"); !
  9. 29.

    use autodie; ! my $fh = IO::Uncompress::Gunzip ->new("myfile.csv.gz"); ! my

    $fh = IO::Compress::Gzip ->new("output.txt.gz"); !
  10. 31.

    use autodie; ! my $fh = IO::Uncompress::Gunzip ->new("myfile.csv.gz"); ! my

    $fh = IO::Compress::Gzip ->new("output.txt.gz"); !
  11. 32.

    use autodie; # <-- won't help ! my $fh =

    IO::Uncompress::Gunzip ->new("myfile.csv.gz"); ! my $fh = IO::Compress::Gzip ->new("output.txt.gz"); !
  12. 34.

    use PerlIO::gzip; ! ! open my $fh, '<:gzip', "myfile.csv.gz"; !

    open my $fh, '>:gzip', "output.txt.gz";
  13. 35.
  14. 37.
  15. 41.
  16. 46.

    $ cpan Dist::Zilla installing 10% of CPAN... installing 20% of

    CPAN... installing 30% of CPAN... installing 40% of CPAN...
  17. 47.

    Checking if you have ExtUtils::MakeMaker 6.30 ... Yes (6.86) Running

    Makefile.PL Configuring superclass-0.002 ... Checking if your kit is complete... Looks good Generating a Unix-style Makefile Writing Makefile for superclass Writing MYMETA.yml and MYMETA.json OK Checking dependencies from MYMETA.json ... Checking if you have version 0.9901 ... Yes (0.9906) Checking if you have File::Temp 0 ... Yes (0.2304) Checking if you have warnings 0 ... Yes (1.18) Checking if you have Module::Load 0.24 ... Yes (0.28) Checking if you have Config 0 ... Yes (5.018002) Checking if you have vars 0 ... Yes (1.03) Checking if you have File::Spec::Functions 0 ... Yes (3.40) Checking if you have strict 0 ... Yes (1.07) Checking if you have File::Find 0 ... Yes (1.23) Checking if you have ExtUtils::MakeMaker 0 ... Yes (6.86) Checking if you have List::Util 0 ... Yes (1.35) Checking if you have Test::More 0 ... Yes (1.001002) Building and testing superclass-0.002 ... cp lib/superclass.pm blib/lib/superclass.pm Manifying blib/man3/superclass.3 PERL_DL_NONLAZY=1 /Users/rjbs/.plenv/versions/18.2/bin/perl5.18.2 "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/lib', 'blib/arch')" t/*.t t/00-compile.t .................. ok t/00-report-prereqs.t ........... # Prerequisite Report: # Version Module # -------- --------------------- # 5.018002 Config # 6.86 ExtUtils::MakeMaker # 1.23 File::Find # 3.40 File::Spec::Functions # 0.2304 File::Temp # 1.35 List::Util # 0.28 Module::Load # 1.001002 Test::More # 1.07 strict # 1.03 vars # 0.9906 version # 1.18 warnings t/00-report-prereqs.t ........... ok t/compile-time-file.t ........... ok t/compile-time.t ................ ok t/inherit-classfromclassfile.t .. ok t/inherit-classfromfile.t ....... ok t/inherit-pmc.t ................. ok t/inherit-returns-false.t ....... ok t/inherit.t ..................... ok t/version-check.t ............... ok All tests successful. Files=10, Tests=50, 1 wallclock secs ( 0.04 usr 0.02 sys + 0.36 cusr 0.05 csys = 0.47 CPU) Result: PASS Manifying blib/man3/superclass.3 Installing /Users/rjbs/.plenv/versions/18.2/lib/perl5/site_perl/5.18.2/superclass.pm Installing /Users/rjbs/.plenv/versions/18.2/man/man3/superclass.3 Appending installation info to /Users/rjbs/.plenv/versions/18.2/lib/perl5/5.18.2/darwin-2level/perllocal.pod OK Successfully installed superclass-0.002 Installing /Users/rjbs/.plenv/versions/18.2/lib/perl5/site_perl/5.18.2/darwin-2level/.meta/superclass-0.002/install.json Installing /Users/rjbs/.plenv/versions/18.2/lib/perl5/site_perl/5.18.2/darwin-2level/.meta/superclass-0.002/MYMETA.json Building and testing TAP-Harness-Restricted-0.002 ... cp lib/TAP/Harness/Restricted.pm blib/lib/TAP/Harness/Restricted.pm Manifying blib/man3/TAP::Harness::Restricted.3 PERL_DL_NONLAZY=1 /Users/rjbs/.plenv/versions/18.2/bin/perl5.18.2 "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/lib', 'blib/arch')" t/*.t t/00-compile.t ......... ok t/00-report-prereqs.t .. # Prerequisite Report: # Version Module # -------- --------------------- # 6.86 ExtUtils::MakeMaker # 1.23 File::Find # 3.40 File::Spec::Functions # 0.2304 File::Temp # 1.005 File::pushd # 1.35 List::Util # 0.051 Path::Tiny # 3.30 TAP::Harness # 0.008 Test::FailWarnings # 1.001002 Test::More # 1.07 strict # 0.002 superclass # 1.18 warnings t/00-report-prereqs.t .. ok t/test.t ............... ok All tests successful. Files=3, Tests=3, 0 wallclock secs ( 0.03 usr 0.01 sys + 0.24 cusr 0.03 csys = 0.31 CPU) Result: PASS Installing /Users/rjbs/.plenv/versions/18.2/lib/perl5/site_perl/5.18.2/TAP/Harness/Restricted.pm Installing /Users/rjbs/.plenv/versions/18.2/man/man3/TAP::Harness::Restricted.3 Appending installation info to /Users/rjbs/.plenv/versions/18.2/lib/perl5/5.18.2/darwin-2level/perllocal.pod OK Successfully installed TAP-Harness-Restricted-0.002 Installing /Users/rjbs/.plenv/versions/18.2/lib/perl5/site_perl/5.18.2/darwin-2level/.meta/TAP-Harness-Restricted-0.002/install.json Installing /Users/rjbs/.plenv/versions/18.2/lib/perl5/site_perl/5.18.2/darwin-2level/.meta/TAP-Harness-Restricted-0.002/MYMETA.json Expiring 2 work directories. 2 distributions installed
  18. 48.

    t/00-report-prereqs.t ........... ok t/compile-time-file.t ........... ok t/compile-time.t ................ ok t/inherit-classfromclassfile.t

    .. ok t/inherit-classfromfile.t ....... ok t/inherit-pmc.t ................. ok t/inherit-returns-false.t ....... ok t/inherit.t ..................... ok t/version-check.t ............... ok All tests successful. Files=10, Tests=50, 1 wallclock secs ( 0.04 usr 0.02 sys + 0.36 cusr 0.05 csys = 0.47 CPU) Result: PASS Manifying blib/man3/superclass.3 Installing /Users/rjbs/.plenv/versions/18.2/lib/perl5/site_perl/5.18.2/superclass.pm Installing /Users/rjbs/.plenv/versions/18.2/man/man3/superclass.3 Appending installation info to /Users/rjbs/.plenv/versions/18.2/lib/perl5/5.18.2/darwin-2level/ perllocal.pod OK Successfully installed superclass-0.002 Installing /Users/rjbs/.plenv/versions/18.2/lib/perl5/site_perl/5.18.2/darwin-2level/.meta/ superclass-0.002/install.json Installing /Users/rjbs/.plenv/versions/18.2/lib/perl5/site_perl/5.18.2/darwin-2level/.meta/ superclass-0.002/MYMETA.json Building and testing TAP-Harness-Restricted-0.002 ... cp lib/TAP/Harness/Restricted.pm blib/lib/TAP/ Harness/Restricted.pm Manifying blib/man3/TAP::Harness::Restricted.3 PERL_DL_NONLAZY=1 /Users/rjbs/.plenv/versions/18.2/bin/perl5.18.2 "-MExtUtils::Command::MM" "- MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/lib', 'blib/arch')" t/*.t t/00-compile.t ......... ok t/00-report-prereqs.t .. # Prerequisite Report: # Version Module # -------- --------------------- # 6.86 ExtUtils::MakeMaker # 1.23 File::Find # 3.40 File::Spec::Functions
  19. 49.

    t/00-compile.t ......... ok t/00-report-prereqs.t .. # Prerequisite Report: # Version

    Module # -------- --------------------- # 6.86 ExtUtils::MakeMaker # 1.23 File::Find # 3.40 File::Spec::Functions # 0.2304 File::Temp # 1.35 List::Util # 0.28 Module::Load # 1.001002 Test::More # 1.07 strict # 1.03 vars # 0.9906 version # 1.18 warnings t/00-report-prereqs.t ........... ok t/compile-time-file.t ........... ok t/compile-time.t ................ ok t/inherit-classfromclassfile.t .. ok t/inherit-classfromfile.t ....... ok t/inherit-pmc.t ................. ok t/inherit-returns-false.t ....... ok t/inherit.t ..................... ok t/version-check.t ............... ok t/pod-syntax .................... not ok ha ha ha sucker
  20. 60.

    ! ! system(cowsay => $motto); if ($?) { my $exit

    = $? >> 8; die "it exited $exit"; }
  21. 61.

    ! ! system(cowsay => $motto); if ($?) { my $exit

    = $? >> 8; my $signal = $? & 127; die "it exited $exit" . ", signal $signal"; }
  22. 62.
  23. 66.
  24. 70.

    my @todo = sort { $a->todo eq 'eat pie' ?

    -1 : $b->todo eq 'eat pie' ? 1 : $a->priority <=> $b->priority } stuff_i_gotta_do;
  25. 71.

    use Sort::ByExample 'sbe'; ! my $sorter = sbe( [ 'eat

    pie', 'eat cake' ], { xform => sub { $_[0]->todo }, fallback => sub { $_[3]->priority <=> $_[2]->priority }, } ); ! my @todo = $sorter->( stuff_i_gotta_do );
  26. 72.

    use Sort::ByExample 'sbe'; ! my $sorter = sbe( [ 'eat

    pie', 'eat cake' ], # <---- { xform => sub { $_[0]->todo }, fallback => sub { $_[3]->priority <=> $_[2]->priority }, } ); ! my @todo = $sorter->( stuff_i_gotta_do );
  27. 76.

    not ok - matching text # got: 'Everything is okay!'

    # expected: 'Everything is okay!'
  28. 78.

    use Test::BinaryData; ! my $want = read_expected_file; my $have =

    perform_some_operation; ! is_binary($have, $want, "matching text"); !
  29. 79.

    # have (hex) have want (hex) want # 457665727974 Everyt

    = 457665727974 Everyt # 68696e67a069 hing.i ! 68696e672069 hing i # 73a06f6b6179 s.okay ! 73206f6b6179 s okay # 21---------- ! = 21---------- !
  30. 80.

    # have (hex) have want (hex) want # 457665727974 Everyt

    = 457665727974 Everyt # 68696e67a069 hing.i ! 68696e672069 hing i # 73a06f6b6179 s.okay ! 73206f6b6179 s okay # 21---------- ! = 21---------- !
  31. 81.

    # have (hex) have want (hex) want # 457665727974 Everyt

    = 457665727974 Everyt # 68696e67a069 hing.i ! 68696e672069 hing i # 73a06f6b6179 s.okay ! 73206f6b6179 s okay # 21---------- ! = 21---------- !
  32. 84.
  33. 86.

    • locking over NFS is "interesting • SQL locks are

    released if your connection is interrutped
  34. 87.

    • locking over NFS is "interesting • SQL locks are

    released if your connection is interrutped • (use autoreconnect? you won't notice!)
  35. 88.

    • locking over NFS is "interesting • SQL locks are

    released if your connection is interrutped • (use autoreconnect? you won't notice!) • sometimes a really stupid hack is good enough
  36. 89.

    use DBIx::Locker; ! my $locker = DBIx::Locker->new(\%arg); ! for my

    $todo (@agenda) { my $lock = $locker->lock($todo->id); ... }
  37. 90.

    CREATE TABLE semaphores ( id int PRIMARY KEY AUTO_INCREMENT, lockstring

    varchar(128) UNIQUE, created datetime NOT NULL, expires datetime NOT NULL, locked_by text NOT NULL );
  38. 91.

    CREATE TABLE semaphores ( id int PRIMARY KEY AUTO_INCREMENT, lockstring

    varchar(128) UNIQUE, created datetime NOT NULL, expires datetime NOT NULL, locked_by text NOT NULL );
  39. 96.

    use less 'cpu'; ! use less 'memory'; ! use less

    'stack'; ! use less 'processes';
  40. 97.

    use less 'cpu'; ! use less 'memory'; ! use less

    'stack'; ! use fewer 'processes';
  41. 100.
  42. 102.
  43. 103.

    $sock->send("UPDATE $key $value"); ! Use of uninitialized value ($key) in

    concatenation (.) or string 5.10's Best Change (that's 5.8-safe)
  44. 108.

    ! ! if (length $xyz) { ... } ! !

    ! ! ! 5.12's Best Change (that's 5.8-safe)
  45. 109.

    ! if (length $xyz) { ... } ! if (length($xyz

    // $xyz)) { ... } ! ! 5.12's Best Change (that's 5.8-safe)
  46. 110.

    ! if (length $xyz) { ... } ! if (length($xyz

    // $xyz)) { ... } ! if (defined $xyz && length $xyz) { ... } 5.12's Best Change (that's 5.8-safe)
  47. 111.

    if (length $xyz) { ... } ! if (length($xyz //

    $xyz)) { ... } ! if (defined $xyz && length $xyz) { ... } ! if (length $xyx > 0) { ... } 5.12's Best Change (that's 5.8-safe)
  48. 114.

    package Mr::Fusion 1.234; use strict; sub produce_energy { my ($self,

    garbage) = @_; ... return $Watt * 1.21 * (10 ** 9); } 5.14's Best Change (it's a tie)
  49. 115.

    package Mr::Fusion 1.234 { use strict; sub produce_energy { my

    ($self, garbage) = @_; ... return $Watt * 1.21 * (10 ** 9); } } 5.14's Best Change (it's a tie)
  50. 116.
  51. 117.

    (my $y2013 = $y2012) =~ s!Mario!Luigi!g; ! my $y2013 =

    $y2012 =~ s!Mario!Luigi!gr; ! 5.14's Best Change (it's a tie)
  52. 118.

    (my $y2013 = $y2012) =~ s!Mario!Luigi!g; ! my $y2013 =

    $y2012 =~ s!Mario!Luigi!gr; ! my @y2013 = map {s!Mario!Luigi!gr} @y2012; 5.14's Best Change (it's a tie)
  53. 125.

    my $fact = sub { my $n = shift; $n

    == 1 ? 1 : $n * __SUB__->( $n - 1 ); }; 5.16's Best Change (the other one)
  54. 129.

    my %hash = (a => 1, b => 2, c

    => 3); 5.20's Best Change??
  55. 130.

    my %hash = (a => 1, b => 2, c

    => 3); @hash{ qw( a c ) } ➜ (1, 3) 5.20's Best Change??
  56. 131.

    my %hash = (a => 1, b => 2, c

    => 3); @hash{ qw( a c ) } ➜ (1, 3) %hash{ qw( a c ) } ➜ (a => 1, c => 3); 5.20's Best Change??
  57. 132.

    my %hash = (a => 1, b => 2, c

    => 3); @hash{ qw( a c ) } ➜ (1, 3) %hash{ qw( a c ) } ➜ (a => 1, c => 3); @array = qw( a b c d ); 5.20's Best Change??
  58. 133.

    my %hash = (a => 1, b => 2, c

    => 3); @hash{ qw( a c ) } ➜ (1, 3) %hash{ qw( a c ) } ➜ (a => 1, c => 3); @array = qw( a b c d ); %array[ 0, 2, 1 ] 5.20's Best Change??
  59. 134.

    my %hash = (a => 1, b => 2, c

    => 3); @hash{ qw( a c ) } ➜ (1, 3) %hash{ qw( a c ) } ➜ (a => 1, c => 3); @array = qw( a b c d ); %array[ 0, 2, 1 ] ➜ (0 => 'a', 2 => 'c', 1 => 'd' ); 5.20's Best Change??
  60. 139.

    my $user = { ... rjbs => { ..., goals

    => [ "eat risotto", "eat pie", ] }, };
  61. 140.
  62. 151.
  63. 159.
  64. 164.

    use experimental 'postderef'; $array_ref->@[ 0, 1, 5 ]; $hash__ref->@{ qw(a

    b) ]; $array_ref->%[ 0, 1, 5 ]; $hash__ref->%{ qw(a b) ];
  65. 165.

    use experimental 'postderef'; $array_ref->@[ 0, 1, 5 ]; $hash__ref->@{ qw(a

    b) ]; $array_ref->%[ 0, 1, 5 ]; $hash__ref->%{ qw(a b) ]; $glob_ref->*{SCALAR}; # Sorry!
  66. 168.
  67. 172.

    $ perl -Dspot your-program.plx $ perl -d:Xyz your-program.plx -D is

    for debugging perl's code -d is for debugging Perl code
  68. 175.
  69. 177.

    $^P

  70. 178.

    0x001 debug sub entry/leave 0x002 call DB::DB per statement 0x004

    turn off optimizer 0x008 save more stuff 0x010 keep sub definition info 0x020 single-step 0x040 use subroutine addrs 0x080 report "goto &sub" 0x100 better eval names 0x200 better sub names 0x400 source in @{"_<$file"}
  71. 179.

    0x001 debug sub entry/leave 0x002 call DB::DB per statement 0x004

    turn off optimizer 0x008 save more stuff 0x010 keep sub definition info 0x020 single-step 0x040 use subroutine addrs 0x080 report "goto &sub" 0x100 better eval names 0x200 better sub names 0x400 source in @{"_<$file"}
  72. 180.

    0x001 debug sub entry/leave 0x002 call DB::DB per statement 0x004

    turn off optimizer 0x008 save more stuff 0x010 keep sub definition info 0x020 single-step 0x040 use subroutine addrs 0x080 report "goto &sub" 0x100 better eval names 0x200 better sub names 0x400 source in @{"_<$file"}
  73. 181.

    package Devel::Stupid; ! package DB { sub DB { my

    ($package, $filename, $line) = caller; return unless $filename eq $0; Devel::LineTimer::emit_trace($filename, $line); } }
  74. 182.
  75. 187.

    sub emit_trace { my ($filename, $line) = @_; state $prev;

    @code = @{"::_<$filename"}; my $now = Time::HiRes:time();
  76. 188.

    sub emit_trace { my ($filename, $line) = @_; state $prev;

    @code = @{"::_<$filename"}; my $now = Time::HiRes:time(); $line_of_code = $code[ $line ];
  77. 189.

    sub emit_trace { my ($filename, $line) = @_; state $prev;

    @code = @{"::_<$filename"}; my $now = Time::HiRes:time(); $line_of_code = $code[ $line ]; if ($prev) {
  78. 190.

    sub emit_trace { my ($filename, $line) = @_; state $prev;

    @code = @{"::_<$filename"}; my $now = Time::HiRes:time(); $line_of_code = $code[ $line ]; if ($prev) { my $took = $time - $prev{time};
  79. 191.

    sub emit_trace { my ($filename, $line) = @_; state $prev;

    @code = @{"::_<$filename"}; my $now = Time::HiRes:time(); $line_of_code = $code[ $line ]; if ($prev) { my $took = $time - $prev{time}; printf "%8.04f %s", $took, $prev{code}; }
  80. 192.

    sub emit_trace { my ($filename, $line) = @_; state $prev;

    @code = @{"::_<$filename"}; my $now = Time::HiRes:time(); $line_of_code = $code[ $line ]; if ($prev) { my $took = $time - $prev{time}; printf "%8.04f %s", $took, $prev{code}; } $prev = { time => $time, code => $line_of_code }; }
  81. 195.
  82. 199.

    if ( $not_likely && $really_rare && $does_this_ever_happen ) { #

    some really # annoying-to-maintain # code }
  83. 204.

    sub alive { my ($ident) = @_; ! my $sock

    = IO::Socket::INET->new( Proto => 'udp', PeerAddr => "$HOST:$PORT", ); ! unless ($sock) { warn "error opening UDP socket: $!"; return; } ! my $data = JSON->new->encode({ ident => $ident, user => getpwuid($>) || '(unknown)', }); ! $sock->send($data) or warn "couldn't send: $!"; }
  84. 205.

    my $sock = IO::Socket::INET->new( Proto => 'udp', LocalHost => 0,

    LocalPort => 3030, MultiHomed => 1, ); while (1) { my $addr = $sock->recv(my $data, 1024); my (undef, $remote) = sockaddr_in($addr); my $ip_addr = inet_ntoa($remote_addr); ! ## log data and ip_addr to file }
  85. 208.

    my $f = 20; ! # prepare for spawning! !

    while ($f--) { if (fork) { next; } else { # do stuff sleep 30; exit; } } ! while (1) { my $pid = wait; last if $pid == -1; say "$pid exited"; }
  86. 210.

    my $f = 20; ! # prepare for spawning! !

    while ($f--) { if (fork) { next; } else { # do stuff sleep 30; exit; } } ! while (1) { my $pid = wait; last if $pid == -1; say "$pid exited"; }
  87. 211.

    my $f = 20; ! # prepare for spawning! !

    while ($f--) { if (fork) { next; } else { require Dist::Zilla; sleep 30; exit; } } ! while (1) { my $pid = wait; last if $pid == -1; say "$pid exited"; }
  88. 213.

    my $f = 20; ! # prepare for spawning! !

    while ($f--) { if (fork) { next; } else { require Dist::Zilla; sleep 30; exit; } } ! while (1) { my $pid = wait; last if $pid == -1; say "$pid exited"; }
  89. 214.

    my $f = 20; ! # prepare for spawning! require

    Dist::Zilla; ! while ($f--) { if (fork) { next; } else { # do work exit; } } ! while (1) { my $pid = wait; last if $pid == -1; say "$pid exited"; }
  90. 219.

    package PostForkINC; ! sub import { my ($self, $code) =

    @_; ! my $pid = $$; ! my $callback = sub { return if $pid == $$; my (undef, $filename) = @_; $code->($filename); return; }; ! unshift @INC, $callback; };
  91. 220.

    package PostForkINC::Alive; ! sub import { my ($class, $ident) =

    @_; ! require PostForkINC; PostForkINC->import(sub { my ($filename) = @_; $filename =~ s{\.pm\z}{}; alive("postfork.$ident.$filename"); }); } use PostForkINC::Alive 'pie-eater';
  92. 221.

    postfork.riddle-mda.Class-ISA postfork.riddle-mda.Crypt-SSLeay postfork.riddle-mda.Crypt-SSLeay-CTX postfork.riddle-mda.Crypt-SSLeay-MainContext postfork.riddle-mda.Crypt-SSLeay-X509 postfork.riddle-mda.DBD-mysql-GetInfo postfork.riddle-mda.DBIx-Class-Cursor postfork.riddle-mda.DBIx-Class-SQLMaker postfork.riddle-mda.DBIx-Class-SQLMaker-LimitDialects postfork.riddle-mda.DBIx-Class-SQLMaker-MySQL

    postfork.riddle-mda.DBIx-Class-Storage-DBI-Cursor postfork.riddle-mda.DBIx-Class-Storage-DBI-mysql postfork.riddle-mda.Data-Hive-PathPacker postfork.riddle-mda.Data-Hive-PathPacker-Strict postfork.riddle-mda.Email-Date-Format postfork.riddle-mda.Encode-Byte postfork.riddle-mda.Encode-CJKConstants postfork.riddle-mda.Encode-CN postfork.riddle-mda.Encode-CN-HZ postfork.riddle-mda.Encode-JP postfork.riddle-mda.Encode-JP-JIS7 postfork.riddle-mda.Encode-KR postfork.riddle-mda.Encode-KR-2022_KR postfork.riddle-mda.Encode-MIME-Header postfork.riddle-mda.Encode-TW postfork.riddle-mda.HTML-Entities postfork.riddle-mda.HTML-HeadParser postfork.riddle-mda.HTML-Parser postfork.riddle-mda.HTTP-Config postfork.riddle-mda.HTTP-Headers-Util postfork.riddle-mda.HTTP-Request-Common postfork.riddle-mda.Hash-Merge postfork.riddle-mda.LWP-Protocol-https postfork.riddle-mda.Net-DNS-RR-A postfork.riddle-mda.Net-DNS-RR-CNAME postfork.riddle-mda.Net-DNS-RR-MX postfork.riddle-mda.Net-DNS-RR-PTR postfork.riddle-mda.Net-DNS-RR-SOA postfork.riddle-mda.Net-HTTPS
  93. 223.

    [alias] ci = commit -a cl = clean -dfx cc

    = cherry-pick ff = merge --ff-only fx = commit -a --amend -C HEAD ix = diff --cached st = status -sb fap = fetch --all --prune wip = commit -a -m WIP git = !git
  94. 224.

    hist = log --graph --all \ --color=always \ --decorate !

    shist = log --graph \ --color=always \ --decorate
  95. 225.
  96. 227.
  97. 228.

    $ git re-edit • if there are dirty files, edit

    them • otherwise, edit the files edited in last commit • or supply a commit to edit the files changed in it
  98. 229.

    if ($commit) { chomp(@changed = grep /\S/, qx{git show --pretty="format:"

    --name-only $commit}); } else { chomp(@changed = qx{git status -- porcelain}); exit 1 unless $? == 0; @changed = grep !/^\?\? /, @changed unless $opt{q}; s/^.. // or die "<$_>???\n" for @changed; s/.* -> // for @changed; die "Fucking shell, how does it work?\n" if grep / /, @changed; ! chomp(@changed = qx{find @changed -type f }) if @changed; exit 1 unless $? == 0; }
  99. 230.

    extending git is easy • the git-* convention • it's

    all built on mostly-simple commands • (even if some of them are sort of dumb) • look at the commands I showed for examples
  100. 234.
  101. 235.
  102. 236.
  103. 237.
  104. 238.
  105. 239.
  106. 240.
  107. 241.
  108. 242.
  109. 245.

    • brand new server every time! • user accounts created

    automatically • vim, emacs, whatever you need: installed
  110. 246.

    • brand new server every time! • user accounts created

    automatically • vim, emacs, whatever you need: installed • all thrown away when you're done
  111. 248.
  112. 249.

    • brand new server every time! • user accounts created

    automatically • vim, emacs, whatever you need: installed • all thrown away when you're done
  113. 250.

    • brand new server every time! • user accounts created

    automatically • vim, emacs, whatever you need: installed • all thrown away when you're done • but where are my dotfiles?
  114. 251.
  115. 253.

    dots: ! - repo: git@github.com:rjbs/rjbs-dots.git - repo: git@github.com:rjbs/rjbs-osx-dots.git - repo:

    git@github.com:rjbs/rjbs-vim-dots.git - repo: rjbs@git.rj.bs:git/rjbs-mail-dots.git - repo: rjbs@git.rj.bs:git/rjbs-private-dots.git
  116. 254.

    dots: ! - repo: git@github.com:rjbs/rjbs-dots.git - repo: git@github.com:rjbs/rjbs-osx-dots.git - repo:

    git@github.com:rjbs/rjbs-vim-dots.git - repo: rjbs@git.rj.bs:git/rjbs-mail-dots.git - repo: rjbs@git.rj.bs:git/rjbs-private-dots.git
  117. 255.

    dots: ! - repo: git@github.com:rjbs/rjbs-dots.git - repo: git@github.com:rjbs/rjbs-osx-dots.git - repo:

    git@github.com:rjbs/rjbs-vim-dots.git - repo: rjbs@git.rj.bs:git/rjbs-mail-dots.git - repo: rjbs@git.rj.bs:git/rjbs-private-dots.git
  118. 256.

    dots: ! - repo: git@github.com:rjbs/rjbs-dots.git - repo: git@github.com:rjbs/rjbs-osx-dots.git - repo:

    git@github.com:rjbs/rjbs-vim-dots.git - repo: rjbs@git.rj.bs:git/rjbs-mail-dots.git - repo: rjbs@git.rj.bs:git/rjbs-private-dots.git
  119. 257.

    ! dots: ! - repo: git@github.com:rjbs/rjbs-dots.git - repo: git@github.com:rjbs/rjbs-osx-dots.git -

    repo: git@github.com:rjbs/rjbs-vim-dots.git - repo: rjbs@git.rj.bs:git/rjbs-mail-dots.git - repo: rjbs@git.rj.bs:git/rjbs-private-dots.git ! - repo: rjbs@git.wo.rk:git/rjbs-work-dots.git
  120. 258.

    Dude, where's my .zshrc? ! ! dots: ! - repo:

    git@github.com:rjbs/rjbs-dots.git - repo: git@github.com:rjbs/rjbs-osx-dots.git - repo: git@github.com:rjbs/rjbs-vim-dots.git - repo: rjbs@git.rj.bs:git/rjbs-mail-dots.git - repo: rjbs@git.rj.bs:git/rjbs-private-dots.git ! ! !
  121. 259.

    dots: - repo: git@github.com:sharpsaw/loop-dots.git - repo: git@github.com:rjbs/rjbs-dots.git - repo: git@github.com:rjbs/rjbs-osx-dots.git

    - repo: git@github.com:rjbs/rjbs-vim-dots.git - repo: rjbs@git.rj.bs:git/rjbs-mail-dots.git - repo: rjbs@git.rj.bs:git/rjbs-private-dots.git
  122. 261.
  123. 263.

    use ... • get your dotfiles under version control •

    …and shared between your computers
  124. 264.

    use ... • get your dotfiles under version control •

    …and shared between your computers • …but still with per-host-specific stuff
  125. 265.

    use ... • get your dotfiles under version control •

    …and shared between your computers • …but still with per-host-specific stuff • …and split between shareable and private
  126. 266.

    use ... • get your dotfiles under version control •

    …and shared between your computers • …but still with per-host-specific stuff • …and split between shareable and private • …so you can share your config!
  127. 267.

    use ... • get your dotfiles under version control •

    …and shared between your computers • …but still with per-host-specific stuff • …and split between shareable and private • …so you can share your config! • …and maybe do more pairing!
  128. 275.
  129. 276.
  130. 286.
  131. 288.
  132. 289.
  133. 290.
  134. 291.
  135. 292.
  136. 293.

    You already produce a lot of data, that can tell

    you a lot about what you're doing! (that's the point)
  137. 294.

    sub did_reading { my ($self, $prev) = @_; # Recorded

    is the number of items that were 14 days old yesterday. The # number of items 15 days old today should be fewer. my %count; # stupid passing of $self is a temporary situation -- rjbs, 2013-11-04 my @bookmarks = Ywar::Instapaper->bookmark_list($self); my $old_14 = grep { $_->{time} < $^T - 14 * 86_400 } @bookmarks; my $old_15 = grep { $_->{time} < $^T - 15 * 86_400 } @bookmarks; my $last = $prev->{measured_value}; my %result; if ($old_15 < $last) { my $closed = $last - $old_15; @result{ qw(note met_goal) } = ("items read or deleted: $closed", 1); } $result{value} = $old_14; return \%result; }
  138. 295.

    sub bookmark_list { my ($self, $configger) = @_; my $c_key

    = $configger->consumer_key; my $c_secret = $configger->consumer_secret; my $ua = LWP::Authen::OAuth->new( oauth_consumer_secret => $c_secret, oauth_token => $configger->oauth_token, oauth_token_secret => $configger->oauth_token_secret, ); my $r = $ua->post( 'https://www.instapaper.com/api/1/bookmarks/list', [ limit => 200, oauth_consumer_key => $c_key, ], ); my @bookmarks = sort {; $a->{time} <=> $b->{time} } grep {; $_->{type} eq 'bookmark' } @{ JSON->new->decode($r->decoded_content) }; return @bookmarks; }
  139. 296.

    sub bookmark_list { my ($self, $configger) = @_; my $c_key

    = $configger->consumer_key; my $c_secret = $configger->consumer_secret; my $ua = LWP::Authen::OAuth->new( oauth_consumer_secret => $c_secret, oauth_token => $configger->oauth_token, oauth_token_secret => $configger->oauth_token_secret, ); my $r = $ua->post( 'https://www.instapaper.com/api/1/bookmarks/list', [ limit => 200, oauth_consumer_key => $c_key, ], ); my @bookmarks = sort {; $a->{time} <=> $b->{time} } grep {; $_->{type} eq 'bookmark' } @{ JSON->new->decode($r->decoded_content) }; return @bookmarks; } LWP::Authen::OAuth
  140. 297.
  141. 299.

    API Auth • Basic HTTP Authentication: means sharing pw •

    In-site token generation: user as token broker
  142. 300.

    API Auth • Basic HTTP Authentication: means sharing pw •

    In-site token generation: user as token broker • OAuth 1: strict protocol, complex helper libs
  143. 301.

    API Auth • Basic HTTP Authentication: means sharing pw •

    In-site token generation: user as token broker • OAuth 1: strict protocol, complex helper libs • OAuth 2: it's more like a state of mind
  144. 302.

    sub bookmark_list { my ($self, $configger) = @_; my $c_key

    = $configger->consumer_key; my $c_secret = $configger->consumer_secret; my $ua = LWP::Authen::OAuth->new( oauth_consumer_secret => $c_secret, oauth_token => $configger->oauth_token, oauth_token_secret => $configger->oauth_token_secret, ); my $r = $ua->post( 'https://www.instapaper.com/api/1/bookmarks/list', [ limit => 200, oauth_consumer_key => $c_key, ], ); my @bookmarks = sort {; $a->{time} <=> $b->{time} } grep {; $_->{type} eq 'bookmark' } @{ JSON->new->decode($r->decoded_content) }; return @bookmarks; }
  145. 304.

    my $client = Net::OAuth::Client->new( $self->api_key, $self->secret, site => 'https://oauth.withings.com/', request_token_path

    => '/account/request_token', authorize_path => '/account/authorize', access_token_path => '/account/access_token', callback => 'oob', );
  146. 305.

    my $client = OAuth::Lite2::Client::WebServer->new( id => $id, secret => $secret,

    authorize_uri => q{https://runkeeper.com/apps/authorize}, access_token_uri => q{https://runkeeper.com/apps/token}, ); ! my $url = $client->uri_to_redirect( redirect_uri => q{http://rjbs.manxome.org/}, ); ! say $url; chomp( my $code = <STDIN> ); ! my $access_token = $client->get_access_token( code => $code, redirect_uri => q{http://rjbs.manxome.org/}, ) or die $client->errstr; ! print Dumper({ access_token => $access_token->access_token, expires_at => time() + $access_token->expires_in, refresh_token => $access_token->refresh_token, });
  147. 306.

    my $auth = base64_encode("$user:$pass", ""); my $ua = LWP::UserAgent->new(keep_alive =>

    1); $ua->default_header(Authorization => "Basic $auth"); my $res = $ua->get("https://api.feedbin.me/v2/entries.json");
  148. 309.
  149. 310.
  150. 312.
  151. 313.
  152. 315.

    package SampleBot; use Moses; server 'irc.perl.org'; nickname 'sample-bot'; channels '#bots';

    event irc_bot_addressed => sub { my ($self, $nickstr, $channel, $msg) = @_[OBJECT, ARG0, ARG1, ARG2]; my ($nick) = split /!/, $nickstr; $self->privmsg( $channel => "$nick: Hey there." ); }; SampleBot->run;
  153. 316.

    event START => sub { my ($self) = $_[OBJECT]; $self->delay(300

    => 'consider_nagging'); }; ! event consider_nagging => sub { my ($self) = $_[OBJECT]; $self->delay(300 => 'consider_nagging'); return if $self->timer_running; return if $self->nagged_recently; $self->send_angry_privmsg; };
  154. 318.
  155. 320.

    event consider_nagging => sub { my ($self) = $_[OBJECT]; $self->delay(300

    => 'consider_nagging'); return if $self->timer_running; return if $self->nagged_recently; $self->send_angry_privmsg; };
  156. 321.

    event consider_nagging => sub { my ($self) = $_[OBJECT]; $self->delay(300

    => 'consider_nagging'); return if $self->timer_running; return if $self->nagged_recently; if ($self->being_ignored) { $self->send_angry_sms; } else { $self->send_angry_privmsg; $self->being_ignored(1); } };
  157. 322.

    event consider_nagging => sub { my ($self) = $_[OBJECT]; $self->delay(300

    => 'consider_nagging'); return if $self->timer_running; return if $self->nagged_recently; if ($self->being_ignored) { $self->send_angry_sms; } else { $self->send_angry_privmsg; $self->being_ignored(1); } };
  158. 324.

    sub sms { my ($self, $number, $msg) = @_; !

    my $ua = LWP::UserAgent->new; my $res = $ua->post( "https://api.twilio.com/2010-04-01/Accounts/$SID/SMS/Messages", { From => $my_twilio_number, To => $number, Body => $msg, }, Authorization => "Basic $AUTH}", ); }
  159. 326.
  160. 328.
  161. 329.
  162. 330.
  163. 331.
  164. 332.

    POE::Component::Server::SimpleHTTP->new( ALIAS => 'httpd', ADDRESS => 0, PORT => $self->httpd_port,

    HANDLERS => [ { DIR => '^/sms$', SESSION => 'Synergy', EVENT => '_http_sms', }, ], );
  165. 333.

    POE::Component::Server::SimpleHTTP->new( ALIAS => 'httpd', ADDRESS => 0, PORT => $self->httpd_port,

    HANDLERS => [ { DIR => '^/sms$', SESSION => 'Synergy', EVENT => '_http_sms', }, ], ); event _http_sms => sub { my ($kernel, $self, $req, $res) = @_[KERNEL, OBJECT, ARG0, ARG1]; $response->code(200); $response->content( $self->response_for($req) ); $kernel->call( 'httpd', 'DONE', $response ); };
  166. 336.

    If you're not mashing up web service APIs with an

    asynchronous daemon… …you are living a half life.
  167. 337.

    If you're not mashing up web service APIs with an

    asynchronous daemon… …you are living a half life.
  168. 339.
  169. 340.
  170. 344.
  171. 346.