Search code examples
luaargumentsparameter-passing

passing an argument through assert(loadfile(play.lua))(argument) doesnt assign anything to arg[1] inside play.lua


I have a script play.lua that uses a filename as an argument in order to play the notes written on each line of the file. Im trying to write a script jukebox.lua that will run play.lua with various arguments based on an input, but the global argument table wont hold the arguments i assign using loadfile

play.lua (section that errors)

local name = "file " .. arg[1]

for line in io.lines(arg[1]) do
--[[note playing code]]--
print(".")
  end

My first attempt looked like this, but would return an error saying arg[1] was the nil value when trying to assign arg[1] to a variable in play.lua

jukebox.lua

assert(loadfile("play.lua"))("file1")

Then I tried assigning arg[1] in jukebox.lua

arg[1] = "file1"
assert(loadfile("play.lua")

this ran the code with no errors, but using lua jukebox.lua would play nothing and print nothing while lua play.lua file1 would play the file as normal and would print(".") for each line in the file file1. I also tried dofile and require with similar results

My question: Is writing assert(loadfile("play.lua"))("file1") in the script not identical to writing lua play.lua file1 in the console?

Edit: I made a new script play1.lua with the entirety of the code provided below.

play.lua

local name = "file " .. arg[1]

for line in io.lines(arg[1]) do
print(".")
  end

jukebox.lua

arg[1] = "file1"
assert(loadfile("play.lua"))()

Solution

  • The Lua standalone interpreter both puts the command-line arguments into the global arg and passes them to the chunk that it calls. In other words, when you do lua play.lua file1, something like this happens:

    arg = {"file1"}
    assert(loadfile("play.lua"))("file1")
    

    And the script can then use either the varargs syntax ... or the global arg to access them. Your play.lua uses the latter. assert(loadfile("play.lua"))("file1") gives an error because it's only setting up the former. assert(loadfile("play.lua")) isn't doing anything because it's only loading the chunk, not actually calling it. Adding an extra set of empty parentheses, i.e., assert(loadfile("play.lua")(), will fix that, and in combination with you setting arg[1], will make it work.