nunojob:~ dscape/08$ echo The Black Sheep

Archive for the ‘English’ Category

dreamhost insanity day

The deal was – well – insanely good.

Unlimited storage and traffic, 1 domain name (plus all the extras) for two years. If you inserted 202 as promo code you would get a final price of 11USD.

I was lucky enough to get an update from Pedro while dreamhost was working and got a great deal. Even got a new domain name I was looking for: dscape.org! Yay! I had to use Google Checkout to buy as the website was not very stable and I didn’t want to risk it with a credit card transfer.

As one would expect *not* dreamhost.com was down for most of the day after the news started spreading on twitter. Dreamhost guys called that sluggish!? A hosting company website down by self DoS attack? As Alanis Morrissette would say “isn’t that ironic?”

The only thing visible thing that dreamhost did to change this was change the price to 22USD. Whoever decided that is clearly not the brightest crayon in the box. A hosting company is about having a stable service. You never charge different prices for the same service in the same day. If you want to do an insane promo, be prepared. Is it that hard to come up with a way to get the same (or more) customers without having your website on his knees and old customers leaving your service??

Final Considerations: How many cancelled their subscriptions paying 10USD a month for this deal? How much of a money loss will that represent for dreamhost? Is this a clear sign of a urgent need for income? Is it just insanity? How much money did Google made on this (1USD per transfer)? How many new domains were registered today?

Some photo updates

Portugal at MoMa

Portugal at MoMa

No new years eve photos are online (yet). But if you feel like checking Christmas, Tony’s Birthday After-Party and a nice Manhattan party you can check those links.

For all my readers (Hello mom,  hows google translator working out for you?) I wish you all a great new year. I would wish the same to non-readers but hey I guess it doesn’t make sense as you won’t read it!

Happy new year.

RSA Encrypt & Decrypt in ruby

Well I finished the encrypt with RSA on ruby some hours ago and felt like sharing :)

Case you feel like doing something back for me just download the latest release of my beta twitter client and send me some comments to my email. It’s pretty hard to test something when my environment is completely contaminated !

require 'openssl'
require 'Base64'

class Rudolph
  class Crypt
    def initialize data_path
      @data_path = data_path
      @private   = get_key 'id_rsa'
      @public    = get_key 'id_rsa.pub'
    end

    def encrypt_string message
      Base64::encode64(@public.public_encrypt(message)).rstrip
    end

    def decrypt_string message
      @private.private_decrypt Base64::decode64(message)
    end

    def self.generate_keys data_path
      rsa_path = File.join(data_path, 'rsa')
      privkey  = File.join(rsa_path, 'id_rsa')
      pubkey   = File.join(rsa_path, 'id_rsa.pub')
      unless File.exists?(privkey) || File.exists?(pubkey)
        keypair  = OpenSSL::PKey::RSA.generate(1024)
        Dir.mkdir(rsa_path) unless File.exist?(rsa_path)
        File.open(privkey, 'w') { |f| f.write keypair.to_pem } unless File.exists? privkey
        File.open(pubkey, 'w') { |f| f.write keypair.public_key.to_pem } unless File.exists? pubkey
      end
    end

    private
    def get_key filename
      OpenSSL::PKey::RSA.new File.read(File.join(@data_path, 'rsa', filename))
    end
  end
end

Rudolph – Yet another Twitter client

I felt like trying the Shoes framework. Here are the results so far. When I get some free time I’ll try to post some guidelines to do something like this.

Webpage: http://the-shoebox.org/apps/105

Github: http://github.com/dscape/rudolph

Apache CouchDB

It’s official. yey! Great news :) 

Damien’s post.

NYU visit to hawthorn

I had to pleasure to be one of the hosts for NYU group visit in Hawthorn. The students were very lucky and got to see really good talks. Robert Morris presented explained why services are so important for IBM and how research applies to business. It was really an excellent spontaneous talk and it was to bad he didn’t stick around so I could talk to him about it. Then they got to see talk on Stream Processing and how to manage real time processing and analysis for quantities of data that are possible considered impossible to handle by most common people. I also managed to see Grady Booch for the first time, in second life. He also gave an great talk about the beauty of software (www.booch.com/architecture/blog/artifacts/Turing%20Lecture.ppt) and showed the potential of second life for this kind of event. By then both Robert and Grady had my curiosity set on the future in what concerns intellectual property but I guess that’s not a good subject for showing IBM to graduate students :) eheh. It finished in beauty  with Laxmi talking about the famous Genographic Project (https://www3.nationalgeographic.com/genographic). For those who still don’t know the genographic project is a joint venture between IBM and National Geographic where they try to find out more about the history of migrations using DNA. Cool!! The social aspect was also really important and I think students were happy with the feedback we gave them about IBM. By the way the lack of blog posts is mostly because Twitter is taking over all my blog post that can fit in under one hundred and something chars.

SVN Hub

Source LeviFig

Clojure – Ulisses this one is for you

Clojure is a dynamic programming language that targets the Java Virtual Machine. It is designed to be a general-purpose language, combining the approachability and interactive development of a scripting language with an efficient and robust infrastructure for multithreaded programming. Clojure is a compiled language – it compiles directly to JVM bytecode, yet remains completely dynamic. Every feature supported by Clojure is supported at runtime. Clojure provides easy access to the Java frameworks, with optional type hints and type inference, to ensure that calls to Java can avoid reflection.

Clojure is a dialect of Lisp, and shares with Lisp the code-as-data philosophy and a powerful macro system. Clojure is predominantly a functional programming language, and features a rich set of immutable, persistent data structures. When mutable state is needed, Clojure offers a software transactional memory system and reactive Agent system that ensure clean, correct, multithreaded designs.

Now that sounds nice right? Give it a try.

Favorite cartoon characters

I love cartoons. Being more specific I love watching Southpark and The Simpsons. So I was watching an episode right now and decided to post some shorts clips from my favorite characters in the shows.

Both shows have nice characters that make me laugh a lot. For instance Cartman / Butters episodes normally put me rolling on the couch laughing. Butters is hilarious. From the Simpsons Ralph is my favorite character. Too bad is not featured that often in the episodes.

So here goes some shorts clips on those two and if you want you can always whole the seasons of southpark online at southparkstudios.com/episodes. Enjoy!

Git, SVN, CVS

Just a few days ago I was talking to a friend of mine completely astonished that he was using CVS at work. Not only he was using it, he was being taught how to use it. I told him about SVN existence and the fact that even though SVN (Subversion) was some kind of evolution on CVS it still sucked big time. I then showed him some of my projects on git and some popular website that make it easier to track your git repo. I went on trying to explain how much easier, more reliable and light git was and how it was a really wonderful piece of software for any developer. Open source does make the world a better place. What I had no clue about was that git was originally written by Linus Torvald. Really I had no idea until today when I found this talk on this old friend from prt.sc.

Some Pictures from New York

Thank you Susan for taking them while I still haven’t bought a decent camera :) I will probably have some more when Mailar decides to put them online. Maybe once he returns from SVL.

