当前位置: 首页 > 知识库问答 >
问题:

letrec的混淆,方案

壤驷安和
2023-03-14

我正在努力区分let, letrec, let*...因为方案不是我的主要编程语言,我的内存不存在很长时间...我有这个功能...现在我很困惑这里的letrec...这又是recursion.that我能理解...但是不能在这段代码中建立足够的连接...(也许仍然对递归感到困惑)有人能解释为什么这里需要letrec吗

(define myFunc
  (lambda (start end res func)
    (letrec ((func:rec_func
              (lambda (x i y)
                (if (>= i start)
                    (func:rec_func (cons i x) (- i res) (cons (func i) y))  ;; line6
                    (cons x (cons y '()))))))                               ;; line7
      (func:rec_func '() end '()))))

(编辑)我所理解的是它的尾部递归

-

-

此函数返回x,y的列表,其边界为start,end,因此它检查索引i是否在边界内,如果是,则执行第6行

-

共有3个答案

莫骞仕
2023-03-14

[Q1]它是递归的尾部吗?

回答是的,它执行尾部递归。

[Q2]那么,应该始终使用letrec进行尾递归吗?

回答有两种方式来解释你的问题。

>

  • 我们是否应该始终使用letrec作为尾部递归?我想你不是故意问这个的。但是

    答案是否定的。顶级lambda函数也可以用于尾部递归。

    letrec是否应该始终使用尾部递归?

    答案是:任何递归函数最好是尾递归的。如果可以,您应该使其尾递归。

    [Q3]那么line6是什么?

    第6行的代码执行递归调用。

    比如说,开始是0,结束是5,恢复是1。在对func的第一个调用中:rec\u func,x是空列表,i是5,y是空列表。

    当在第6行调用第一个递归函数时,参数是(cons i x)(-i res)(cons(func i)y),其计算结果为:(5)4和((func 5)

    在下一次迭代中,参数是(4.5)3((func 4)(func 5))

    它一直持续到i小于start。然后递归停止,结果为((0 1 2 3 4 5)((func 0)(func 1)(func 2)(func 3)(func 4)(func 5))

    当满足递归的终止标准时,即<代码>(

  • 桓兴腾
    2023-03-14

    如果我没记错的话,这个构造需要的是letrec,而不是let,因为func:rec\u func的主体是指它自己。如果在此处使用了let或,则嵌套lambda中的符号func:rec\u func将绑定到顶级表单外可见的任何定义,如果没有此类定义,则未定义-这也不是您想要的。

    淳于泓
    2023-03-14

    letrec、let和let*的不同之处在于它们执行程序可用的声明的时间。

    (letrec ((X (you could use X here))
             (Y (you could use X here too))
             )
         (X also is available here)
    )
    
    
    (let   ((X (nope, X isn't declared yet))
             (Y (in fact, no declaration body will see X))
             )
         (But X is available here)
    )
    
    
    (let* ((X (X isn't available here))
             (Y (but you could use it here))
             )
         (X also is available here)
    )
    

    总结:

    1. 用letrec声明的变量的范围都在letrec的主体内。编译器执行了一些魔术,以便在声明结束后替换引用
    2. 用let*声明的变量范围是在声明变量后let*范围内的所有表达式
    3. 用let声明的变量的范围只是let的主体,而不是声明部分
     类似资料:
    • 我尝试在android studio中使用Proguard,但Proguard似乎没有混淆类名,例如,我的应用程序结构和配置: 和配置 但当我尝试在应用程序中触发异常时: ADB控制台中列出了异常: 只有方法被混淆了,MainActivity.class没有

    • 我一直在摆弄Proguard配置,我想测试只是为了优化 但我仍然会遇到这样的错误: java.lang.IllegalArgumentExc0019:找不到[org/apache/log/log4j/core/jackson/Log4jXmlMoules](有1个已知的超级类)和[org/apache/log/log4j/core/jackson/Log4jJsonMoules](有4个已知的超级

    • Powershell的混淆目前已经使用的越来越多,国内外也有了较多的研究,在今年的BH大会上也有对应的议题,关注点是反混淆,那么里面的一些姿势很值得我们学习,我们提供一些混淆实例,来让大家对于PS的混淆做到一个初步了解,也为防御混淆提供一些思路。 实例 在混淆之前,先看看powershell编码执行的方式。 -EC,-EncodedCommand,-EncodedComman,-EncodedCo

    • 而RNDecryptor的addData方法如下: 我不明白这一行实际上是要做什么,它对加密流的每一个块都调用: 假设我有一个1000字节的块,而HMACLength是32。 提前道谢。

    • 但如果我用: 如果需要,我很乐意提供整个SSCE,但目前,为了让事情更简短,下面是TableModel的getValueAt()和setValueAt()方法: 数据只是Person类型的arraylist(一个具有明显变量(String)fName、(String)sName和(LocalDate)DOB的类) 任何帮助都将不胜感激!

    • 我已经通过字符串的拆分方法留档,但结果并不像预期的那样。当我们将限制参数设置为负值的字符串拆分时,它总是附加一个空值。为何要这样做呢?考虑一些案例 我希望这两张照片都是3。 现在,由于没有找到匹配项,通常的split with limit方法应该打印0,但它创建了一个带有空字符串的数组。 现在我有了一个匹配项,无限制参数的split方法可以很好地工作。它是我预期的输出,但为什么它不在本例中创建一个