Posts de ‘Tiago Peczenyj’

[Tiago Peczenyj] MooseX - a new Ruby DSL for Object Oriented Programming (and much more)

Friday, February 7th, 2014

MooseX is a postmodern object DSL for Ruby Build Status Gem Version

This is a DSL for object creation, aspects, method delegation and much more. It is based on Perl Moose and Moo, two important modules who add a better way of Object Orientation development (and I enjoy A LOT). Using a declarative stype, using Moose/Moo you can create attributes, methods, the entire constructor and much more. But I can’t find something similar in Ruby world, so I decide port a small subset of Moose to create a powerfull DSL for object construction.

Of course, there is few similar projects in ruby like

But the objetive of MooseX is different: this is a toolbox to create Classes based on DSL, with unique features like

  • method delegation ( see ‘handles’)
  • lazy attributes
  • roles
  • parameterized roles
  • composable type check
  • events

and much more.

This rubygem is based on this modules:

See also:

  • Joose, a javascript port of Moose.
  • Perl 6 Perl 6 OO programming style.

Why MooseX? Because the namespace MooseX/MooX is open to third-party projects/plugins/extensions. You can upgrade your Moo(se) class using other components if you want. And there is one gem called ‘moose’ :/

THIS MODULE IS EXPERIMENTAL YET! BE CAREFUL!

Talk is cheap. Show me the code!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
require 'moosex'

class Point
  include MooseX

  has x: {
    is: :rw,      # read-write (mandatory)
    isa: Integer, # should be Integer
    default: 0,   # default value is 0 (constant)
  }

  has y: {
    is: :rw,
    isa: Integer,
    default: lambda { 0 }, # you should specify a lambda
  }

  def clear!
    self.x= 0     # to run with type-check you must
    self.y= 0     # use the setter instad @x=
  end
end

# now you have a generic constructor
p1  = Point.new                       # x and y will be 0
p2  = Point.new( x:  5 )              # y will be 0
p3  = Point.new( x:  5, y: 4)

Installation

Add this line to your application’s Gemfile:

gem 'moosex'

And then execute:

$ bundle

Or install it yourself as:

$ gem install moosex

You need ruby 2.0.x or superior.

Description

MooseX is an extension of Ruby object system. The main goal of MooseX is to make Ruby Object Oriented programming easier, more consistent, and less tedious. With MooseX you can think more about what you want to do and less about the mechanics of OOP. It is a port of Moose/Moo from Perl to Ruby world.

Read more about Moose on http://moose.iinteractive.com/en/

Motivation

It is fun

Usage

You just need include the MooseX module in your class and start to describe the attributes with our DSL. This module will inject one smart constructor, acessor and other necessary methods.

Instead the normal way of add accessors, constructor, validation, etc

1
2
3
4
5
6
7
8
9
10
11
12
class Foo
  attr_accessor :bar, :baz, :bam

  def initialize(bar=0, baz=0, bam=0)
    unless [bar, baz, bam].all? {|x| x.is_a? Integer }
      raise "you should use only Integers to build Foo"
    end
    @bar = bar
    @baz = baz
    @bam = bam
  end
end

you can do this:

1
2
3
4
5
6
7
8
9
class Foo
  include MooseX

  has [:bar, :baz, :bam], {
    is: :rw,
    isa: Integer,
    default: 0
  }
end

