Page 1 of 2
Modules and name clashing.
Posted: Sat Jun 22, 2013 5:24 pm
by luis
I'm trying to see how PB modules works.
Suppose you write a lib in source form using modules, and when the user of your lib includes it in his main project there is some name clashing.
Example of a worst case scenario:
Code: Select all
Procedure func()
Debug "main"
EndProcedure
DeclareModule lib1
#test_const = 111
Declare func(par)
EndDeclareModule
Module lib1
Procedure func(par)
Debug "lib1 func:" + par
EndProcedure
EndModule
DeclareModule lib2
#test_const = 222
Declare func(par)
EndDeclareModule
Module lib2
Procedure func(par)
Debug "lib2 func:" + par
EndProcedure
EndModule
lib1::func(lib1::#test_const)
lib2::func(lib2::#test_const)
func()
The user want to use a lib1 made from you, a lib2 made from someone else, and inside his project he has a function "func()" clashing twice: with lib1 and lib2.
It seem (if I'm not missing something) right now the only option (apart changing some of the sources OBVIOUSLY please don't suggest that) is to use the fully qualified name for everything, as I did above.
This can be ok if you have not much to call, but imagine if it's not the case.
Couldn't be partially solved accepting this code (currently not compilable because raises an error) ?
Code: Select all
Procedure func()
Debug "main"
EndProcedure
DeclareModule lib1
#test_const = 111
Declare func(par)
EndDeclareModule
Module lib1
Procedure func(par)
Debug "lib1 func:" + par
EndProcedure
EndModule
DeclareModule lib2
#test_const = 222
Declare func(par)
EndDeclareModule
Module lib2
Procedure func(par)
Debug "lib2 func:" + par
EndProcedure
EndModule
; all the above is identical
UseModule lib1 ; don't raise an error anymore here
func(#test_const) ; and here call the func in the only matching module instead
UseModule lib2 ; now the matching modules would be two... potential problem
lib2::func(lib2::#test_const) ; but not if I fully qualify it (or close the previous module before, I can choose)
::func() ; I want to call the global func(), so I just prepend "::" to it
In many circumstances this could end up in a lot of less typing, by choosing wisely the best path.
Just thinking out loud, and considering probably it's still a GOOD idea to use prefix like lib1_func() etc, even when using modules.
Comments about all this ?
EDIT: corrected a typo
Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 6:36 pm
by Little John
As far as I can see at the moment, I think
UseModule maybe better should not be introduced into PB 5.20 final. Much better IMHO would be, to allow
With with modules:
Code: Select all
Procedure func()
Debug "main"
EndProcedure
DeclareModule lib1
#test_const = 111
Declare func(par)
EndDeclareModule
Module lib1
Procedure func(par)
Debug "lib1 func:" + par
EndProcedure
EndModule
DeclareModule lib2
#test_const = 222
Declare func(par)
EndDeclareModule
Module lib2
Procedure func(par)
Debug "lib2 func:" + par
EndProcedure
EndModule
;--- all the above code is identical to Luis' code ---
With lib1
::func(::#test_const)
EndWith
With lib2
::func(::#test_const)
EndWith
func()
Using
With, we can also save some typing, and the code IMHO is much clearer and better readable than with using
UseModule. And the concept and meaning of
With is already familiar to all PB users with a certain level of experience.
See also
this feature request.
Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 7:06 pm
by User_Russian
Little John, Then it will be not possible to connect multiple modules
Code: Select all
DeclareModule lib1
#test_const = 111
Declare func(par)
EndDeclareModule
Module lib1
Procedure func(par)
Debug "lib1 func:" + par
EndProcedure
EndModule
DeclareModule lib2
#test_const_1 = 222
Declare func1(par)
EndDeclareModule
Module lib2
Procedure func1(par)
Debug "lib2 func:" + par
EndProcedure
EndModule
UseModule lib1
UseModule lib2
func(#test_const)
func1(#test_const_1)
Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 7:14 pm
by freak
There is also a HideModule command which closes the module again. Then you can open another one.
Actually, if you have two modules with the same procedure in their declaration, I would strongly advice to
always call the procedure with the fully qualified name. Otherwise your code will become very hard to read and manage because you never know which procedure you are calling without looking at the context. Even worse: By moving the call to a different place in the code you might end up calling a diffferent procedure!
The UseModule command is meant for the cases where there is no ambiguity and therefore taking the shortcut to remove the module prefix is not a problem. If there is possible cause for confusion, using the full names will make your life easier.

Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 7:26 pm
by Little John
freak wrote:There is also a HideModule command which closes the module again. Then you can open another one.
Actually, if you have two modules with the same procedure in their declaration, I would strongly advice to
always call the procedure with the fully qualified name. Otherwise your code will become very hard to read and manage because you never know which procedure you are calling without looking at the context. Even worse: By moving the call to a different place in the code you might end up calling a diffferent procedure!
The UseModule command is meant for the cases where there is no ambiguity and therefore taking the shortcut to remove the module prefix is not a problem. If there is possible cause for confusion, using the full names will make your life easier.

As far as I can see, using
With / EndWith would have the same advantages as
UseModule / HideModule, but without its potential disadvantages, no?

Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 7:39 pm
by freak
Your "With" syntax would require to write the "::" prefix everywhere. I don't like that very much.
As I said, opening/closing modules frequently is not a good idea anyway. If you look around how people use modules in other languages you see the same as well: There is usually just a block of "using" (or similar) keywords at the top of the code that import the needed modules and then they are never closed again. Either a module is fully imported or it is just referenced with the module prefix. A mix is not a good idea imho.
This is why the keyword is called "UseModule" and not "OpenModule": Opening something implies that it needs to be closed after use. But that is not the common use case here. You can just "use" the module and never "unuse" it. If you really want to though you can do it. That is what HideModule is for.
Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 7:52 pm
by luis
freak wrote:
Actually, if you have two modules with the same procedure in their declaration, I would strongly advice to always call the procedure with the fully qualified name.
I see what you mean... unfortunately that's a lot of typing, especially if not only procedures but constants too are involved... (see 1st post) but I think I agree, especially since my idea would indeed make the code more "context" dependent.
freak wrote: Otherwise your code will become very hard to read and manage because you never know which procedure you are calling without looking at the context. Even worse: By moving the call to a different place in the code you might end up calling a diffferent procedure!
Since this is something that can easily happen especially if your module is used by different people, what do you think about what I wrote above:
luis wrote:Just thinking out loud, and considering probably it's still a GOOD idea to use prefix like lib1_func() etc, even when using modules.
?
Probably better this than a situation like the one I showed in my first post. That's the point I would have liked to have some feedback about.
I'm oriented towards this kind of solution, and I would like to hear any reason stating this is overkill, if any. There is the fact I could simply use the full qualified name and so "move" the prefix to another place: instead of inside the name, before the "::".
I'm in doubt.
EDIT: I just saw the auto-complete does not honor the module name to filter the procedures names, so if if I write
lib1::fun.... in reality it does match any fun*.*() anywhere.
This is another point in favor of using lib1_fun() as the name of procedures even if inside modules, to filter them easily and in a consistent way.
Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 8:43 pm
by Fred
You can also see the Modules like a way to a a new library in PureBasic: the functions you want to expose needs to be unique (even accross the whole PB commandset as you can't name a procedure the same than an internal command). To me it's better to remove the prefix and find function name which can works with UseModule, and if you import 2 modules with the same functions, then you need to prefix them. May be I will change the way UseModule checks the ambiguity: for now it raises an error if one function collide. But we could change that to raise the error when the ambigus function is called, so you have to choose the right one for this case. It should be more flexible.
Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 8:49 pm
by luis
Fred wrote:But we could change that to raise the error when the ambigus function is called, so you have to choose the right one for this case. It should be more flexible.
I think that would be nice, thanks.
Remains the fact autocomplete is not "module-aware" so for now I tend to be inclined to use a prefix in the name to solve this even if I would prefer to avoid it.
It's a lot useful to see only what it's pertinent to a specific library (module) and currently this doesn't seem possible not using a prefix.
Right ?
Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 9:49 pm
by BorisTheOld
I can't see why people are having so much trouble with Modules -- they are a standard programming construct that everyone should know about.
A module is just a block of related code that is one level up from a procedure. A module contains one or more procedures, and some data, that can be considered as a "black box", in the same way that a class is a black box. And like a class, procedures and data in the module can be made visible to code outside the module.
Typically, modules are coded as Include files that are compiled right in the application, compared to a library which is precompiled for static or dynamic linking. And like libraries, it doesn't matter what names are used inside the modules, because nothing outside is aware of them.
Public names need to be uniquely identified, and this is done by prefixing the name with the module name:
ModuleName::ProcedureName
ModuleName::DataName
This is not rocket science.
And please, everyone, stop whining about having to type a few extra characters, or that the compiler should be able to read your mind.
Try to be professional.
Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 10:03 pm
by luis
@boristheold
I didn't learn anything from your post, since you are explaining something already understood, and I didn't get an answer to my question.
Did you try to understand the sense of the thread ?
Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 10:11 pm
by Fred
Autocomplete will be updated, but I don't see why you should code depending of your IDE features. What if you change your code editor, you will change you way of coding ?
Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 10:19 pm
by luis
Fred wrote:Autocomplete will be updated
Nice, thank you
Fred wrote:, but I don't see why you should code depending of your IDE features. What if you change your code editor, you will change you way of coding ?
Autocomplete for me it's so important (read: useful) it's just like a feature of the language. So if one editor give me an autocomplete "module-aware" and another one not, and I cannot use the first editor for some reason than YES, I would change the naming conventions to use the feature reduced autocomplete at the best of its possibilities, not losing the ability to filter only the procedures available in a specific module.
If autocomplete wouldn't be available in any form, then I wouldn't have to try to keep something I don't have.
Re: Modules and name clashing.
Posted: Sat Jun 22, 2013 11:46 pm
by freak
As Fred said, think of a module like a Library: As such, the public interface of a Module should be well designed with descriptive names and not export things that are not needed.
Example: If the Module is called "Animation", call the public function "CreateAnimation()" and not just "Create()". Yes, "Animation::Create()" tells you what you need to know, but on its own "Create()" could mean anything. And if you have two modules that create something you have a conflict. But if one module has a CreateAnimation() function and the other has a CreateGame() function then there is no conflict even if you use UseModule on both.
If you give the public function good names then the chance for an actual collision with the names is very low. Of course, if you export procedures like "proc()" and variables like "x" then you will run into conflicts very soon.
Of course this is just my opinion. You can as well use the module concept exactly so you can name the function Create() and not CreateAnimation(). But then in my opinion it is also better to use the fully qualified names rather than using UseModule. If the module name becomes part of the meaning of what the function does, then it should also be written on every call to make clear what the line is supposed to do.
Imho, these are the two styles that are useful with Modules
- give descriptive names that stand on their own, use UseModule and only write the full name to avoid (rare) conflicts
- give shorter names for simplicity inside the module and write the full name outside to keep the meaning of the call clear
Just my opinion of course.
Re: Modules and name clashing.
Posted: Sun Jun 23, 2013 12:01 am
by BorisTheOld
freak wrote:Just my opinion of course.
Good suggestions.
Modules, like any other language features, are not a panacea for poor programming practices.
Sadly, many (most?) programmers don't understand the benefits of well designed, well structured, well documented, and well tested code.