Is 'namespace export ... ' necessary, in order to use the variable/procs of that namespace in a different namespace using the 'namespace import *' command.
Should we really do the 'export' in the source namespace and 'import'in the destination namespace.
All namespace export does is make commands available for namespace import and prompts them to appear in a simple-mode namespace ensemble (though you've got other options for that). If you don't want to support namespace import, you don't have to; just never export anything.
You invoke commands in another namespace using the fully-qualified syntax:
::the::other::namespace::command "some argument, as normal"
You can also use partial namespace names; that's pretty common as a leading :: is a bit ugly...
In general, I don't want to do namespace import/export: I want the variables/procs to stay where they are. Importing might pollute the destination namespace, which is against the namespace's design.
Related
In perl, sometimes it is necessary to specify the function name in the use statement.
For example:
use Data::DPath ('dpath');
will work but
use Data::DPath;
won't.
Other modules don't need the function names specified, for example:
use WWW::Mechanize;
Why?
Each module chooses what functions it exports by default. Some choose to export no functions by default at all, you have to ask for them. There's a few good reasons to do this, and one bad one.
If you're a class like WWW::Mechanize, then you don't need to export any functions. Everything is a class or object method. my $mech = WWW::Mechanize->new.
If you're a pragma like strict then there are no functions nor methods, it does its work simply by being loaded.
Some modules export waaay too many functions by default. An example is Test::Deep which exports...
all any array array_each arrayelementsonly arraylength arraylengthonly bag blessed bool cmp_bag cmp_deeply cmp_methods cmp_set code eq_deeply hash
hash_each hashkeys hashkeysonly ignore Isa isa listmethods methods noclass
none noneof num obj_isa re reftype regexpmatches regexponly regexpref
regexprefonly scalarrefonly scalref set shallow str subbagof subhashof
subsetof superbagof superhashof supersetof useclass
The problem comes when another module tries to export the same functions, or if you write a function with the same name. Then they clash and you get mysterious warnings.
$ cat ~/tmp/test.plx
use Test::Deep;
use List::Util qw(all);
$ perl -w ~/tmp/test.plx
Subroutine main::all redefined at /Users/schwern/perl5/perlbrew/perls/perl-5.20.2/lib/5.20.2/Exporter.pm line 66.
at /Users/schwern/tmp/test.plx line 2.
Prototype mismatch: sub main::all: none vs (&#) at /Users/schwern/perl5/perlbrew/perls/perl-5.20.2/lib/5.20.2/Exporter.pm line 66.
at /Users/schwern/tmp/test.plx line 2.
For this reason, exporting lots of functions is discouraged. For example, the Exporter documentation advises...
Do not export method names!
Do not export anything else by default without a good reason!
Exports pollute the namespace of the module user. If you must export try to use #EXPORT_OK in preference to #EXPORT and avoid short or common symbol names to reduce the risk of name clashes.
Unfortunately, some modules take this too far. Data::DPath is a good example. It has a really clear main function, dpath(), which it should export by default. Otherwise it's basically useless.
You can always turn off exporting with use Some::Module ();.
The reason is that some modules simply contain functions in them and they may or may not have chosen to export them by default, and that means they may need to be explicitly imported by the script to access directly or use a fully qualified name to access them. For example:
# in some script
use SomeModule;
# ...
SomeModule::some_function(...);
or
use SomeModule ('some_function');
# ...
some_function(...);
This can be the case if the module was not intended to be used in an object-oriented way, i.e. where no classes have been defined and lines such as my $obj = SomeModule->new() wouldn't work.
If the module has defined content in the EXPORT_OK array, it means that the client code will only get access to it if it "asks for it", rather than "automatically" when it's actually present in the EXPORT array.
Some modules automatically export their content by means of the #EXPORT array. This question and the Exporter docs have more detail on this.
Without you actually posting an MCVE, it's difficult to know what you've done in your Funcs.pm module that may be allowing you to import everything without using EXPORT and EXPORT_OK arrays. Perhaps you did not include the package Funcs; line in your module, as #JonathanLeffler suggested in the comments. Perhaps you did something else. Perl is one of those languages where people pride themselves in the TMTOWTDI mantra, often to a detrimental/counter-productive level, IMHO.
The 2nd example you presented is very different and fairly straightforward. When you have something like:
use WWW::Mechanize;
my $mech = new WWW::Mechanize;
$mech->get("http://www.google.com");
you're simply instantiating an object of type WWW::Mechanize and calling an instance method, called get, on it. There's no need to import an object's methods because the methods are part of the object itself. Modules looking to have an OOP approach are not meant to export anything. They're different situations.
I can't find answer what is the difference in namespace definition using double :: ( when I read source files where both are used ) between:
namespace eval somenamespace {
}
and
namespace eval ::somenamespace {
}
sample without ::
https://github.com/tcltk/tcllib/blob/master/modules/generator/generator.tcl#L16
sample with ::
https://github.com/tcltk/tcllib/blob/master/modules/ftp/ftp.tcl#L56
It's a bit like path names. If you are in the root directory (the unnamed / path) it makes no difference if you use bar or /bar: both refer to the /bar directory. If you are in /foo, it matters very much if you use bar or /bar: the first refers to the /foo/bar directory, and the second still refers to the /bar directory.
:: is like / for namespace names. In the root namespace (the empty :: name) it makes no difference if you use bar or ::bar: both refer to the ::bar namespace. If you are in ::foo, it matters very much if you use bar or ::bar: the first refers to the ::foo::bar namespace, and the second still refers to the ::bar namespace.
Documentation: namespace
In general, it depends on the context in which the code is run. If it is run in the global namespace, there is no difference between the two. If it is run inside another namespace (e.g., in ::foo for the sake of argument) there's a difference (since one creates ::foo::somenamespace).
For packages it makes little difference, the scripts provided by package ifneeded — and hence run by package require — are actually run by this line (inside tclPkg.c, in the function PkgRequireCore):
code = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL);
That is, they're always in the global context, the :: namespace.
I'm reading from an Oculus Rift and writing via serial to control an Arduino, but I'm having some problems with namespaces since I'm new to C++.
The beginning of my code goes like this:
#using <System.dll>
#include "OVR.h"
#include <iostream>
#include <conio.h>
using namespace System;
using namespace System::IO::Ports;
using namespace System::Threading;
using namespace OVR;
The original error ocurred when I tried to use String, since it is defined in both System and OVR. I changed the code to System::String but now I got an error telling me that System is ambiguous because it is already defined in OVR::System
Is there some way to avoid this conflict? Some way to exclude OVR::String and OVR::System from being affected by the 'using' clause? I can't get rid of one of the 'using' clauses because I have a lot of reference to the members of those namespaces in my code.
First, you can always fully-qualify a name to use it specifically:
::System::String^ string; // this will always work
You can also use specific using directives to disambiguate without having to fully-qualify names:
using ::System::String;
String^ string;
Using directives can be placed at any level and will only affect this level. For instance, if you put one at the global level, all of your file will be affected by it. If you put it inside a function, only your function will be affected by it.
Also, I don't know if you realize it, but you're using C++CLI, an extension to C++ that lets you use .NET classes with C++-like code. This only works on Microsoft platforms.
The OVR namespace includes tons of things which have common names and might conflict with something you're using, so don't import it. In other words, don't do this:
using namespace OVR;
Instead, import the specific OVR items that you want like this:
using OVR::Matrix4f;
You can now using the Matrix4f class unadorned in your code, without having to worry about other types that you didn't import conflicting.
If there's still an issue where you're going to have a conflict (say you need to use the OVR Matrix4f class and your own Matrix4f class) then you have two options. Either accept that you're going to have to use explicit namespaces for one of them, or create typedefs for one of them:
typedef OVR::Matrix4f OVRMat4;
Matrix4f foo;
OVRMat4 foo;
Synopsis
How do you declare variables in a namespace while using the use statement? (ie., without declaring the namespace with the variable name)
How do you reference namespace variables with the "use" statement without a container reference. (ie., trace(foo) rather than trace(a.foo) [seems kinda pointless if I have to state this after already switching to the namespace])
Explanation
Having read Grant Skinner's "Complete Guide to Using Namespaces", and other articles, such as Jackson Dustan's "Better OOP Through Namespaces", I'm left with the above unanswered questions. I feel as though I'm missing some basic principle, but I can't seem to get namespaces to work. The following examples are written for use with the Flash IDE, so assume the following...
locus.as
package com.atriace {
public namespace locus = "atriace.com";
}
testA.as
package com.atriace {
public class testA {
import com.atriace.locus;
locus var foo:String = "Apple";
public function testA() {}
}
}
testB.as
package com.atriace {
public class testB {
import com.atriace.locus;
use namespace locus;
public function testB() {
trace(foo);
}
}
}
Document Class:
import com.atriace.testA;
import com.atriace.testB;
var a:testA = new testA();
trace(a.foo); // results in "Apple"
var b:testB = new testB(); // compile error: variable "foo" not defined.
Issue #1
In my mind, a namespace is little more than an object to hold variables that has scope level access. Ergo, global is a namespace visible to all functions (since it's the root scope), local is namespace (specific to the current and child scopes), and so on. If true, then switching to a namespace with use should allow you to simply declare variables that happen to exist in both the local and custom namespaces. For example:
use namespace locus
var bar:String = "test"; // this now *should* exist in both local & locus scope/namespace.
Since I'm unaware of a method to iterate over a namespace like a normal object, I don't know whether this is what happens. Furthermore, I haven't seen any cases where someone has declared a custom namespace variable this way, so I assume namespace variables must always be explicitly defined.
Issue #2
You might ask, "what's the goal here?" Quite simply, we want a dynamic pool of variables and methods that any new classes can add to (within the same package). By switching to this namespace prior to calling methods, we can reduce the wordiness of our code. So, class.method() becomes just method().
In testB.as we'd fully expect an error to occur if we never imported the testA.as class and instantiated it; especially because foo isn't a static member of the class (nor do we want it to be). However, since we've instantiated foo at least once, the namespace locus should now have a variable called foo, which means that when testB.as gets instantiated, and the constructor seeks a value for foo, the namespace already has one.
Obviously, there's a flaw in this thinking since the Flash compiler complains that foo has never been declared, and the only way I can reference foo from the document class is by referencing the container (ie., a.foo rather than just switching to the namespace with use, and tracing foo directly).
For the sake of argument, neither inheritance nor static members are a solution to this dilema. This is both an excercise in learning better code techniques, and an answer to the structure of a large utility class that has complicated dependencies. Given the absence of a variable/method, you could simply code around it.
I know it's not a heavily documented topic, which is why I'm hoping some sage here may see what I'm missing. The help would be much appreciated. :)
"use namespace" is for the consumer side. You always have to include the namespace in any declaration:
MyNamespace var foobar : uint;
If you wish to add namespaced package-global variables (you shouldn't as a general rule), you have to define each one of them in a separate .as file as packages only allow one publicly-visible definition per file at the top-level.
In your example above you are using namespaces incorrectly. A namespace can span multiple classes, but does not achieve the cross-class functionality you are looking for. This is more the domain of aspect-oriented programming.
EDIT
I want to group together related functions to show that they are related.
If I have local:f1() and local:f2() then I could just change their names to local:menu-f1() and local:menu-f2() but is there a mechanism in the XQuery language to group related functions?
OP
I am very excited to discover that XQuery functions can be declared in a namespace other than local:. Where can I find info about how this works?
Having always declared functions in this way;
declare function local:foo() {
3+4
};
.. and used them in this way;
local:foo()
.. I discover that they can be declared like this;
declare namespace baz = "fred:bloggs";
declare function baz:foo() {
3+4
};
.. and used like this;
baz:foo()
But I can only find reference-like information about declare namespace and declare function separately, not tutorial-like information about how XQuery function namespaces work in general.
Is there a newbie guide to XQuery function namespaces?
I'm using a Saxon processor - XQuery 1.0.
What you are probably using are normal XQuery namespaces - what you probably are looking for are modules. You can put a bunch of functions in its own module namespace like this:
module namespace foo = "http://www.myurl.com/foo";
declare function foo:bar($args as item()*) as item()* {
() (: do something cool :)
};
Afterwards you can import the module in you main query and call the function:
import module namespace foo = "http://www.myurl.com/foo";
foo:bar(<my-element/>)
The problem is, that it is not standardized, how the processor has to find the query. And I don't know how Saxon implements the module resolving mechanism (you should look into the documentation and/or write to the Saxon mailing list).
But most XQuery processors look at the path given by an "at" clause relative from the location of the query. So to have something that should work on most implementations: For example you could store the module in a file named foo.xq and place it into the same directory than your main query and then for the module import you would write:
import module namespace foo = "http://www.myurl.com/foo" at "foo.xq";
which gives a hint to the XQuery engine where it should look for the module.
You can find some (not a lot at the moment) documentation about this stuff at http://www.xquery.me/ - hope this helps.
EDIT
Ok I see, you only want to group your functions. To do that you already figured out everything you need to know. But I still want to emphasize that splitting your query up into modules would probably be the better solution for your use-case (it's just somehow nicer, since your have more modularity and in the upcoming XQuery 3.0 recommendation you will even have the possibility to put stuff like private functions and variables in there). But if your query does not get big, your solution is of course also ok.
You can think about XML namespaces the same way you would think about namespaces in C++. In XQuery, functions, elements, collections, variables, attributes etc can be in an own namespace (again - like in C++). There are some implicitely defined namespaces like xs (the XML Schema namespace where you can find the data types like boolean, integer etc), local (a namespace where you can put in functions so that you are not forced to define your own namespace in a main query), fn (where all functions from the "XQuery 1.0 and XPath 2.0 functions and operators" recommendation are defined). But the prefix of this function is only an alias - you can use whatever you want.
So let's say you have the following code in the prolog of your query:
declare namespace blubb = "http://www.w3.org/2001/XMLSchema";
blubb:integer would be exactly the same type than xs:integer - the same holds for functions:
declare namespace l = "http://www.w3.org/2005/xquery-local-functions";
With declaring that you can access every function in the local namespace with the "l" prefix (so l:bar() if local:bar() exists).
If you do not type a prefix, XQuery assumes that this function is in the "fn" namespace. This is why bot
fn:concat("Hello ", "World!")
and
concat("Hello ", "World!")
are equivalent. You can change this behavior. You could include this line into the prolog:
declare default function namespace "http://www.w3.org/2005/xquery-local-functions";
which would tell the XQuery processor that you do not want to prefix local functions (so bar() would be equivalent to local:bar()).
I am not sure if I answered your questions or at least was able to bring in some clarity. I do not know about a tutorial for that (since in the beginning it is somehow confusing but in the end you realize that there is not a lot to say about since the mechanisms are much simpler than they look in the first place). The document where I always look up stuff is the recommendation at http://www.w3.org/TR/xquery/
If this does not help you please try to qualify and I can try again with an explanation..