Contributing

  1. Fork it ( http://github.com/peczenyj/MooseX/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request Push to the branch (git push origin my-new-feature)

[Tiago Peczenyj] Adding a ‘dry run’ capability to your Moose class with MooseX::Role::DryRunnable

Sunday, April 7th, 2013

A ‘dry run’ is a testing process where the effects of a possible failure are intentionally mitigated. For example, an aerospace company may conduct a “dry run” test of a jet’s new pilot ejection seat while the jet is parked on the ground, rather than while it is in flight. Or, in software development, we can change the behavior of some methods in order to test, like avoid change data into a database (logging the action instead).

There are many ways to implement this capability. For example, we can add an explicity return in each method and test some condition. I will show some options in this article and we will find how to use the module MooseX::Role::DryRunnable in our Moose classes (Perl).

One simple example in Perl, reading from an environment variable DRY_RUN.

1
2
3
4
5
6
7
package Foo;

sub bar {
  logger->debug("Foo::bar @_");
  return if $ENV{'DRY_RUN'};
  ...
}

(more…)

[Tiago Peczenyj] Lazy::Bool my first module in CPAN

Wednesday, January 23rd, 2013

Lazy::Bool is my first module in CPAN (The Comprehensive Perl Archive Network). It is a simple module (only 60 lines) and few methods/operators but can be useful in some situation. The source code can be found in my github.

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
use Lazy::Bool;
use Test::More tests=> 3;
my $a = 6;
my $b = 4;
my $x  = Lazy::Bool->new(sub{ $a > $b });
my $false = Lazy::Bool::false;

my $result = ($x | $false) & ( ! ( $false & ! $false ) );

# now the expressions will be evaluate
ok($result,    "complex expression should be true");
ok(!! $x ,  "double negation of true value should be true");
ok(!!! $false, "truple negation of false value should be true");

(more…)

[Tiago Peczenyj] Schwartzian transform

Tuesday, January 22nd, 2013

I will show in this post one of the most useful things that I learn in Perl: the famous Schwartzian transform. With examples in Ruby

In computer science, the Schwartzian transform is a Perl programming idiom used to improve the efficiency of sorting a list of items. This idiom is appropriate for comparison-based sorting when the ordering is actually based on the ordering of a certain property (the key) of the elements, where computing that property is an intensive operation that should be performed a minimal number of times. The Schwartzian Transform is notable in that it does not use named temporary arrays.

Wikipedia en.wikipedia.org/wiki/…

1
2
3
4
5
6
7
8
array = 1..5

def foo(x)
    # some expensive calculation...
  x.to_s
end

array.sort { |a,b| foo(a) <=> foo(b) }

In this example, foo are called 12 times. With +5 more elements in this array we jump to 52 calls. If foo is very expensive it is a waste of cpu. What we can do? Memoize is an option but I need to add an extra gem in my project. The solution is… Schwartzian transform!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
array = 1..5

def foo(x)
    # some expensive calculation...
  x.to_s
end

array.map{ |original|
  [original, foo(original)]  # add the original and pre-calculated value
}.sort { |a,b|
  a.last <=> b.last          # perform comparation
}.map{|x|
  x.first                    # extract the original, drop the pre-calculated value
}

In this case we use the double of memory (to store the original and foo(original)) but we call foo only 5 times.

We can use this pattern to solve other problems, sort is just one of them. Every time when we have one expensive calculation and we call this many times, maybe we can solve using this technique.

Now, look at this code:

1
2
3
4
5
6
7
8
array = 1..5

def foo(x)
    # some expensive calculation...
  x.to_s
end

array.sort_by{|x| foo(x) }

Using sort_by we can use the power of Schwartzian transform for many cases if our sort is based on a simple comparation.

The original version, in perl

1
2
3
4
@sorted = map  { $_->[0] }
          sort { $a->[1] cmp $b->[1] }
          map  { [$_, foo($_)] }
               @unsorted;

Other languagens has some kind of support like D 2.0, with schwartzSort function. You can find an example in PHP Here.

[Tiago Peczenyj] Codility Equi Task Solution in Modern Perl

Thursday, January 10th, 2013

Codility is one of the most common services used to apply test codes (for job applications, for example). Here you can find a task sample to pratice before try the real test. The present sample is the Equi Task, and the propose is very simple.

Imagine an array with N elements. There is a P value (0 <= P <= N) who solve the problem below?

A[0] + A[1] + ... + A[P−1] = A[P+1] + ... + A[N−2] + A[N−1].

In other words, where is the equilibrium index of this array?

For example, consider the following array A consisting of N = 7 elements:

A[0] = -7   A[1] =  1   A[2] = 5
A[3] =  2   A[4] = -4   A[5] = 3
A[6] =  0

P = 3 is an equilibrium index of this array, because:

A[0] + A[1] + A[2] = A[4] + A[5] + A[6]

The task is build one subroutine called equi who will receive the array should return the value of P, or -1 if there is no equilibrium index.

Easy? Well, there is another challenge: create a O(n) solution.

Here is my solution in Perl:

use strict;
use warnings;
use v5.10;
use List::Util qw(sum first);

sub equi {
  my (@A)   = @_;
  my $right = sum(@A);
  my $size  = scalar @A;

  my $p     = first {
    state $pivot  = 0;
    state $left  += $pivot;
    $pivot  = $A[$_];
    $right -= $pivot;

    $left == $right
  } 0 .. $size - 1;

  $p // -1
}

use Test::More tests => 4;

is(equi(-7,1,5,2,-4,3,0),3,"example");
is(equi(1..5),-1,"simple");
is(equi(),-1,"trivial");
is(equi(555),0,"single");

Using Perl 5.10 or superior, you can run the code and see the result

1..4
ok 1 - example
ok 2 - simple
ok 3 - trivial
ok 4 - single

I’m using two new features: the defined-or operator and state variables.

The defined-or is like a regular logic or BUT consider only undefined values as ‘false’. Instead doing this:

1
(defined $p)? $p : -1

you can do only

1
$p // -1

0 is a valid value for P, but 0 is false for boolean operations. For example, te code below fails:

1
$p || -1

the test ‘single’, where I have only one element.

The List::Util first subroutine is similar to grep, we can pass a block and an array, and we evaluate the block for each element of the array until the block returns a true value, then stops. If I can’t find anything, the subroutine return undef.

Another feature is the state variable. Instead do this

1
2
my $pivot = 0;
my $p = first { ... ; $pivot  = $A[$_]; ... }

We just declare the state variable

1
2
my $pivot = 0;
my $p = first { state $pivot = 0; ... ; $pivot  = $A[$_]; ... }

In this case, $pivot is a state variable. The keyword state declares a lexically scoped variable, just like my. However, those variables will never be reinitialized, contrary to lexical variables that are reinitialized each time their enclosing block is entered.

And sum returns the sum of all elements of this array.

I think now is easy to read and understand the code. Perl is not difficult to read, we just need practice.

[Tiago Peczenyj] Spell Correct in GNU AWK

Saturday, December 29th, 2012

Based on Peter Norvig Spell Correct

# Usage: gawk -v word=some_word_to_verify -f spelling.awk [ big.txt
[ big2.txt ... ]]
# Gawk version with 15 lines -- 04/13/2008
# Author: tiago (dot) peczenyj (at) gmail (dot) com
# Based on : http://norvig.com/spell-correct.html
function edits(w,max,candidates,list,        i,j){
       for(i=0;i<  max ;++i) ++list[substr(w,0,i) substr(w,i+2)]
       for(i=0;i< max-1;++i) ++list[substr(w,0,i) substr(w,i+2,1)
substr(w,i+1,1) substr(w,i+3)]
       for(i=0;i<  max ;++i) for(j in alpha) ++list[substr(w,0,i)
alpha[j] substr(w,i+2)]
       for(i=0;i<= max ;++i) for(j in alpha) ++list[substr(w,0,i)
alpha[j] substr(w,i+1)]
       for(i in list) if(i in NWORDS) candidates[i] = NWORDS[i] }