By the way doesn’t that duck look menacing? :\ More pictures? Here.

No reason to disapear

Well ever since I started working time for my blog has been less. I really dislike that as this little corner gives me a lot of joy not only in the moment of writing but also for the great joy that is sharing information and enabling others to learn new and exciting technologies. That’s one of the things I want to talk about today. The power of sharing.

Last two weeks I was contacted by people (mostly experienced people) that were using either my k-anonimity algorithm or my open source online testing system. The fact that people are using my silly scripts is rewarding enough but the networking opportunities and being a person enabler is really what thrills me the most. It’s pleasant to see people overcome their difficulties, help them learn a new technology and then seeing the final result. I hope to continue receiving your kind emails about my work. I will always have 5 minutes to help.

I think that if you are a blogger but you don’t share what your doing your missing out. Your code will vanish into some CD or will just remain in some folder, buried forever. Let your code live. Let it enable others. Let it grow. In the meantime it will help you get wherever you want. Actually I got another exciting news just for sharing. But unfortunately I cant disclose them just yet. It involves being invited to help writing a free Ruby on Rails book. Sorry, had to say it :) How cool is that?

Actually, the most boring thing about working at large corporation is the fact that you cannot share what you do. It no longer belongs to you and even if it’s ok to share it you have to follow a complex process to get authorization to do so. So no one does! Everybody is waiting to sue so you simply can’t do things that you assume would be ok. Referring a copyright brand without referring that the brand belongs to x can cost the company a significant amount (and your job :P) and they simply can’t risk it. But oh well. The least you can say is that the good things cancel that out.

I have beenworking on DB2 and I’m widely surprised by the quality of the pureXML support and overall behavior of the solution. The lack of advertising and tools that IBM distributes with DB2 doesn’t give you the same amount of trust that other better advertised and with better tools databases do. But when you get down to business you will realize that DB2 and Oracle are on a league of their own. Just talking to the clients will make you realise that they buy because other databases can’t handle the amount of information. And if you do XML, for the next 6 months at least I’m sure that DB2 will be miles ahead. How much longer will it take for companies to realize that storing xml in clobs ain’t probably the best solution? Anwser: Not much…

Oh, final note! I finally picked the theme for my masters thesis. It will be about data mining in xml databases so if you feel like you have a nice tittle suggestion for it just leave it in the comment box. It will be greatly appreciated.

Open Source Online Testing System (OSOTS)

I simply can’t believe that I forgot to post this project in my blog. Anyway if you have to deploy a multiple choice test and you feel like messing arround with Ruby on Rails and DB2 here goes the link.

Open Source Online Testing System (OSOTS)

thetravelhat.com – The Travel Hat Journey Has Begun

So what is the travel hat?

It’s simple. It’s the unique hat of power – my precious – that travels all around the world. There are some simple rules. You are expected to try to give the hat as soon as possible, to a good friend in which you trust. That friend is expected to take it to a new city where the hat has never been before. Diversity is a major factor for the hat so it’s supposed to go to new and exciting places every time he travels. If you can you should choose for the diversity of the destination. Once reached that destination the search for a new owner begins.

This is still a alpha version so there are some known issues like the invalid rss feed (aka the nonexistent rss feed, because the stylesheet is still not implemented)

Upcoming Features:

  • Does not highlight current location.
  • Does not show total miles traveled.
  • Does not show total countries visited.
  • Does not list the nationalities that held the hat.
  • Stylesheet to create the feed from the XML file.
  • Administration system with db2 pureXML.
  • Improve (aka do some) webdesign.

Follow it’s latest adventures on thetravelhat.com.

MeMe

Also known as I’m extremely bored. Sorry for the nudity but hey, I just followed instructions.

MeMe by you.

1.Take a picture of yourself right now.
2. Don’t change your clothes, don’t fix your hair…just take a picture. (should be super-easy with Photobooth)
3. Post that picture with NO editing.
4 Post these instructions with your picture.

Lego Mac Pro

Não gosto muito de usar o meu blog para fazer simples foward de um artigo de outro estáminé. Para isso uso o botão share no google reader. (caso me queiram adicionar a lista de amigos, o meu email está aqui)

Mas desta vez não consigo resistir. É que este post no blog da MAKE deixou-me com um sorriso parvo na cara de achar a ideia de fazer um caixa com lego tão fixe. E claro, tinha que ser um mac! Faz-me lembrar dos projectos insanos do Anders como montar um PC numa banheira e por-lo a correr mergulhado em óleo. Até partilhava o link mas não me lembro bem o nome que ele deu ao vídeo no youtube. (Anders where’s the video of the PC you assembled on a bathtub? Because of you this is now the worse post in the history of internet.)

Para que este artigo não seja completamente inútil partilho também que vi que existem empresas que contratam especialistas com legos, especialmente pessoal que trabalha com os technics. É um skill porreiro para fazer protótipos. Na Bang & Olufsen usam lego para a simular a mecânica do prototipo e flash/director para a demonstração interactiva do dispositivo.

Fica a imagem e o link para o artigo original.

Lego Mac Pro 2

