标签: metaprogramming

与原始函数一起修饰的函数,而无需重写该函数

如果我有一个装饰器和一个函数,但我想使用装饰后的函数以及该函数的未装饰版本,我该怎么办?

我没有太多使用装饰器,从我所能找到的来看,似乎你必须编写两个单独的函数来完成此任务,或者使用函数作为参数调用装饰器,这在处理多个函数时可能会有些混乱装饰者。

为了解决这个问题,我编写了一个函数,然后使用一种有点迂回的方式来装饰该函数并在事后返回该装饰函数。所以我可以访问该函数的未修饰版本和修饰版本。据我所知,实现这一目标的方法有点被人看不起,但到目前为止它对我来说一直有效。我无法想象这是解决这个问题的最佳方法。

本质上,我将想要装饰的函数与装饰器函数一起传递给检查函数文本的方法,将语法添加到@decorator文本中,然后将装饰器函数__builtins__临时添加到模块中,以便我可以将exec文本转换为字典来定义新的修饰函数。这个新的函数对象是从字典中提取出来的,并作为新的修饰函数返回。

我很确定这不是解决这个问题的最佳方法。我不认为它适用于所有情况,但我也不想每次都调用修饰函数或重写函数。

python metaprogramming decorator python-decorators

1
推荐指数
1
解决办法
599
查看次数

访问模块中包含的 ruby​​ 方法的符号

鉴于 Ruby 2.2

module A
  def self.a
    "a"
  end
end
Run Code Online (Sandbox Code Playgroud)

如何访问A.a以便分配给变量并稍后调用它?

我已经尝试过以下方法:

x = A::a.to_sym
send x           # NoMethodError: undefined method `a' for main:Object
Run Code Online (Sandbox Code Playgroud)

以下作品:

x = -> { A.a }
x.call
Run Code Online (Sandbox Code Playgroud)

由于我在数组中同时拥有命名空间函数和非命名空间函数,有没有办法可以做到这一点send

我真的不想污染命名空间include A

ruby metaprogramming ruby-2.2

1
推荐指数
1
解决办法
697
查看次数

检查元组是否包含某种类型的元素

我正在尝试通过实现一些功能来学习 C++ 模板元编程。我知道已经在 stackoverflow 上提供了这个特定问题的解决方案,我感兴趣的是了解为什么这个解决方案不起作用。这是代码:

template < std::size_t... Ns , typename... Ts >
auto tail_impl( std::index_sequence<Ns...> , std::tuple<Ts...> t )
{
   return  std::make_tuple( std::get<Ns+1u>(t)... );
}

template <class F, class... R >
tuple<R...> tail( std::tuple<F,R...> t )
{
   return  tail_impl( std::make_index_sequence<sizeof...(R)>() , t );
}


template<class X, class F, class... R>
constexpr bool check_for_type(tuple<F,R...> t) {
    if constexpr(is_same<F,X>::value) {
        return true;
    } 
    return check_for_type<X>(tail(t));
}


template<class X>
constexpr bool check_for_type(tuple<> t) {
    return false;
}


