【问题标题】:Scala Machine EmulatorScala 机器模拟器
【发布时间】:2021-01-27 19:07:59
【问题描述】:

我正在构建一个堆栈机器模拟器,但我无法弄清楚如何在加载和存储情况下更新环境/地图。我的目标是弄清楚如何更新地图并进行迭代以获得用于更新地图的正确值。

case class LoadI(s: String) extends StackMachineInstruction
case class  StoreI(s: String) extends StackMachineInstruction
    def emulateSingleInstruction(stack: List[Double],
                                 env: Map[String, Double],
                                 ins: StackMachineInstruction): (List[Double], Map[String, Double]) = {
        ins match{
            case AddI => stack match{
                case i1 :: i2 :: tail => (i1 + i2 :: tail, env)
                case _ => throw new IllegalArgumentException()
            }
            case PushI(f) => (f :: stack,env)

            //broken
            case LoadI(s) => stack match {
                case Nil => throw new IllegalArgumentException()
                case i1 :: tail => (tail,env) match {
                    case (top,env) => (top, env + s -> top ) // Not clear on how to update an environment
                }
            }
            //broken
            case StoreI(s) => stack match {
                case Nil => throw new IllegalArgumentException()
                case i1 :: tail => // Need to take the value that s maps to in the environment. Let the value be v. Push v onto the top of the stack.
            }

            case PopI => stack match{
                case Nil => throw new IllegalArgumentException()
                case i1 :: tail => {
                    (tail,env)
                }
            }
        }
    }

这是我在不同文件中的测试用例示例

test("stack machine test 3") {
        val lst1 = List(PushI(3.5), PushI(2.5), PushI(4.5), PushI(5.2), AddI, LoadI("x"), LoadI("y"), LoadI("z"), StoreI("y"), LoadI("w"))
        val fenv = StackMachineEmulator.emulateStackMachine(lst1)
        assert(fenv contains "x")
        assert(fenv contains "y")
        assert(fenv contains "z")
        assert( math.abs(fenv("x") - 9.7 ) <= 1e-05 )
        assert( math.abs(fenv("y") - 2.5 ) <= 1e-05 )
        assert( math.abs(fenv("z") - 3.5 ) <= 1e-05 )
    }

【问题讨论】:

  • 这段代码引用了stackoverflow.com/questions/64331351/…,但它仍然太少,无法确定哪个变量是哪个,它们应该做什么等。请显示更完整的示例,其中执行此模式匹配。跨度>
  • @MateuszKubuszok 我刚刚进行了编辑以显示完整的模拟器。这有帮助吗?提前致谢
  • 您的问题是关于如何实现堆栈机器或如何在scala中使用地图?为什么要把这两件事混为一谈?
  • @pedrofurla 我更关心的是实现堆栈机器。好点,对此感到抱歉。

标签: scala pattern-matching load emulation store


【解决方案1】:

您可以使用.updated 更新地图。或者添加一个元组,但 Scala 必须知道某事是一个元组(map + a -&gt; b 被视为(map + a) -&gt; b,所以你必须使用map + (a -&gt; b))。

您可以使用.get、.getOrElse.apply 从地图中提取值。他们将:返回Option,在丢失时返回值或默认值,或者在丢失时提取值或抛出。所以最后一种需要检查。

如果您还记得模式可以在模式匹配中组合,您可以将解释器编写为:

def emulateSingleInstruction(stack: List[Double],
                             env: Map[String, Double],
                             ins: StackMachineInstruction): (List[Double], Map[String, Double]) =
  (ins, stack) match {
    case (AddI, i1 :: i2 :: tail)          => ((i1 + i2) :: tail) -> env
    case (PushI(f), _)                     => (f :: stack) -> env
    case (LoadI(s), i1 :: tail)            => tail -> env.updated(s, i1)
    case (StoreI(s), _) if env.contains(s) => (env(s) :: stack) -> env
    case (PopI, _ :: tail)                 => tail -> env
    case _                                 => throw new IllegalArgumentException()
  }

【讨论】:

  • 好的,这项工作,但我得到的值更新不是 Map[String,Double] 的成员。我有以下内容:case LoadI(s) =&gt; stack match { case Nil =&gt; throw new IllegalArgumentException() case i1 :: tail =&gt; s -&gt; env.update(s, i1) }
  • 谢谢你!我正在使用完整版的 IntelliJ IDEA
  • 就目前而言,我收到了type mismatch; found : (String, scala.collection.immutable.Map[String,Double]) required: (List[Double], Map[String,Double]) case (LoadI(s), i1 :: tail) =&gt; s -&gt; env.updated(s, i1)
  • 现在试试,我已经修正了小错误
  • 一切正常。我遇到了运行时错误,但我现在要对其进行调试。
猜你喜欢
  • 2021-01-27
  • 1970-01-01
  • 2011-06-15
  • 1970-01-01
  • 2011-02-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
相关资源
最近更新 更多