VIP de Programming

   

気になった発言とか簡易まとめ
ある程度まとまったらwikiにうpしよう!
レス集

[Ruby]Lispっぽく振舞ってみる

On Lispを読んでいてちょっと思いついたネタでも。 RUBY_VERSION >= ‘1.8.7’ でよろしく。

# きもい下準備

instance_exec(self) do |toplevel|
  (class << toplevel ; self ; end).class_eval do
    define_method :defun do |name, &block|
      (class << toplevel ; self ; end).class_eval do
        define_method name, &block
      end
    end
  end
end

alias let instance_exec

# 元のCommon Lisp版とRuby版

# (let ((counter 0))
#   (defun new-id   () (incf counter))
#   (defun reset-id () (setq counter 0)))

let(0) do |counter|
  defun :new_id do
    counter += 1
  end
  defun :reset_id do
    counter = 0
  end
end

# 試運転

5.times do
  p new_id  # => 1, 2, 3, 4, 5
end
reset_id
3.times do
  p new_id  # => 1, 2, 3
end

発端はselfに対してのinstance_execでletがやれるとオモタこと。

instance_execでトップレベルでのselfをtoplevelに縛り付けてやって、その内側でdefunをModule#definie_methodで定義することで、defunがどっから呼ばれても関数的メソッドをトップレベルに定義したことにできる。

(self « obj ; self ; end)は、きちゃないけどobjの特異クラスを得るためのイディオム。よいこはなるべくマネしちゃダメだぞ。

Permalink
Comments (View)

[Ruby]実例で学ぶワンライナーRuby入門$3

あーデータ処理簡単にしたいなーってな時に
Rubyの便利な使い方としてワンライナーがあるが、
よくまとめられているサイトが無いのでまとめてみる。三回め

requireする

さてさておそらく今回までが基本的なこと。
Rubyもといスクリプト言語の魅力は、その記述の軽快さと豊富なライブラリだろう。
ただライブラリはものによってrequire(rubyの場合)しなきゃならん。
こいつがワンライナーで書くときにくせになるというわけだ。

たとえばBase64でひたすらエンコするのを作るとしよう。

$ ruby -e 'require "base64";while gets;puts Base64.encode64($_.chomp);end'

とまあ長くなってしまう。
ここで起動時にrequireしてくれる便利な-rオプションを使おう。

$ ruby -r base64 -ple '$_=Base64.encode64($_)'

するとこんなに短くできる!!
-r base64require 'base64'して -ple以下を実行。
-lとは-p-nでのgetsを毎回chompしてくれる有難いオプションなのだww

※補足

つっこまれないように、このコードは以下のように書くこともできる。なぜこう書けるかは、
それぞれ調べたり考えたりしてもらいたい。

$ ruby -e 'require "base64"' -nle 'puts Base64.encode64($_)'
$ ruby -ple '$_=[$_].pack("m*")'

連続requireしたーり

では本日の最後に、入力されたURIをBase64エンコードするコードを作ってみよう。

$ ruby -r base64 -r open-uri -ne 'puts Base64.encode64(open($_).read)'

-r base64-r open-uriでそれぞれ必要なライブラリを読み込んで -neで実行というわけだ。

おわったーり

なんか今日は短かったな。補足の補足をすると

$ ruby -e 'require "base64"' -ne 'puts Base64.encode64($_)'

getsの度にrequireされるけどrubyは多重requireは見事に弾いてくれるのでおそらく問題ない。
次回は、コメントやスレを見て決めたーり

Permalink
Comments (View)

[Ruby]実例で学ぶワンライナーRuby入門$2

あーデータ処理簡単にしたいなーってな時に
Rubyの便利な使い方としてワンライナーがあるが、
よくまとめられているサイトが無いのでまとめてみる。二回め

実行時オプションによって楽する方法

さてさて前回の最終コードを見てみよう

$ ls -l | ruby -e 'while gets;puts split[0];end'

よくよく見てみると while gets…..endの下りは一行ずつ処理する時には必ず付いてしまう
もはや定型文だ。そこでrubyには実行時オプションに自動的にこれを補完するオプションがある

while getsで囲む-n

たとえば-nは実行時

while gets
 ...
end

で囲まれているように実行する。これを使えば上のコードは

$ ls -l | ruby -ne 'puts split[0]'

と書ける(・∀・)便利!!
※なんで-neかは-eをつけないとワンライナーにならないから

while gets ...; print $_; endでかこむ-p

さらに言えば一行ずつなんらかの処理をして表示も定型じゃね?
ってことで-pオプションがある

while gets
  ...
puts $_
end

ただしこれは 最後のgets, readlineを表示する$_を表示するので破壊的メソッドを利用してあげてね!
たとえばこれと現在何行目のgetsか調べる$.をつかって、