Lego Mac Pro 2

Happy Birthday Anerds

Hey Anders! Here’s a picture of your birthday party at Portugal. Ten people attended and two of them actually know who you are!! How great is that!? :X More pictures will be here as soon as Pedro does the f*cking work :D

Mondrian Multidimensional K-Anonymity in Ruby

Article: Mondrian Multidimensional K-Anonymity

Lame Ruby Implementation:

# ==================================================================================
# anonymization: group.rb
# ==================================================================================
ENVIRONMENT = 'release' #'release'

require 'set'
require 'rubygems'
require 'ruby-debug' if ENVIRONMENT == 'debug'

# ==================================================================================
# class group
#
# usage:
#  require 'group'
#
#  g = Group.new <quasi_ids>, <filename>
#  g.anonymize <k>
#
# example:
#
# lefevre.db
# 
#     0             2   < -- quasi_ids
#
#   |age|  sex  | zipc | disease      |
#---+---+-------+------+--------------+--
# 0 | 25  Male    53711 Flu           |
# 1 | 25  Female  53712 Hepatitis     |
# 2 | 26  Male    53711 Bronchitis    |
# 3 | 27  Male    53710 Broken_Arm    |
# 4 | 27  Female  53712 AIDS          |
# 5 | 28  Male    53711 Hang_Nail     |
#---+---+-------+------+--------------+--
#
# irb
#  >> require 'group'
#  >> g = Group.new [0,2], 'lefevre.db'
#  >> g.anonymize 2, 'degen'
# ==================================================================================
class Group
  # create a setter method for @tuples, @filename
  # so that g.tuples = x works
  attr_writer :tuples, :filename
  
  @@debug = { 'best_attribute' => ENVIRONMENT == 'debug',
              'intersection'   => ENVIRONMENT == 'debug',
              'split'          => ENVIRONMENT == 'debug',
              'ordering'       => ENVIRONMENT == 'debug',
              'vars'           => ENVIRONMENT == 'debug',
              'args'           => ENVIRONMENT == 'debug'
           }
  # ================================================================================
  # to create a new group with Group.new
  # ================================================================================
  # needs to remove the full_ids from the read.
  def initialize(quasi_ids, filename, depth=0, available_ids=nil)
    # if no valid attributes are given quasi are used
    available_ids = quasi_ids if available_ids.nil?
    
    # initialize the instance vars
    @tuples = []
    @quasi_ids = quasi_ids
    @available_ids = available_ids
    @depth = depth

    # serves as wilcard so that no file is read on recursion
    filename == '*wc' ? @filename = nil : @filename = filename
    
    if @@debug['args'] and @depth == 0
      debug_puts "args : file => #{@filename}"
      debug_puts "args : k => #{@k}"
      debug_puts "args : quasi_ids => #{@quasi_ids.to_s}"
    end
              
    
    # run the read and backup procedures
    read
  end
  
  # ================================================================================
  # anonymization
  # ================================================================================
  def anonymize(k, heuristic='degen', partial_order=[])
    
    if @@debug['vars']
      #debug_puts "dvars : @tuples #{@tuples}" 
      debug_puts "dvars : @available_ids #{@available_ids},"
      debug_puts "dvars : @depth #{@depth}"
    end

    # stop case
    if isnt_splittable? k
      debug_puts "dsplit: no split available for k-level #{k} with size" +
                 " #{@tuples.size}" if @@debug['split']

      # sort and generalize remaining attributes
      @available_ids.each do |attribute|
        sort attribute
        generalize attribute
      end

      # exit
      return
    end

    # where and in what attribute should we split
    # these functions have a heavy effect on the usefulness of the information
    # for the k-anonymity table
    split_attribute  = find_split_attribute @available_ids, heuristic, partial_order
    split_pos        = find_split_position split_attribute

    # create the groups for the 
    # recursion
    group1 = Group.new @quasi_ids, '*wc', @depth + 1, @available_ids.clone
    group2 = Group.new @quasi_ids, '*wc', @depth + 1, @available_ids.clone

    # split at the given position
    split split_pos, group1, group2

    if split_groups_satisfy_k_anonymity?(k,group1,group2)
  
      debug_puts "dsplit: no more split available with attribute" + 
          " #{split_attribute} (g1: #{group1.size}, g2: #{group2.size})" if @@debug['split']

      # generalize by split_attribute and then remove it from the available
      # attributes array
      generalize split_attribute
      @available_ids.delete split_attribute

      # anonymize remaining available attributes
      anonymize k, heuristic, partial_order

    else # splitting successful
      debug_puts "dsplit: splitting on attribute #{split_attribute} at" +
                 " position #{split_pos} of #{@tuples.size}" if @@debug['split']
      
      # assign the two groups to this instance
      @group1 = group1
      @group2 = group2
      
      group1.anonymize k, heuristic, partial_order
      group2.anonymize k, heuristic, partial_order
      
      #@tuples = []
    end
  end

  # ================================================================================
  # io and backup related 
  # ================================================================================
  # read @tuples from @filename
  def read
    unless @filename.nil?
      f = File.open @filename
      f.each_line do |line|
        @tuples < < line.rstrip.split("\t\t")
      end
      f.close
    end
  end
  

  # reset the class to reuse
  def reset
    @available_ids  = @originally_available_ids
    @tuples = []
    read
  end

  # ================================================================================
  # overrides
  # ================================================================================
  # number of tuples
  def size
    @tuples.size
  end

  # ================================================================================
  # aux
  # ================================================================================
  # to_s
  
  def to_s
    
    str = ""
    
    unless @tuples.empty?
      @tuples.each do |line| 
        @tuples[0].size.times { |i| str << line[i].to_s + "\t\t"}
        str << "\n"
      end
    end

    str
  end

  # shows a yaml representation of internal object
  def to_y
    require 'yaml'
    y self
  end

  private
  
  def debug_puts(message)
    ident=''
    @depth.times {|i| ident+="  "}
    puts ident + message
  end

  # ================================================================================
  # aux for anonymization
  # ================================================================================
  # finds the attribute with the largest range. According to LeFevre this is a good
  # heuristic to find the attribute on
  def find_split_attribute(attributes_list, heuristic, partial_order)

    debug_puts "dorder: choosing from" + 
               " #{attributes_list.to_s}" if @@debug['ordering']

    best_attrib = -1
    best_attrib_count = 0.0

    attributes_list = find_minimal_elements partial_order, attributes_list

    debug_puts "dorder: minimal list is" +
               " #{attributes_list.to_s}" if @@debug['ordering']

    attributes_list.each do |attribute|
      values = @tuples.map{|t| t[attribute]}.to_set
  
      # degen heuristic: split on the attribute that had more degeneracy
      if heuristic == 'degen'
        if values.size < best_attrib_count or best_attrib == -1
          best_attrib = attribute
          best_attrib_count = @tuples.size.to_f / values.size.to_f
        end
      elsif heuristic == 'single'
        if values.size < best_attrib_count or best_attrib == -1
          best_attrib = attribute
          best_attrib_count = values.size
        end
      else #default
        if values.size > best_attrib_count
          best_attrib = attribute
          best_attrib_count = values.size
        end
      end
    end

    debug_puts "dbest : best atribute is #{best_attrib} with" + 
               " count #{best_attrib_count}" if @@debug['best_attribute']
    
    return best_attrib
  end
  
  #  returns the position of the leftmost or rightmost median element.
  #  used to split in lhs and rhs 
  def find_split_position(attribute_id)
    sort attribute_id
    
    median_pos = @tuples.size / 2
    median = @tuples[median_pos][attribute_id]
    
    split_pos_high = median_pos
    split_pos_low  = median_pos
    
    # split point correspond to highest index that has median value
    split_pos_high += 1 while (@tuples.size >= split_pos_high + 2) and
                              (@tuples[split_pos_high + 1][attribute_id] == median)
      
    high_smaller_group_size = 
            [split_pos_high + 1, @tuples.size - split_pos_high - 1].min

    # split point correspond to lowest index that has median value
    split_pos_low -= 1 while (split_pos_low > 1) and
                              (@tuples[split_pos_low - 1][attribute_id] == median)
    
    low_smaller_group_size = 
            [split_pos_low, @tuples.size - split_pos_low].min
    
    # choose the one with the largest group
    if high_smaller_group_size > low_smaller_group_size
      split_pos = split_pos_high
    else
      split_pos = split_pos_low - 1
    end
    
    return split_pos
  end
  
  # finds minimal elements from the list of the given attribute list according to
  # partial order specified in partial_order. partial_order contains all complete chains.
  def find_minimal_elements(partial_order, possible_elements)
    
    if partial_order.empty?
      debug_puts "dorder: no ordering specified" if @@debug['ordering']
      
      return possible_elements
    end

    # choose all possible_elements that arent in partial_order
    # those are minimal
    minimal_list = possible_elements.select { |element| !partial_order.flatten.member?(element) }
    
    # haskell goodies ^^
    # restrict partial_order to values in possible_elements
    restricted_partial_order = partial_order.map { |l| l.select { |element| possible_elements.member?(element) } }
    
    if @@debug['ordering']
      debug_puts "dorder: possible_elements list is" + 
                 " #{possible_elements.to_s}"
      debug_puts "dorder: partial_order list is" +
                 " #{partial_order.to_s}" 
      debug_puts "dorder: restricted_partial_order is" + 
                 " #{restricted_partial_order.to_s}"
    end

   non_zero_chains = restricted_partial_order.select { |chain| not chain.empty? }

   non_zero_chains.each do |c|
     candidate = c[0]
     
     minimal = !restricted_partial_order.any? do |chain|
        chain.member?(candidate) and chain[0] != candidate
     end
     
     if minimal and not minimal_list.member?(candidate)
       minimal_list << candidate
     end
   end

   return minimal_list
  end

  # replaces attribute value with generalization that cover all tuples.
  # Expects tuples to be sorted by attribute.
  def generalize(attribute)
    min_val = @tuples[0][attribute]
    max_val = @tuples[-1][attribute]
    
    unless min_val == max_val
      @tuples.each do |t|
        t[attribute] = [min_val, max_val]
      end
    end
    
  end

  def split(split_pos, group1, group2)
    group1.tuples = @tuples[0..split_pos]
    group2.tuples = @tuples[split_pos+1..@tuples.size]
  end

  def sort(attribute)
    @tuples = @tuples.sort_by { |t| t[attribute] }
  end
  
  # ================================================================================
  # verbose conditions
  # ================================================================================
  def isnt_splittable?(k)
    k < 2 or group_cant_be_split_for_level?(k) or no_split_attributes_are_available?
  end
  
  def group_cant_be_split_for_level?(k)
    @tuples.size < 2*k
  end
  
  def no_split_attributes_are_available?
    @available_ids.empty?
  end
  
  def split_groups_satisfy_k_anonymity?(k,group1,group2)
    group1.size < k or group2.size < k
  end
