Page 2 of 2

Re: Remove name conflict check for modules and internal comm

Posted: Thu Sep 12, 2013 5:56 am
by Danilo
freak wrote:Replacing a builtin function is not a good idea.
freak, it is not about replacing internal commands. I do this sometimes for bug workarounds by using macros.
I thought modules are here to prevent naming conflicts, but that's not the case as we learn now. If you write
a game engine module, you may want to add functions like LoadSprite() and LoadSound() to it.
If you write a module for drawing stuff, you want to use Box(), Line(), Circle(), Ellipse() in your module.
A special math module may contain standard functions like Abs(), Sin(), Cos(), Sqr(), Tan(), Log(), Log10(), ...

It is not possible now, because many hundred, common procedure names are reserved by PB already.
Most of this are very commonly used names, used nearly everywhere in the world (math, drawing, ..).
Maybe PB has already over 1.000 commands, I didn't count them.

It is clear in nearly every language that you can't use reserved keywords, so nobody writes procedures like If(), While(), Wend().
Also, this are not very useful names for procedures. Hope you understand what I mean.
Luckily API commands all end with underscore '_', otherwise there would be many more thousands of useful names reserved,
that would conflict with our own module procedures.

Fred added '_' to the end of all API functions to prevent name clashes between API and PB functions (like 'LoadImage'), and now we users have
the same problem inside our own modules. We need to write LoadImage__() now, because LoadImage() and LoadImage_() are already used
and can lead to problems! :D

In gDrawing I used names like gClear(), gPlot(), gBox(), gRoundBox(), gLine(), gLineXY(), gPie(), gPieXY(), gArc(), gArcXY(), gEllipse(), gEllipseXY(),
gCircle(), gCircleXY(), gBezier(), gCurve(), gClosedCurve(), gTriangle(), gPoly(), gDrawImage(), gDrawAlphaImage(), gDrawClippedImage(),
gDrawText(), gDrawRotatedText(), ...

Now we have to continue doing the same. I really thought modules would fix this problem with always using unique names, because it is a separate "namespace".

Maybe you can re-think that again and find a way to change it little bit, so we are also able to use common procedure names,
even if they are already used by PureBasic. I provided some ideas, and I think using something like "System::" for all PB and API
functions would be really good. This would only be required if there is a name conflict, otherwise you can use PB functions like before.

It is the same if we use two modules from Tips & Tricks from different authors. If there is a name conflict, we can use the full qualified
name, like ts_soft::DoSomething() and freak::DoSomething(). For PB we could use System::LoadSprite() to prevent conflicts with other module names, if they appear.

The situation now is that PB forbids us to use many hundred useful names for our own module functions, and some hundred more will be added in the future, for sure... ;)
Modules could solve this problems, and I think the main reason for developing the module stuff was to prevent such naming conflicts in the future,
with so many thousand users, writing millions of procedures every year...

Re: Remove name conflict check for modules and internal comm

Posted: Thu Sep 12, 2013 8:52 pm
by BorisTheOld
Danilo wrote:Modules could solve this problems, and I think the main reason for developing the module stuff was to prevent such naming conflicts in the future, with so many thousand users, writing millions of procedures every year...
No -- one of the aims of modules is to help prevent naming conflicts now, not in the future.

The best you can do is name your variables, constants, and procedures, so they have a good chance of being unique for a long time. Over the years I've used the same naming conventions for COBOL, ASM, BASIC, FORTRAN, PL/I, etc, etc -- long names and Polish notation. And during that time I've had very few naming problems, because the prefixes tend to create names that are unlikely to exist in English.

I'd suggest that you don't fret about what might happen in the future, but develop naming conventions for your code that will minimize the need to make future changes. Sometimes, though, the universe will grab you by the ass, and you'll be forced to make some changes. There's really nothing else that can be done.

Here's an example of how I get around naming conflicts.

The following "Set" statement assigns "True" to a boolean property having external (public) scope. The property belongs to an object that is private to the class that contains this statement.

Code: Select all

Macro Me
  *Self
EndMacro
;
Macro True
  #lVALUE_TRUE
EndMacro
;
Macro Set (bvsObjectName, bvsDataParmName, bvsValue)
  bvsObjectName\set#bvsDataParmName(bvsValue)
EndMacro
;
Set(Me\proApplicationPanel, exlHorizontalAlignment, True) 
The "Set" statement creates the following code:

Code: Select all

