我有这样的功能:
def check_if_correct_type(type, value)
# nil.test!
# eval(type.classify(value)) rescue return false
# true
case type
when "integer"
!!Integer(value) rescue return false
when "float"
!!Float(value) rescue return false
else
return true
end
true
end
样本将是
check_if_correct_type("integer", "a")
我尝试改变这样的功能:
check_if_correct_type(type, value)
!!(eval(type.classify(value))) rescue return false
true
end
这是抛出错误。我该如何解决。我对元编程很陌生,所以有点迷失。
更新1:
"adfadf".kind_of?(String) #=> true
123.kind_of?(String) #=> false
# The "Fixnum" class is actually used for integers
"adfadf".kind_of?(Fixnum) #=> false
123123.kind_of?(Fixnum) #=> true
12.3.kind_of?(Float) #=> true
"sadf".kind_of?(Float) #=> false
12.kind_of?(Float) #=> false
以上对我来说不合适吗?函数将找到对象的类型,对于我来说,答案需要如下:
check_if_correct_type("integer", "1221") #=> true
check_if_correct_type("float", "1.24") #=> true
check_if_correct_type("string", "asds12") #=> true
check_if_correct_type("float", "asdasd1.24") #=> false
其中
“1.24”.kind_of?(浮动)#=>假
这就是为什么转换对我有用。希望现在问题更清楚了。
更新2:
如果我使用公开发送,这就是我得到的。
!! public_send( “整数” .capitalize( “1”))
ArgumentError:参数数量错误(1表示0)
from(pry):4:in capitalize'
[5] pry(main)> !!public_send("integer".classify("1"))
ArgumentError: wrong number of arguments (1 for 0)
from /home/aravind/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/activesupport-4.2.0/lib/active_support/core_ext/string/inflections.rb:187:in
classify'
注意:classify是Ruby on Rails的一部分,而不是Ruby。
答案 0 :(得分:1)
我建议您按如下方式编写方法:
def correct_type?(type, str)
case type.downcase
when "integer"
!!to_integer(str)
when "float"
!!to_float(str)
else
raise ArgumentError, "type must be 'integer' or 'float'"
end
end
其中to_integer(value)
(to_float(value)
)是一个返回value.to_i
(value.to_f
)的方法,如果value
是整数的字符串表示形式(浮点数) ,否则返回nil
。方法to_integer
和to_float
非常有用,因为它们可以告诉您字符串是否可以转换为给定的数字类型,如果可以,则为您提供数值。
在考虑如何实施to_integer
和to_float
之前,我想对correct_type?
的需求提出疑问。而不是:
str = "33"
if correct_type?("integer", str)
n = str.to_i
puts n
else
...
end
写下来不是更好:
if (n = to_integer("33"))
puts n
else
...
end
基本上有两种方法可以编写方法to_integer
和to_float
。首先是你采取的方法:
def to_integer(str)
raise ArgumentError unless str.is_a? String
s = str.gsub(/\s/,'')
Integer(s) rescue nil
end
def to_float(str)
raise ArgumentError unless str.is_a? String
s = str.gsub(/\s/,'')
return nil if to_integer(s)
Float(s) rescue nil
end
to_integer("3") #=> 3
to_integer("-3") #=> -3
to_integer("+ 3") #=> 3
to_integer("cat") #=> nil
to_integer("3.14") #=> nil
to_integer(:cat) #=> ArgumentError: ArgumentError
to_float("3.14") #=> 3.14
to_float("-3.14") #=> -3.14
to_float("+ 3.14") #=> 3.14
to_float("cat") #=> nil
to_float("3") #=> nil
to_float(:cat) #=> ArgumentError: ArgumentError
第二种方法是使用正则表达式:
def to_integer(str)
raise ArgumentError unless str.is_a? String
s = str.gsub(/\s/,'')
s[/^[+-]?\s*\d+$/] ? s.to_i : nil
end
def to_float(str)
raise ArgumentError unless str.is_a? String
s = str.gsub(/\s/,'')
return nil if to_integer(s)
s[/^[+-]?\s*\d+\.\d+$/] ? s.to_f : nil
end
to_integer("3") #=> 3
to_integer("-3") #=> -3
to_integer("+ 3") #=> 3
to_integer("cat") #=> nil
to_integer("3.14") #=> nil
to_integer(:cat) #=> ArgumentError: ArgumentError
to_float("3.14") #=> 3.14
to_float("-3.14") #=> -3.14
to_float("+ 3.14") #=> 3.14
to_float("cat") #=> nil
to_float("3") #=> nil
to_float(:cat) #=> ArgumentError: ArgumentError
答案 1 :(得分:1)
无需使用eval
发送消息。您只需使用send
:
def check_if_correct_type(type, value)
!!send(type.capitalize, value) rescue return false
true
end
注意:Ruby核心库或Ruby标准库中没有任何名为classify
的方法。还要注意,只是盲目地捕捉所有异常是一个非常糟糕的主意。
答案 2 :(得分:0)
我没有看到在这个例子中使用元编程的观点。你应该避免在没有它的地方使用它。一般来说,您的程序逻辑应该是:
a)检查输入值的类型。 b)将类型与作为参数输入的类型进行比较。或者在代码中:
def check_if_correct_type(type, value)
actual_type = value.class.name
return actual_type.downcase == type.downcase
end
p check_if_correct_type('string', 'test') #=> true
p check_if_correct_type('integer', 'test2') #=> false
这可以在一行中缩短,但在两行中做得更清楚,以更清楚地说明发生了什么。
答案 3 :(得分:0)
如果你想检查对象的类,正确的方法是:
"adfadf".kind_of?(String) #=> true
123.kind_of?(String) #=> false
# The "Fixnum" class is actually used for integers
"adfadf".kind_of?(Fixnum) #=> false
123123.kind_of?(Fixnum) #=> true
12.3.kind_of?(Float) #=> true
"sadf".kind_of?(Float) #=> false
12.kind_of?(Float) #=> false
没有理由使用Integer()
或Float()
方法来检查类型。这些是类型转换方法,它们会将其他类型转换为Float或Fixnum。如果你想尝试转换一个类型可以转换为Float或数字,这是一种方法,但可能有更好的方法。
一般而言,作为普通计划流程的一部分,您绝不应该计划提出和拯救例外;一个原因是因为它很慢。异常应该用于错误和异常/异常情况,而不是常规条件,以便经常引起异常。
绝对不要开始将eval
带入其中,geez为什么要这样做呢?
答案 4 :(得分:0)
这就是我最终解决问题的方法
def check_if_correct_type(type, value)
!!eval("#{type.classify}(value)") rescue return false
true
end
此函数的示例输出如下,您想知道它是否有单词
[25] pry(main)> value = "1"
=> "1"
[26] pry(main)> !!eval("#{type.classify}(value)")
=> true
[27] pry(main)> value = "a"
=> "a"
[28] pry(main)> !!eval("#{type.classify}(value)")
ArgumentError: invalid value for Float(): "a"
from (pry):28:in `eval'
[29] pry(main)> value = "1.4"
=> "1.4"
[30] pry(main)> type = "integer"
=> "integer"
[31] pry(main)> !!eval("#{type.classify}(value)")
ArgumentError: invalid value for Integer(): "1.4"
from (pry):31:in `eval'