Rmarkdown 中的 Raku 代码

安装

首先,首先安装 R 编程语言。在此之后,运行 R 并执行以下命令来安装 rmarkdown: install.packages("rmarkdown")。在安装 rmarkdown 时,我收到以下错误消息:

Error: .onLoad failed in loadNamespace() for 'tcltk', details:
  call: dyn.load(file, DLLpath = DLLpath, ...)
  error: unable to load shared object '/usr/lib/R/library/tcltk/libs/tcltk.so':
  libtk8.6.so: cannot open shared object file: No such file or directory

这可以通过安装包 tk 来解决,然后继续安装 rmarkdown。

Rmarkdown 的代码块

你可以用 rmarkdown 做的几乎所有都可以用“常规” markdown 来做的事情。然而,rmarkdown 的一个突出特性是它能够执行代码块并返回结果。为此,rmarkdown 使用了 knitr 包,这是一个使用 R 生成动态报告的引擎,除了 R 之外,它还支持其他语言引擎,您可以使用这些引擎来计算来自其他语言的代码。要列出可用引擎的名称,请在 R REPL 中执行 names(knitr::knit_engines$get()) 命令。就像“常规” markdown 一样,代码块可以用三个反勾号创建,然后是代码,最后是另外三个反勾号。如果希望计算代码块,请在花括号 {} 中指定语言,该语言位于前三个反勾号之后。例如,要执行 Perl 5 代码,可以在 {} 中指定 perl:

```{perl}
sub factorial {
    my ($n) = @_;
    return 1 if $n == 0;
    return factorial($n - 1) * $n;
}

for (1..4) {
    print "Factorial of $_: ", factorial($_), "\n";
} 
```

如果任何表达式求值了,将按照如下方式处理,结果将显示在源代码下面:

sub factorial {
    my ($n) = @_;
    return 1 if $n == 0;
    return factorial($n - 1) * $n;
}

for (1..4) {
    print "Factorial of $_: ", factorial($_), "\n";
} 
## Factorial of 1: 1
## Factorial of 2: 2
## Factorial of 3: 6
## Factorial of 4: 24

代码块的选项可以在花括号中指定。例如,为了防止对代码块的计算,您必须将 eval 设置为 FALSE:

```{perl, eval=FALSE}
my $name = 'Nemy';
print "Hello, $name!\n";
```

这阻止了代码块的求值,只显示源代码:

my $name = 'Nemy';
print "Hello, $name!\n";

要隐藏源代码并且仍然显示它的求值,可以将 echo 设置为 FALSE:

```{perl, echo=FALSE}
my $name = 'Nemy';
print "Hello, $name!\n";
```

只有结果被展示出来:

## Hello, Nemy!

在花括号中可以指定一些选项。下面是我常用的一些选项的小列表:

  • engine-默认为Rknitr 将用命名语言计算这个块,例如 engine = 'python'
  • eval-默认情况下为 TRUE。如果为 FALSE, knitr 将不会在代码块中运行代码。
  • echo-默认情况下为 TRUE。如果为 FALSE, knitr 将不会在最终文档中显示其结果上面的代码块中的代码。
  • collapse-默认为 FALSE。如果为 TRUE,knitr 将把该块创建的所有源代码块和输出块折叠成单个块。
  • comment-默认情况下是 ##。knitr 将在最终文档的每行结果的开头添加的一个字符串,例如 comment = '#=>'

在这里可以找到关于不同选项的更多信息。

Rmarkdown 中的 Raku

到目前为止,knitr 不支持 Raku 的语言引擎。但是,您可以使用 knitr 的引擎语言可扩展性来执行 rmarkdown 中的 Raku 代码块,方法是在您的文件中添加以下 R 代码块:

```{r setup}
library(knitr)
eng_raku <- function(options) {
  # create a temporary file
  f <- basename(tempfile("raku", '.', paste('.', "raku", sep = '')))
  on.exit(unlink(f)) # cleanup temp file on function exit
  writeLines(options$code, f)
  out <- ''

  # if eval != FALSE compile/run the code, preserving output
  if (options$eval) {
    out <- system(sprintf('raku %s', paste(f, options$engine.opts)), intern=TRUE)
  }

  # spit back stuff to the user
  engine_output(options, options$code, out)
}

knitr::knit_engines$set(raku=eng_raku)
```

这个变通方法是从这里这里 得到的。

这将允许你这样做:

```{r, engine='raku'}
say [*] 1..5;
```

但是,您可以使用 Perl 5 的引擎语言并通过将 engine.path 设置为 raku 使其路径更改为 Raku 可执行文件的路径,而不是在每个正在处理 Raku 代码的文件中添加这段 R 代码。然后,您可以通过如下方式处理 Raku 代码:

```{perl, engine.path='raku'}
say [*] 1..5;
```

现在您应该能够计算 Raku 代码块:

```{perl, engine.path='raku', comment='#=>', collapse=TRUE}
class Point {
    has $.x = 0;
    has $.y = 0;
    method distance-to-center() {
        return sqrt($!x**2 + $!y**2);
    }
}

my $p = Point.new(x => 3, y => 4);
say $p.distance-to-center();
```

会被处理成如下这样:

class Point {
    has $.x = 0;
    has $.y = 0;
    method distance-to-center() {
        return sqrt($!x**2 + $!y**2);
    }
}

my $p = Point.new(x => 3, y => 4);
say $p.distance-to-center();

#=> 5

补遗

这篇文章是受我的启发,我希望有一个简单的设置,转录课堂笔记使用 vim。注释可能闪烁着 LATEX,一些代码片段,并转换为 .pdf 文件,以便在此过程中进行审阅。rmarkdown 的易用性和广泛的功能使其成为这项工作的合适工具。

要从 vim 直接将 .rmd 转换为 .pdf 文件,我的 .vimrc 中有以下一行映射到 F5,以简化过程:

autocmd Filetype rmd map <F5> :!echo<space>"require(rmarkdown);
<space>render('<c-r>%')"<space>\|<space>R<space>--vanilla<enter>

如您所见,这只是在 R 中加载 rmarkdown 包,将当前 .rmd 文件传递给函数 render,并将其结果传递给 R --vanilla 以使程序非交互式。

注意,您可能需要安装 pandoc 才能正常工作。对于 pandoc latex 模板,我使用了 eisvogel.latex 的一个稍微改进版本。

以下是所有注释的 YAML 前言(元数据)的示例:

---
title: "Raku in rmarkdown"
author: "Luis F. Uceta"
date: Aug 13, 2018

output: 
    pdf_document:
        latex_engine: pdflatex
        toc: true
        template: eisvogel.latex

fontsize: 12pt
geometry: margin=1in 
linkcolor: red
urlcolor: blue
---

这是这个文件的 pdf,使用了之前的 YAML 前言和前面提到的 latex 模板。请注意,此 pdf 可能不反映对本文所做的最新更改。