gpt4 book ai didi

ruby - 是否可以在 Ruby 中创建(或模拟)关键字?

转载 作者:数据小太阳 更新时间:2023-10-29 07:48:14 24 4
gpt4 key购买 nike

我刚刚开始学习 Ruby,但对于如何利用它作为 OOPL 的独特性,我已经有了很好的想法。我的第一个标题恰如其分地描述了:是否可以在 Ruby 中创建(或模拟)关键字?我在 repl 中玩了一会儿,发现了一些关于别名的有趣事情。

例如,如果您尝试通过说

来为关键字 class 添加别名
alias :magic :class

它似乎可以工作,因为它输出 nil。但是,它只是别名 Object#class 方法;我的猜测是没有办法给关键字起别名,因为关键字不是常量,很可能被硬编码到解释器本身。

(不过,这个小实验确实产生了一个有趣的结果。通常,如果没有显式的 self 标识符,您将无法调用 Object#class 方法;只需键入 repl 中的 class 会产生语法错误,因为它与关键字 class 混淆了。但是,通过为 Object#class 方法起别名,解释器不再获取混淆,所以你可以使用没有标识符的别名。非常漂亮。)

现在,以我对 Ruby 的有限了解,我认为模拟关键字的方法,例如 class,应该是这样的:

# in some file Magic.rb
module Magic
def self.type
# do something to evaluate the given block as a class definition
yield if block_given?
end
end

Magic.type Awesome do
def initialize;end

def who_am_i?
puts "I'm Awesome!"
end
end

x = Awesome.new # desired output: #<Awesome:0x1234abc>
x.who_am_i? # desired output: "I'm Awesome!"

但这比我希望的还要丑陋。有什么想法吗?

编辑:经过一些修补和谷歌搜索后,我发现了我认为是一个很好的解决方案,利用匿名类实例化、 block 和 Object#const_set:

def type aName, &block
Object.const_set(aName, Class.new(Array, &block))
end

type :AwesomeArray do
def intialize
puts "Initialized."
end
def magic
puts "DO ALL THE MAGICKS!"
end
end

x = AwesomeArray.new # --> #<Awesome:0x12335abc>
puts x.is_a? AwesomeArray # --> true
puts x.is_a? Array # --> true
puts x.is_a? Object # --> true
x.magic # --> "DO ALL THE MAGICKS!"
x |= [1, 2, 3] # --> [1, 2, 3]

用户定义的 type 方法有效地模拟了 class 关键字。或者,您可以使用字符串而不是符号调用 type,并在将 aName 传递给 Class 时添加 to_sym 调用。新的。或者两者都做!

def type aSymbol, &block
Object.const_set(aSymbol, Class.new(Array, &block))
end

def type_str aString, &block
type aString.to_sym, &block
end

现在,作为 Ruby n00b(r00b?),这样做有什么继承性或传统上的吗?例如,它在某些方面是否真的很昂贵或危险?

最佳答案

TL;DR:如果您没有充分的理由这样做,请不要

顺便说一句,您无法模拟关键字。它们内置于解析器中。您所能做的就是像您想出的那样进行元编程黑客攻击……但是:


并不是说它效率低得多:

       user     system      total        real
type method: 0.000000 0.000000 0.000000 ( 0.000034)
class keyword: 0.000000 0.000000 0.000000 ( 0.000030)

这只是糟糕的形式。为什么要用无用的方法使全局 namespace 困惑,使您的代码更难被其他人阅读?阅读的代码远远多于编写的代码。以后不要让别人或自己的事情变得更难。

这也有一些范围陷阱,稍后会回到字节中。示例:

2.0.0p0 :001 > def type aName, &block                                                                                                                                                                                                              
2.0.0p0 :002?> Object.const_set(aName, Class.new(Array, &block))
2.0.0p0 :003?> end
=> nil
2.0.0p0 :004 > a = 'hi'
=> "hi"
2.0.0p0 :005 > type :Hi1 do
2.0.0p0 :006 > puts a
2.0.0p0 :007?> end
hi
=> Hi1
2.0.0p0 :008 > class Hi2
2.0.0p0 :009?> puts a
2.0.0p0 :010?> end
NameError: undefined local variable or method `a' for Hi2:Class
from (irb):9:in `<class:Hi2>'
from (irb):8

block 作用域不同于作用域。此外,这不能正确处理类变量(尽管没有充分的理由你不应该使用 Ruby 的类变量......):

2.0.0p0 :012 > type :T1 do
2.0.0p0 :013 > @@t1test = 'hi'
2.0.0p0 :014?> end
(irb):13: warning: class variable access from toplevel
=> T1
2.0.0p0 :015 > T1.class_variables
=> [:@@t1test]
2.0.0p0 :018 > class T2
2.0.0p0 :019?> @@t2test = 'bork'
2.0.0p0 :020?> end
=> "bork"
2.0.0p0 :021 > Object.class_variables
=> [:@@t1test]
2.0.0p0 :022 > T2.class_variables
=> [:@@t2test, :@@t1test]

如您所见,您的 block 形式将类变量泄漏给每个类(从 Object 派生而来)。不太好。

关于ruby - 是否可以在 Ruby 中创建(或模拟)关键字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17239775/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com