*Self\proApplicationPanel\setexlHorizontalAlignment(#lVALUE_TRUE)

bvs (in the macros) = by value string
pro = private object
exl = external (public) boolean property
setexlHorizontalAlignment = the "set" procedure name of the "exlHorizontalAlignment" property
We generate all our code from templates in our data dictionary, so future naming conflicts won't be a problem -- just change a feature definition, then regenerate and recompile -- problem solved.

But whatever coding methods are used, it's always worthwhile developing strict coding and naming conventions for everything: variables, constants, procedures, files, etc, etc, including program layout, comments, and documentation.

Even a hobby programmer can benefit from developing a few simple coding rules.

Re: Remove name conflict check for modules and internal comm

Posted: Fri Sep 13, 2013 6:17 am
by Danilo
BorisTheOld wrote:We generate all our code from templates in our data dictionary, so future naming conflicts won't be a problem -- just change a feature definition, then regenerate and recompile -- problem solved.
Problem solved for your generated stuff to let it compile, but if you develop libraries for other people, it is not as easy as that.
For generated stuff even names like class_window_meth_open_ret_i_args3_l_i_s() are no problem. Even completely unreadable or encrypted names are no problem.

We can write modules now, and we are able to avoid naming conflicts with PB commands now (usefulness is limited, because we can't use commands like Box, Line, Ellipse, ... inside modules).
But PB gets new commands every release. So our own modules, even if several years old, can break in the future with the current implementation, if PB adds a new command name we already used.

For a library, I have to change the name then and tell my customers that they have to change it too, because PB got a new command
that conflicts with a name inside my module, and PB's new commands are higher in priority. Even if my command is not in global namespace -
it is inside my (protected) module!
So I can't create stable Interfaces with modules that customers can use. I can change the internals like I want, not affecting any users.
If the interface itself breaks, it is a very bad thing because it affects all users of the library, maybe customers that paid for it.

Currently I see only two possibilities to really avoid the problem:
1.) Give my module procedures really unique, ugly names.
Pro: Minimizes the chance of a name conflict with future PB commands.
Con: Nobody wants to use such a module. Even myself wouldn't want to use it then.

2.) Change the system little bit, so this conflicts can't happen anymore. PB commands get the virtual "System::" namespace.
Pro: Works in many other programming languages without conflict, because the module/namespace name is part of the whole name.
The name "Module1::Function()" does not collide with "Function()" and "System::Function()". It can only collide with itself.
Con:


I am repeating myself, and you will not get my point anyway.

Everything has been said (with detailed reasons for this feature request and wish), and I hope (and think) at least Fred understands what I am talking about.
I am pretty sure he understands the problem, but I'm not sure he will change it anymore, now that it is already done. ;)

Re: Remove name conflict check for modules and internal comm

Posted: Fri Sep 13, 2013 11:39 am
by freak
Your module can also stop working because a command is removed or changed in the future. Modules will not save you there. The purpose of modules is not to write code that is guaranteed to work for all future versions. This is simply impossible with a language that evolves.
Danilo wrote:Currently I see only two possibilities to really avoid the problem:
1.) Give my module procedures really unique, ugly names.
Pro: Minimizes the chance of a name conflict with future PB commands.
Con: Nobody wants to use such a module. Even myself wouldn't want to use it then.
I think you are exaggerating here. How often did you have a naming conflict between a procedure you wrote and a PB function that was introduced later before modules were added? I had this problem maybe once so far (don't really remember), and i haven't heard of many people that had this problem either. What makes you think this will become a big problem now?

We did consider all of this during the design stages. In our opinion, this is not a big enough issue to justify making the module concept more complex the way you propose.

Re: Remove name conflict check for modules and internal comm

Posted: Fri Sep 13, 2013 12:36 pm
by PMV
As i doesn't want to just prevent future conflicts, i would more like
to prevent current conflicts. But of course, it is very ugly to overwrite
existing build in functions. Even so in OOP thats a common feature to
overwrite existing functions, i doesn't like that kind, too. I just come
often to the point, that i want to call a function the same way as it
already exists. :)

I will never use "UseModule" as that is somehow that kind of feature.
Instead i will always write the fully qualified name. By using a module,
it will always be easy to see, if it is a PB command or a module-command.
As PB commands doesn't have a module-name. So it would be a really
nice feature, if we could use the same function-name for public functions
from modules as PB commands are named.

But, of course there is still a conflict inside of such a module itself.
By defining a function with the same name as a PB command, you can't
call this function inside of that module. To solve this problem, there could
be a rule. Just allow public module functions to be named the same way
as PB commands, and with something like "self::", they could even
be still called inside of a module. Or just the module name itself.

I really like that idea, but of course, modules are not targeted to prevent
that (for me) annoying conflicts ... i still really like modules and can't wait for
the final (and maybe first bugfix version) to get starting with it. :mrgreen:

MFG PMV

Re: Remove name conflict check for modules and internal comm

Posted: Fri Sep 13, 2013 5:53 pm
by Danilo
freak wrote:We did consider all of this during the design stages. In our opinion, this is not a big enough issue to justify making the module concept more complex the way you propose.
Fine. No need to discuss it any further, as final decision has been made already. PMV, eesau and myself just have to live with it.

One last question:

The following code works with PB5.20 beta 18. Is this correct code, according to PureBasic syntax rules as you understand them? (I think so, just want to double check)

Code: Select all

DeclareModule __GadgetHelper_Internal
    EnableExplicit
    Declare __GetGadgetData_Internal(gadget, index=0)
    Declare __SetGadgetData_Internal(gadget, value, index=0)
EndDeclareModule

Module __GadgetHelper_Internal
    
    Global NewMap gadgetData.i()
    
    Procedure __GetGadgetData_Internal(gadget, index=0)
        ProcedureReturn gadgetData(Str(gadget)+":"+Str(index))
    EndProcedure
    
    Procedure __SetGadgetData_Internal(gadget, value, index=0)
        gadgetData(Str(gadget)+":"+Str(index)) = value
    EndProcedure
    
