本博客是本人接着[本体小本营][1]之前关于Jess的官方文档的补充翻译,前一部分请看转载的Jess 7.2p2——Java平台规则引擎官方文档翻译1。因为对JESS理解有限,如有失误,敬请留言。
你能定义自己的函数,用deffunction结构,deffunction的结构如下所示:
(deffunction <function-name> [<doc-comment>] (<parameter>*)
<expr>* [<return-specifier>])
必须是符号。每个必须是变量名。可选的是一个双引号字符串,可以描述函数的用途。可能有任意数量表达式。可选的给出的函数的返回值。它可以是返回函数的显式使用,也可以是任意值或表达式。在deffunctions的控制流是通过控制流函数如foreach实现的,如果,虽然。以下例子是deffunction实现返回它的两个数值中较大的一个:
Jess> (deffunction max (?a ?b)
(if (> ?a ?b) then
(return ?a)
else
(return ?b)))
TRUE
注意以上函数也可以同时写成如下形式:
Jess> (deffunction max (?a ?b)
(if (> ?a ?b) then
?a
else
?b))
TRUE
这个功能现在可以被任何一个Jess函数调用来使用。例如:
Jess> (printout t "The greater of 3 and 5 is " (max 3 5) "." crlf)
The greater of 3 and 5 is 5.
通常一个deffunction包含特定的参数数目。写一个deffunction,其中包含任意数量的参数,使最后的形式参数是一个多变量的前缀——“$”字符。当deffunction被调用,多变量将包含所有剩余的参数作为一个列表传递给函数。一个deffunction可以接受不超过一个通配符,通配符必须在函数的最后一个参数。
您还可以用java编写的函数自定义Jess语言。这些与内置函数没有什么区别,事实上,您使用定义内置函数的统一口来编写它们。详情见这里。
有时一个Jess函数不会表现得完全像你希望的那样。defadvice结构让你写一些Jess代码,这些代码将在每一次Jess函数被调用的之前或者之后运行。defadvice可以让你轻松地“包装”额外的代码在任何Jess的功能,例如它执行在(因此可以改变被真正的函数看到的参数列表,或者通过返回其自身价值来达到其完全的短路)之前或执行在真正的函数之后(因此可以看到真正的函数的返回值并可能改变它。)defadvice 提供了一个好的方式对于那些Jess附件内容作者,它扩展了Jess而不需要改变任何内部代码。
这是一些例子展示了defadvice如何使用。
这个拦截调用’plus’ (+) 并且增加了另外的参数 ‘1’, 因此 (+ 2 2) 变成了 (+ 2 2 1) -> 5. 变量 ‘$?argv’ 是特殊指定的. 它通常是指真正的Jess函数被调用时将收到的参数列表。
Jess> (defadvice before + (bind $?argv (create$ $?argv 1)))
TRUE
Jess> (+ 2 2)
5
这个例子使得所有的加法等于1(即所谓的短路)。defadvice通过返回值,使得函数每次被调用时都保持真正的函数功能。
Jess> (defadvice before + (return 1))
TRUE
Jess> (+ 2 2)
1
这个例子从+函数的返回值中减去1,?retval是另一个有意思的变量——它是真正函数的返回值。当我们完成后,我们利用undefadvice移除advice。
Jess> (defadvice after + (return (- ?retval 1)))
TRUE
Jess> (+ 2 2)
3
Jess> (undefadvice +)
Jess> (+ 2 2)
4