【问题标题】:How to use IN with a block instead of an object?如何将 IN 与块而不是对象一起使用?
【发布时间】:2014-01-11 06:17:44
【问题描述】:

Rebol 中的 IN 函数判断字段是否在对象中:

USAGE:
    IN object word

DESCRIPTION:
    Returns the word or block in the object's context.
    IN is a native value.

ARGUMENTS:
    object (any-object! block!)
    word -- (modified if series) (any-word! block! paren!)

声称它适用于对象或块。如果我用一个对象尝试它就可以了:

>> in object [foo: 10 bar: 20] 'foo
== foo

但如果我只是尝试使用原始块,它会返回 NONE:

>> in [foo: 10 bar: 20] 'foo
== none

如果它不支持块,我想我会理解的(Rebol2 不支持)。但是在什么情况下它不会返回允许块的 NONE?

冒着将这两个问题合二为一的风险,接受 BLOCK 有什么意义!对于word 参数?如果您有一组要查找的单词,我认为这需要一个块,但它似乎只是返回块:

>> in object [foo: 10 bar: 20] [mumble frotz bar]
== [mumble frotz bar]

>> in object [foo: 10 bar: 20] [mumble frotz]
== [mumble frotz]

冒着提出这三个问题的风险,参加 PAREN 有什么意义!单词有吗?

【问题讨论】:

  • 这是 rebol3 中的新行为吗?我似乎无法使用 rebol2 或红色的块:** Script Error: in expected object argument of type: object port ** Near: in [foo: 10 bar: 20] 'foo
  • @GeekyI 它似乎不在 Rebol2 中。但是 Red 0.6.1 似乎接受块作为参数......尽管它的结果似乎是错误的。 obj: make object! [a: 10 b: 20 c: 30] 然后in obj [a c] 返回对象而不是反弹块。您可能会在他们的跟踪器上提出问题以澄清意图。
  • 我刚刚意识到这是 1 中的 3 个问题,因此混乱:-p,我的意思是第一个问题(所以呃..我还不能@提及任何人..?)
  • (@GeekyI 对 OP 的提及会被忽略,如果这是您唯一与之交谈的人,因为当 cmets 出现在他们的问题上时,OP 总是会收到通知。) = > 我没有仔细阅读您的错误。你不能说IN BLOCK!单词!在任何解释器中...块不是在其中查找单词的上下文。您可以说 IN OBJECT!堵塞!在 Rebol3 中,是的,这是一个新功能。

标签: object rebol rebol3


【解决方案1】:

IN 函数主要不是用于在对象中搜索单词,它用于返回 in 对象或 Rebol 术语中绑定的单词或单词块到对象。它是 BIND 函数的变体,在不同于 BIND 的情况下很有用。

如果对象中没有该名称的单词,它会返回 none,这很明智。这给它带来了可以在条件表达式中用作单词检测功能的附带好处,但这不是它的主要用途。

IN 可以将一个对象块作为其对象参数,然后尝试依次将单词绑定到每个对象,返回一个绑定到块中具有该单词的第一个对象的单词。这意味着对 Rebol 3 GUI 的旧设计进行覆盖字查找的相对快速的方法,但在这种情况下它被证明不是最好的方法,因此 GUI 现在不使用该设计。但是,IN block word 被保留为一个潜在有用的功能,以备将来在其他地方使用。

在您的示例中,该块中没有对象,因此 IN 无法将单词绑定到任何对象。这就是 IN 没有返回的原因。

如果你为 word 参数传入一个块,它会在返回之前将该块绑定到对象。这是为了允许像do in obj [print a] 这样的代码。不过,它不会执行bind/copy,所以你应该小心这样的代码。或者也许 IN object block 应该复制 - 改变它是否为时已晚?为 word 参数传递一个括号应该与传递一个块具有相同的绑定行为。

上次我检查时,我们不支持将对象和单词参数都设置为块。这是因为我们无法为这种行为应该是什么找到一个好的模型,至少很明显。覆盖词查找实际上不适用于词块,因为结果是不确定的。

如果有一个函数可以将一个块按顺序重新绑定到一系列对象,特别是对于重新创建 Rebol 的非真正嵌套的作用域,这会很有用,但是如果该函数是 IN 会很混乱。

【讨论】:

  • 长话短说:FIND 是多态的并返回 LOGIC!的“是对象中的关键”,而 IN 与 BIND voodoo 相关......而不是因为名称而您可能认为它的作用。我认为这里让我担心的是 FIND 与块如此不同和反对,如果“有钥匙”是一个单独的东西来防止事故,那会更安全。也许 HAS 可以重新用于返回布尔结果的东西(对于制作函数的东西来说,这不是一个很好的词,IMO)......并且 FIND 总是返回系列位置?即使具有多态能力,也应该具有不变量。
  • 我不打算就本该发生的事情展开一场激烈的战争,所以让我们暂时专注于现状。 FIND 是多态的,因为它是一个动作,在 Rebol 中只有动作或动作包装器是多态的。内部不调用动作的本地人不是多态的。 IN 是一个介词,因此该函数适用于在英语中使用它的情况,例如get in obj 'aset in obj 'a 200do in obj [something]。它存在的主要原因是代码清晰,否则我们可以只使用 BIND。单独使用 IN 没有意义。
【解决方案2】:

这可能没有那么有用,但由于没有明确提及,我认为现在是解决您的第一个问题的“正确”方法:

red>> first find [foo: 10 bar: 20] 'foo
== foo:

这对 rebol2 不起作用,但 quoteing set-word! 可以:

>> first find [foo: 10 bar: 20] quote [foo:]
== foo:

仍然有返回set-word!的轻微缺点

【讨论】:

  • 是的,FIND 是检查某物何时在块中的正确操作。这个问题(及其答案)最终与 IN 是什么有关。在问了这个问题多年后,我明白它的目的是反转 BIND 的参数顺序......不是 FIND 的一种形式。
  • @HostileFork 那么问题是in 可能是has-key 的新手错误。实际上,作为更通用的 contains 就像 python 的 in 关键字
  • 是的,我理解这种困惑(我也有过)。但事实证明,IN 的这种定义具有广泛的应用。而不是foo/method1 a b | foo/method2 c d | foo/method3 e f,你可以说do in foo [method1 a b | method2 c d | method3 e f](好吧,假设foo中没有a,b,c,d,e,f!)。或许如果错误消息能够提供更多信息来引导人们在尝试使用块作为查看位置时找到 FIND,那么这可能是两全其美?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-19
  • 1970-01-01
  • 1970-01-01
  • 2013-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多