Namespaces: An Elegant Approach For Avoiding Name Conflicts
There are cases where name conflicts in scripts can lead to awkward problems, and the concept of namespaces can provide a powerful solution for those. Realizing this, I have implemented this concept for our software products RP Fiber Power, RP Resonator, RP Coating and RP ProPulse.
In this article, I show you with a typical example what the problem is and how that solution with namespaces works. It may thus be of interest even for people using other programming languages offering namespaces, e.g. C++; the general ideas are the same, although the syntax is a bit different. You know, such concepts are often explained in a very abstract way; a good example from real life can be very helpful.
What's the Problem?
Imagine that we generate a computer model for a fiber amplifier with two amplifier stages based on two different fibers. For example, there could be a single-mode fiber for the preamplifier and a double-clad fiber as a power amplifier.
Our software RP Fiber Power comes with a large set of fiber data files, mostly for commercially available fibers, each one defining variables like
r_co (the core radius) and functions like
s_abs_Yb(l) (the absorption cross-sections). The problem is quite obvious: if you simply include the data files for both fibers, the first one will define e.g. the variable
r_co, and the second one will override that with its own value – a typical name conflict!
In principle, there is an easy solution: make a copy of the data file for the second fiber, where you rename all variables and functions – for example, from
r_co2. Obviously, however, that is not really convenient. We could in principle deliver all those data files with variable and function names containing some product code, but that would again be relatively awkward to use: who would like to have variable names like
How to Use Namespaces
Namespaces provide an elegant solution. Essentially, you use a namespace called stage1 for the first amplifier stage and another namespace called
stage2 for the second stage. Before reading a data file, you just declare the defined namespace:
calc namespace: define stage1: begin include "Yb-Liekki Yb1200-6-125.inc" end namespace: define stage2: begin include "Yb-CorActive DCF-YB-10-128.inc" end
As a result, the variables and functions defined in the first data file get “
stage1.” added to their names. For example, the core radius will be stored in
stage1.r_co instead of simply
In principle, the problem is already solved with that. However, a second feature is highly convenient when later using the defined quantities. For example, you can use the following code when defining the two amplifier stages:
calc begin namespace: use stage1: begin set_device(1); set_ns('stage1'); set_fiber(L_f, No_z_steps, 'Yb'); add_ring(r_co, N_Yb); pump1 := addinputchannel(P_pump_in, l_p, 'I_p', loss_p, dir_p); signal1 := addinputchannel(P_signal_in, l_s, 'I_s', loss_s, forward); finish_fiber(); end; namespace: use stage2: begin set_device(2); set_ns('stage2'); set_fiber(L_f, No_z_steps, 'Yb'); add_ring(r_co, N_Yb); pump2 := addinputchannel(P_pump_in, l_p, 'I_p', loss_p, dir_p); signal2 := addinputchannel(P_signal_in, l_s, 'I_s', loss_s, forward); finish_fiber(); end; end
Here, we have declared within an expression that we will use a certain namespace
stage1 and later
stage2. As a result, we do not have to put
stage2. in front of every name; that is now done automatically.
When we write
use instead of
define in a namespace statement, this means that the namespace applies only to those items which can already be found in that namespace. Others, which are not defined in there, remain unaffected. For example, we really get the channel index
pump1 defined, not
A further detail: by calling the function
set_ns(), we tell the fiber model which namespace is associated with it. This is important because the software retrieves some fiber data from certain variables and functions – for example, it normally would take the upper-state lifetime from the variable
tau_Yb, and the mentioned function call changes that to
There are some further tricks which I do not want to completely describe here. Just to give you some examples:
- One can always enforce the use of the global namespace by putting
std.In front of a name.
- It is possible to exempt certain items – or just all constants – from the application of a namespace. Example: “namespace: define stage1, global constants:” would exempt all global constants.
Those who already have a user license can get a free update in order to enjoy namespaces as well – just tell us.
This article is a posting of the RP Photonics Software News, authored by Dr. Rüdiger Paschotta. You may link to this page, because its location is permanent.
Note that you can also receive the articles in the form of a newsletter or with an RSS feed.
Share this with your friends and colleagues, e.g. via social media:
These sharing buttons are implemented in a privacy-friendly way!