Erlang中的命名空间和记录

um6iljoc  于 2022-12-08  发布在  Erlang
关注(0)|答案(4)|浏览(160)

Erlang显然有一个 namespace 的概念,我们每天都使用application:start()之类的东西。
我想知道是否有记录的命名空间。在我的应用程序中,我定义了记录用户。一切都很好,直到我需要包括来自RabbitMQ的rabbit.hrl,它也定义了用户,这与我的冲突。
在线搜索并没有解决这个问题。我考虑过重命名我的用户记录,并在它前面加上一些前缀,比如“myapp_user”。这将解决这个问题,直到我怀疑我遇到了另一个冲突,比如我的记录“session”。
我的选择是什么?给我的所有记录添加前缀myapp_是一个好的做法,还是有一个真实的的支持记录的命名空间,我只是没有找到它?

**编辑:**谢谢大家的回答。我了解到的是,这些记录是全球性的。被接受的回答非常清楚。正如我所料,我将在所有记录中添加前缀。

qco9c6ql

qco9c6ql1#

I would argue that Erlang has no namespaces whatsoever. Modules are global (with the exception of a very unpopular extension to the language), names are global (either to the node or the cluster), pids are global, ports are global, references are global, etc.
Everything is laid flat. The namespacing in Erlang is thus done by convention rather than any other mean. This is why you have <appname>_app , <appname>_sup , etc. as module names. The registered processes also likely follow that pattern, and ETS tables, and so on.
However, you should note that records themselves are not global things: as JUST MY correct OPINION has put it, records are simply a compiler trick over tuples. Because of this, they're local to a module definition. Nobody outside of the module will see a record unless they also include the record definition (either by copying it or with a header file, the later being the best way to do it).
Now I could argue that because you need to include .hrl files and record definitions on a per-module basis, there is no such thing as namespacing records; they're rather scoped in the module, like a variable would be. There is no reason to ever namespace them: just include the right one.
Of course, it could be the case that you include record definitions from two modules, and both records have the same name. If this happens, renaming the records with a prefix might be necessary, but this is a rather rare occurrence in my experience.
Note that it's also generally a bad idea to expose records to other modules. One of the problems of doing so is that all modules depending on yours now get to include its .hrl file. If your module then change the record definition, you will have to recompile every other module that depends on it. A better practice should be to implement functions to interact with the data. Note that get(Key, Struct) isn't always a good idea. If you can pick meaningful names (age, name, children, etc.), your code and API should make more sense to readers.

8iwquhpp

8iwquhpp2#

您需要以一种不太可能与其他记录冲突的方式命名所有记录,或者您只需要不在模块之间使用它们。在大多数情况下,我将把记录视为不透明的数据结构,并向定义记录的模块添加功能以访问它。这将避免您遇到的问题。

wyyhbhjk

wyyhbhjk3#

I may be slapped down soundly by I GIVE TERRIBLE ADVICE here with his deeper knowledge of Erlang, but I'm pretty sure there is no namespaces for records in Erlang. The record name is just an atom grafted onto the front of the tuple that the compiler builds for you behind the scenes. (Records are pretty much just a hack on tuples, you see.) Once compiled there is no meaningful "namespace" for a record.
For example, let's look at this record.

-record(branch, {element, priority, left, right}).

When you instantiate this record in code...

#branch{element = Element, priority = Priority, left = nil, right = nil}.

...what comes out the other end is a tuple like this:

{branch, Element, Priority, nil, nil}

That's all the record is at this point. There is no actual "record" object and thus namespacing doesn't really make any sense. The name of the record is just an atom tacked onto the front. In Erlang it's perfectly acceptable for me to have that tuple and another that looks like this:

{branch, Twig, Flower}

There's no problem at the run-time level with having both of these.
But...
Of course there is a problem having these in your code as records since the compiler doesn't know which branch I'm referring to when I instantiate. You'd have to, in short, do the manual namespacing you were talking about if you want the records to be exposed in your API.
That last point is the key, however. Why are you exposing records in your API? The code I took my branch record from uses the record as a purely opaque data type. I have a function to build a branch record and that is what will be in my API if I want to expose a branch at all. The function takes the element , priority , etc. values and returns a record (read: a tuple). The user has no need to know about the contents. If I had a module exposing a (biological) tree's structure, it too could return a tuple that happens to have the atom branch as its first element without any kind of conflict.
Personally, to my tastes, exposing records in Erlang APIs is code smell. It may sometimes be necessary, but most of the time it should remain hidden.

k5ifujac

k5ifujac4#

只有一个记录命名空间,并且与函数和宏不同,只能有一个具有名称的记录。但是,对于 * 记录字段 *,每个记录都有一个命名空间,这意味着在不同记录中具有相同名称的字段没有问题。这就是为什么在每个记录访问中必须始终包括记录名称的原因之一。

相关问题