end

# hack on array to display lists correctly
class Array
  def to_s
    "[" + self.join(',') + "]"
  end
end

What am I about?

I used wordle in innovation camp to help with the creativity process. Now I saw a nice post on prt.sc and decided to give my delicious a try. Here’s the result:

Travelling will change you

I just felt like sharing two things. A thought, and a video.

First the thought. The gift of our generation as is globalization. Don’t waste it. Use it at your own advantage. So go visit the world. Meet great people (1, 2). Try new things. Learn things from different cultures. Be silly. Enjoy yourself.

Each day I feel more eager about taking a next step. And each day I try to anticipate the next one so I’ll be ready when the time comes. What should I learn? What do I feel like doing next? Where can I do the most impact to help myself and others, while enjoying myself? (No Anders, not in that way… Go sit in the corner)

It’s up to you to make things happen and whoever keeps saying you can’t. Well, tell them to fuck off. You can, just try hard enough. It always worked for me and I’m just some average guy from some university lost in the north of corruption paradise.

As responses to my question this is what I figured out. I want to be somewhere where I can do what I’m excited about 100% of the time (so googles out, they only do 20% time. And they seem to be on low wages) I choose the place were I’ll be doing my internship based on the assumption and really think I made the right choice :) But I’ll report on that as soon as I start on October 6th.

