无法在 ruby 中使用 eval 执行 Class(argument)
Not able to do Class(argument) with eval in ruby
我有这样的功能:
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
上面的方法对我不起作用 kind_of?函数将找到对象的类型,对我来说答案需要是这样的:
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?(浮动)#=> false
这就是转换对我有用的原因。希望现在问题更清楚了。
更新 2:
如果我使用 public 发送,这就是我得到的结果。
!!public_send("integer".capitalize("1"))
ArgumentError:参数数量错误(1 代表 0)
来自(撬):4:在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
分类'
注意:分类是 Rails 上 Ruby 的一部分,而不是 Ruby。
我看不出在此示例中使用元编程有什么意义。您应该避免在不需要它的地方使用它。一般来说,你的程序的逻辑应该是:
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
这可以在一行中做得更短,但分两行来更清楚地说明发生了什么。
如果你想检查一个对象的class,正确的方法是这样的:
"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 或 numeric 的类型,这是一种方法,但可能有更好的方法。
一般来说,您不应该计划将引发和拯救异常作为普通程序流程的一部分;一个原因是因为它非常慢。异常应该用于错误和 unusual/exceptional 条件,而不是经常引发异常的常规条件。
绝对不要开始将 eval
带入其中,天哪,你为什么要那样做?
我建议你把你的方法写成这样:
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)
)是一种方法,returnsvalue.to_i
(value.to_f
)如果value
是字符串表示整数(浮点数),否则 returns 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
无需使用eval
发送消息。您可以只使用 send
代替:
def check_if_correct_type(type, value)
!!send(type.capitalize, value) rescue return false
true
end
注意:在 Ruby 核心库或 Ruby 标准库中的任何地方都没有名为 classify
的方法。另请注意,盲目捕获所有异常是一个非常糟糕的主意。
这就是我最终解决问题的方式
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'
我有这样的功能:
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
上面的方法对我不起作用 kind_of?函数将找到对象的类型,对我来说答案需要是这样的:
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?(浮动)#=> false
这就是转换对我有用的原因。希望现在问题更清楚了。
更新 2:
如果我使用 public 发送,这就是我得到的结果。
!!public_send("integer".capitalize("1"))
ArgumentError:参数数量错误(1 代表 0)
来自(撬):4:在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
分类'
注意:分类是 Rails 上 Ruby 的一部分,而不是 Ruby。
我看不出在此示例中使用元编程有什么意义。您应该避免在不需要它的地方使用它。一般来说,你的程序的逻辑应该是:
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
这可以在一行中做得更短,但分两行来更清楚地说明发生了什么。
如果你想检查一个对象的class,正确的方法是这样的:
"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 或 numeric 的类型,这是一种方法,但可能有更好的方法。
一般来说,您不应该计划将引发和拯救异常作为普通程序流程的一部分;一个原因是因为它非常慢。异常应该用于错误和 unusual/exceptional 条件,而不是经常引发异常的常规条件。
绝对不要开始将 eval
带入其中,天哪,你为什么要那样做?
我建议你把你的方法写成这样:
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)
)是一种方法,returnsvalue.to_i
(value.to_f
)如果value
是字符串表示整数(浮点数),否则 returns 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
无需使用eval
发送消息。您可以只使用 send
代替:
def check_if_correct_type(type, value)
!!send(type.capitalize, value) rescue return false
true
end
注意:在 Ruby 核心库或 Ruby 标准库中的任何地方都没有名为 classify
的方法。另请注意,盲目捕获所有异常是一个非常糟糕的主意。
这就是我最终解决问题的方式
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'