dram.me

CLIPS系统编译

补遗

  1. 可以通过命令find . -name "*.c" -exec grep -o -P 'EnvDefineFunction.+"\K[a-z-]+' {} \;生成关键字列表,再经由-f传入rlwrap。—— 2017-08-02

  2. 生成关键字的命令,可以进一步完善:find . -name "*.c" -exec grep -o -P '(AddConstruct|EnvDefineFunction).+?"\K[a-z-]+' {} \;。—— 2017-08-03

  3. 当前makefile.gcc不支持64x分支,临时可通过直接编译所有C文件实现:gcc -Wall -o clips -lm *.c。—— 2017-08-07

  4. 64x分支关键字列表生成:find . -name "*.c" -exec grep -o -P '(AddConstruct|AddUDF).+?"\K[^"]+' {} \;。—— 2017-08-07

  5. 编译时可以传入-DLINUX=1,即:gcc -DLINUX=1 -Wall -o clips -lm *.c。—— 2017-08-08

  6. CLIPS仓库中Makefile文件路径最近做了调整,并且新增了64x分支的Makefile,所以编译命令可以变更为:make -C $(CORE) -f makefile.lnx。—— 2017-08-10

CLIPS是用于构建专家系统(Expert System)的工具(或者也可以认为是语言)。在官方网站上有发布版下载,这里介绍直接基于SVN稳定分支构建的流程。

首先使用SVN或者git svn获取代码,例如:

git svn clone https://svn.code.sf.net/p/clipsrules/code/

之后可以基于如下Makefile编译:

CORE=code/branches/63x/core
FILE=code/makefiles/ubuntu/makefile.gcc

clips:
	( cd $(CORE) && git clean -dfx )
	ln $(FILE) $(CORE)/Makefile
	make -C $(CORE)
	ln $(CORE)/clips .

为便于交互命令行使用,可以借助rlwrap工具,例如封装以下SHELL脚本:

#!/bin/sh

CLIPS=/path/to/clips

exec rlwrap -b '"()&|~;' -c -e '' -f . -q '"' -r -s 2000 $CLIPS "$@"

Mercury的IO系统

之前我觉得Mercury的IO系统在实现上可能类似于Haskell,要全然掌握门槛较高,想着待对语言有一定了解后再看,没有深究。但最近有两个示例让我其产生了好奇。

一是Peter Wang在Mercury Wiki编写的教程里,有一个练习:如果更换包含状态变量的语句顺序,会有怎样的结果?例如:

main(IO0, IO) :-
       write_string("dear ", IO1, IO2),
       write_string("Hello, ", IO0, IO1),
       write_string("world!\n", IO2, IO).

输出的结果和正常的顺序相同,没有变化:

Hello, dear world!

由此可以猜测Mercury会基于状态变量的实例化(instantiation)情况重新组织语句。

再一个例子是Mercury自带的C接口调用的简单示例。其中对io::di和io::uo变量没有太多操作,和我以前猜测的复杂数据结构封装相去甚远。

Prolog中的term expansion

SWI-Prolog Web开发教程有用到http_dispatch:http_handler,从文档中可知该指令使用了term expansion特性。

但有个奇怪的问题,对于以下代码:

:- use_module(library(http/http_dispatch)).
:- use_module(library(http/thread_httpd)).

% :- http_handler(/, say_hi, []).
:- http_dispatch:http_handler(/, user:say_hi, []).

say_hi(_Request) :-
    format('Content-type: text/plain~n~n'),
    format('Hello World!~n').

main :- http_server(http_dispatch, [port(8000)]).

如果在调用http_handler加了http_dispatch前缀,那么之后的say_hi/1也会被追加http_dispatch前缀。

具体可以查看Paul Moura的讨论

Swift获取随机数

补遗

  1. 可以直接利用Foundation中的FileHandle读取文件,不需要用Glibc。—— 2017-05-18

数值类型安全中一文中有将Swift获取随机数作为示例呈现,以下代码基于/dev/urandom实现:

import func Glibc.close
import func Glibc.open
import func Glibc.read
import var Glibc.O_RDONLY

let count = 5

let buffer = UnsafeMutablePointer<Int8>.allocate(capacity: count)

let fd = open("/dev/urandom", O_RDONLY)
read(fd, buffer, count)
close(fd)

for i in 0..<count {
    print(buffer[i])
}

buffer.deallocate(capacity: count)

Swift的Glibc模块

补遗

  1. Swift强大的C接口能力的另一个例子是Swift Package Manager中对接系统库的示例。—— 2017-05-16

Swift语言在整体的设计基调上相对传统,但也不乏创新的点。这里要来说说的是其对C库的支持。

Swift包括一个Glibc模块,是对Glibc API的封装,而Swift的创新点在于利用clang实现了C头文件的解析和封装,这样接口封装这样繁重的工作可以自动化地完成。

以下通过Swift中一小段代码来感受下Glibc的便利性,代码摘取自benchmark/utils/DriverUtils.swift

import Glibc

typealias TimeT = timespec
func getTime() -> TimeT {
  var ticks = timespec(tv_sec: 0, tv_nsec: 0)
  clock_gettime(CLOCK_REALTIME, &ticks)
  return ticks
}

其中timespec、clock_gettime、CLOCK_REALTIME都是C库原生定义的名称,不需要任何修改就可以直接在Swift代码中使用。另外对于ticks的初始化,是对timespec结构体的实例化,较C代码更为简洁。

下面再给出一个直接调用time获取时间的示例代码:

import Glibc

var now = time_t()
time(&now)
print(now)

或者:

import Glibc
var now = time(nil)
print(now)

← older posts