Now, the video. This is Randy Pausch. Randy was a excellent teacher that achieved everything he wanted from life (ie). He gave a course (and later a masters) that was similar to what Peter tried to do in CD-DIP Summer School. Very inspiring life story. Kudos to him.

Ralph Wiggum

While in Denmark I had the privilege to know many interesting people. One of those, Anders, is a real head case (like myself). In his Easter holidays he produced this video where he found all the quotes in episodes of the Simpsons that are included in Bloodhound Gang’s Ralph Wiggum song. Ralph was always my favorite Simpsons character, but I guess I’m not alone :P Now, be amazed.

By the way. What’s your favorite Simpsons character? :)

CDDIP 08 – Innovation Camp – First Week in Denmark

CDDIP

Pictures here. I´ll add some presentations and prototypes soon.

Diablo 3 – Cinematic Trailer

Promete.. Podem visitar o site que acabou de abrir a coisa de uma hora.

Cuidado com os tigres

Mais uma excelente talk do Steve Yegge.

Scala, now, is the tiger that’s going to kill Java. Because their [type-talisman] argument now has become a paradox, similar to the Paul Graham Blub Paradox thing, right? Because they’re like, “Well, we need static typing in order to engineer good systems. It’s simply not possible otherwise.”

The Scala people come in and they go: “Your type system suuuuuucks. It’s not sound. It’s not safe. It’s not complete. You’re casting your way around it. It doesn’t actually prevent this large class of bugs. How many times have you written catch (NullPointerException x) ... in Java? Our type system doesn’t allow [things like] that.”

Our type system does what you said your type system was doing.

So, therefore, you should be using it! ∴

And the Java people look at it and go: “Wehellll… (cough cough)… I mean, yeah, I mean… (*ahem*)(running finger under collar, as if sweating profusely) They say, “Welllll… you know… it’s awfully… cummmmmbersome… I…”

“We can actually get around the problems in practice that you guys say your type system is solving through Good Engineering Practices.”

(laughter begins to grow)

HA!!! (I point accusingly at the audience, and there’s more laughter)

Yeah.

So Scala is creating a real problem for [Java's] static typing camp now. Because their last little bastion of why they’re using it, the whole tigers argument, they’re like, “Ah, well… we… we keep shotguns in our house.” [This is what they've been reduced to.]

OK? Yeeeeahhhh…

So back to dynamic languages!

Wouldn’t ANTLR be better if written in a dynamic language?

I think making a tool like ANTLR is a non-dynamic language is a shot in the foot!

It just makes sense to use dynamic languages to create meta-language tools. Would facilitate the work of the developer and of the ones writing grammars taking away all that java trash that helps in nothing to make out stuff work. ANTLR is great, but all the negative aspects (from end-user point of view) arise from the fact of having all that unnecessary information and needing to declare types and other stuff that ARE NOT NATURAL for a grammar to have. And the way it’s implemented in Java is just a way of copying the way (bad) dynamic languages work.

grammar Expr; 

options {
  output = AST;
  ASTLabelType = CommonTree;
} 

prog
     : ( stat
         { System.out.println( $stat.tree.toStringTree() ); }
       )+
     ;

stat
     : expr NEWLINE -> expr
     | ID '=' expr NEWLINE -> ^('=' ID expr)
     | NEWLINE ->
     ; 

expr
     : multExpr ( ( '+'^ | '-'^ ) multExpr )*
     ;

multExpr
     : atom ( '*'^ atom )*
     ;

atom
     : INT
     | ID
     | '('! expr ')'!
; 

ID
     : ( 'a'..'z' | 'A'..'Z' )+
     ;

INT
     : '0'..'9'+
     ; 

NEWLINE
     : '\r'? '\n'
     ; 

WS
     : ( ' ' | '\t' | '\n' | '\r' )+
       { $channel=HIDDEN; }
     ;
grammar Expr; 

options {
  output = AST;
} 

prog
     : ( stat
         { puts $stat.to_tree }
       )+
     ;

stat
     : expr NEWLINE
     | ID '=' expr NEWLINE -> ^ // mark the root somehow
     | NEWLINE
     ; 

expr
     : multExpr ( ( '+'^ | '-'^ ) multExpr )*
     ;

multExpr
     : atom ( '*'^ atom )*
     ;

atom
     : INT
     | ID
     | '('! expr ')'!
; 

ID
     : ( 'a'..'z' | 'A'..'Z' )+
     ;

INT
     : '0'..'9'+
     ; 

NEWLINE
     : '\r'? '\n'
     ; 

WS
     : ( ' ' | '\t' | '\n' | '\r' )+
       { skip }
     ;

Just wish I had the time to implement it in Ruby and prove my point! Maybe in the masters thesis..

By the way, the ANTLR Book is great. If you want to learn about grammars and creating DSL’s you will love it. But be advised, you’ll hate the java trash that comes with it.

By the way Google changed their icon.

But once again, who gives a fuck? I sure don’t.

famfamfam flag iconset yaml representation on ruby

First download the flags from famfamfam into a folder called flags (pngs only,
no subfolders!).

Now in the bash:

cd flags
wget http://www.iso.org/iso/iso3166_en_code_lists.txt
ls > file.txt
irb

Now your on the interactive ruby shell (irb).

# If you want to use this as a script just copy 
# the bash lines and put them as
# system 'cd flags'
# system 'wget ...' and so on

# We start treating the output from the ls
# open the ls output
f = File.new 'file.txt'                            
# place the file in lines
lines = f.readlines                                
# map those who have 2 digits codes
lines = lines.select { |line| line.size == 7 }    
# get the 2 digits 
lines = lines.map { |line| line[0..1] }            
f.close

