Pyke 逻辑编程入门(17):知识库之“特别库”


特别库


只有一个“特别的”知识库,名叫 special。

特别知识库里装的是各种辅助性知识,以有趣的形式,确定陈述是否真实。

特别库里的知识项是 Python 函数,在程序运行中做些“特别”的事情。

这些“特别”的函数是:

  • 函数 claim_goal
  • 函数 check_command
  • 函数 command
  • 函数 general_command

函数 Claim_goal

函数 claim_goal 没有参数。

special.claim_goal()

它的行为方式,像是 Prolog 的 cut 操作。

一般有多个规则,用于尝试证明目标(结论)是否成立。规则应用的顺序,按其在 .krb 文件中的排列,逐一尝试。一个规则失败,就接着试下一个。规则全部失败,则目标失败。

示例

假设我要把数字 N 解释成“N 只狗”,就用到以下规则:

one_dog
    use n_dogs(1, '1 dog')

n_dogs
    use n_dogs($n, $phrase)
    when
        $phrase = "%d dogs" % $n

程序的逻辑有问题。当 n 等于 1 时,两个规则都要用到,但第二个规则不能正确适用。这时,函数 special.claim_goal() 可以解决这个问题:

one_dog
    use n_dogs(1, '1 dog')
    when
        special.claim_goal()

n_dogs
    use n_dogs($n, $phrase)
    when
        $phrase = "%d dogs" % $n

在 n 等于 1 时,special.claim_goal() 阻止适用第二个规则。

说明

规则 when 子句里调用函数 special.claim_goal() 时,其余的规则不再参与证明原目标。于是,如果 special.claim_goal() 引起回溯,目标立即失败,不再试用别的规则。

这种结束的方式,就像 if-then-else 结构中的“else”的作用。只有当规则 when 子句中的前提条件真实正确时,才能在其后使用 special.claim_goal()

你不必在其后适用的规则中,添加额外的前提条件,去确保它们没有发生。

如果上例中没有函数 special.claim_goal(),你只好这样写:

one_dog
    use n_dogs(1, '1 dog')

n_dogs
    use n_dogs($n, $phrase)
    when
        check $n != 1
        $phrase = "%d dogs" % $n

这个简单的例子,很容易在第二个规则中,加入命令 check。不过,一般地说,检查以前出现的条件是很困难的,尤其如果涉及到多个规则,并且它们有各自的条件。

运行命令

其余三个函数,在你的 Pyke 程序运行时,以命令运行处理其他程序。这三个函数执行后,有不同的输出结果。

这三个函数,都使用 Python 标准库函数 subprocess.Popen。

这三个函数,都有以下三个参数,传递给 subprocess.Popen:

  • 必须的参数 $command。
    • 它是个元组,告诉程序按照参数的值运行,例如 (ls, '-l')。
  • 可选的参数 $cwd。
    • 指定程序当前运行的硬盘目录。
    • 如果未设值,或设为 None,则当前工作目录保持不变。
  • 可选的参数 $stdin。
    • 是个字符串,指明程序的标准输入。
      • 如果程序的输入有多行,$stdin 必须包括嵌入的新行,如:“line 1/nline 2/n”。
    • 如果未设值,或设为 None,则该程序没有标准输入。

如果发生回溯,这些函数全部失败。

函数 Check_command

special.check_command($command [, $cwd [, $stdin]])

如果 $command 程序运行返回 0,它适用成功;返回其他值,失败。程序向 stdout 和 stderr 的输出,无意义。

>>> from pyke import knowledge_engine
>>> engine = knowledge_engine.engine()
>>> engine.prove_1_goal('special.check_command((true))')
({}, None)
>>> engine.prove_1_goal('special.check_command((false))')
Traceback (most recent call last):
    ...
CanNotProve: Can not prove special.check_command((false))

函数 Command

special.command($stdout, $command [, $cwd [, $stdin]])

它输出到 stdout。$command 程序向 stderr 的输出,无意义。

$stdout 是包含多行内容的元组,行尾的换行符都删除了。

如果程序返回值不是 0,则引发意外 subprocess.CalledProcessError。

>>> from __future__ import with_statement
>>> from pyke import pattern, contexts
>>> def run_command(entity, command, cwd=None, stdin=None):
...     with engine.prove_goal(
...            'special.%s($output, $command, $cwd, $stdin)' % entity,
...            command=command,
...            cwd=cwd,
...            stdin=stdin) /
...       as gen:
...         for vars, no_plan in gen:
...             print vars['output']
>>> run_command('command', ('echo', 'hi', 'mom'))
('hi mom',)
>>> run_command('command', ('ls',))   # doctest: +NORMALIZE_WHITESPACE
('fact_bases.txt', 'index.txt', 'links', 'question_bases.txt',
 'rule_bases.txt', 'special.txt')
>>> run_command('command', ('ls', '-l', 'links')) # doctest: +ELLIPSIS
('-rw-r--r-- 1 ... links',)
>>> run_command('command', ('tail', '-n', '5', 'template.txt', '-'),
...             '..',   # cwd (doc/source)
...             'stdin: line 1/nstdin: line 2/nstdin: line 3/n')
...     # doctest: +NORMALIZE_WHITESPACE
('==> template.txt <==',
 '   } catch(err) {}',
 '  ',
 '',
 '',
 '',
 '',
 '==> standard input <==',
 'stdin: line 1',
 'stdin: line 2',
 'stdin: line 3')
>>> run_command('command', ('false',))
Traceback (most recent call last):
    ...
CalledProcessError: Command 'false' returned non-zero exit status 1
special.general_command($output, $command [, $cwd [, $stdin]])

$command 程序给你全部输出的最一般的形式。

$output 是有三个成员的元组:(exit_status, stdout, stderr)。stdout 和 stderr 都是有换行符的字符串。

>>> run_command('general_command', ('echo', 'hi', 'mom'))
(0, 'hi mom/n', '')
>>> run_command('general_command', ('cat', 'foobar'))
(1, '', 'cat: foobar: No such file or directory/n')
>>> run_command('general_command', ('tail', '-n', '5', '../../r2w.ini', 'foobar'))
...     # doctest: +NORMALIZE_WHITESPACE
(1,
 "==> ../../r2w.ini <==/ntarget_directory = 'html'/nmacros =
     ''/n/n[uservalues]/nversion = '0.2'/n",
 "tail: cannot open `foobar' for reading: No such file or directory/n")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值