$ ls -l | ruby -pe 'sub!(/^/,"%4d "%$.)'

とすれば$ ls -l | cat -nみたいに表示できる!(こっちのが短いwww)
実行例:

$ ls -l | ruby -pe 'sub!(/^/,"%4d "%$.)'
   1 -rw-r--r-- 1 j u  7954 1988-12-11 12:44 a
   2 -rw-r--r-- 1 j u  7954 1990-04-21 21:14 b
   3 drwx------ 1 j u  4096 2004-06-12 00:41 dir1
   4 -rw-r--r-- 1 j u   965 2008-06-12 01:49 file3

"%4d "%$.format("%4d ", $.)と同じ意味、C言語で言うsprintf

毎回splitしてくれる-a

さて最後は毎回

$F = $_.split

してくれる-a-p-nと一緒に使う。
これを使えば最初のコードは

$ ls -l | ruby -ane 'puts $F[0]'

と書けるわけだ!-aneオプションはと覚えようww!!
この姉オプションはかなーり使えるのでぜひぜひ覚えてもらいたい

おわり

誰も見てない書くならイマノウチ。
次回は、requireオプションです(一瞬で終わりそうww)

Permalink
Comments (View)

[Ruby]実例で学ぶワンライナーRuby入門$1

あーデータ処理簡単にしたいなーってな時に
Rubyの便利な使い方としてワンライナーがあるが、
よくまとめられているサイトが無いのでまとめてみる。一回目

perlだろ常考……とか awkとかsed使えなんていっちゃだめ><

はじめに

とりあえず端末とかターミナルとかコマンドプロンプトとかの使い方を勉強しといてください。

簡単なやり方

さて、第一回目はワンライナーrubyの簡単な使い方を説明しておく。

通常rubyを実行すると ruby標準入力をインタプリタに渡す感じで実行される。
ワンライナーrubyとして実行するなら

$ ruby -e 'print "うはwwおkwww"'

こんな感じで実行しよう。
さてさてこれを実行するとうはwwおkwwwと端末に表示されるだろう。
つまり-eオプションをつけると 引数のコードを実行してくれると言うわけだ!

Q>なんか文字化けするんだけど?
A>そんなときは

$ ruby -Ku -e 'print "うはwwおkwww"'

みたいにエンコードを指定してあげよう!

ls -lを処理する。

では簡単に説明したところで 最も身近で最も処理し難いls -lコマンドの結果を処理してみよう!

ls -lの結果はフィールド分け(タブ)ではなく、空白なので

$ ls -l | cut -f 2

とかやっても切り出すことができない不便な野郎なのだ。
そこでワンライナーrubyを使うわけだ!

$ ls -l | ruby -e 'while i=gets;puts i.split[0];end'

これを実行すると以下のようにパーミッションだけが抽出できたのではないだろうか?

drwxr-xr-x
drwxr-xr-x
-rw-r--r--
-rw-r--r--
drwxr-x---
drwx------
-rw-------
-rwxr-xr-x

うはwww便利wwwおkwwwと感じたか うはwww長げぇwww と思ったかは知らないが
こんな風に実際にファイルに書き込まずに ちょちょいと実行できるのがワンライナーの魅力であるのだ

組み込み変数$_

さてさてRubyには組み込み変数なるちょいと便利な変数が存在するのをご存知だろうか?
おそらく$1とか$stderrなんて変数は使ったことあるんじゃないかな?
これが組み込み変数である。

さてさてこの組み込み変数の中に $_と言うものがある。
これは最後にgetsreadlineとかした内容が格納される。
これを使えば上のコードはi=getsする必要がなくなるって訳だ

上のコードを$_を使って書き換えるとこうなる。

$ ls -l | ruby -e 'while gets;puts $_.split[0];end'

ちょいと短くなった。わけだ。

最後の式の値を評価する習性

では、ここでRubyで関数・メソッドをつくる時の書き方を復習しよう

def nibai(x)
    x * 2
end

ただ2倍するだけの関数だが、大抵の人は最後にreturnを書かないだろう
これがRubyの性質・最後の式の値を評価するということである
でがこれを使ってみよう。
とりあえずコードを見てほしい

$ ls -l | ruby -e 'while gets;puts split[0];end'

上との違いは$_.split[0]が変更されている点である。
一見するとなにをsplit()しているのか分からないようだが、Rubyは最後の式を評価するという習性があるので その手前のwhie getsgetsを評価して、gets()の結果をsplit()してる訳だ!

おわり

次回は、実行時オプションによって楽する方法です。

当分 んなことしってるぜーベイビーだったり こうした方が楽だろみたいなツッコミどころ満載な 内容だが我慢してくれ。

windowsではどうなってるか分からないので誰か追記してくれるとありがたい。

Permalink
Comments (View)