# Then the iso file
# open the iso file
f = File.new 'iso3166_en_code_lists.txt' 
# get rid of the notes          
f.readline                                         
# place the file in iso
iso = f.readlines                                  
# create a new hash
hashed_iso = {}                                    
# select non empty lines
iso.select { |a| !a.rstrip.empty? }.map do |b|
  # remove the whitespaces and split in ';'     
  aux = b.rstrip.split ';'     
  # place info in the hash                    
  hashed_iso[aux[1].downcase] = aux[0].capitalize  
end
f.close

# Now we cross information giving more 
# importance to what's in the iso.
iso_famfamfam = hashed_iso.select {
  # select those who have flags in famfamfam
  |k,v| lines.member? k                            
}.sort_by {
  # sort them by the name the user will see
  |pair| pair[1]                                   
}

# Now we create the contents to store in the yaml file
# create the yaml first line
yaml_lines = "hash: \n"                           
iso_famfamfam.each do |pair|
  # for each pair, create the yaml
  # representation and put in yaml_lines
  yaml_lines < < '  ' + pair[0] + ': ' 
                         + pair[1] + "\n"    
end 

yaml_lines &lt;&lt; "array: ---\n"

iso_famfamfam.each do |pair|
  yaml_lines << '- - ' + pair[0] + "\n  - " 
                            + pair[1] + "\n" 
end 

# put it in a file
f = File.new 'flags.yml', 'w'
f.write yaml_lines
f.close

#sample for loading the yaml into ruby
f = File.new 'flags.yml'
fy = YAML.load f

Now you have your yaml representation of the flags. Do what you please. Personally I’m going to use the file to load it to Ruby when my Ruby on Rails app starts and use it as part of the registration system in the

Windows Live Mess

Não estão todos incrédulos que esteja a postar sobre isto!? Eu estou. Acabei de ler este artigo genial. Para ler, rir, reler e rir outra vez.

Fica uma pequena citação e o artigo original:

How on earth does Microsoft continue to pour massive resources into building the same frigging synchronization platforms again and again? Damn, they just finished building something called Windows Live FolderShare and I haven’t exactly noticed a stampede to that. I’ll bet you’ve never even heard of it. The 3,398th web site that lets you upload and download files to a place on the Internet. I’m so excited I might just die.

Mas não se fica por aqui. Mais aqui:

Java 6 for Mac OS X Leopard is here!!

In the most impressive development of the week I have just discovered that Java 6 was finally released for Mac OS X. I’m in complete disbelief.

Now I almost believe that IBM DB2 Express-C for mac will be released in less that a month. :P

More on this here.

Functional vs Imperative: Round 1

Imperative in python
Functional on a object oriented flavor in ruby

Note: You can do the opposite, ruby in imperative and python in functional (I’m guessing on the python part, but it’s probably true)

# choose all values from a list that are not in a matrix

# imperative in python
res = []

for value in list:
  present = False
  for mlist in matrix:
    if value in mlist:
      present = True
      break
   if not present:
     res.append(value)
# functional in ruby
res = list.select { |value| !matrix.flatten.member? value }

# restrict the matrix to values in list

# imperative strikes back
res = []

for mlist in matrix:
  current_mlist = mlist[:]
  for mvalue in mlist:
    if mvalue not in list:
      current_mlist.remove(mvalue)
  res.append(current_mlist)
# functional responds
res = matrix.map do |mlist| 
  mlist.select { |mvalue| list.member? mvalue } 
end

ROTD: Having fun with Ruby sort and sort_by methods

Simple sorting.

First comes a demonstration of the most common error :P
Then a simple sort
After that comes a first sort_by
And then a complete sort_by (sorted first by fname and then by lname).

