理解递归函数的隐式错误

理解递归函数的隐式错误

我最初的想法是加里克·佩施克 导入文件夹内的所有 .tex 文件,但我希望我的Lua函数也能在子文件夹内进行搜索。

不幸的是,我无法让该Lua函数在子文件夹中工作。值得注意的是,TeX 不会将此视为错误,任何 .tex 文件都将被正确处理,但文件夹则不会。


function inputAll(dir)
    for content in lfs.dir(dir) do
        if ("." ~= content) and (".." ~= content)  then
            fullpath = dir .."/".. content
                contentType = lfs.attributes(fullpath, "mode")
            if isTexFile(content, contentType) then
                    tex.sprint("\\input{" .. fullpath .. "}")
            elseif ("directory" == contentType) then
                return inputAll(fullpath)
            end
        end
    end
end
function isTexFile(dirOrFolder, contentType)
    return ("file" == contentType) and (string.find(dirOrFolder, ".+%.tex"))
end

按照提出的想法斯基恩 使用内部函数,结果是相同的:它适用于文件,但不适用于文件夹。


function inputAll(dir)
    local function inner(m)
        for content in lfs.dir(m) do
            if ("." ~= content) and (".." ~= content)  then
                fullpath = m .."/".. content
                    contentType = lfs.attributes(fullpath, "mode")
                if isTexFile(content, contentType) then
                        tex.sprint("\\input{" .. fullpath .. "}")
                elseif ("directory" == contentType) then
                    return inner(fullpath);
                end
            end
        end
    end
    inner(dir)
end
function isTexFile(dirOrFolder, contentType)
    return ("file" == contentType) and (string.find(dirOrFolder, ".+%.tex"))
end

以下是一些系统详细信息:

Mac Os X: 10.13.6
TeX 3.141592653 (TeX Live 2022)
LuaTeX, Version 1.15.0 (TeX Live 2022)
|_Compiled with lua version 5.3.6
TeXShop: 4.44 (4.44)

结论

正如 David Carlisle 指出的那样,当最新指令不使用时,TexLive 2022 中的 LuaTeX 实际上能够进行递归return

使用 TexLive 2018 时,无论有没有 都无法工作return。不幸的是,我没有保存任何证据,所以你必须相信我的话。
我仍然不清楚如果提供合适的尾递归算法,LuaTex 是否会工作:
据我所知,Lua需要return语句才能正确执行尾递归。LuaTex 我真的不知道。


最后的话:

我在其他一些作品中也曾尝试过 lua 递归tex,看来使用合适的算法就可以纯 lua(不确定是否需要)将允许使用return语句没有问题。

经过纯 lua我的意思是不要弄乱tex表格。例如:tex.sprint( ... )

我没有足够的时间去理解所有的 lfs 库代码,以了解是否有另一种方法可以以列表形式获取内容(无需我先准备数据,而是自己创建)。

下面的代码足以证明我的意思

