【Scheme】Scheme 编程学习 (七) —— Macros 宏
原视频地址: https://www.bilibili.com/video/BV1Kt411R7Wf?p=7
Macros in scheme
Scheme 语言中的宏,一般我们会在各种编程语言中见到宏,在 Scheme 中也是同样的 idea
I - 问题 (The problem)
(define num 3)
; 定义符号 num 为 3
(cond
((zero? num) (display "Z"))
((positive? num) (display "P"))
(else (display "N")))
设置一个条件判断,如果 num 为 0 ,则打印 Z (z 代表 zero 零),若为正数则打印 P (p 代表 positive 正数) , 其他则打印 N (n 代表 negative 负数)
II - 隐藏复杂度 (Hiding complexity)
- How can we avoid repeating ourselves?
如何避免重复,编程通用的方式是 DRY (don’t repeat yourself 不要重复你自己) - How can we speak at the right level?
如何在一个高的层面 (in a high level) 使用 Scheme
避免重复的原因是,我们一次表达出了一个概念 (express a concept),我们不需要在每次使用的时候都重新表达这个概念 (without re-express it every time),另一种原因是,我们不必要去思考底层实现 (implementation),转而去思考更高层面的问题。
仅用代码实现一次 (code your concept once),其他时候只需要引用 (refer to) 它,这里我们希望做的事是避免 (avoid) 重复代码中的条件表达式 (cond expression),do once and leave it alone.
在编程语言中 (In program languages), 有多种方式 (several way) 来实现
- Functions 编写函数
- Classes 使用类
- Extending the language 扩展语言
- Code generation 程序生成代码
(比如 Qt 扩展了 C++,并在编译时使用元对象系统生成 moc 相关的C++代码) - Macros 宏
- Code generation 程序生成代码
III - 初次尝试 (First attempt)
(define (3-state
value
positive-body
zero-body
negative-body)
(cond
((zero? value) zero-body)
((positive? value) positive-body)
(else negative-body)))
我们定义一个函数 3-state 需要四个入参 value, positive-body, zero-body, negative-body
这个函数体是一个条件表达式 (cond expression)
尝试调用
(3-state
100 (display "P") (display "Z") (display "N"))
; PZN
这种方式定义与调用会执行所有的 Scheme 语句,所以我们无法直接定义函数来实现。
IV - 解决方案 (A solution)
因此我们需要定义宏 (macros),定义 syntax ,
(define-syntax
3-state
(syntax-rules ()
((3-state
value positive-body zero-body negative-body)
(cond
((zero? value) zero-body)
((positive? value) positive-body)
(else negative-body)))))
第二个参数为 syntax-rules ,这里是需要做的匹配和需要扩展的模板 (the matching you should do, the template you should expand), 使用模式匹配 (pattern),并使用内容替换 (substitute in code)
> (3-state
100 (display "P") (display "Z") (display "N"))
; P
调用
> (3-state
0 (display "P") (display "Z") (display "N"))
; Z
> (3-state
-100 (display "P") (display "Z") (display "N"))
; N
V - 其他的实现方式 (How else could we do this?)
在其他语言中如何实现
5.1 - 宏 (Macros)
在 C 中使用 Macros 举例如下
/* MACROS */
#define THREESTATE(VALUE,PBODY,ZBODY,NBODY) \
{\
int v = (VALUE); \
if (v == 0) { (ZBODY); }\
else if (v > 0) { (PBODY); }\
else { (NBODY); }\
}
int main()
{
THREESTATE(3, print("P\n"), print("Z\n"), print("N\n"));
return 0;
}
macros 为 literal expression 无法调试 (debug),
如何在 scheme 中使用 substitute
5.2 - 引用 (Quoting)
这是一部分 JavaScript 代码,函数体使用字符串来定义 (body express in strings),通过 eval 函数来调用。文章来源:https://www.toymoban.com/news/detail-736473.html
function threeState( value, pbody, zbody, nbody )
{
if (value === 0) { eval( zbody ); }
else if (value > 0) { eval( pbody ); }
else { eval( nbody ); }
}
threeState(
3, "print('P')", "print('Z')", "print('N')" );
5.3 - 函数指针 (Function pointers)
def three_state(
value, p_body_fn, z_body_fn, n_body_fn):
if value == 0: z_body_fn()
elif value > 0: p_body_fn()
else: n_body_fn()
def pr( x ):
def ret():
print x
return ret
three_state(3, pr("P"), pr("Z"), pr("N"))
5.4 - 类 (class)
class TestJava {
interface IThreeStateBodies {
void positiveBody();
void zeroBody();
void negativeBody();
}
static void threeState(
int value, IThreeStateBodies bodies ) {
if ( value == 0 ) bodies.zeroBody();
else if ( value > 0 ) bodies.positiveBody();
else bodies.negativeBody();
}
public static void main( String[] args ) {
threeState( 3,
new IThreeStateBodies() {
public void positiveBody() {
System.out.println( "P" );
}
public void zeroBody() {
System.out.println( "Z" );
}
public void negativeBody() {
System.out.println( "N" );
}
}
);
}
Java 通过定义 Interface文章来源地址https://www.toymoban.com/news/detail-736473.html
到了这里,关于【Scheme】Scheme 编程学习 (七) —— Macros 宏的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!