在OCaml/F#中以正确的副作用顺序重新实现List.map? [英] Re-implementing List.map in OCaml/F# with correct side effect order?

查看:60
本文介绍了在OCaml/F#中以正确的副作用顺序重新实现List.map?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据此先前的答案

您可以这样实现List.map:

let rec map project = function
  | [] -> []
  | head :: tail ->
      project head :: map project tail ;;

但是,它是这样实现的:

but instead, it is implemented like this:

let rec map project = function
  | [] -> []
  | head :: tail ->
      let result = project head in
      result :: map project tail ;;

他们说,这样做是为了确保以预期的顺序调用投影函数,以防其产生副作用,例如

They say that it is done this way to make sure the projection function is called in the expected order in case it has side effects, e.g.

map print_int [1;2;3] ;;

应该打印123,但是第一个实现将打印321.但是,当我在OCaml和F#中自己测试它们时,它们会产生完全相同的123结果.

should print 123, but the first implementation would print 321. However, when I test both of them myself in OCaml and F#, they produce exactly the same 123 result.

(请注意,我正在OCaml和F#REPL中对此进行测试-评论中的尼克表示这可能是导致我无法复制的原因,但是为什么?)

(Note that I am testing this in the OCaml and F# REPLs--Nick in the comments suggests this might be the cause of my inability to reproduce, but why?)

我误会什么?有人可以详细说明为什么他们应该产生不同的命令,以及我该如何复制吗?这与我以前对OCaml代码的先前理解背道而驰,因此这令我感到惊讶,我想确保不要重蹈覆辙.当我读完这两本书时,我读到的是完全相同的东西,带有无关的中介绑定.

What am I misunderstanding? Can someone elaborate why they should produce different orders and how I can reproduce? This runs contrary to my previous understanding of OCaml code I've written in the past so this was surprising to me and I want to make sure not to repeat the mistake. When I read the two, I read it as exactly the same thing with an extraneous intermediary binding.

我唯一的猜测是使用cons进行表达式求值的顺序是从右到左,但这似乎很奇怪?

My only guess is that the order of expression evaluation using cons is right to left, but that seems very odd?

这纯粹是为了更好地了解OCaml如何执行代码的研究,我并不需要为生产代码创建自己的List.map.

This is being done purely as research to better understand how OCaml executes code, I don't really need to create my own List.map for production code.

推荐答案

因此,当您具有这样的map实现时:

So when you have an implementation of map like this:

let rec map f = function
  | [] -> []
  | a::l -> f a :: map f l

map调用中的任何功能应用程序(f a)都不能保证按照您期望的顺序进行评估.因此,当您尝试这样做时:

none of the function applications (f a) within the map calls are guaranteed to be evaluated sequentially in the order you'd expect. So when you try this:

map print_int [1;2;3]

您将得到输出

321- : unit list = [(); (); ()]

自从这些功能应用程序没有按特定顺序执行以来.

since by the time those function applications weren't executed in a specific order.

现在,当您像这样实现map时:

Now when you implement the map like this:

let rec map f = function
  | [] -> []
  | a::l -> let r = f a in r :: map f l

您正在强制按期望的顺序执行功能应用程序,因为您明确调用了评估let r = f a的代码.

you're forcing the function applications to be executed in the order you're expecting because you explicitly make a call to evaluate let r = f a.

现在,当您尝试:

map print_int [1;2;3]

您将获得

123- : unit list = [(); (); ()]

因为您已明确地努力按顺序评估功能应用程序.

because you've explicitly made an effort to evaluate the function applications in order.

这篇关于在OCaml/F#中以正确的副作用顺序重新实现List.map?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