2010-10-27 18 views
0

Comme l'indique le titre, Ruby autorise-t-elle les types de produits cartésiens? Je ne trouve rien là-dessus.Ruby, autorise-t-elle les constructeurs de produits cartésiens?

Merci

+0

Est-ce que cela permet? Oui. L'implémente-t-il dans une bibliothèque standard? Probablement pas, mais ne serait pas difficile à mettre en œuvre – Chubas

+0

@Chubas: Je pense que "ne serait pas difficile à mettre en œuvre" est un euphémisme * brut *. Avant de pouvoir implémenter des types de produits, vous devez d'abord implémenter un système de types, et malgré l'excellent travail du projet [Diamondback Ruby] (http://WWW.CS.UMD.Edu/projects/PL/druby/), C'est probablement encore un projet de recherche pluriannuel au niveau du doctorat. –

+0

Eh bien, qu'est-ce que Trevor veut vraiment? (Mis à part, bien sûr, d'une bonne leçon dans le fait que les types ne sont pas vraiment ce qu'il semble penser qu'ils sont ...) –

Répondre

3

Ruby est-ce que vous semblez permet pas du tout types , du moins pas dans le sens à utiliser le mot « type ». Par conséquent, il ne prend évidemment pas en charge les types de produits. Ruby est un langage dit "dynamiquement typé" (utilisant la définition pragmatique du jargon du programme "type") ou un langage non typé (utilisant la définition mathématique de type-type). types de produits "n'a tout simplement pas de sens du tout. Ou, si vous le souhaitez, vous pouvez voir une langue dynamiquement typée en tant que langue typée statiquement avec un seul type qui est le type somme de tous les types dynamiques.

Cependant, vous pouvez construire évidemment valeurs que aurait un type de produit si Ruby avait des types du tout:

class Tuple 
    include Enumerable; include Comparable 

    class << self 
    alias_method :[], :new 

    def call(length) 
     class_name = :"Tuple#{length}" 
     return const_get class_name if const_defined? class_name 
     const_set class_name, Class.new(self) { 
     (@length = length).times do |i| define_method :"_#{i+1}" do @ary[i] end end 
     } 
    end 
    end 

    def to_s; "(#{@ary.join(', ')})" end 
    def inspect; "#<#{self.class} (#{@ary.map(&:inspect).join(', ')})>" end 
    def to_a; @ary.dup end 
    def [](*args) @ary[*args] end 
    def each(*args, &block) @ary.each(*args, &block) end 

    def <=>(other) 
    raise TypeError unless other.is_a? self.class 
    raise TypeError unless each_with_index.all? {|el, i| other.instance_variable_get(:@ary)[i].instance_of?(el.class) } 
    map.with_index {|el, i| el <=> other.instance_variable_get(:@ary)[i] }.find(0) {|cmp| !cmp.zero? } 
    end 

    def initialize(*args) 
    raise ArgumentError unless args.length == self.class.instance_variable_get(:@length) 
    (@ary = args).freeze 
    end 
end 

Cela vous donnera un moyen de construire n-uplets , qui sont bien sûr des cas particuliers de types de produits. Par exemple, ceci:

t3 = Tuple.(3)[1, :two, 'three'] 

construira un triple avec le type de tuple (Fixnum, Symbol, String), ce qui est un cas particulier du type de produit Fixnum × Symbol × String. Mais il n'y a aucun moyen de représenter et/ou appliquer ces types dans Ruby.

Si vous voulez approfondir les systèmes de types pour Ruby, le projet Diamondback Ruby est un bon point de départ. Il comprend tuple types, par exemple, qui sont une instance de types de produit.