function correct(word            ,candidates,i,list,max,temp){
       edits(word,length(word),candidates,list)
       if (!asort(candidates,temp)) for(i in list)
edits(i,length(i),candidates)
       return (max = asorti(candidates)) ? candidates[max] : word }

BEGIN{ if (ARGC == 1) ARGV[ARGC++] = "big.txt" # http://norvig.com/big.txt
       while(++i<=length(x="abcdefghijklmnopqrstuvwxyz"))
alpha[i]=substr(x,i,1)
       IGNORECASE=RS="[^"x"]+" }

{      ++NWORDS[tolower($1)]   }

END{   print (word in NWORDS) ? word : "correct("word")=> "
correct(tolower(word)) }

[Tiago Peczenyj] hello

Saturday, December 29th, 2012

Hello World!

[Tiago Peczenyj] FFmpeg new version

Thursday, December 22nd, 2011

Changelog for 0.9 version.

Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest.

version 0.9:

- openal input device added
- boxblur filter added
- BWF muxer
- Flash Screen Video 2 decoder
- lavfi input device added
- added avconv, which is almost the same for now, except
for a few incompatible changes in the options, which will hopefully make them
easier to use. The changes are:
* The options placement is now strictly enforced! While in theory the
options for ffmpeg should be given in [input options] -i INPUT [output
options] OUTPUT order, in practice it was possible to give output options
before the -i and it mostly worked. Except when it didn’t – the
behavior was
a bit inconsistent. In avconv, it is not possible to mix input and output
options. All non-global options are reset after an input or
output filename.
* All per-file options are now truly per-file – they apply only to the next
input or output file and specifying different values for different files
will now work properly (notably -ss and -t options).
* All per-stream options are now truly per-stream – it is possible to
specify which stream(s) should a given option apply to. See the Stream
specifiers section in the avconv manual for details.
* In ffmpeg some options (like -newvideo/-newaudio/…) are irregular in the
sense that they’re specified after the output filename instead of before,
like all other options. In avconv this irregularity is removed,
all options
apply to the next input or output file.
* -newvideo/-newaudio/-newsubtitle options were removed. Not only were they
irregular and highly confusing, they were also redundant. In
avconv the -map
option will create new streams in the output file and map input streams to
them. E.g. avconv -i INPUT -map 0 OUTPUT will create an output stream for
each stream in the first input file.
* The -map option now has slightly different and more powerful syntax:
+ Colons (‘:’) are used to separate file index/stream type/stream index
instead of dots. Comma (‘,’) is used to separate the sync
stream instead
of colon.. This is done for consistency with other options.
+ It’s possible to specify stream type. E.g. -map 0:a:2 creates an
output stream from the third input audio stream.
+ Omitting the stream index now maps all the streams of the given type,
not just the first. E.g. -map 0:s creates output streams for all the
subtitle streams in the first input file.
+ Since -map can now match multiple streams, negative mappings were
introduced. Negative mappings disable some streams from an already
defined map. E.g. ‘-map 0 -map -0:a:1′ means ‘create output
streams for
all the stream in the first input file, except for the second audio
stream’.
* There is a new option -c (or -codec) for choosing the decoder/encoder to
use, which allows to precisely specify target stream(s) consistently with
other options. E.g. -c:v lib264 sets the codec for all video
streams, -c:a:0
libvorbis sets the codec for the first audio stream and -c copy copies all
the streams without reencoding. Old -vcodec/-acodec/-scodec
options are now
aliases to -c:v/a/s
* It is now possible to precisely specify which stream should an AVOption
apply to. E.g. -b:v:0 2M sets the bitrate for the first video
stream, while
-b:a 128k sets the bitrate for all audio streams. Note that the
old -ab 128k
syntax is deprecated and will stop working soon.
* -map_chapters now takes only an input file index and applies to the next
output file. This is consistent with how all the other options work.
* -map_metadata now takes only an input metadata specifier and applies to
the next output file. Output metadata specifier is now part of the option
name, similarly to the AVOptions/map/codec feature above.
* -metadata can now be used to set metadata on streams and chapters, e.g.
-metadata:s:1 language=eng sets the language of the first stream to ‘eng’.
This made -vlang/-alang/-slang options redundant, so they were removed.
* -qscale option now uses stream specifiers and applies to all streams, not
just video. I.e. plain -qscale number would now apply to all
streams. To get
the old behavior, use -qscale:v. Also there is now a shortcut -q
for -qscale
and -aq is now an alias for -q:a.
* -vbsf/-absf/-sbsf options were removed and replaced by a -bsf option which
uses stream specifiers. Use -bsf:v/a/s instead of the old options.
* -itsscale option now uses stream specifiers, so its argument is only the
scale parameter.
* -intra option was removed, use -g 0 for the same effect.
* -psnr option was removed, use -flags +psnr for the same effect.
* -vf option is now an alias to the new -filter option, which uses
stream specifiers.
* -vframes/-aframes/-dframes options are now aliases to the new
-frames option.
* -vtag/-atag/-stag options are now aliases to the new -tag option.
- XMV demuxer
- LOAS demuxer
- ashowinfo filter added
- Windows Media Image decoder
- amovie source added
- LATM muxer/demuxer
- Speex encoder via libspeex
- JSON output in ffprobe
- WTV muxer
- Optional C++ Support (needed for libstagefright)
- H.264 Decoding on Android via Stagefright
- Prores decoder
- BIN/XBIN/ADF/IDF text file decoder
- aconvert audio filter added
- audio support to lavfi input device added
- libcdio-paranoia input device for audio CD grabbing
- Apple ProRes decoder
- CELT in Ogg demuxing
- G.723.1 demuxer and decoder
- libmodplug support (–enable-libmodplug)
- VC-1 interlaced decoding
- libutvideo wrapper (–enable-libutvideo)
- aevalsrc audio source added
- Ut Video decoder
- Speex encoding via libspeex
- 4:2:2 H.264 decoding support
- 4:2:2 and 4:4:4 H.264 encoding with libx264
- Pulseaudio input device
- Prores encoder
- Video Decoder Acceleration (VDA) HWAccel module.
- replacement Indeo 3 decoder
- new ffmpeg option: -map_channel
- volume audio filter added
- earwax audio filter added
- libv4l2 support (–enable-libv4l2)
- TLS/SSL and HTTPS protocol support
- AVOptions API rewritten and documented
- most of CODEC_FLAG2_*, some CODEC_FLAG_* and many codec-specific fields in
AVCodecContext deprecated. Codec private options should be used instead.
- Properly working defaults in libx264 wrapper, support for native presets.
- Encrypted OMA files support
- Discworld II BMV decoding support
- VBLE Decoder
- OS X Video Decoder Acceleration (VDA) support
- compact and csv output in ffprobe
- pan audio filter
- IFF Amiga Continuous Bitmap (ACBM) decoder
- ass filter #meldels
- CRI ADX audio format demuxer
- Playstation Portable PMP format demuxer
- Microsoft Windows ICO demuxer
- life source
- PCM format support in OMA demuxer
- CLJR encoder
- new option: -report
- Dxtory capture format decoder
- cellauto source

