在代码字符串中使用 `include` 和 `using`

huangapple go评论65阅读模式
英文:

Using `include` and `using` inside a string of code

问题

我正在尝试评估一个包含Ruby代码的字符串,在实例的上下文中进行评估,同时保留标准的Ruby方法,如using(用于细化)和include

这是我最简化的示例。我希望用户代码(字符串)能够原样工作,而无需对其进行修改。Context#run方法是我希望进行必要更改的地方。

require 'fileutils'

module SomeUserRefinement
  refine String do
    def header
      "=== #{self} ==="
    end
  end
end

class Context
  def run(code)
    instance_eval code
  end

  def some_instance_method
    puts "works"
  end
end

user_code = <<~CODE
  using SomeUserRefinement    # not working
  include FileUtils           # not working
  puts 'Caption'.header
  some_instance_method
CODE

context = Context.new
context.run user_code
英文:

I am trying to evaluate a string that contains Ruby code, in the context of an instance, while maintaining standard Ruby methods such as using (for refinements) and include.

Here is my most stripped down example. I would like to make the user code (string) work as is, without modification to it. The Context#run method is where I am hoping to make the necessary changes.

require &#39;fileutils&#39;

module SomeUserRefinement
  refine String do
    def header
      &quot;=== #{self} ===&quot;
    end
  end
end

class Context
  def run(code)
    instance_eval code
  end

  def some_instance_method
    puts &quot;works&quot;
  end
end

user_code = &lt;&lt;~CODE
  using SomeUserRefinement    # not working
  include FileUtils           # not working
  puts &#39;Caption&#39;.header
  some_instance_method
CODE

context = Context.new
context.run user_code

答案1

得分: 2

您的整体意图除了“...我想让用户代码(字符串)原封不动地工作,不需要对其进行修改”之外,有点不太清楚,这在任何情况下可能都不起作用(例如,如果用户代码不好,它将始终失败,就像这里一样)

简短回答
按设计,您所请求的实现根本不可能。此外,您的示例尝试混合使用实例方法和类实例方法,同时使用相同的接收器,这也是不可能的。

更长的回答

如果您发布了实际的错误消息,它将显示:

undefined method `using' for #<Context:0x00007ff65eda4498> (NoMethodError)

这是因为using不是一个实例方法。(include也适用相同的规则)

好吧,让我们尝试利用您的实例的特殊类(eigenclass)

class Context
  def run(code)
    singleton_class.instance_eval code
  end
end

新错误

`using': Module#using is not permitted in methods (RuntimeError)

如果我们阅读refinements的文档,我们会看到:

作用域

您可以在顶层、类和模块内激活refinements。您不能在方法作用域内激活refinements。 Refinements会在当前类或模块定义结束时激活,或者在顶层使用时,在当前文件结束时激活。

include没有相同的限制,模块可以在方法作用域内包含在实例的eigenclass中;但是,您的代码还需要能够在相同的上下文中使用相同的接收器调用some_instance_method,这是不可能的。

英文:

Your overall intent is a bit unclear other than "...I would like to make the user code (string) work as is, without modification to it", which may or may not work in any given circumstance (e.g. if the user code is no good then it will always fail, as it does here)

Short Answer
Your requested implementation is simply not a functional possibility by design. Additionally your example attempts to mix and match instance methods and class instance methods while using the same receiver, which is also not possible.

Longer Answer

Had you posted the actual error message it would have shown:

undefined method `using&#39; for #&lt;Context:0x00007ff65eda4498&gt; (NoMethodError)

This is because using is not an instance method. (same applies to include)

Okay so let's try to leverage the eigenclass for your instance

class Context
  def run(code)
    singleton_class.instance_eval code
  end
end

New error

`using&#39;: Module#using is not permitted in methods (RuntimeError)

If we read through the docs for refinements we see:
> Scope
>
>You may activate refinements at top-level, and inside classes and modules. You may not activate refinements in method scope. Refinements are activated until the end of the current class or module definition, or until the end of the current file if used at the top-level.

include does not have the same limitation and modules can be included in the eigenclass of an instance in a method scope; however your code also needs to be able to call some_instance_method in the same context with the same receiver, which is not possible.

huangapple
  • 本文由 发表于 2023年6月22日 14:24:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76529084.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定