int main( int …
Run Code Online (Sandbox Code Playgroud)

c++ templates metaprogramming template-meta-programming

1
推荐指数
1
解决办法
1006
查看次数

用于模块属性的 Elixir 元编程

我有这个模块

defmodule ElixirMeta.LangLoader do

  @external_resource [Path.join([__DIR__, "es.json"]),
                      Path.join([__DIR__, "en.json"])]

  defmacro __using__(_) do
    for lang <- ["es", "en"] do
      {:ok, body} = File.read(Path.join([__DIR__, "#{lang}.json"]))
      {:ok, json} = Poison.decode(body)
      quote do
        def lang(unquote(lang)), do: unquote(Macro.escape(json))
      end
    end
  end
end

defmodule ElixirMeta.Lang do
  use ElixirMeta.LangLoader
end
Run Code Online (Sandbox Code Playgroud)

我知道我可以定义一个函数,如:

def lang(unquote(lang)), do: unquote(Macro.escape(json))
Run Code Online (Sandbox Code Playgroud)

并且可以这样调用:

Lang.lang("es")
Run Code Online (Sandbox Code Playgroud)

甚至修改它的函数名,像这样:

def unquote(:"lang_#{lang}")(), do: unquote(Macro.escape(json))
Run Code Online (Sandbox Code Playgroud)

并像这样被调用:

Lang.lang_es
Run Code Online (Sandbox Code Playgroud)

但是可以对模块属性做同样的事情吗?

并且作为模块属性编译(?)我认为不可能从宏初始化它?也许我必须在before_compile宏中做到这一点?

出于示例的目的,我想访问Lang.lang_es作为 a@lang_es@lang_en LangLoader属性

macros metaprogramming elixir

1
推荐指数
1
解决办法
721
查看次数

Julia 宏中的“UndefVarError”

为了帮助我的调试(也为了更好地理解 Julia 宏的工作原理),我试图定义一个简单的宏,用“进入”和“离开”通知环绕代码块。这是我到目前为止想出的:

macro dbg(block_title, expr)
    quote
        title = $block_title
        println("Entering $title")
        $expr
        println("Leaving  $title")
    end
end
Run Code Online (Sandbox Code Playgroud)

乍一看,它似乎做我想要的:

julia> @dbg "first test" begin
           println("does it work?")
       end
Entering first test
does it work?
Leaving  first test
Run Code Online (Sandbox Code Playgroud)

然而,一旦涉及到变量,就没有任何作用了,我得到 UndefVarError了所有变量的访问。看起来宏内部和外部的范围是不同的:

julia> @dbg "initialization" begin
           foo = rand(10)
           println("foo = ", foo)
       end
Entering initialization
foo = [0.9178016919066918, 0.6004694971609528, 0.5294790810682284, 0.04208146400653634, 0.09271603217172952, 0.2809448815925, 0.68236281020963, 0.8313876607106496, 0.07484095574744898, 0.14099531301938573]
Leaving  initialization

julia> foo
ERROR: UndefVarError: foo not defined
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

metaprogramming julia

1
推荐指数
1
解决办法
108
查看次数

遍历 std::initializer_list

//parameter pack sum example

constexpr int sum(int N= 0)
{
    return N;
}
template<typename ...Args>
constexpr int sum(int first, int second, Args ...N)
{
    return first + second + sum(N...);
}

int main()
{
    std::cout << sum<int>(1,6,3);
}
Run Code Online (Sandbox Code Playgroud)

是否有可能在编译时通过std::initializer_list<int>我如何递归迭代来计算这个总和。

c++ metaprogramming initializer-list c++11 parameter-pack

1
推荐指数
1
解决办法
1191
查看次数

有没有办法告诉软件包启用了哪些功能?

假设我想确保实现接口的人具有特定的实验性功能,

package Foo {
  use experimental "signatures";

}
Run Code Online (Sandbox Code Playgroud)

有没有办法确定 Foo 启用了哪些功能,或者更具体地说是“实验性功能”?

perl metaprogramming pragma package

1
推荐指数
1
解决办法
139
查看次数

基于条件的模板重载

使用类型特征,我可以执行以下操作:

template<typename Rect> Rect& move(Rect& rc, size_type<Rect> delta)
{
    rc.left += delta.width;
    rc.right += delta.width;
    rc.top += delta.height;
    rc.bottom += delta.height;
    return rc;
}
template<typename Rect> Rect& move(Rect& rc, point_type<Rect> to)
{
    int w = w(rc);
    int h = h(rc);
    rc.left = to.x;
    rc.top = to.y;
    rc.right = rc.left + w;
    rc.bottom = rc.top + h;
    return rc;
}
Run Code Online (Sandbox Code Playgroud)

但是如何在不更改函数名称的情况下允许传递任何大小和点类型?显然我不能这样做:

template<typename Rect, typename Size> Rect& move(Rect& rc, Size delta);
template<typename Rect, typename Point> Rect& move(Rect& rc, Point to); …
Run Code Online (Sandbox Code Playgroud)

c++ templates overloading metaprogramming template-meta-programming

1
推荐指数
1
解决办法
67
查看次数

使用 Module#prepend 查询 str_enum

我有一个 Rails 模型,它使用str_enum gem。

我正在构建一个生成器,它读取模型并为它们创建页面,因此我希望能够了解str_enum附加到模型的内容。

例如

class User < ApplicationRecord
  str_enum :email_frequency, %i[every daily weekly], default: 'every'
end
Run Code Online (Sandbox Code Playgroud)

理想情况下,我希望能够查询User模型并了解str_enum附加到email_frequency,其值为every, daily& weekly

一旦我能理解str_enum给定字段附加了一个,我就可以将该字段复数化并获取值:

irb(main):004:0> User.email_frequencies
=> ["every", "daily", "weekly"]
Run Code Online (Sandbox Code Playgroud)

这里也有人问这个问题,建议使用Module#prepend. 我熟悉prepend有条件地将方法插入模型中。

我该如何使用它来解决这个问题?

编辑

这对于验证非常简单,例如:从模型中获取验证

ruby metaprogramming

1
推荐指数
1
解决办法
106
查看次数

Ruby:为什么传递给 send() 的输入被包装在 Hash 中?

我在 Ruby 中使用 send() 方法来调用我定义的方法。该方法采用OpenStruct.

这是一个片段,显示了我如何使用send以下方法调用我的方法:

my_open_struct = OpenStruct.new(foo: "foo")

result = @my_object.send(
            :my_method_that_takes_an_openstruct,
            name_of_openstruct_param: my_open_struct)
Run Code Online (Sandbox Code Playgroud)

的问题是,内部my_method_that_takes_an_openstructOpenStruct参数是得到包裹在一个Hash,从而导致在记录这样的输出:

Just before calling send #<OpenStruct foo="foo">
Inside my_method_that_takes_an_openstruct: {:name_of_openstruct_param=>#<OpenStruct foo="foo">}
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况,我该如何防止这种包装行为?

ruby metaprogramming

1
推荐指数
1
解决办法
28
查看次数