每个Common Lisp程序员都知道宏是一个强大的工具.除了其他方面,已经使用Common Lisp宏在Lisp之上添加面向对象而不改变语言规范; read-macros是另一种具有思维弯曲功能的构造.
另一个允许元编程的程序是Forth.Forth采用"单词"和"生成单词"的方式略有不同.
我想知道,从涉及两种语言的人那里,如果普通的lisp宏和前面的结构在广度/功率方面具有可比性:你可以用前者做一些你不能用后者做的事吗?或相反亦然?
当然,我不是在谈论两种语言的图灵完整性:我在谈论元编程能力.C是Turing-complete,但只有傻瓜会说C宏与Common Lisp的功能相当.
Forth着名的允许用户通过为控制流定义新单词来改变语言(超出标准给出的单词:DO,LOOP,BEGIN,UNTIL,WHILE,REPEAT,LEAVE IF,THEN,ELSE,CASE,ENDCASE等)
是否有人们实际创建自己的新控制流程词的常见例子?有哪些典型和有用的例子?或者标准已经定义了人们实际需要的一切?
我希望找到一些有用的语言扩展示例,这些示例已经被接受或证明通常有助于使语言更具表现力.
在 C 中,局部变量存在于函数内部并包含如下值:
void main(){
int a = 5;
int b = 9;
}
Run Code Online (Sandbox Code Playgroud)
在 Gforth 手册中,他们这样描述局部变量:
: swap { a b -- b a }
b a ;
1 2 swap .s 2drop
Run Code Online (Sandbox Code Playgroud)
但它似乎是一个带有两个参数a和b的函数。
另一个关于 Forth 语言的教程显示了一个像这样的变量:
variable a
3 a ! ( ! to store the value )
Run Code Online (Sandbox Code Playgroud)
那么,哪一个是正确的呢?
我想在Gforth写一个while()循环.不幸的是,由于缺少示例,在线唯一的教程没有用,计数循环的例子(我不想要的)看起来根本不同.
如何表示这样的事情的一些具体例子是什么?
while (x > 3) { print(x); x--; }
Run Code Online (Sandbox Code Playgroud)
或者,实际上,只是表达形式的任何具体方式:
while (predicate) { expression(s) }
Run Code Online (Sandbox Code Playgroud) 在Gforth中,有没有办法将整数值添加到浮点值?
有点像1 + 2.1
?如果我这样做,1 2.1e f+
我得到一个错误,我猜测是因为值不在同一个堆栈上.我知道我可以这样做1.0e 2.1e f+
,但那并不是我想弄清楚怎么做.
我有一个神秘的错误,用于减去各种长度的无符号整数的算法.它几乎适用于每对数字,但如果n不小于单元格中的位数(2^n +1)-(2^n - 1) <> 2
.我无法理解为什么算法不起作用.
数字存储在"cellimal"系统中的数组中(base = 2 ^ bits),最低有效单元格为lowmem.ad1处的数组将从ad2处的数组中减去,两者都是相同的维度len,结果应存储在ad2:
false borrow ! len 0
do i ad2 + @ borrow @ +
i ad1 + @ 2dup u< dup borrow !
if 1 swap 0 d- drop \ subtraction with borrow
else - \ subtraction without borrow
then i ad2 + ! cell
+loop
Run Code Online (Sandbox Code Playgroud)
注意:我认为错误来自于从包含零值的单元格借用...
也许有人可以纠正算法?
Gforth 中有与forget
Forth 对应的词吗?
我见过 about marker
,但它没有相同的行为。该list
命令似乎也没有给出程序列表。
我想查看内存中程序的列表,就像list
BASIC 中的旧程序一样 - 我认为这也是原始 Forth 中的行为。
我正在使用Gforth,我想在定义中创建一个单词。在 Gforth 的命令行中我可以输入:
create foo
ok
Run Code Online (Sandbox Code Playgroud)
或者更具体地说,我定义了一个数组函数,它需要堆栈上的大小并使用该数组的地址创建一个字:
: array ( n -- ) ( i -- addr)
create cells allot
does> cells + ;
Run Code Online (Sandbox Code Playgroud)
因此,如果我输入,10 array foo
我就可以稍后使用foo
。
但如果我在另一个定义中编写,10 array foo
则会出现编译错误。我尝试用s" foo"
which 编译替换 foo ,但它在运行时爆炸,说:
尝试使用零长度字符串作为名称
有没有办法做到这一点?
在 Forth 中,如果栈顶为零,是否有一个常用词来有条件地退出过程(返回)?我正在考虑在递归过程中使用它而不是 IF。
当一个单词被重新定义时,是否可以访问旧单词?
想象一下有一个词foo
被定义和重新定义
: foo ( n -- 2*n ) 2* ; ok
: foo ( n -- 2*n+1 ) foo 1+ ; redefined foo ok
10 foo . 21 ok
Run Code Online (Sandbox Code Playgroud)
foo
这里执行了两个定义。
是否可以执行第一个定义(“second-foo”)?
21 second-foo . 42 ok
Run Code Online (Sandbox Code Playgroud)
到see
它吗?
see second-foo
: foo
2* ; ok
Run Code Online (Sandbox Code Playgroud) forth ×10
gforth ×10
algorithm ×1
arrays ×1
biginteger ×1
common-lisp ×1
compilation ×1
control-flow ×1
definition ×1
lisp ×1