2

Je m'excuse d'avance pour avoir posé cette question à nouveau. J'ai posé cette question précédemment en ce qui concerne une implémentation Haskell here, mais j'ai toujours des difficultés à comprendre comment cela fonctionne. Aussi, je trouve le concept d'un langage de programmation minimaliste absolument fascinant et ne peut pas s'en éloigner ... de toute façon, ce n'est pas un endroit pour être nostalgique de la beauté de la programmation fonctionnelle.Mise en œuvre de iota en ruby ​​

Alors! J'ai trouvé un site sur les langages de programmation ésotériques et j'ai découvert Iota. Iota est sans doute le plus petit langage fonctionnel. Vous pouvez en savoir plus à ce sujet ici: "Iota and Jot: the simplest languages?" Voici l'implémentation de référence de Iota dans le schéma:

(let iota() 
    (if (eq? #\* (read-char)) ((iota)(iota)) 
     (lambda (c) ((c (lambda (x) (lambda (y) (lambda (z) ((x z)(y z)))))) 
        (lambda (x) (lambda (y) x)))))) 

Mais, lorsque je tente quelque chose d'équivalent dans l'élégance à la mise en œuvre Scheme en Ruby on finit par cracher un « mauvais proc ". Quelqu'un peut-il m'aider à comprendre pourquoi Ruby se comporte de cette façon et comment cela peut être mieux mis en œuvre. Tout en essayant de faire fonctionner cela, j'ai gardé S, K, et BASIS séparé juste pour la lisibilité.

J'ai inclus deux tests en bas. Le premier doit renvoyer I (BASIS[BASIS]), mais renvoie à la place un proc qui ne produit pas le même résultat que I. Le deuxième test doit renvoyer K, mais renvoie une erreur.

S = lambda {|f| lambda {|g| lambda {|x| f[x][g[x]] }}} 
K = lambda {|x| lambda {|y| x }} 
BASIS = lambda {|c| c[S][K] } 

iota = lambda{|s| 
    s = s.chars 
    i = lambda { 
     if s.next == '*' 
     i[i] 
     else 
     BASIS 
     end 
    } 
} 

p BASIS[BASIS][1]   # => 1 
p iota["*ii"][1]   # => #<Proc:0x000000010016b290> 

p K[1][2]     # => 1 
p iota["*i*i*ii"][1][2] # => line 3:in `[]': can't convert Proc into Integer (TypeError) 

Répondre

1

Merci à sepp2k Je pense que j'ai tout compris, voici la réponse pour toute personne intéressée:

S = lambda {|f| lambda {|g| lambda {|x| f[x][g[x]] }}} 
K = lambda {|x| lambda {|y| x }} 
BASIS = lambda {|c| c[S][K] } 

iota = lambda{|s| 
    s = s.chars 
    i = lambda { 
     if s.next == '*' 
     i[][i[]] 
     else 
     BASIS 
     end 
    } 
    i[] 
} 

p BASIS[BASIS][1]   # => 1 
p iota["*ii"][1]   # => 1 

p K[1][2]     # => 1 
p iota["*i*i*ii"][1][2] # => 1 
4

Sur la ligne 9, vous appelez i[i], mais i ne prend aucun argument - que le lambda retourné par i fait. Vous devez donc appeler i sans arguments, puis appeler le résultat de l'appel i avec i comme argument, c'est-à-dire i[][i].

+0

Merci, exactement ce que je avais besoin. Il retourne quand même les mauvaises valeurs pour 'K' et' I' (in iota). Pour 'I' il retourne un objet' proc' et pour 'K' il renvoie' 2' ... ce qui pourrait être la bonne valeur, bien que je m'attendrais à ce qu'il retourne '1'. –