>> h = [{'fname' => 'Nuno', 'lname' => 'Job'},
  {'fname' => 'Nuno', 'lname' => 'Fonseca'},
  {'fname' => 'Catarina', 'lname' => 'Pinto'},
  {'fname' => 'Nuno', 'lname' => 'Pinto'},
  {'fname' => 'Nuno', 'lname' => 'Antunes'}
]
>> h.sort
NoMethodError: undefined method '< =>' for 
{"lname"=>"Job", "fname"=>"Nuno"}:Hash
from (irb):35:in `sort'
from (irb):35
from :0
>> h.sort{|a,b| a['fname'] < => b['fname']}
=> [{"lname"=>"Pinto", "fname"=>"Catarina"},
{"lname"=>"Job", "fname"=>"Nuno"},
{"lname"=>"Fonseca", "fname"=>"Nuno"},
{"lname"=>"Pinto", "fname"=>"Nuno"},
{"lname"=>"Antunes", "fname"=>"Nuno"}]
>> h.sort_by{|p| p['fname']}
=> [{"lname"=>"Pinto", "fname"=>"Catarina"},
{"lname"=>"Job", "fname"=>"Nuno"},
{"lname"=>"Fonseca", "fname"=>"Nuno"},
{"lname"=>"Pinto", "fname"=>"Nuno"},
{"lname"=>"Antunes", "fname"=>"Nuno"}]
>> h.sort_by{|p| [p['fname'], p['lname']]}
=> [{"lname"=>"Pinto", "fname"=>"Catarina"},
{"lname"=>"Antunes", "fname"=>"Nuno"},
{"lname"=>"Fonseca", "fname"=>"Nuno"},
{"lname"=>"Job", "fname"=>"Nuno"},
{"lname"=>"Pinto", "fname"=>"Nuno"}]

Haskell $

Note: I know you will look away as soon as you see f x. Please don’t. You can see some interesting things in this post.

I was on the train with João and I was delighted to see my old friend $. I also miss composite (.) but $ is really the coolest shortcut Haskell gives a developer. So what is $?

It’s defined as:

f ($) x = f x

What does it does?

Prelude> let f x = map (succ) $ filter ( < 5 ) x
Prelude> f [4,5,7]
[5]
Prelude> let f  = zipWith ($)
Prelude> f [succ,id] [5,4]
[6,4]

Ulisses gave me the weird example. The first one was created by myself. In the first one we filter a list for numbers that are inferior to five and then we apply succ function to it. That is, we add one. :P Without $ we would have

Prelude> let f x = map (succ) (filter ( < 5 ) x)
Prelude> f [4,5,7]
[5]

So we got the parenthesis off and that always great to help make the code more readable. At least I simply love this symbol. Ulisses sample is quite more complex. First off all because it is in point-free/point-less notation. zipWith is a function that receives two lists and applies then function provided pair by pair. Like if I want to add [1,2,3] and [3,2,1] I can:

Prelude> zipWith (+) [1,2,3] [3,2,1]
[4,4,4]

Ain’t it cool? So in this function we simply apply function that goes in the first list (id and succ) to the numbers in the second. Looks easy like this doesn’t it? ;) If it doesn’t just to read it and digest it and you’ll figure it out easily.

Let code the same samples in Ruby. Unfortunately zipWith (should I commit it? :P) doesn’t exist in ruby I’ll have to work with another sample using plain zip (it’s the same as zipWith (\a b -> [a]++[b])).

irb(main):001:0> [1,2,3].zip([3,2,1])
=> [[1, 3], [2, 2], [3, 1]]

Well ruby handles this pretty well without $. We just need to do:

irb(main):002:0> [1,2,3].zip [3,2,1]

Because it’s object oriented this kind of issues don’t exist in Ruby. There are no expressions with large number of parenthesis as well. despite this I must agree that the Haskell version is far more readable than the ruby one:

irb(main):003:0> [4,5,7].select { 
  |i| i < 5 
}.map { |i| i.succ }
=> [5]

But I still miss $.I miss coding in Haskell. It’s just plain fun.

I hope that I have helped you see why languages like Haskell and Scheme do matter, and others like Python and Ruby can be both useful and fun to work with!

Site do dia

http://nao.quero.imposto.ms/

history | awk ‘{print $2}’ | sort | uniq -c | sort -rn | head

dscape@dscape:~$ history | awk '{print $2}' \
| sort | uniq -c | sort -rn | head
86 sudo
45 cd
27 ll
23 ./script/server
21 rm
17 ls
12 vim
7 startx
5 glxinfo
4 su

The Mist – Movie Review in three words

Worst movie ever.

DB2 Rocks

qs = Question.find_by_sql 
"select X.* from ots_schema.questions," +
  "XMLTABLE (\'$d/question\' passing document as \"d\" " + 
    "COLUMNS question_text VARCHAR(200)" + 
    "PATH \'question_text\') as X"
qs.first.question_text.lstrip
=> "Which of the following is the correct syntax to set the DB2COMM variable to TCPIP?\n  "

If DB2 was had a good DB2 driver and a ActivePureXML (or something adapter) it would so f*ckin rock. Just look at the sample. And the dynamic nature of ruby would enable the flexibility of xml documents.

Please IBM please. DB2 for mac and decent support on Ruby. Don’t make me write things like this no more:

# Once again fixing IBM_DB bugs the ugly way
# with_scope anyone?
add_index :'ots_schema.users', :login

or

t.column :document, :xml

Google reinvents the wheel

About porting Ruby on Rails to Javascript:

In an effort to increase developer productivity at Google, Steve tried to convince the company to adopt Rails (and consequently Ruby) as a programming language. When that fell on deaf ears (Google really does not want to increase the number of languages that must be supported by their infrastructure), Steve decided to do what any other frustrated programmer would do: he ported Rails to JavaScript. Line by line. In 6 months. Working 2000 hours. Steve is a coding stud.

From: Steve Yegge ported Rails to JavaScript

In this six months Steve could have contributed to the rails core and improved the framework to a great extent. If he found security issues like the article refers than he should have fixed them in rails. I cannot even begin to understand why he didn’t by the way. Or at least reported them.

My conclusion of seeing that google allowed a employee to waste 6 months of work because they don’t want to increase the number of languages that must be supported by their infrastructure is that Google is Dumb.

Steve seems like a smart guy so if I was told to rewrite Ruby on Rails by an employer I cannot understand why he didn’t – at the very least – refused to do so and pointed out how stupid it was to reinvent the wheel. I simply hate javascript and love ruby. I think javascript is the worst thing there is in the internet. That’s one of the reasons I decided to take a chance on XForms. Well but that’s a personal opinion and has nothing to do with the case!
The question is:

So will this bring something new to the web?

Yes! But it’s not that this wheel is great and the other was flat. It can bring something but just because Google has the power to do that, in any language they decide to use. They have the man power to go beyond what rails offer.

But does this make the decision less dumb?

No. They could do it in rails and improve a great open source product.
Or is it that hard for engineers at google to learn a new language??

has_one :through

Finally we will be able to refactor our ugly code when we have this situation (changeset 9067):

class User < ActiveRecord::Base
  has_many :channels
end
class Channel < ActiveRecord::Base
  belongs_to :network
  belongs_to :user
end
class Group < ActiveRecord::Base
  has_many :channels
  has_one :network, 
    :through => :channels,
    :conditions => ['channels.alive? = ?', true]
end

Another good news is that the RubyForge place for the OTS project was finally approved. So guess I will be doing some work on it this afternoon.

Valid and Well-formed XML Documents in Ruby on Rails

If your working with DB2 on Rails you probably need to check if the xml document is – at least – well formed.

I found a neat plugin called validates-xml that uses REXML to see if documents are well formed.

To install it simply

svn co http://validates-xml.googlecode.com/svn/trunk/ validates-xml-read-only

And copy that folder to vendor/plugins.

You can easily integrate schema validation with a validates_xml_with_schema method. But you should use REXML as it cames with the standard ruby bundle since version 1.8.

To use it simply restart your server and

validates_xml :xmldocument

That’s it!

Yet Another Ruby on Rails Web Application – Teaser

Rails::ActiveRecord XQuery && DB2::Mac

Most rails developers use OS-X. Mostly because rails is built-in the latest release (Leopard) and TextMate offers a great IDE to use with Rails. Some could argue that it also works nicely on Windows but I really believe that Rails ain’t done to be used on a Windows Platform. Many articles and interviews with rails creator DHH second this statement. Rails is easy to develop in OS X and deploy in a Linux distro of your choice.

In my most recent screen-cast I explored an interesting technique of taking advantage of rails RESTful design and DB2 pureXML features to easily create a web-service that could query a relational databases with XML support (like DB2). As you must know DB2 Express-C is distributed freely and offers no limitation to home users/small companies. So it would be awesome to expand ActiveRecord to support xml elements, if a schema was provided to the database.

I’m aware that a pure xml database stategy would be a bad approach but there are situations when it simply makes sense. And in those situations one would profit greatly of two things wich are missing.

  • XML Support for ActiveRecord – in construction?
  • DB2 for Mac – will this ever exist?

Antonio Cangiano is creating a plugin that revolves around this concepts, but in a DB2 centered perspective. In my opinion it would be best if the rails plugin worked not only for DB2 but for any database adapter with XML support – as long as such is provided.

Let me give you a sample. Imagine that you have a database model for translating you rails application. It could be something like:

Languages

  • ID, int
  • DOCUMENT, XML

Imagine that the xml file is

<language isoname="pt-PT">
  <hello>Olá</hello>
  <bye>Até a próxima!</bye>
</language>
(...)

If this makes sense in your application then you could easily do something like register your model to observe (see observer design pattern) the session['language'] for changes and, if it’s changed, it would get all the XML for that language – it would fall back to default if such was not available – and create the hash with the values. The problem with this approach – besides making no sense for the internationalization problem! – is that in the observer model you would have to:

Language.find :first

And fetch the whole xml and then process it. If the XML document has 10MB, it would take some time. With XQuery support on ActiveRecord we could simply

Language.find :first, 
  :xcondition => ["//language[@isoname==?]", 
    session['language']]

Or, if we simply wanted to say hello in many languages – like flickr in their first page – we could simply

Language.find :first, :xcondition => '//hello'

There are just two problems that prevent rails developers from being able to do this kind of things. And those are the lack of XQuery abilities in ActiveRecord and the fact that Mac developers cannot use DB2.

Summer School CDDIP 2008, Struer, Denmark – Selected!

I was selected for all paid trip Struer (Denmark) representing University of Minho – Portugal in the Summer School CDDIP 2008 Erasmus IP program. As far as I know at least five lucky Portuguese students will attend.

But what is CDDIP? CDDIP stands for Conceptual Design and Development of Innovative Products and the goal is to facilitate better interdisciplinary and multidisciplinary collaboration for BSc and MSc students with different technical backgrounds.

If you are from another country and you are also going you can leave me a comment. See you there!

METS Standard with IBM DB2 Express C using XForms as user-interface and Ruby on Rails as a Rest Web-services

HIGH QUALITY VERSION DOWNLOAD HERE

Well, here is the long promised screen-cast. The amount of topics covered is simply huge. To get you ready for the screen-cast I prepared some other more introductory screen-cast as well as some articles on these subjects. I’m sorry that I don’t have the time to document the REST, but I really advice to invest some time learning it as it’s a very pragmatic way of delivering high quality web services.

I strongly advice you to download this screen-cast from rapidshare as both Youtube and Google Videos quality is really awful. You can download it from here.

This work was really fun to do. So I hope to have the opportunity to develop it further and manage nested rest routes like /mets/1/agents to return the agents of the first submission information package (sip) using some cool DB2 pureXML features. I really feel that with a good plugin to help users take full advantage of DB2 pureXML features and a little of imagination this web-service could be of some use.

I also expect to complete the xforms model as it is not indexing a fileptr to each category when such is selected. I hope to implement this soon enough.

Here are the associated resources I developed:

And here are the other two screencasts I produced to introduce you to XForms and METS:

I also advice you to take a look at this articles. All of them where very helpful to my work.

Working different models in the same form on Ruby on Rails

Well it’s been a heck of a week, loving somethings on rails and hating others :P

Anyway I had a problem with working with different models on a form. If you are having the same kind of issues I’ll give you some pointers:

My notes file is so big I think I’ll never solve all those issues. *g* Anyway another pointer I can give you is to check out haml. I didn’t used it but it sure is simpler than html.

Quote of the day

Quote.create(
:quote => ‘Great spirits have often encountered violent opposition from weak minds.’,
:author => ‘Albert Einstein’
)

Random in Ruby on Rails

So your doing a find on your model and you want a random instance. I didn’t find a method to do this so I decided to make my own.

In this case I wanted a random quote. So after generating the model all I had to do was:

def self.random
  Quote.find_by_id rand(Quote.count) + 1
end

And now you can simply call your random quotes in any controller action you desire. Just

@rquote = Quote.random

If this is the lamest ruby ever please feel free to give me some feedback :) I will be delighted to learn a different way!

[EDIT: Discussion about this at Rails Core]

Skitch Invites (Mac OS X only)

I have been receiving some emails asking me how do I create these images. Well I use Skitch, which is one of my favorite Mac OS X apps (along with Books, Textmate and iSync). Unfortunately it’s still invite only.

Anyway if your interested in giving Skitch a try just leave a comment in this post, and I’ll send it to the email you provided as soon as possible.

Howto: Change folder icon in Leopard

Copy the icon you want to use (PNG), browse to the folder you want to change the icon.

Now select it and press command + I. Now select the folder and press command + V to paste the icon.

Skitchcast: Ruby Gems is now on v1.0

Here how to update your gem to 1.0 and RoR to 2.0.2

Jing is useless

I mean 57 views and my screen-cast is off line? File format sucks, they don’t support resizing the video (so it’s a 1280×800 movie!!!), and as they impose SWF file format – which is damn hard to convert as it’s not suitable for video by the way – I had to use the screencast.com website. Some sites are not recommended for children. Well, screencast.com is not recomended for anyone. It’s that bad.

The first time I needed to show the screen-cast to someone the bandwidth had already been exceeded. How can TechSmith make a industry leader like camtasia and then a flop like this?

Either way Skitch seems fun so I’ll be skitch-casting for now on!

This is my first one.

[EDIT: I have Skitch invites. Just drop a line in the comments if you want one]

Follow

Get every new post delivered to your Inbox.