v icon indicating copy to clipboard operation
v copied to clipboard

Confusion between v modules and subdirectories

Open bakul opened this issue 2 years ago • 9 comments

Describe the bug

If the code has "import os" and it is in a directory with a subdir called "os" the compilation fails if the subdir "os" has no .v files.

Expected Behavior

Program run correctly.

Current Behavior

$ v run x.v
x.v:2:1: builder error: cannot import module "os" (no .v files in "/home/bakul/src/v-lang/os")
    1 | module main
    2 | import os
      | ~~~~~~~~~
    3 | fn main() { println(os.args) }

Reproduction Steps

$ mkdir os
$ cat > x.v <EOF
module main
import os
fn main() { println(os.args) }
EOF
$ v run x.v

Possible Solution

No response

Additional Information/Context

v should not usurp local name space. Suggest looking at how go handles this.

V version

Any

Environment details (OS name and version, etc.)

all

bakul avatar Feb 06 '23 04:02 bakul

Although V is similar to Go, it is not Go.

V uses subdirs as local modules. This means if you have a local subdir which matches a V standard lib module, V is going to look at your local subdir instead of the standard lib module.

This is a very useful feature, allowing you to make changes without affecting the standard lib files.

Go has a lot of problems doing something similar.

JalonSolov avatar Feb 06 '23 12:02 JalonSolov

This is a very useful feature, allowing you to make changes without affecting the standard lib files.

This is not a common use pattern. Worse, it will confuse users. There should be a distinct way of referring to modules in local subdir vs standard modules.

bakul avatar Feb 06 '23 15:02 bakul

While I am reading someone's V code, if I read "import os", there is no reason for considering that the imported module is not the one in the standard vlib. I think some special annotation that clearly states "this is not from vlib" is necessary.

JoanaBLate avatar Feb 06 '23 17:02 JoanaBLate

Maybe something like:

import os // from vlib
import .os // from cwd

StunxFS avatar Feb 08 '23 18:02 StunxFS

Maybe something like:

import os // from vlib
import .os // from cwd

@StunxFS

I like your syntax.

Now, after seeing your sample, I started to wonder what happens if someone writes code exactly like that, importing 2 "os" modules. I know it is not advisable. But how should V handle this case?

Obviously, in the code we would need a syntax for differentiating the call to the vlib 'os' from the call to the custom 'os'.

So, calls to custom 'os' would have to be prefixed with ".". But that conflicts with the syntax for enums.

I remember that V uses '@' for escaping reserved words. Maybe we could use the same syntax ('@os') everywhere (imports and functions).

On a second thought, it is easy to create hard to find bugs if the programmer forgets the prefix ('@') when calling a function that both modules have.

And I fear that step by step V becomes less simple and small than what it intended to be.

The most simple solution is not to allow modules with names that match builtin V modules at all.

If someone really needs a custom module called 'os'. It just name it as 'myos'. Absolutely clear. No need for adding any special rule to the language.

JoanaBLate avatar Feb 09 '23 12:02 JoanaBLate

The most simple solution is not to allow modules with names that match builtin V modules at all.

@JoanaBLate as simple as this

import os // from vlib
import .os as my_os // from cwd

StunxFS avatar Feb 09 '23 16:02 StunxFS

That's not simple, though. It would require modifications to V syntax, compiler, etc.

"Simple" is just naming your own module my_os (or anything else that doesn't collide with a V standard module) instead of os.

JalonSolov avatar Feb 09 '23 17:02 JalonSolov

Isn't it simple? For me it is, also that syntax would also help to differentiate imports of local or installed modules in ~/.vmodules or those of vlib

StunxFS avatar Feb 09 '23 17:02 StunxFS

import os // from vlib
import .os as my_os // from cwd

It is indeed simple, but since you agree to use the prefix "my_os" (inside functions), all you need is to name your module as "my_os":

  • you write the module "my_os"
  • you import "my_os"
  • you call "my_os" functions

JoanaBLate avatar Feb 09 '23 18:02 JoanaBLate