Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

require() not working correctly in interactive shell #1824

Closed
Zirunis opened this issue May 9, 2024 · 5 comments
Closed

require() not working correctly in interactive shell #1824

Zirunis opened this issue May 9, 2024 · 5 comments
Labels
area-Core This affects CC's core (the Lua runtime, APIs, computer internals). bug A problem or unexpected behaviour with the mod.

Comments

@Zirunis
Copy link

Zirunis commented May 9, 2024

Minecraft Version

1.16.x

Version

1.101.3

Details

require(filePath) doesn't work correctly with following setup:

  1. There is a folder in the home directory (in my case called "datatypes")
  2. It contains two lua files (in my case "Bidict.lua" and "Set.lua") with one importing the other (in my case the former importing the latter via Set = require("Set")
  3. Starting the interactive lua shell from the home directory
  4. Importing the lua file which imports the other lua file (in my case: Bidict = require("Bidict")

While it can find 'Bidict.lua', during its import it tries importing 'Set' inside of 'Bidict.lua' which fails. It can't find the module throwing a stack-trace with all the locations it looked for it. Unfortunately it is cut off so I can't paste it here. The logs also didn't have anything of interest.
Interestingly, starting the interactive shell from the folder containing the two files works fine. My programs in the home directory which import 'Bidict' just like I'm trying to in the shell also work fine.

I hope you can reproduce the bug. Please let me know if I can be of any further assistance!

@Zirunis Zirunis added the bug A problem or unexpected behaviour with the mod. label May 9, 2024
@SquidDev SquidDev added the area-Core This affects CC's core (the Lua runtime, APIs, computer internals). label May 9, 2024
@SquidDev
Copy link
Member

SquidDev commented May 9, 2024

Thanks for the report!

I'm afraid I'm getting a little stuck on following your reproduction steps (testing on CC 1.110.3, but I don't think this code has change much since).

Importing the lua file which imports the other lua file (in my case: Bidict = require("Bidict")

I'm slightly surprised/confused by this step. I wouldn't expect this to work — if you're running from the root directory, require("Bidict") will look for files at /Bidict.lua, and so shouldn't find /datatypes/Bidict.lua.

I'd also expect you to hit this problem with the programs in the root directory too. Just to check, you're not changing package.path anywhere are you?

This is my current setup, with the following files:

  • datatypes/Set.lua, just containing print("Set").
  • datatypes/Bidict.lua, containing print("Bidict"); require("Set")

Then opening the Lua REPL and running the following:

A CC computer. I have run ls /andls /datatypesto show there are exactly two files on the disk, and then opened the Lua REPL and runrequire("Bidict")`. There's an error saying the module cannot be found

Am I missing/misunderstanding a step here?

@Zirunis
Copy link
Author

Zirunis commented May 9, 2024

Thanks for the fast reply!

I'd also expect you to hit this problem with the programs in the root directory too. Just to check, you're not changing package.path anywhere are you?

Nope

I'm slightly surprised/confused by this step. I wouldn't expect this to work — if you're running from the root directory, require("Bidict") will look for files at /Bidict.lua, and so shouldn't find /datatypes/Bidict.lua.

Yeah, I'm sorry, I messed up the description at that step. I'm actually calling require("datatypes/Bidict") which should work, right?

This is what I'm actually running:
requireNotWorking1
requireNotWorking2

This works even though the files are the same:
requireWorking

I have now noticed that my programs in the home directory calling require("datatypes/Bidict") in the same exact way actually don't work either. So it does not have to do with the interactive shell but require() in general.

@fatboychummy
Copy link
Contributor

fatboychummy commented May 9, 2024

Files are required from the currently running program, so if /startup.lua requires datatypesDemo/Bidict, then Bidict.lua would need to require datatypesDemo/Set.

Alternatively...

Updating package.path

In your root file, you will want to have some approximation of the following code:

package.path = package.path .. ";/datatypesDemo/?.lua;/datatypesDemo/?/init.lua"

What this does is tells require that it should search in the datatypesDemo folder for * or */init.lua, where * is replaced by your require string.

Then, you can leave Bidict.lua as is, to require("Set"). As well, in your root file, you can just require("Bidict") now, instead of needing to include the folder name.

@Zirunis
Copy link
Author

Zirunis commented May 9, 2024

Thank you for your answer but that makes no sense to me. How are dependencies then handled in the general case? I'd need to go through all dependencies and replace their require(relativePath) which would work fine on its own with a require(absolutePath)? That can't be right. Especially since there might even be naming conflicts. Who is to say that dependency A and dependency B don't both have a separate dependency like 'utils' that is contained in each of their directories? Now when my program imports these two dependencies it 1. Doesn't know where to look and 2. Might choose the wrong one if I use the package.path solution?

@Zirunis
Copy link
Author

Zirunis commented May 9, 2024

Nevermind. I looked it up and you're right. require() seems to just suck.
However for people stumbling across this in the future: I found out that there is a better way. There is an argument passed to an api when it is require()'d which is the argument given to require() itself, which is either its absolute path or the relative path as seen from the importing program. So one can do something like this at the top of each file:

local pathToThisFile = (...):match("(.-)[^%.]+$")  --turns "datatypes.Bidict" into "datatypes."
local Set = require(pathToThisFile .."Set")

In this case you'd always have to import files using dot-notation, but changing the pattern to also transform something like "datatypes/Bidict.lua" into "datatypes." shouldn't be too hard.

@Zirunis Zirunis closed this as completed May 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-Core This affects CC's core (the Lua runtime, APIs, computer internals). bug A problem or unexpected behaviour with the mod.
Projects
None yet
Development

No branches or pull requests

3 participants