我非常提倡学习多种编程语言。这主要是因为我容易对我最常用的语言感到厌烦。它也教会了我新的、有趣的编程方法。
用多种语言编写同一个程序是学习它们之间异同的好方法。之前,我写过文章,展示了用 C & C++、使用 Node.js 的 JavaScript 以及 Python 和 Octave 编写的相同示例数据绘图程序。
本文是关于用不同编程语言编写“猜数字”游戏的另一个系列文章的一部分。在这个游戏中,计算机选择一个 1 到 100 之间的数字,并要求您猜测。程序循环直到您猜对为止。
学习一门新语言
冒险进入一门新语言总是让人感到尴尬——我觉得我好像在浪费时间,因为使用我熟悉且一直使用的工具会快得多。幸运的是,一开始,我也非常热衷于学习新事物,这帮助我克服了最初的痛苦。一旦我学到新的视角或我从未想到的解决方案,事情就会变得有趣起来!学习新语言也帮助我将新技术反向移植到我旧的、经过测试的工具中。
当我开始学习一门新语言时,我通常会寻找一个教程,向我介绍它的语法。一旦我对语法有了感觉,我就开始编写一个我熟悉的程序,并寻找可以适应我需求的示例。
什么是 Racket?
Racket 是 Scheme 家族中的一种编程语言,它是 Lisp 的一种方言。Lisp 也是一个语言家族,这使得当您想学习 Lisp 时,很难决定从哪个“方言”开始。所有实现都具有不同程度的兼容性,而这种过多的选择可能会让新手望而却步。我认为这很可惜,因为这些语言真的很有趣,也很刺激!
从 Racket 入手是有道理的,因为它非常成熟和通用,而且社区非常活跃。由于 Racket 是一种类似 Lisp 的语言,因此一个主要特征是它使用前缀表示法和大量的括号。函数和运算符通过将它们放在操作数列表的前面来应用
(function-name operand operand ...)
(+ 2 3)
↳ Returns 5
(list 1 2 3 5)
↳ Returns a list containing 1, 2, 3, and 5
(define x 1)
↳ Defines a variable called x with value of 1
(define (f x y) (* x x))
↳ Defines a function called f with two parameters called x and y that returns their product.
这基本上就是您需要了解的关于 Racket 语法的所有内容;其余的是从 文档中学习函数,文档非常详尽。语法还有其他方面,例如关键字参数和引用,但对于此示例,您不需要它们。
掌握 Racket 可能很困难,而且它的语法可能看起来很奇怪(特别是如果您习惯了像 Python 这样的语言),但我发现它用起来非常有趣。一个很大的优势是 Racket 的编程环境 DrRacket,它非常支持,特别是当您刚开始使用这门语言时。
主要的 Linux 发行版提供了 Racket 的软件包版本,因此 安装 应该很容易。
Racket 中的猜数字游戏
这是用 Racket 编写的“猜数字”程序的一个版本
#lang racket
(define (inquire-user number)
(display "Insert a number: ")
(define guess (string->number (read-line)))
(cond [(> number guess) (displayln "Too low") (inquire-user number)]
[(< number guess) (displayln "Too high") (inquire-user number)]
[else (displayln "Correct!")]))
(displayln "Guess a number between 1 and 100")
(inquire-user (random 1 101))
将此清单保存到名为 guess.rkt
的文件中并运行它
$ racket guess.rkt
以下是一些示例输出
Guess a number between 1 and 100
Insert a number: 90
Too high
Insert a number: 50
Too high
Insert a number: 20
Too high
Insert a number: 10
Too low
Insert a number: 12
Too low
Insert a number: 13
Too low
Insert a number: 14
Too low
Insert a number: 15
Correct!
理解程序
我将逐行浏览程序。第一行声明了清单所用的语言:#lang racket
。这可能看起来很奇怪,但 Racket 非常擅长为新的领域特定语言编写解释器。不过,不要惊慌!您可以按原样使用 Racket,因为它工具非常丰富。
现在来看下一行。(define ...)
用于声明新的变量或函数。在这里,它定义了一个名为 inquire-user
的新函数,该函数接受参数 number
。number
参数是用户必须猜测的随机数。define
过程括号内的其余代码是 inquire-user
函数的主体。请注意,函数名称包含一个破折号;这是 Racket 用于编写长变量名称的惯用风格。
此函数递归调用自身以重复提问,直到用户猜对数字为止。请注意,我没有使用循环;我觉得 Racket 程序员不喜欢循环,只使用递归函数。这种方法是 Racket 的惯用方法,但如果您愿意,循环也是一种选择。
inquire-user
函数的第一步是通过将该字符串写入控制台来要求用户输入一个数字。然后它定义一个名为 guess
的变量,其中包含用户输入的任何内容。read-line
函数 将用户输入作为字符串返回。然后使用 string->number
函数 将字符串转换为数字。在变量定义之后,cond
函数 接受一系列条件。如果满足某个条件,它将执行该条件内的代码。这些条件 (> number guess)
和 (< number guess)
之后跟随着两个函数:一个 displayln
,它向用户提供线索;以及一个 inquire-user
调用。当用户没有猜对数字时,该函数再次调用自身。当不满足这两个条件时,即用户输入了正确的数字时,将执行 else
子句。程序的关键是这个 inquire-user
函数。
但是,该函数仍然需要被调用!首先,程序要求用户猜测一个 1 到 100 之间的数字,然后它使用一个随机数调用 inquire-user
函数。随机数是使用 random
函数 生成的。您需要告知该函数您想生成一个 1 到 100 之间的数字,但 random
函数生成的整数数字最大为 max-1
,所以我使用了 101。
尝试 Racket
学习新语言很有趣!我非常提倡编程语言的多语言性,因为它为编程带来了新的、有趣的方法和见解。Racket 是开始学习如何使用类似 Lisp 的语言进行编程的绝佳机会。我建议您尝试一下。
评论已关闭。