dire que j'ai un PROC générique code>,
lambda code> ou
méthode code> qui prend un deuxième argument facultatif:
pow = -> (base:, exp: 2) { base**exp }
4 Réponses :
Curry code> ne fonctionne pas avec les arguments de mots clés. Une fonction au curry obtient un paramètre à la fois, ce qui est conceptuellement incompatible avec "tout ordre va bien" des arguments de mots clés. Li>
-
curry code> doit connaître l'attitude exacte. Si vous appelez simplement curry code> sans argument, il ignore les options d'option (en cas de pow = -> (base, exp = 2) {base ** exp} code>, identique à curry (1) code>). Utilisez curry (2) code> pour forcer les deux paramètres. Une fonction au curry ne peut pas connaître un paramètre facultatif suit et lisez l'avenir pour déterminer s'il doit exécuter ou renvoyer une suite au fur et à mesure. LI>
ul>
D'accord. Considérez que le deuxième argument n'est pas facultatif. Comment (si du tout) puis-je faire du curry à partir du deuxième argument? :-)
Afaik, encore une fois pas possible. Curry Code> vous permettra de fournir les arguments dans le même ordre dans la signature de fonction. Si vous voulez curry
x. (A, B) code> dans
xc. (A). (A) code>, vous devrez écrire votre propre:
xc = xc = -> (b, a) {x. (A, b)} .Currier code> ou
xc = -> (b) {-> (a) {x. (A) {x. code>. Sinon, je ne sais pas comment vous communiqueriez l'ordre de paramètre souhaité à
Curry code>.
Je ne pense pas que vous puissiez le faire avec Vous pouvez également créer une fonction d'usine < / p> proc.curry code>, mais il y a toujours la solution Longhand
L'idée d'utiliser une fonction d'usine est définitivement intéressante! :-)
Vous pouvez construire votre propre méthode de curry aromatisée à mot-clé qui collecte des arguments de mots clés jusqu'à ce que les paramètres requis soient présents. Quelque chose comme: L'exemple ci-dessus est limité aux arguments de mots clés uniquement, mais vous pouvez certainement l'étendre pour supporter les arguments de mots clés et les arguments de position. P> P>
Merci beaucoup pour l'exemple de mise en œuvre @stefan! Je pensais aussi dans ces lignes, mais je prévois de la nommer #curry code>. :-P
extension @stefan Réponse ci-dessus selon le dernier commentaire et en ligne avec son extrait:
def curry(method) -> (*args, **kargs) { required = method.parameters.select { |type, _| type == :req } krequired = method.parameters.select { |type, _| type == :keyreq } all_args = (required.length <= args.length) all_keys = krequired.all? { |_, name| kargs.has_key?(name) } if all_args && all_keys final_args = (args + kargs.map {|k,v| {k => v} }) method.call(*final_args) else -> (*args_, **kargs_) { curry(method)[*args, *args_, **kargs, **kargs_] } end } end def foo(a1, b1, c1 = 5, a2:, b2:, c2: 50) { a1: a1, b1: b1, c1: c1, a2: a2, b2: b2, c2: c2} end puts foz = curry(method(:foo)) #=> #<Proc:0x0000000003a255f0@./training.rb:56 (lambda)> puts bar = foz[6, a2: 60] #=> #<Proc:0x0000000003a255f0@./training.rb:56 (lambda)> puts bar[1, b2: 10] #=> {:a1=>6, :b1=>1, :c1=>5, :a2=>60, :b2=>10, :c2=>50} puts baz = bar[1] #=> #<Proc:0x0000000003a17540@./training.rb:64 (lambda)> puts baz[10, b2: 30, c2: 40] #=> {:a1=>6, :b1=>1, :c1=>10, :a2=>60, :b2=>30, :c2=>40}
Pour fixer un argument de position arbitraire, voir Stackoverflow.com/a/34813268/477037