【问题标题】:using memoize in groovy在 groovy 中使用 memoize
【发布时间】:2013-04-08 20:58:20
【问题描述】:

我目前正在使用 spock 在 groovy 中练习测试驱动开发。 我有一组测试,其中 3 个不同的实现做同样的事情:迭代、递归和记忆。 所以我创建了一个抽象类来保存测试,然后创建了 3 个不同的文件来返回具体的类实现来运行测试。我有迭代和递归的工作,但我遇到了 memoize() 的问题

import spock.lang.Specification
abstract class FibonacciTest extends Specification {
    private calculator
    abstract def getCalculator()
    def setup() {
        calculator = getCalculator()
    }
    def "test canary"() {
        expect:
        true
    }
    // more tests
}

class RecursiveFibonacciTest extends FibonacciTest {
    def getCalculator() {
        new RecursiveCalculator()
    }
}

class IterativeFibonacciTest extends FibonacciTest {
    def getCalculator() {
        new IterativeCalculator()
    }
}

class MemoizeFibonacciTest extends FibonacciTest {
    def getCalculator() {
        new MemoizeCalculator()
    }
}

class RecursiveCalculator {
    def getFibonacci(position) {
        if (position < 2) {
            1
        }
        else {
            getFibonacci(position - 1) + getFibonacci(position - 2)
        }
    }
}

class IterativeCalculator {
    def getFibonacci(position) {
        if (position < 2) {
            1
        }
        else {
            def value = 1
            def previousValue = 1
            for (i in 2..position) {
                def temporaryValue = previousValue
                previousValue = value
                value = temporaryValue + previousValue
            }
        value
        }
    }
}

所以我已经完成了迭代和递归的工作,但是在让 memoize 工作时遇到了问题。我认为它应该可以工作,但它不是......有人知道我做错了什么吗?

class MemoizeCalculator {
    def getFibonacci = { position ->
        if (position < 2)
            1
        else
            getFibonacci.call(position - 1) + getFibonacci.call(position - 2)
    }.memoize()
}

【问题讨论】:

    标签: unit-testing groovy tdd memoization spock


    【解决方案1】:

    您不能从声明它的同一语句中引用getFibonacci 变量。要么将 getFibonacci.call 更改为 call,要么在分配变量 (getFibonacci = ...) 之前声明变量 (def getFibonacci)。

    【讨论】:

    • 我尝试了 def getFibonacci,然后设置 getFibonacci = { position -> ... }.memoize() 就像所有文档中所说的那样,但我不断收到意外和其他错误。我想我只是不明白..你能更明确一点吗?我也不明白要调用的不断变化的 getFibonacci.call 。 :/ 抱歉,我只是在学习编程..
    • 完全按照我说的去做。将所有出现的getFibonacci.call 替换为call(在闭包内您不需要限定它自己的方法),或者将def getFibonacci = { ... } 替换为def getFibonacci; getFibonacci = { ... }。这两种解决方案对我来说都很好。 PS:如果您遇到任何错误,请将其作为问题的一部分(确切输出、堆栈跟踪等)显示。
    • 我选择尝试将 getFibonacci.call 替换为 call ,但出现以下错误。 groovy.lang.MissingMethodException:没有方法签名:org.codehaus.groovy.runtime.memoize.Memoize$MemoizeFunction.doCall() 适用于参数类型:(java.lang.Integer) 值:[0] 可能的解决方案:调用(), call([Ljava.lang.Object;), call(java.lang.Object), call([Ljava.lang.Object;), findAll(), equals(java.lang.Object) 在 FibonacciTest.test序列中的第一个数字是 1(FibonacciTest.groovy:22)
    • 你是如何调用这个方法的? calculator.getFibonacci.call(5) 对我有用,但 calculator.getFibonacci(5) 给出了您显示的错误。不确定这是预期的还是 Groovy 错误。我还发现,从 Groovy 2.1.1 开始,在闭包中省略 fibonacci. 并不是绝对必要的。据我记得,它曾经在早期的 Groovy 版本中是必需的。
    • 它被calculator.getFibonacci(5) 调用,实际上,当我通过calculator.getFibonacci.call(5) 调用该方法时,它可以工作.. 但是,它会破坏我的迭代和递归测试。我会尝试你的其他选择,也许
    猜你喜欢
    • 2018-07-19
    • 1970-01-01
    • 2014-06-06
    • 2014-07-16
    • 2016-09-08
    • 1970-01-01
    • 2011-10-18
    • 1970-01-01
    • 2016-07-11
    相关资源
    最近更新 更多