21 运行和创建可执行文件

在开发程序时,很多Racket程序员使用DrRacket编程环境。要在没有开发环境的情况下运行程序,请使用racket(用于基于控制台的程序)或gracket(对于GUI程序)。本章主要介绍如何运行racket和gracket。

21.1 运行racket和gracket

21.1.1 交互模式

21.1.2 模块模式

21.1.3 加载模式

21.2 脚本

21.2.1 Unix脚本

21.2.2 Windows批处理文件

21.3 创建独立可执行文件

21.1 运行racket和gracket

gracket可执行文件和racket一样,但表现上有小的调整,可作为GUI应用程序而不是控制台应用程序。例如,gracket在默认情况下以交互模式运行,使用GUI窗口而不是控制台提示符。然而,GUI应用程序可以以普通的racket运行。

根据命令行参数的不同,racket或gracket在交互模式、模块模式或加载模式下。

21.1.1 交互模式

当racket在没有命令行参数的情况下运行时(除了配置选项,如-j),那么启动REPL使用> 提示符:

Welcome to Racket v8.4 [cs].

>

为了增强你的REPL体验,请参见《xrepl》;有关GNU Readline支持的信息,请参见《readline》。

要初始化REPL的环境,racket首先需要racket/init模块,该模块提供所有racket,并安装pretty-print以显示结果。最后,在启动REPL之前,racket加载(find-system-path 'init-file)报告的文件(如果存在)。

如果提供了任何命令行参数(配置项除外),请添加-i或--repl以重启REPL。例如,

racket -e '(display "hi\n")' -i

在启动时显示“hi”,但仍显示REPL。

如果需要标志的模块出现在-i/--repl之前,它们将取消对racket/init的自动需求。这种行为可用来使用其它语言初始化REPL的环境。例如,

racket -l racket/base -i

使用更小的初始语言(加载速度更快)启动REPL。请注意,大多数模块都不提供Racket的基本语法,包括函数调用语法和require。例如,

racket -l racket/date -i

生成一个对每个表达式都失败的REPL,因为racket/date只提供了几个函数,而不是REPL里需要求值顶层函数调用所需的#%top-interaction#%app绑定。

如果一个需求标志的模块出现在-i/--repl之后,而不是出现在它之前,那么该模块需要在racket/init之后,以增强初始环境。例如,

racket -i -l racket/date

除了racket的导出之外,可以使用racket/date启动一个有用的REPL。

21.1.2 模块模式

如果一个文件参数在任何命令行开关(除了其它配置选项)之前提供给racket,那么这个文件作为一个模块导入,没有REPL启动。例如,

racket hello.rkt

需求"hello.rkt"模块,然后退出。文件名、标志或其它内容之后的任何参数都作为命令行参数保存,以供所需的模块通过current-command-line-arguments使用。

如果使用命令行标志,则可以使用-u或--require-script标志来显示地将文件作为模块。-t或--require标志类似,只是额外的命令行标志由racket处理,而不是为需求的模块保留。例如,

racket -t hello.rkt -t goodbye.rkt

需求"hello.rkt"模块,然后需求"goodbye.rkt"模块,再然后退出。

-l或--lib标志类似于-t/--require,但它需求一个使用lib模块路径而不是文件路径的模块。例如,

racket -l raco

与运行不带参数的raco可执行文件是一样的,因为raco模块是可执行文件的主模块。

请注意,如果你想将命令行标志传递给上面的raco,你需要用--保护这些标志,这样racket就不会试图自己解析它们:

racket -l raco -- --help

21.1.3 加载模式

-f或--load标志直接支持文件中的load顶级表达式,而不是模块文件中的表达式。这个求值就像启动一个REPL并直接键入表达式,只是结果不打印。例如,

racket -f hi.rkts

load "hi.rkts"并退出。请注意,由于给有LISP/Scheme经验的读者的一个说明中解释的原因,加载模式通常是一个坏主意;使用模块模式通常更好。

-e或--eval标志接受表达式直接求值。与文件加载不同,表达式的结果是打印的,就像在REPL中一样。例如,

racket -e '(current-seconds)'

打印自1970年1月1日以来的秒数。

对于文件加载和表达式求值,顶级环境的创建方式与交互模式相同:除非首先指定了另一个模块,否则需求racket/init。例如,

racket -l racket/base -e '(current-seconds)'

很可能运行得更快,因为它使用较小的racket/base语言而不是racket/init初始化求值环境。

21.2 脚本

Racket文件可以在UNIX和Mac OS上转换为可执行脚本。在Windows中,像Cygwin这样的兼容层支持相同类型的脚本,或者可以将脚本实现为批处理文件。

21.2.1 Unix脚本

在UNIX环境(包括Linux和Mac OS)中,可以使用shell的#!约定将Racket文件转换为可执行脚本。文件的前两个字符必须是#!;下一个字符必须是空格或/,并且第一行的其余部分必须是执行脚本的命令。对于某些平台,第一行的总长度限制为32个字符,而且有时需要空间。

使用#lang racket/base代替#lang racket来生成启动时间更快的脚本。

最简单的脚本格式使用racket可执行文件的绝对路径,随后是模块声明。例如,如果racket安装在"/usr/local/bin"中,那么包含以下文本的文件将充当“Hello World”脚本:

#! /usr/local/bin/racket

#lang racket/base

"Hello, world!"

特别是,如果将上述内容放入文件"hello"中,并使该文件可执行(例如,使用chmod a+x hello),然后在shell提示符处键入./hello将生成输出"Hello, world!"。

上述脚本之所以有效,是因为操作系统自动将脚本的路径作为#!启动的程序的参数行,并且因为racket将单个非标志参数视为包含要运行的模块的文件。

一种流行的代替方法是,不指定racket可执行文件的完整路径,而是需求racket位于用户的命令路径中,然后“trampoline“使用/usr/bin/env:

#! /usr/bin/env racket

#lang racket/base

"Hello, world!"

在任何一种情况下,脚本的命令行参数都可以通过current-command-line-arguments获得:

#! /usr/bin/env racket

#lang racket/base

(printf "Given arguments: ~s\n"

(current-command-line-arguments))

如果需要脚本的名称,可以通过(find-system-path 'run-file)获取,而不是(current-command-line-arguments)。

通常,处理命令行参数的最佳方法是使用racket提供的command-line表解析它们。默认情况下,command-line表从(current-command-line-arguments)中提取命令行参数:

#! /usr/bin/env racket

#lang racket

(define verbose? (make-parameter #f))

(define greeting

(command-line

#:once-each

[("-v") "Verbose mode" (verbose? #t)]

#:args

(str) str))

(printf "~a~a\n"

greeting

(if (verbose?) " to you, too!" ""))

尝试使用--help标志运行上述脚本,以查看脚本允许哪些命令行参数。

更普通的trampoline使用/bin/sh加上一些行,这些行是一种语言的注释,另一种语言是表达式。这个trampoline更复杂,但它提供了对racket命令行参数的更多控制:

#! /bin/sh

#|

exec racket -e '(printf "Running...\n")' -u "$0" ${1+"$@"}

|#

#lang racket/base

(printf "The above line of output had been produced via\n")

(printf "a use of the `-e' flag.\n")

(printf "Given arguments: ~s\n"

(current-command-line-arguments))

请注意,#!在Racket中开始一行注释,#|...|#形成块注释。同时,#还启动了一个shell脚本注释,而exec racket则中止了shell脚本以启动racket。这样,脚本文件就变成了/bin/sh和racket的有效输入。

21.2.2 Windows批处理文件

类似的技巧也可以用于在windows中编写Racket代码.bat批处理文件:

; @echo off

; Racket.exe "%~f0" %*

; exit /b

#lang racket/base

"Hello, world!"

21.3 创建独立可执行文件

有关创建和分发可执行文件的信息,参见在《(part ("(lib scribblings/raco/raco.scrbl)" "top"))》中的(part ("(lib scribblings/raco/raco.scrbl)" "exe"))》和《(part ("(lib scribblings/raco/raco.scrbl)" "exe-dist"))》。

(part ("(lib scribblings/raco/raco.scrbl)" "top")).

Racket编程指南——21 运行和创建可执行文件相关推荐

  1. Racket编程指南——23 Racket和Scheme的方言

    23 Racket和Scheme的方言 我们使用"Racket"来指Lisp语言的一种特定方言,它基于Lisp家族的Scheme分支.尽管Racket与Scheme相似,但模块上的 ...

  2. Racket编程指南——4 表达式和定义

    4 表达式和定义 <Racket概要>这一章介绍了一些基本的Racket的句法表:定义.过程程序.条件表达式等等.本节提供这些形式的更详细信息,以及一些附加的基本表. 4.1 标记法 4. ...

  3. Racket编程指南——8 输入和输出

    8 输入和输出 一个Racket端口对应一个流的Unix概念(不要与racket/stream的流混淆). 一个Racket端口(port)代表一个数据源或数据池,诸如一个文件.一个终端.一个TCP连 ...

  4. Racket编程指南——20 并行

    20 并行 Racket提供两种形式的并行(parallelism):前程(futures)和现场(places).在提供多个处理器的平台上,并行可以提高程序的运行时性能. 关于Racket里顺序性能 ...

  5. Racket编程指南——13 类和对象

    13 类和对象 本章基于一篇论文[Flatt06]. 一个类(class)表达式表示一类值,就像一个lambda表达式一样: (class superclass-expr decl-or-expr . ...

  6. iOS_SpriteKit_02_SpriteKit编程指南

    关于Sprite Kit SpriteKit提供了一个图形渲染(rendering)和动画的基础,你可以使用它让任意纹理(textured)图像或精灵动起来.Sprite Kit采用的是传统的渲染循环 ...

  7. iPhone OS编程指南(一)

    原文地址:iPhone OS编程指南(一)作者:若水一叶 介绍 请注意:本文档之前命名为iPhone OS编程指南. iPhoneSDK为创建iPhone的本地应用程序提供必需的工具和资源.在用户的H ...

  8. OpenGL编程指南(第八版)第一个渲染三角形案例代码在win8双显卡电脑VS2015中运行方法总结

    弄了好几天才把第一个程序运行出来,用该博客记录一下参考的博客资料及问题: 写得很好的博客参考资料为: http://blog.csdn.net/IceTeaSet/article/details/50 ...

  9. OpenGL编程指南4:双缓冲实现运行

    1.前言 绘制一个旋转的方块,主要为了说明glutSwapBuffers()函数的用法. 同时也为了学习如何使用GLUT控制输入设备,并打开或关闭空闲处理函数. 2.OpenGL编程及程序剖析 /** ...

最新文章

  1. 树莓派Python编程指南--第一章(起航--启动和运行)
  2. .NET Core快速入门教程 3、我的第一个.NET Core App (CentOS篇)
  3. 如何使用Java和XML Config在Spring Security中启用HTTP基本身份验证
  4. AS3的Number类型变量不指定初始值,则其初始值为NaN,而不是0.0
  5. 5G标准化加速 需应对测试场景复杂性
  6. python连接mysql查询数据返回字典格式
  7. azure云数据库_在Azure SQL数据库中实现动态数据屏蔽
  8. Python基础笔记(二) List、tuple、循环语句
  9. win10创建mysql数据库吗_win10 sqlite3创建的数据库文件在哪
  10. Advanced clustering methods (Cure, Chameleon, Rock, Jarvis-Petrich)
  11. 阿里云云计算 52在线实验--云监控初体验
  12. 华为ensp 交换机vlan配置
  13. 外螺纹对照表_螺纹符号对照表[1]
  14. 彐一夕儿本铺_2019-10-16汉字宫目录
  15. 【复杂网络社团发现】Gephi绘制网络图
  16. 《算法导论》第16章-贪心算法 16.1-活动选择问题(含C++代码)
  17. 二次函数回归方程_高三||【高三专题】三角函数提优专题卷
  18. 工作日记:JavaScript生成随机色
  19. [附源码]计算机毕业设计JAVA领导干部听课评课管理系统
  20. Cannot run program‘C:\Anaconda3\envs\...\python.exe’(in directory):CreateProcess error=2,系统找不到指定文件

热门文章

  1. 【NAS】Samba配置文件解析
  2. Mac之如何将文件夹加入个人收藏
  3. Rockchip RK3288型号获取
  4. 华为设备AP管理命令
  5. 论文笔记(三):PoseCNN: A Convolutional Neural Network for 6D Object Pose Estimation in Cluttered Scenes
  6. 计算机无法连接网络错误651,651错误代码,详细教您宽带连接提示错误651怎么办...
  7. 阿里云ECS服务器 跨域Access-Control-Allow-Origin 问题
  8. 信捷PLC以太网通讯数据采集解决方案
  9. 判决文书网爬虫获取vjkl5失败原因
  10. 微软服务器改dns,Win10修改微软DNS的方法!