有没有办法在函数内部使用“isdefined(:x)”,其中x是在同一个函数中定义的?

时间:2016-11-26 05:15:58

标签: julia

我有一个函数在工作目录的父目录中查找名为“global”的文件。这就是我的想象:

function readglobal()
  if isfile("./global")
    text = readdlm("./global",String,comment_char='/')
  else
    for i = 1:8
      if isfile("../"^i * "global")
        text = readdlm("../"^i * "global",String,comment_char='/')
        break
      end
    end
  end

  isdefined(:text) || error("Could not find global file")

  dict = Dict{String,String}()
  for i in 1:size(text)[1]
    dict[text[i,1]] = text[i,2]
  end
  return dict
end

这不起作用,因为 isdefined 在current_module()中查找全局变量,我从中调用函数。 有没有办法让它按预期工作?要在函数中评估 isdefined(:text)吗?

我使用以下代码解决了这个问题,但我认为上面的代码更清晰。

function readglobal()
  foundit = isfile("./global")
  if foundit
    text = readdlm("./global",String,comment_char='/')
    foundit=true
  else
    for i = 1:8
      foundit = isfile("../"^i * "global")
      if foundit
        text = readdlm("../"^i * "global",String,comment_char='/')
        break
      end
    end
  end

  foundit || error("Could not find global file")

  dict = Dict{String,String}()
  for i in 1:size(text)[1]
    dict[text[i,1]] = text[i,2]
  end
  return dict
end

4 个答案:

答案 0 :(得分:2)

以下是此功能的1.5行版本:

readglobal() = Dict(mapslices(x->=>(x...),readdlm(first(filter(isfile,
  "./$("../"^i)global" for i=0:8)),String;comment_char='/'),2))

如果文件丢失,它甚至会返回错误;)

答案 1 :(得分:2)

编辑:不知怎的,我错过了你找到的解决方法,正如你所说的那样,这与我建议的几乎相同。我不同意第一个代码更清晰,使用isdefined对我来说似乎很苛刻。 foundit标志是正确的方式,恕我直言。

原始回答: 请勿使用isdefined检查是否找到了该文件。而是设置一个标志,例如filefound。这些内容(警告,未经测试):

function readglobal()
    filefound = false
    filepath = "global"
    for i in 0:8
        filefound = isfile(filepath)
        if filefound
            break
        end
        filepath = joinpath("..", filepath)
    end
    filefound || error("Could not find file ")
    text = readdlm(filepath, String, comment_char='/')

    dict = Dict{String,String}()
    for i in 1:size(text, 1)
        dict[text[i,1]] = text[i,2]
    end
    return dict
end

编辑2 :这是一个变体:

function readglobal(filename, maxtries=8)
    tries = 0
    while !isfile(filename) && (tries+=1) <= maxtries
        filename = joinpath("..", filename)
    end
    tries > maxtries || error("Could not find file ")

    text = readdlm(filename, ...
    ...
end

答案 2 :(得分:1)

不是一个确切的答案,但我会使用一个单独的函数:

function get_global_content()
    if isfile("./global")
      return readdlm("./global",String,comment_char='/')
    else
      for i = 1:8
        if isfile("../"^i * "global")
          return readdlm("../"^i * "global",String,comment_char='/')
        end
      end
    end
    error("Could not find global file")
end

function readglobal()
  text = get_global_content()

  dict = Dict{String,String}()
  for i in 1:size(text)[1]
    dict[text[i,1]] = text[i,2]
  end
  return dict
end

或者,看看Nullable,例如,

function readglobalnull()
  text = Nullable()
  if isfile("./global")
    text = Nullable(readdlm("./global",String,comment_char='/'))
  else
    for i = 1:8
      if isfile("../"^i * "global")
        text = Nullable(readdlm("../"^i * "global",String,comment_char='/'))
        break
      end
    end
  end

  isnull(text) && error("Could not find global file")
  text = get(text)

  dict = Dict{String,String}()
  for i in 1:size(text)[1]
    dict[text[i,1]] = text[i,2]
  end
  return dict
end

答案 3 :(得分:0)

Julia的0.7版本有一个@isdefined variable_name宏,能够正确地完成我在这个问题中所要求的内容。它适用于任何局部变量。