如何使用函数args进行元编程?

时间:2017-03-09 08:15:53

标签: scope metaprogramming julia

这是我第二天学习和实验朱莉娅。虽然我仔细阅读了有关元编程的文献记录(但可能不够仔细)和几个类似的线程。我仍然无法弄清楚如何在函数中使用它。 我试着让以下函数更灵活地模拟一些数据:

using Distributions
function gendata(N,NLATENT,NITEMS)
  latent = repeat(rand(Normal(6,2),N,NLATENT), inner=(1,NITEMS))
  errors = rand(Normal(0,1),N,NLATENT*NITEMS)
  x = latent+errors
end

通过这样做:

using Distributions
function gendata(N,NLATENT,NITEMS,LATENT_DIST="Normal(0,1)",ERRORS_DIST="Normal(0,1)")
  to_eval_latent = parse("latent = repeat(rand($LATENT_DIST,N,NLATENT), inner=(1,NITEMS))")
  eval(to_eval_latent)
  to_eval_errors = parse("error = rand($ERRORS_DIST,N,NLATENT*NITEMS)")
  eval(to_eval_errors)
  x = latent+errors
end

但是由于eval不能在当地范围内工作,所以它不起作用。我可以做些什么来解决这个问题?

最初的功能,似乎不是那么快,我是否在表现方面犯了重大错误?

我真的很喜欢任何推荐。 提前谢谢。

2 个答案:

答案 0 :(得分:5)

不需要在那里使用eval,您可以通过将分发类型作为关键字args(或使用默认值命名的args)传递来保持相同的灵活性。解析和评估“字符串式”参数通常会使优化失败,应该避免。

var arr = [];
for (var i=1; i <= 6; i++){
    arr.push(getText(`text${i}`).toLowerCase());
}

答案 1 :(得分:0)

你真的不应该在这里使用eval(更慢,不会产生类型信息,会干扰编译等)但是如果你想要了解什么出了问题,在这里你会怎么做:

将其与其余代码分开:

function gendata(N,NLATENT,NITEMS,LDIST_EX="Normal(0,1)",EDIST_EX="Normal(0,1)")

  # Eval your expressions separately

  LATENT_DIST = eval(parse(LDIST_EX))
  ERRORS_DIST = eval(parse(EDIST_EX))

  # Do your thing

  latent = repeat(rand(LATENT_DIST,N,NLATENT), inner=(1,NITEMS))
  errors = rand(ERROR_DIST,N,NLATENT*NITEMS)
  x = latent+errors      
end

或者使用带引号表达式的插值:

function gendata(N,NLATENT,NITEMS,LDIST_EX="Normal(0,1)",EDIST_EX="Normal(0,1)")

  # Obtain expression objects

  LATENT_DIST = parse(LDIST_EX)
  ERRORS_DIST = parse(EDIST_EX)

  # Eval but interpolate in everything that's local to the function
  # And you can't introduce local variables with eval so keep them
  # out of it.

  latent = eval( :(repeat(rand($LATENT_DIST,$N,$NLATENT), inner=(1,$NITEMS))) )
  errors = eval( :(rand($ERRORS_DIST, $N, $NLATENT*$NITEMS)) )
  x = latent+errors
end

您还可以使用带有let块的单个eval来引入自包含范围:

function gendata(N,NLATENT,NITEMS,LDIST_EX="Normal(0,1)",EDIST_EX="Normal(0,1)")

  LATENT_DIST = parse(LDIST_EX)
  ERRORS_DIST = parse(EDIST_EX)
  x = 
  @eval let
    latent = repeat(rand($LATENT_DIST,$N,$NLATENT), inner=(1,$NITEMS))
    errors = (rand($ERRORS_DIST, $N, $NLATENT*$NITEMS))
    latent+errors
  end
end

((@eval x) == eval(:(x)))

嗯,希望你能更好地理解eval的事情。第二天我的意思是,你应该进行实验;)

相关问题