2015-11-04 57 views
0

由于在编译模块后内联属性,我假设它们的值是恒定的。如果可能的话,我想根据以前创建的属性来定义一个属性。我也希望能够从外部访问它们,我目前的做法是这样的在Elixir中编写属性

@required_fields ~w(email) 
@optional_fields ~w(password role name last_name age country) 

def required_fields, do: @required_fields 
def optional_fields, do: @optional_fields 

@all_fields required_fields ++ optional_fields 
def all_fields, do: @all_fields 

,但我得到这个错误

==编译错误的文件的Web /模型/ user.ex = = **(CompileError)web/models/user.ex:22:undefined function required_fields/0 (elixir)展开宏:Kernel。@/1 web/models/user.ex:22:AristaServer.User(module ) (elixir)lib/kernel/parallel_compiler.ex:97:Kernel.ParallelCompiler.spawn_compilers/8中的anonymous fn/4

任何方式来实现类似的东西?我不想每次重新计算all_fields列表,看起来很浪费。另外,我不想将这两个列表复制并复制到第三个列表中,看起来很容易出错。

回答

1

除非你运行了一个基准测试,否则你对灵丹药剂中“浪费”的直觉可能是错误的。我知道,我已经运行过的每个基准都是这种情况。 只要做到这一点,并担心它的工作后快或慢。

def all_fields, do: required_fields ++ option_fields 

https://en.wikiquote.org/wiki/Donald_Knuth

我的想法是,使用模块的属性可能是更浪费内存,因为那些被转换到代码中的多个项目。如果你把它放在一个变量中,它只会在内存中创建一次。但这只是一个猜测。

但是,如果你真的想要结合模块属性,你可以这样做。

@all_fields @required_fields ++ @optional_fields 
def all_fields, do: @all_fields 

您的问题出现了,因为您无法使用模块中的函数来定义模块属性。

+0

Elixir对这种特殊情况有记忆吗?如果不是,我无法想象它将如何加速'all_fields'并避免调用O(n)的'++'运算符。 –

+0

++运算符只有可变数据的0(n)。如果数据项是不可变的,则++为0(1),(即当你到达这个列表的末尾时,从下一个列表开始)。我不知道这实际上是如何实现++的,但它是一个例子,说明在不变数据环境中,所有关于快速什么的直觉都会被抛出窗口。 –

+0

我挖入代码,'x ++ y'是O(x的大小),所以它介于两者之间。它复制x,然后将x的尾部指向y的头部。 –

1
@required_fields ~w(email) 
@optional_fields ~w(password role name last_name age country) 
@all_fields   @required_fields ++ @optional_fields 


def required_fields, do: @required_fields 
def optional_fields, do: @optional_fields 
def all_fields,  do: @all_fields 

我怀疑你需要两个模块属性和公共方法;考虑只使用一个(如果你只在模块中使用它们,模块属性应该做这个工作,否则你应该使用公共方法)。