[Tiago Peczenyj] YAPC::Brasil 2011 Yet Another Perl Conference

Monday, October 24th, 2011

É com muita satisfação que venho anunciar que a grade de palestras do YAPC::Brasil 2011 já está no ar (minha palestra será sábado)!

http://www.yapcbrasil.org.br/2011/schedule

Esse ano o evento contará ainda com ninguém menos que *brian d foy* como keynote, em sua segunda visita ao Brasil! Brian é o criador da primeira comunidade Perl Mongers do mundo e autor/co-autor de diversos livros de Perl, como “Learning Perl” (o livro da lhama), “Mastering Perl” e “Effective Perl Programming”.

Demais palestras contém temas muito bacanas como Webdev, TDD, OpenData, JavaScript, Facebook e muito mais, em dois dias inteiros regados de palestras de qualidade para todos os níveis de conhecimento.

Mas… dois dias? Não eram três?

Sim, e essa é mais uma novidade: na sexta-feira, dia 4, teremos um mini-curso de UM DIA INTEIRO com o tema “Effective Perl Programming”, ministrado pelo próprio brian d foy!

http://www.yapcbrasil.org.br/2011/minicurso.html

Não fique fora dessa! As vagas são limitadas, então acesse o link e inscreva-se já!

[Tiago Peczenyj] Slides da Apresentação Perl Moderno

Sunday, June 5th, 2011
Perl Moderno

View more presentations from peczenyj.