【问题标题】:Finding a value in a function represented environment在函数表示的环境中查找值
【发布时间】:2018-08-17 09:32:25
【问题描述】:

当要在 bst 环境中找到一个值时,我所要做的就是将我正在寻找的值与节点上的根值进行比较

type 'a tenv = (name * 'a) btree

exception NotFound of name
fun find compare name Leaf = raise NotFound name 
| find compare name (Node (lt, (key, value), rt)) = 
  case compare(name, key) of
    LESS => find compare name lt
  | GREATER => find compare name rt
  | EQUAL => value

但是在一个代表 env 的函数中,而不是一个带有节点和叶子的 bst 中,find 函数的类型是

name * 'a fenv -> 'a

type 'a fenv = name -> 'a

我对函数有了大致的了解,但我对如何遍历环境来查找名称感到困惑。 Bst 有一个节点和一个树状结构。如果可能的话,谁能给个解释?

编辑于

我的工作实现就是这样

exception NotFound of name
val Empty = fn name => raise NotFound name

fun Find(name, env) = env name

fun Bind(name, data, rho) = fn key => if key = name then data else rho 
key 

【问题讨论】:

    标签: sml ml mosml


    【解决方案1】:

    因此,现在将环境表示为一个函数,该函数采用名称并在环境中返回其值或引发异常。
    此函数将是函数的组合,您可以通过应用代表旧环境的函数来“遍历”它。
    (这听起来比实际上更复杂,但可能需要一段时间才能理解它。)

    您可以通过编写一个接受名称并引发异常的函数来创建空环境:

    val empty = fn n => raise NotFound n
    

    查找东西比查找树要短得多,因为环境已经是那个函数了:

    fun find n env = env n
    

    剩下的就是插入:

    fun insert (key, value) env = ... what?
    

    它必须是一个有名字的函数,因为这就是环境

    fun insert (key, value) env = fn n => ... what?
    

    如果nkey 相同,则该函数应返回value

    fun insert (key, value) env = fn n => if n = key then value else ... what?
    

    n 可能会在环境的其余部分中找到,因此我们应用该函数以便在那里查找它:

    fun insert (key, value) env = fn n => if n = key then value else env n
    

    正如他们所说,就是这样。

    从某种意义上说,“遍历”代码已经从查找函数转移到了插入函数。

    测试:

    - val env = insert ("hi", 23) empty;
    val env = fn : string -> int
    - find "hi" env;
    val it = 23 : int
    - find "hello" env;
    
    uncaught exception NotFound
      raised at: ...
    - val env2 = insert ("hello", 999) env;
    val env2 = fn : string -> int
    - find "hello" env2;
    val it = 999 : int
    - find "hi" env2;
    val it = 23 : int
    

    如您所见,将事物表示为函数可以非常紧凑。


    为了看看发生了什么,让我们扩展第一个例子:

    val env = insert ("hi", 23) empty
    

    与(扩展insert的定义)相同:

    val env = fn n => if n = "hi" then 23 else empty n
    

    查找成功:

    find "hi" env
    

    env "hi"
    

    这是

    (fn n => if n = "hi" then 23 else empty n) "hi"
    ->
    if "hi" = "hi" then 23 else empty n
    -> 
    23
    

    失败:

    find "hello" env
    ->
    (fn n => if n = "hi" then 23 else empty n) "hello"
    ->
    if "hello" = "hi" then 23 else empty "hello"
    ->
    empty "hello"
    ->
    raise NotFound "hello"
    

    异常处理示例:

    如果您不处理异常,您将收到“未捕获的异常”错误,如上例所示。

    您需要在使用find的代码中处理异常。
    一个简单的例子:

    fun contains n env = let val _ = find n env
                         in true
                         end
                         handle NotFound nm => false
    
    
    - contains "hello" env;
    val it = false : bool
    - contains "hi" env;
    val it = true : bool
    

    【讨论】:

    • molbdnilo 非常感谢您在 4 小时尝试不同的方法并阅读您的不同解释后更有意义。
    • 抱歉,当我在给定的环境中找不到名称时遇到错误,所以我将我的改写为以下(在我的原始帖子中编辑),但我仍然出错你能告诉我是否我正在检查错误案例错误
    • @laughingllama42 你不应该对任何东西进行任何模式匹配。
    • 但是如果在 find 函数的环境中找不到名称,我该如何检查呢?
    • 你不需要检查——当函数调用链到达empty函数时会抛出异常。这个答案中的三行代码就是一个完整的实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-09
    • 2013-08-18
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多