试图欺骗 NetLogo 执行作为参数传递的函数

Attempting to trick NetLogo into executing a function passed as an argument

以下会产生编译错误。

to-report call-first/last [first/last a-list]
  report first/last a-list
end
正文中的

a-list 突出显示错误:预期命令。

所以我尝试了以下方法。

to-report call-first/last [first/last a-list]
  report first map first/last (list a-list)
end

此代码已编译(!),但当我试图让观察者执行它时

call-first/last first [1 2 3]

call-first/last 突出显示错误消息:CALL-FIRST/LAST 需要 2 个输入。

对替代方法有任何想法吗?

谢谢。

P.S。更大的图景是找到一种方法(如果有的话)在 NetLogo 中编写高阶函数。

更新:

要求观察者执行以下操作正常!

call-first-last [[a-list] -> first a-list] [1 2 3];; => 1

call-first-last [[a-list] -> last a-list] [1 2 3];; => 3

但这确实是一个很长的路要走!

另一个更新:

尝试过

to-report call-first-last [first-last a-list]
  report first map (runresult first-last) (list a-list)
end

编译到此。

但要求观察者 运行 call-first-last "first" [1 2 3] 产生运行时错误:FIRST expected 1 input

所以问题似乎归结为是否有办法(除了使用上面的匿名表达式之外)编写一个 returns 函数的表达式?

我不确定所有细节是否正确,但当我看到您要尝试做的事情时,我的第一个想法是使用 runresult。这有效:

to-report call-first-last [first-last a-list]
  report runresult word first-last a-list
end

使用(例如):call-first-last "last" [1 2 3]

您需要为 wordrunresult 添加一些括号,因为您使用两个以上的术语来处理更复杂的表达式。

So the question seems to come down to whether there is a way (other than using an anonymous expression as above) to write an expression that returns a function?

答案归结为...不。

当您尝试编写 call-first/last first [1 2 3] 时,您尝试使用“简洁语法”将过程传递给高阶过程:直接传递过程的名称,而不是传递像 [=11] 这样的表达式=]. (您可以在 the programming guide 中阅读一些相关内容。)

此语法适用于 mapforeach 等内置 NetLogo 基元,但不适用于用户定义的过程。不用太正式,这样做的原因是 NetLogo 原语的参数是类型化的:NetLogo 知道 map 期望一个报告者作为它的第一个参数,所以它可以解析一个正确调用 map first my-list-of-lists。用户编写的代码不是这样的:NetLogo 知道您的 call-first/last 过程的 first/last 参数的类型应该是什么。

处理这个问题的标准方法是硬着头皮写一些像call-first-last [xs -> first xs] [1 2 3]

如果这真的困扰您,您可以使用 Jen 的解决方案(虽然它会慢一点)。

你也可以write an extension。 NetLogo 扩展允许您编写行为类似于本机 NetLogo 过程的原语,从而支持简洁的语法。如果你有一整套这样的程序,也许是值得的,否则,为了节省几个字符,那就太麻烦了。

(旁注:当然,这取决于你,但我会避免在 NetLogo 变量名称中使用 /。语言允许它,是的,但对于几乎所有寻找在你的代码中,它看起来很像一个除法...)