Pythonでプログラミングする際、「まずコードを書いて、ある程度コードが大きくなってきたらクラスを作って整理する」ということをよくします。
R言語ではなんだかオブジェクト指向の概念が特殊で、その辺の機能を敬遠していましたが、 「普通のオブジェクト指向言語っぽくプログラミングできるR6というライブラリがあるらしい」 と聞きました。
[http://www.slideshare.net/nakamichi/r6-upload:embed:cite]
そこで練習半分、R6を使ってプログラムを書いてみました。 下の記事にある「ChatworkのAPIを叩いてメッセージを投稿する」プログラムをOOPっぽく書きました。
Python等に慣れている人なら、あまり違和感なく利用できると思います。 publicとかprivateにlistで関数を与えるのって、なんだかJavaScriptのコードみたいな見た目になりますね。
library(R6) library(utils) library(RCurl) library(rjson) api <- R6::R6Class("api", public = list( initialize = function(access_token) { private$access_token <- access_token }, # room_idの部屋にメッセージを投稿する post_messages = function(message, room_id) { result <- RCurl::postForm( uri = private$make_uri('rooms', room_id, 'messages'), .opts = list( httpheader = private$make_header(), postfields = private$make_body(message) ) ) return( rjson::fromJSON(result) ) }, # room_idの部屋にメッセージを取得する get_messages = function(room_id, force = FALSE) { result <- RCurl::getForm( uri = paste0( private$make_uri('rooms', room_id, 'messages'), ifelse(force, '?force=1', '?force=0') # とりあえずifelse関数(三項演算子みたいなもの)で ), .opts = list( httpheader = private$make_header() ) ) return ( rjson::fromJSON(result) # jsonをparseする。dataframeの形に成形したほうがいいかな… ) } ), private = list( access_token = NA, url = 'https://api.chatwork.com/v1', make_header = function() { return ( c('X-ChatWorkToken' = private$access_token) ) }, # ChatworkのAPIの種類によってURIの階層の長さが違うので、可変長引数で文字列を渡して"/"区切りに変換する関数を用意 make_uri = function(...) { return ( Reduce( function(x, y){paste(x, y, sep='/')}, as.character(list(private$url, ...)) ) ) }, make_body = function(message) { return ( utils::URLencode(paste0('body=', message)) # win環境では utils::URLencode(iconv(paste0('body=', message), 'SHIFT_JIS','UTF-8')) ) } ) ) # インスタンスを作る client <- api$new(access_token = '82*************') # Chatworkにメッセージを投稿してみる client$post_messages(message = 'Hello Chatwork!', room_id = 41******) # $message_id # [1] 995512653 # チャットのメッセージ一覧を取得 # force = TRUEで、未取得にかかわらず最新の100件を取得 messages <- client$get_messages(room_id = 41******, force = TRUE)
暇があったらライブラリ化してみたいですね。