(Crossposting note:我已经在一周前的Ruby Forum已经问过这个问题了,但是还没有得到任何答复。)
这是我目前所用的(非常)简化的工作版本:
u = new Vector(1.0, 0.0, 0);
在这个例子中,根据T的构造方式,T#调用调用 S#s_method1或S#S_method2,但是在调用的情况下 S#s_method1,s_method1的参数在创建时已经修复 T对象的时间。因此,以下两行,
import MySQLdb
conn = MySQLdb.connect(host = 'localhost', user = 'username', passwd = 'password', port = port, db = 'DBNAME')
cursor = conn.cursor()
query = """SELECT * FROM myschema.mytable;"""
cursor.execute(query)
FILE = cursor.fetchall()
with open('FILE.txt', 'w') as f:
for row in cursor:
f.write("%s\n" % str(row))
产生输出
# A class S with two methods, one which requires one parameter, and
# one without parameters.
class S
def initialize(s); @ms = s; end
def s_method1(i); puts "s_method1 #{i} #{@ms}"; end
def s_method2; puts "s_method2 #{@ms}"; end
end
# A class T which uses S, and "associates" itself to
# one of the both methods in S, depending on how it is
# initialized.
class T
def initialize(s, choice=nil)
@s = S.new(s)
# If choice is true, associate to the one-parameter-method, otherwise
# to the parameterless method.
@pobj = choice ? lambda { @s.s_method1(choice) } : @s.method(:s_method2)
end
# Here is how I use this association
def invoke
@pobj.call
end
end
这正是我所需要的。
现在问我的问题:
在T.new('no arguments').invoke
T.new('one argument', 12345).invoke
nil 的情况下,即我要调用的地方
无参数方法s_method2 no arguments
s_method1 12345 one argument
,我可以得到我的可调用对象
choice
在s_method2
非 nil 的情况下,我必须构造一个@s.method(:s_method2)
对象
使用`lambda。这不仅看起来笨拙,而且让我感觉有点
不舒服。我们这里有一个关闭,它连接到
初始化方法里面的环境,我不确定是否这样
在某些情况下可能会因内存泄漏而导致麻烦。
是否可以轻松绑定方法对象(在本例中)
choice
到固定参数?
我的第一个想法是使用
Proc
但这并没有实现我的目标。它不会返回可调用的@s.method(:s_method1)
对象,而是实际执行@s.method(:s_method1).curry[choice]
(这不是错误,而是记录的行为)。
关于如何实现目标的任何其他想法?
答案 0 :(得分:3)
此选项很简单,但可能不是您正在寻找的内容:
class T
def initialize(s, choice=nil)
s = S.new(s)
@choice = choice
@pobj = s.method(choice ? :s_method1 : :s_method2)
end
def invoke
@pobj.call(*@choice)
end
end
T.new('no arguments').invoke
T.new('one argument', 12345).invoke
#=> s_method2 no arguments
#=> s_method1 12345 one argument
# Allows setting default parameters for methods, after they have been defined.
module BindParameters
refine Method do
def default_parameters=(params)
@default_params = params
end
def default_parameters
@default_params || []
end
alias_method :orig_call, :call
def call(*params)
merged_params = params + (default_parameters[params.size..-1] || [])
orig_call(*merged_params)
end
end
end
以下是一个例子:
def f(string)
puts "Hello #{string}"
end
def g(a, b)
puts "#{a} #{b}"
end
using BindParameters
f_method = method(:f)
f_method.default_parameters = %w(World)
f_method.call('user') # => Hello user
f_method.call # => Hello World
g_method = method(:g)
g_method.default_parameters = %w(Hello World)
g_method.call # => Hello World
g_method.call('Goodbye') # => Goodbye World
g_method.call('Goodbye', 'User') # => Goodbye User
您的代码可以重写:
class T
using BindParameters
def initialize(s, *choice)
s = S.new(s)
@pobj = s.method(choice.empty? ? :s_method2 : :s_method1)
@pobj.default_parameters = choice
end
def invoke
@pobj.call
end
end
T.new('no arguments').invoke # => s_method2 no arguments
T.new('one argument', 12_345).invoke # => s_method1 12345 one argument
如果修补Method类是可以接受的,可以使用:
class Method
def default_parameters=(params)
@default_params = params
end
def default_parameters
@default_params || []
end
alias_method :orig_call, :call
def call(*params)
merged_params = params + (default_parameters[params.size..-1] || [])
orig_call(*merged_params)
end
end
T成为:
class T
def initialize(s, *choice)
s = S.new(s)
@pobj = s.method(choice.empty? ? :s_method2 : :s_method1)
@pobj.default_parameters = choice
end
def invoke
@pobj.call
end
end
如果您不想污染方法类,这种方式可能更清晰:
class MethodWithDefaultParameters
attr_accessor :default_parameters
attr_reader :method
def initialize(receiver, method_symbol)
@method = receiver.public_send(:method, method_symbol)
@default_parameters = []
end
def call(*params)
merged_params = params + (default_parameters[params.size..-1] || [])
method.call(*merged_params)
end
def method_missing(sym, *args)
method.send(sym, *args)
end
end
T成为:
class T
def initialize(s, *choice)
s = S.new(s)
@pobj = MethodWithDefaultParameters.new(s, choice.empty? ? :s_method2 : :s_method1)
@pobj.default_parameters = choice
end
def invoke
@pobj.call
end
end
欢迎任何评论或建议!