EndModule


DeclareModule GadgetHelper
    EnableExplicit
    Macro GetGadgetData(gadget, index=0)
        __GadgetHelper_Internal::__GetGadgetData_Internal(gadget, index)
    EndMacro
    
    Macro SetGadgetData(gadget, value, index=0)
        __GadgetHelper_Internal::__SetGadgetData_Internal(gadget, value, index)
    EndMacro
    
EndDeclareModule

Module GadgetHelper
EndModule


GadgetHelper::SetGadgetData(1, 12)
GadgetHelper::SetGadgetData(2, 30)

Debug GadgetHelper::GetGadgetData(1)
Debug GadgetHelper::GetGadgetData(2)

For index = 1 To 10
    GadgetHelper::SetGadgetData(1, index+100, index)
Next

For index = 1 To 10
    Debug GadgetHelper::GetGadgetData(1, index)
Next
There is only one issue in the IDE:

Code: Select all

GadgetHelper::SetGadgetData(
GadgetHelper::GetGadgetData(
Both commands show wrong quick help in IDE status bar. Would be nice if at least this could be corrected, as it should only
be a priority issue within the IDE quick help procedures.

The following code shows correct quick help:

Code: Select all

Procedure Function(a,b)
EndProcedure


DeclareModule Module1
    Macro Function(a,b,c,d,e,f)
    EndMacro
EndDeclareModule

Module Module1
EndModule


Function(
Module1::Function(

Re: Remove name conflict check for modules and internal comm

Posted: Fri Sep 13, 2013 6:18 pm
by BorisTheOld
Danilo wrote:......For a library, I have to change the name then and tell my customers that they have to change it too, because PB got a new command that conflicts with a name inside my module, and PB's new commands are higher in priority......
I recently encountered a "name change" situation with PB -- FrameGadget must now be used instead of Frame3DGadget. I solved the problem by changing one line of code and recompiling all my programs. I was able to do this because I had wrapped each PB function in a class. And I had done this so that I could use my existing standards. The following example uses macros to show the technique:

Code: Select all

Macro QQFrame          ; old version
  Frame3DGadget
EndMacro

Macro QQFrame          ; new version
  FrameGadget
EndMacro
I doubt that PB will ever have a "QQFrame" statement.

I've already explained, in a previous post, how naming standards can avoid the problem, but you could get more fancy if you wish.

You could create complex wrappers, in the form of modules or classes, for PB features. This will give you absolute control over what your code sees. So, if PB changes some aspect of its functionality, all you have to do is change the module or class then recompile your code.

As for library names, most programming languages have the ability to declare names in code that are different from the exported names. So, if you export names in the form "danilo_procname", your customers might choose to change them using some sort of "prototype" or "alias" declaration. Or he might just use them the way you provide them.

I can honestly say that in all my years of programming, you're the first person I've ever encountered who can't understand that name conflicts are a non-issue. Naming conventions, macros, and wrappers, cover most situations. And for libraries, a simple declaration change and recompile are all that's needed.

You need to be proactive and use a lot of common sense. The word "then" is probably not a good choice of variable name, even though PB doesn't use it in "if" statements.

Re: Remove name conflict check for modules and internal comm

Posted: Fri Sep 13, 2013 6:42 pm
by Danilo
BorisTheOld wrote:And for libraries, a simple declaration change and recompile are all that's needed.
Correct. And all users of the library have to change their sources, if the interface of the library changes because I have to rename a public module procedure.
Internal I can change everything like I want, without affecting the users that use the library. They do use the public interface, so it should never change.

I need to forecast what commands could be added to future PB version, to not use this name. Or, I can use macros like shown in my last posting to prevent such possible future name collisions
and make the module interface stable.

Re: Remove name conflict check for modules and internal comm

Posted: Sat Sep 14, 2013 2:24 am
by BorisTheOld
@danilo

Yes, your external interface names should never need to change because the internals of your code are hidden from the user. The point I was making is that your external names may conflict with the user's names, and he has the option of declaring different names for his own code. So your earlier argument, that changes to PB commands will affect your library users, doesn't seem to hold up.

As for forecasting what commands could be added to future PB versions, good luck. That's like trying to forecast when you might be hit by lightening. I think your best bet is to go with macros and naming conventions. :)

Re: Remove name conflict check for modules and internal comm

Posted: Sat Sep 14, 2013 6:06 am
by Danilo
Thanks to everybody for the lively discussion! To use Macros is the solution - we shouldn't use Modules directly.
It is little bit ugly, but at least it is possible to prevent future name conflicts and use reserved PureBasic command names (Box, Line, Circle)
within our own modules.
It's too bad we can't use the new module feature without such workarounds for preventing (future) name conflicts, but hey,
at least we can do what we want to do, avoiding PureBasic's limitations.

Just always remember the priority within modules: Macros -> PB commands -> our own module procedures -> System API commands.
Outside of modules it seems to be: Macros -> PB and System API commands (equal priority) -> our own procedures.