function excludeDependencyRecursive(csvListOfGroupIdColonArtifactId, result, textDecorator)  
  if (csvListOfGroupIdColonArtifactId) then
    local beginIndex, endIndex = string.find(csvListOfGroupIdColonArtifactId,",");
    
    texio.write_nl( "term and log", "beginIndex : " .. (beginIndex or "nil") .. " endIndex : " .. (endIndex or "nil"))
    
    local first = string.sub(csvListOfGroupIdColonArtifactId, 1, getEndIndex(endIndex, csvListOfGroupIdColonArtifactId))
    --[[ first is always a valid string ]]
    local groupId, artifactId = getGroupAndArtifact(first)
    
    result = result .. textDecorator("<dependency>") .. "\\+ \\\\"
    result = result .. textDecorator("<groupId>" .. groupId .. "</groupId>") .. "\\\\"
    result = result .. textDecorator("<artifactId>" .. artifactId .. "</artifactId>") .. "\\\\"
    result = result .. textDecorator("\\dots") .. "\\- \\\\"
    result = result .. textDecorator("</dependency>") .. "\\\\"
  
    --[[ lua's shortcircut for IF endIndex THEN string.sub ELSE nil ]]
    local rest  = endIndex and string.sub(csvListOfGroupIdColonArtifactId, 1+endIndex, #csvListOfGroupIdColonArtifactId)
    texio.write_nl( "term and log", "first : " .. first .. " rest : " .. (rest or "nil"))

    return excludeDependencyRecursive(rest, result, textDecorator)
  end
  return result
end

--[[ can throw an error if the groupAndArtifact is not a string of the form A:B ]]
function getGroupAndArtifact(groupAndArtifact)
  --[[ both are local ]]
  local beginIndex, endIndex = string.find(groupAndArtifact,":");
  
  local first = string.sub(groupAndArtifact, 1, endIndex-1)
  local rest = string.sub(groupAndArtifact, 1+endIndex, #groupAndArtifact)
  return first, rest
end

function getEndIndex(index, string)
  --[[ lua version of C if then else ( A ? B : C) ]]
    return index and (index - 1) or #string
end

你所看到的是一个不太优雅的装饰器,你可以用

excludeDependencyRecursive(csvListOfGroupIdColonArtifactId, "", orangeBackgroudDecorator) 

在哪里

greenBackgroudDecorator = function (x) return "\\colorbox[HTML]{".. colorGreen .."}{" .. x .. "}" end

对于那些对 \\、\+、\- 感到疑惑的人,excludeDependencyRecursive 的调用者正在使用 latex 的tabbing环境


非常感谢大家的帮助,我是真心的。

答案1

如果我从目录开始

$ ls -lR
.:
total 15
-rwxrw-r--+ 1 davidc davidc  652 Aug 12 08:30 aa.log
-rwxrw-r--+ 1 davidc davidc  596 Aug 12 08:30 aa.lua
-rwxrw-r--+ 1 davidc davidc 9639 Aug 12 08:30 aa.pdf
-rwxrw-r--+ 1 davidc davidc   52 Aug 12 08:22 aa.tex
drwxrwxr-x+ 1 davidc davidc    0 Aug 12 08:26 dirtop

./dirtop:
total 2
-rwxrw-r--+ 1 davidc davidc 3 Aug 12 08:17 a.tex
-rwxrw-r--+ 1 davidc davidc 3 Aug 12 08:17 b.tex
drwxrwxr-x+ 1 davidc davidc 0 Aug 12 08:17 dir1
drwxrwxr-x+ 1 davidc davidc 0 Aug 12 08:25 dir2

./dirtop/dir1:
total 2
-rwxrw-r--+ 1 davidc davidc 3 Aug 12 08:17 1a.tex
-rwxrw-r--+ 1 davidc davidc 3 Aug 12 08:17 1b.tex

./dirtop/dir2:
total 2
-rwxrw-r--+ 1 davidc davidc 3 Aug 12 08:25 2a.tex
-rwxrw-r--+ 1 davidc davidc 3 Aug 12 08:25 2b.tex

使用 aa.tex

\directlua{
require("aa")
inputAll("dirtop")
}

\bye

和aa.lua

function inputAll(dir)
    for content in lfs.dir(dir) do
         if ("." ~= content) and (".." ~= content)  then
            fullpath = dir .."/".. content
                contentType = lfs.attributes(fullpath, "mode")
            if isTexFile(content, contentType) then
                    tex.sprint("\\input{" .. fullpath .. "}")
            elseif ("directory" == contentType) then
                return inputAll(fullpath)
            end
        end
    end
end
function isTexFile(dirOrFolder, contentType)
    return ("file" == contentType) and (string.find(dirOrFolder, ".+%.tex"))
end

然后我得到

$ luatex aa
This is LuaTeX, Version 1.15.1 (TeX Live 2023/dev) 
 restricted system commands enabled.
(./aa.tex (./dirtop/a.tex) (./dirtop/b.tex) (./dirtop/dir1/1a.tex)
(./dirtop/dir1/1b.tex) [1{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/up
dmap/pdftex.map}])</usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfon
ts/cm/cmr10.pfb>
Output written on aa.pdf (1 page, 9639 bytes).
Transcript written on aa.log.

显示 luatex 停止在第一个目录。原因是return删除了以下内容:

function inputAll(dir)
    for content in lfs.dir(dir) do
         if ("." ~= content) and (".." ~= content)  then
            fullpath = dir .."/".. content
                contentType = lfs.attributes(fullpath, "mode")
            if isTexFile(content, contentType) then
                    tex.sprint("\\input{" .. fullpath .. "}")
            elseif ("directory" == contentType) then
                inputAll(fullpath)
            end
        end
    end
end
function isTexFile(dirOrFolder, contentType)
    return ("file" == contentType) and (string.find(dirOrFolder, ".+%.tex"))
end

给出

$ luatex aa
This is LuaTeX, Version 1.15.1 (TeX Live 2023/dev) 
 restricted system commands enabled.
(./aa.tex (./dirtop/a.tex) (./dirtop/b.tex) (./dirtop/dir1/1a.tex)
(./dirtop/dir1/1b.tex) (./dirtop/dir2/2a.tex) (./dirtop/dir2/2b.tex) [1{/usr/lo
cal/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}])</usr/local/tex
live/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb>
Output written on aa.pdf (1 page, 9640 bytes).
Transcript written on aa.log.

显示目录树的完整递归传递

相关内容