LoginSignup
0
0

More than 3 years have passed since last update.

【R】 関数のコードを文字列として取得する

Last updated at Posted at 2020-03-08

趣旨

わかってますよ、、、このニッチすぎる需要。

ですが、関数のコードをcharacterデータ(文字列)として取り扱えれば、コードの修正作業を{stringr}とかに任せられたり、コードを保存し損ねた関数を取り出せるので、何とか標記の件を実現したかったわけです。

コードを取得したい関数
f1 <- function(){
  print("正岡子規")
  fx <- function(){cat("有名な\nやーつ\n")}
  fx()
  "a" %>% 
    print() 
  print(paste("柿食へば", 
              "鐘が鳴るなり", 
              "法隆寺"))
  # 小峠ではない
}

やり方

試行錯誤の末、こういう方法を考えました。
自己流です。ご指摘ウェルカムです。

x <- paste(as.character(getSrcref(f1)), collapse = "\n")

はい、これだけです。

では実際に表示してみます。

> cat(x)
function(){
  print("正岡子規")
  fx <- function(){cat("有名な\nやーつ\n")}
  fx()
  "a" %>% 
    print() 
  print(paste("柿食へば", 
              "鐘が鳴るなり", 
              "法隆寺"))
  # 小峠ではない
}

まったく同じものが取得できました!イェーイ

クラスもちゃんとfunctionからcharacterになっています。

> class(f1)
[1] "function"
> class(x)
[1] "character"

余談1

getSrcref()で取得したオブジェクトは一見文字列なのですが、実際はsrcrefという ちょっと何言ってるか分からない クラスのオブジェクトです。characterでもvectorでもないです。

それに関連して、as.character()も厳密にはsrcrefクラスに適合したメソッドas.character.srcref()を使うほうが安全ですが、総称的関数たるas.character()を使っても全く問題ないです。

> class(getSrcref(f1))
[1] "srcref"

> as.character.srcref(getSrcref(f1))
 [1] "function(){"                                    
 [2] "  print(\"正岡子規\")"                          
 [3] "  fx <- function(){cat(\"有名な\\nやーつ\\n\")}"
 [4] "  fx()"                                         
 [5] "  \"a\" %>% "                                   
 [6] "    print() "                                   
 [7] "  print(paste(\"柿食へば\", "                   
 [8] "              \"鐘が鳴るなり\", "               
 [9] "              \"法隆寺\"))"                     
[10] "  # 小峠ではない"                               
[11] "}" 

余談2

srcrefオブジェクトを取得する方法は上記以外にもう一つあります。

> attributes(f1)[[1]]

一応クラスを確認すると、ちゃんとsrcrefクラスオブジェクトをゲットしてます。

> class(attributes(f1)[[1]])
[1] "srcref"

余談3

今まではc()を使って抽出してきたのですが・・・

> cat(as.character(c(f1)))
function () 
{
    print("正岡子規")
    fx <- function() {
        cat("有名な\nやーつ\n")
    }
    fx()
    "a" %>% print()
    print(paste("柿食へば", "鐘が鳴るなり", "法隆寺"))
}

おわかりいただけただろうか・・・。

  • コード内の改行位置が元と異なる。
    具体的には、引数毎の改行、パイプ演算子%>%{ggplot}+毎の改行等は全て消えてしまう。
  • 逆に大括弧{}の前後は強制的に改行してしまう。
  • #のメモ書き等も消えてしまう。

という問題点があったので、どうにか解決できないかと試行錯誤しているうちに今回の方法を編み出しました。

おわりに

お試しあれ~~~。

Enjoy!

おしまい。

参考文献

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0