1

My question is inspired from this question that I asked earlier. Here is the code.

\documentclass{article}
\usepackage{parskip,luacode}
\begin{luacode*}
M = {}         -- the module
complex = {} -- global complex numbers registry
local mt = {} --metatable for complex numbers
   function new (r, i)
       local cp = {}
        cp = {r=r, i=i}
        return setmetatable(cp,mt)
      end
      M.new = new        -- add 'new' to the module
    function M.op (...)
    local _ENV = complex
        return ...
      end  
      function M.add (c1, c2)
        return new(c1.r + c2.r, c1.i + c2.i)
      end
      function M.tostring (c)
        return string.format("(%g,%g)", c.r, c.i) --to avoid +-
      end
    mt.__tostring = M.tostring
    mt.__add = M.add
\end{luacode*}
\newcommand\cpxNew[2]{%
    \directlua{%
        complex[\luastringN{#1}] = M.new(#2)
    }%
}
\newcommand\cpxPrint[1]{%
    \directlua{tex.sprint(tostring(complex[\luastringN{#1}]))}%
}

\newcommand\cpxOp[1]{%
    \directlua{%
        tex.print(tostring(M.op(#1)))
    }%
}
\begin{document}
\cpxNew{a}{3,4}
\cpxPrint{a} \par
\cpxOp{complex.a + complex.a} \par
%\cpxOp{a+a}
\end{document}

It gets compiled. I get expected output too, except for the commented last command \cpxOp{a+a}. When I un-comment it, I get the error (arithmetic on nil value). I need such thing for setting metatables. I expect the answer (6,8). However, I am getting nil. The previous command \cpxOp{complex.a +complex.a} gives expected answer. What is the problem with the function M.op(...). I have set up local _ENV to complex and so I expect to get same answer as \cpxOp{complex.a + complex.a} for the command \cpxOp{a+a}. This does not happen. What may be the reason? Any help will be appreciated. Thanks.

4
  • 1
    Changing _ENV doesn't have the effect you are looking for because Lua is not a macro language. If you had written return a instead of return ... in M.op, Lua would have used complex.a, but in your example the global a is looked up before M.op is even called. So the new _ENV isn't in effect at that point. – Marcel Krüger Apr 19 '20 at 19:11
  • So how to evaluate ... in the environment complex? – user61681 Apr 20 '20 at 5:11
  • The question isn't where ... is evaluated, it is in which scope a appears. So if you would want this, you would have to set local _ENV=complex in the \directlua block in \cpxOp – Marcel Krüger Apr 20 '20 at 16:35
  • How to set local_ENV = complex in the \directlua block? – user61681 Apr 20 '20 at 17:00
2

Your macro \cpxNew is registering an element inside the complex table (in your case, complex.a or complex["a"]). If you call a, you get nil as it is an undefined element. A workaround is defining a new command so you have not to write complex

EDIT

If you don't mind breaking things, you can equal complex and _G (global variable).

%!TEX program = lualatex
\documentclass{standalone}
\usepackage{luacode}
\begin{luacode*}
    M = {}        -- the module
    complex = _G -- global complex numbers registry
    local mt = {} --metatable for complex numbers

    function new (r, i)
    local cp = {}
    cp = {r=r, i=i}
    return setmetatable(cp,mt)
    end

    M.new = new        -- add 'new' to the module

    function M.op (...)
    local _ENV = complex
    return ...
    end

    function M.tostring (c)
    return string.format("(%g,%g)", c.r, c.i) --to avoid +-
    end
    mt.__tostring = M.tostring
\end{luacode*}
\newcommand\cpxNew[2]{%
    \directlua{%
    complex[\luastringN{#1}] = M.new(#2)
}%
}
\newcommand\cpxPrint[1]{%
\directlua{tex.sprint(tostring(complex[\luastring{#1}]))}%
}


\newcommand\cpxOp[1]{%
\directlua{%
tex.print(tostring(M.op(#1)))
}%
}
%Workaround
\newcommand\cpxOpp[1]{%
    \directlua{%
    tex.print(tostring(M.op(complex[\luastring{#1}])))
    }%
}
\begin{document}
\cpxNew{a}{3,4}
\cpxPrint{a}
\cpxOp{a+a}
\end{document}

Now your code works.

enter image description here

3
  • 1
    Sorry, I expect something different. I have modified the question. Have a look at it. – user61681 Apr 20 '20 at 4:55
  • See again. I've edited my answer. – user193767 Apr 20 '20 at 6:08
  • Can there be a better way out of running it in complex environment rather than polluting global space? – user61681 Apr 20 '20 at 12:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.