a thingie i really hate in monkey...

Monkey Archive Forums/Monkey Discussion/a thingie i really hate in monkey...

Salmakis(Posted 2015) [#1]
the import stuff, either im to stupid or it is stupid. im not sure.

if i anyhow import a file 2 times, then monkey is freaking out like "Duplicate identifier 'Bla' found in module 'bla' and module 'bla'.
even if those are the same files.
monkey should just check if the same file is allready imported and then ignore any other import of the same file.

often i want to include stuff from severeal points so that jungle and jentos can highlight & intellisence it to me.

but it is sometimes horrible when i merge project branches to handle then the "who includes what" stuff.


Danilo(Posted 2015) [#2]
I have the same problem.

I have a module xyz and an optional sub-module xyz.abc that, when included, depends on the main module.
Couldn't get that to work because of the same "Duplicate identifier 'Bla' found in module 'bla' and module 'bla'.
I could possibly have 10 or 20 such sub-modules, but now I have to include everything into one big module
and add compiler-options and checks like #INCLUDE_XYZ_ABC = True and #INCLUDE_XYZ_DEF = True etc.
#IF INCLUDE_XYZ_ABC
   ' ...
#ENDIF

#IF INCLUDE_XYZ_DEF
   ' ...
#ENDIF

I would like:
Import xyz     ' main lib
Import xyz.abc ' optional add-on
Import xyz.def ' optional add-on
' [...]

If I do it like this, xyz.abc and xyz.def complain that they don't know about types defined in main 'xyz'.
If I Import xyz within the sub-modules, MonkeyX complains that stuff is already declared (because it's now included multiple times).


ImmutableOctet(SKNG)(Posted 2015) [#3]
@Salmakis: You seem to be handling modules incorrectly. It sounds like you're having a name conflict with the module-name. In Monkey, the module name can be used like a "namespace" of sorts. You can use it in your code to manually describe a type, instead of using the standard shorthand. Monkey effectively handles each module one time, so the only problems I can think of are circular module-referencing and file-name conflicts. You might want to read my reply to Danilo.

@Danilo: You might need to split up your modules a bit more. Mojo does what you're trying to do, and it doesn't have any problems. Though, it is using private imports, so that might have something to do with it. Monkey doesn't have forward declarations like languages like C and C++, so the closest thing is to import anyway. Privately importing might be your best bet. I don't get what you were doing with the preprocessor, though. A module gets preprocessed exactly once, but it does use imports as tangents when preprocessing.

Private imports can be done by simply setting the access-level to private as you normally would; again, see how Mojo does it.


Danilo(Posted 2015) [#4]
Thanks ImmutableOctet(SKNG), but could you elaborate a bit please, when to use Private Imports and when to use Public Imports?

For example in vector.monkey I see:
' Imports (Public): 

' ImmutableOctet: 
Import boxutil 
Import util 
Import ioelement 
Import sizeof 
 
' Imports (Private): 
Private 

' BRL: 
Import brl.stream 

Public

' [...]

' Imports (Other): 
#If Not VECTOR_DELEGATE_SUPPORTLAYER 
    Private 
#End 

Import supportlayer 

#If Not VECTOR_DELEGATE_SUPPORTLAYER 
    Public 
#End 

What's the reason you import brl.stream as Private and importing all other modules as Public?
Why not Import everything as Private to the module? And supportlayer is imported as Private or Public,
depending on preprocessor flags!?!
How do you exactly decide what you need to import as Public and what parts/modules as Private?
Why do we get "Duplicate identifier 'Bla' found in module 'bla'" sometimes, and sometimes it works without conflicts?

Thanks in advance!


ImmutableOctet(SKNG)(Posted 2015) [#5]
@Danilo: After looking into it more, I don't think Monkey has the issue I was thinking it had. If you could put together an example of the conflict, I'd be happy to look into it. From my testing, I can't seem to break it. The closest thing I can think of is name conflicts. For example, if you import 'mojo.graphics' and 'mojo2.graphics' in the same context (Publicly/locally), then you'll get errors about the ambiguity of a shared name; the 'Image' classes (Which are both different). There's also the problem of module-names being "first-class citizens", as they can be used like namespaces. In other words, you can't use a class that has the same name (Case sensitive) as a module, unless you explicitly declare the desired element. In other words, you'd probably use an alias, or rename the module.

As for private modules; I usually import modules as private when they're potentially not required, or they act as an implementation detail. With private imports, you can use code from the module you import, but that code may or may not be accessible to the module(s) importing your own module. I should also mention that you can use public aliases to private implementation details. For example, if module 'y' has a function called 'A', and module 'x' privately imports 'y', it can declare an alias to 'A', called 'Test'. However, the original function, 'A' would still be a private implementation detail. So, if another module 'main' (For example) would import x, it would only have access to the alias. The big points here are abstraction, and keeping unneeded details away from the user, who just wants the minimal functionality of a module. Case in point, the I/O functionality of my 'vector' module does not have anything to do with math directly. But, if someone wanted to serialize one, they could, and they wouldn't have to deal with the potential "bloat". This also makes things more encapsulated, as you wouldn't have to worry about name conflicts from side-modules. If Monkey's compiler was more advanced, like what Mark wants to do with Monkey 2, then there would also be potential chances for optimization using this approach.

To make a long story short, only use private imports when you want to support something, but that functionality isn't relevant to most cases. Mojo does this with its 'app' and 'input' modules, which Mojo 2 takes advantage of. Mojo 2 lets you use Mojo functionality, without having any dependency on the original Mojo's graphical functionality. That being said, it's able to take advantage of it optionally, by importing 'mojo.graphics' privately.

Also, from what I remember about 'VECTOR_DELEGATE_SUPPORTLAYER', that was done for testing purposes, the default configuration does not publicly open that implementation detail. To be honest, the 'supportlayer' sub-module was meant for 'IntObject' and 'FloatObject' support, anyway. Unfortunately, those containers don't implicitly convert to their internal storage type. They have conversion methods for several types, and for generic classes, that's a problem. And to be fair, I probably should use private imports more frequently. And trust me, I'm no stranger to import conflicts.

I'm probably a bit late in asking this, but what version of Monkey are you running? Imports are slightly different after V82A.

EDIT: I should also mention that Monkey only generates code for what's used. This also helps when dealing with private imports and optional functionality. Monkey can be forced to compile a module completely by using the reflection filter.


Danilo(Posted 2015) [#6]
Thanks again, ImmutableOctet(SKNG)! Using Private imports within the sub-module, I got now the error:
ATTENTION: Compilation error reported by Trans: Cannot convert from Renderer to Renderer.

Looks like MonkeyX thinks the Public Renderer within the main module is different from the same Renderer when imported private within the Sub-Module.

Had the feeling that your tip of splitting the imports into more separate files is probably the last chance to get this working. Tested it. Works.
And after it works now, I can't reproduce the error mentioned above anymore. Private Renderer can now get converted to Public Renderer. :D

Thanks again! (btw, I'm using latest v84b)


Salmakis(Posted 2015) [#7]
been a while, but thank you mr ImmutableOctet(SKNG) for pointing this out!