上下文和属性问题
假设我想生成以下输出:
public String toString() {
return this.getFirstName() + "," + this.getLastName() + "," + this.getAge();
}
从下面的模板和自定义递归构建标记函数:
template-toString: {this.get<%property%>() <%either not context.build-markup/EOB [{+ "," +}][""]%> }
build-markup/vars template-toString [property] ["FirstName" "LastName" "Age"]
我的问题是避免最后一个元素与 {+ "," +} 连接
我的想法是使用 context.build -带有 EOB 属性(块结束)的标记,当处理最后一个元素时,该属性将设置为 true。然后我可以在上面的 template-toString 中使用 not context.build-markup/EOB [{+ "," +}][""] 来连接或不与 {+ "," +} :
context.build-markup: context [
EOB: false
set 'build-markup func [
{Return markup text replacing <%tags%> with their evaluated results.}
content [string! file! url!]
/vars block-fields block-values
/quiet "Do not show errors in the output."
/local out eval value n max i
][
out: make string! 126
either not vars [
content: either string? content [copy content] [read content]
eval: func [val /local tmp] [
either error? set/any 'tmp try [do val] [
if not quiet [
tmp: disarm :tmp
append out reform ["***ERROR" tmp/id "in:" val]
]
] [
if not unset? get/any 'tmp [append out :tmp]
]
]
parse/all content [
any [
end break
| "<%" [copy value to "%>" 2 skip | copy value to end] (eval value)
| copy value [to "<%" | to end] (append out value)
]
]
][
n: length? block-fields
self/EOB: false
actions: copy []
repeat i n [
append actions compose/only [
;set in self 'EOB (i = n)
set in system/words (to-lit-word pick (block-fields) (i)) get pick (block-fields) (i)
]
]
append actions compose/only [
append out build-markup content
]
foreach :block-fields block-values actions
if any [(back tail out) = "^/" (back tail out) = " " (back tail out) = "," (back tail out) = ";" (back tail out) = "/" (back tail out) = "\"] [
remove back tail out
]
]
out
]
]
但我的尝试失败了(所以我评论了 ;set in self 'EOB (i = n) 因为它不起作用)。如何更正代码以获得我想要的?
Let's say I want to generate this output:
public String toString() {
return this.getFirstName() + "," + this.getLastName() + "," + this.getAge();
}
from the template below and a custom recursive build-markup function:
template-toString: {this.get<%property%>() <%either not context.build-markup/EOB [{+ "," +}][""]%> }
build-markup/vars template-toString [property] ["FirstName" "LastName" "Age"]
My problem is to avoid the last element to be concatenate with {+ "," +}
My idea was to use a context.build-markup with an EOB property (End Of Block) that would be set to true when last element is processed. Then I could use in template-toString above either not context.build-markup/EOB [{+ "," +}][""] to concatenate or not with {+ "," +} :
context.build-markup: context [
EOB: false
set 'build-markup func [
{Return markup text replacing <%tags%> with their evaluated results.}
content [string! file! url!]
/vars block-fields block-values
/quiet "Do not show errors in the output."
/local out eval value n max i
][
out: make string! 126
either not vars [
content: either string? content [copy content] [read content]
eval: func [val /local tmp] [
either error? set/any 'tmp try [do val] [
if not quiet [
tmp: disarm :tmp
append out reform ["***ERROR" tmp/id "in:" val]
]
] [
if not unset? get/any 'tmp [append out :tmp]
]
]
parse/all content [
any [
end break
| "<%" [copy value to "%>" 2 skip | copy value to end] (eval value)
| copy value [to "<%" | to end] (append out value)
]
]
][
n: length? block-fields
self/EOB: false
actions: copy []
repeat i n [
append actions compose/only [
;set in self 'EOB (i = n)
set in system/words (to-lit-word pick (block-fields) (i)) get pick (block-fields) (i)
]
]
append actions compose/only [
append out build-markup content
]
foreach :block-fields block-values actions
if any [(back tail out) = "^/" (back tail out) = " " (back tail out) = "," (back tail out) = ";" (back tail out) = "/" (back tail out) = "\"] [
remove back tail out
]
]
out
]
]
But my attempt failed (so I commented ;set in self 'EOB (i = n) because it doesn't work). How to correct the code to get what I want ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我非常确定您可以通过比这更干净的方式实现您的目标。无论如何,我可以告诉你为什么你所做的事情不起作用!
你的
n
是表达式长度? block-fields
,并且您的repeat
循环将上升到n
。但是block-fields
包含单个参数[property]
!因此,它从 1 循环到 1。您大概想要测试枚举
块值
(在本例中范围为 1 到 3)的内容,然后处理它如果索引达到 3,则唯一。换句话说,您的set in self 'EOB
表达式需要成为block-values
枚举的一部分,而不是block-字段
。这会给你你想要的行为:
这绝对行不通:
...因为你正在处理
i
和n
都是 1 的情况,对于该循环的单次迭代。这意味着(i = n)
为真。因此,您获得的“actions”元代码是这样的:接下来,您使用多余的组合运行代码(因为没有 PAREN!,您可以省略 COMPOSE/ONLY):
这会在您的
中添加一行actions
元代码,显然:像往常一样,我建议您学习使用 PROBE 和 PRINT 来查看和检查您在每个阶段的期望。 Rebol 擅长转储变量等......
I'm quite certain you could be achieving your goal in a cleaner way than this. Regardless, I can tell you why what you're doing isn't working!
Your
n
is the expressionlength? block-fields
, and yourrepeat
loop goes up ton
. Butblock-fields
contains the single parameter[property]
! Hence, it loops from 1 to 1.You presumably wanted to test against something enumerating over
block-values
(in this example a range from 1 to 3) and then handle it uniquely if the index reached 3. In other words, yourset in self 'EOB
expression needs to be part of your enumeration overblock-values
and NOTblock-fields
.This would have given you the behavior you wanted:
This absolutely won't work:
...because you are dealing with a situation where
i
andn
are both 1, for a single iteration of this loop. Which means(i = n)
is true. So the meta-code you get for "actions" is this:Next you run the code with a superfluous composition (because there are no PAREN!s, you could just omit COMPOSE/ONLY):
Which adds a line to your
actions
meta-code, obviously:As per usual I'll suggest you learn to use PROBE and PRINT to look and check your expectations at each phase. Rebol is good about dumping variables and such...
你似乎把简单的事情变得非常复杂:
You seem to making something simple very complicated: