[ruby-list:46154] メソッドArgumentのParenthesisについて

View: New views
10 Messages — Rating Filter:   Alert me  

[ruby-list:46154] メソッドArgumentのParenthesisについて

by Shingo Hagiwara :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

本当にくだらない質問で申し訳ありません。

現在、NetBeans6.5.1を使ってRubyを書いているのですが、
Source補完機能を使ったとき、メソッドで「()」付きで補完される場合と、
「()」無しで補完される場合があります。
例えばですが、
hoge arg1 arg2
と補完される場合と、
foo(arg1, arg2)
と言う場合があると言うことです。

この括弧の省略ができるというのは知っているつもりなのですが、
この二つに何か差異はあるのでしょうか?

また、括弧を構文的に付けないことを許している理由はなんなのでしょうか?
個人的には括弧を付けないとBasicを思い出して非常に気持ちが悪い気がします。

上記2点もし気が向けば返答いただけると幸いです。


[ruby-list:46155] Re: メソッドArgumentのParenthesisについて

by rubikitch :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

From: Shingo Hagiwara <rindou@...>
Subject: [ruby-list:46154] メソッドArgumentのParenthesisについて
Date: Fri, 3 Jul 2009 21:51:04 +0900

るびきちです。

> Source補完機能を使ったとき、メソッドで「()」付きで補完される場合と、
> 「()」無しで補完される場合があります。
> 例えばですが、
> hoge arg1 arg2
> と補完される場合と、
> foo(arg1, arg2)
> と言う場合があると言うことです。
>
> この括弧の省略ができるというのは知っているつもりなのですが、
> この二つに何か差異はあるのでしょうか?

hoge arg1 arg2
ではなくて
foo bar arg1
ではないかと?
そのときは
foo(bar(arg1))
と同じ意味です。

hoge arg1, arg2

hoge(arg1, args2)
は等価です。

hogeとかfooではなくて実際のコード例を見てみたいものです。

> また、括弧を構文的に付けないことを許している理由はなんなのでしょうか?
> 個人的には括弧を付けないとBasicを思い出して非常に気持ちが悪い気がします。

記号を多くしすぎないことが理由だったと思います。
このおかげで可読性を上げることができます。

たとえば、Rakefile(Ruby版make)には、こんなふうに書けます。
ふつうのRubyスクリプトですが、括弧が省略可能なことと、ブロック構文の
絶妙な美しさのおかげで、設定用ミニ言語のように見えます。

file "foo.o" => "foo.c" do
  sh "gcc -c foo.c"
end

もし、括弧を全部つけてしまうと、

file({"foo.o" => "foo.c"}) do
  sh("gcc -c foo.c")
end

となり、見辛くなってしまいます。

もし、Rubyが括弧省略不可能でガチガチな言語ならば、好きになれません。
--
rubikitch
Blog: http://d.hatena.ne.jp/rubikitch/
Site: http://www.rubyist.net/~rubikitch/
Twit: http://twitter.com/rubikitch/
『Ruby逆引きハンドブック』 http://d.hatena.ne.jp/rubikitch/20090525/rubybook


[ruby-list:46156] Re: メソッドArgumentのParenthesisについて

by 5.5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

5.5 です。

私が,括弧が省略できてとくに嬉しいなあと思うのは,
・引数が括弧を含む式になっているとき
・引数が複数あるとき
です。

puts(a*(x1+sin(y1)), b*(x2-cos(y2)))

puts a*(x1+sin(y1)), b*(x2-cos(y2))

いま無理矢理作った例ですが,実際的なプログラミングにおいても,
省略が嬉しいことはまあ伝わるでしょうか。

視覚心理学でいう“群化”によって,メソッド名と各引数がそれぞれ
カタマリに見えるのも目にやさしいです。

一言で言えば,入れ子になったものよりも,(見かけ上)ただ並べら
れたもののほうが一目で把握しやすいということだと思います。

※私は素人ですが,Ruby はメソッド呼び出しの自由度・記述性に心
砕いて設計されているのかなあと思います。

--
5.5@...


[ruby-list:46157] Re: メソッドArgumentのParenthesisについて

by Shingo Hagiwara :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

お二人ともお返事ありがとうございました。

記述性が上がるというのは確かにそうですね。
しかし可読性については、疑問があります。
個人的にはPerlの様に他人のコードは分からないという状況になりかねないからです。

ちなみに、るびきちさんの具体的なコードが見てみたいとのことで。
その僕が違和感を感じたコード(コード補完)とは

REXML::Elementオブジェクトに対する補完でして、
add_attributeに対しては
element.add_attribute(key, value)

と補完されます。しかし、add_elementでは
element.add_element element, attrs
と補完されました。共にNetbeans6.5.1です。

おそらく補完データを書いた人が違うのでしょうね。
それで流儀が違うと言うのかもしれません。

ちなみに気持ちが悪いなぁと思ってしまうのは、例えば
p REXML::Element.new("hoge").add_element REXML::Element.new("foo")
.parent.add_element(REXML::Element.new("bar")).parent.to_s

とやると当然エラーですが、

p REXML::Element.new("hoge").add_element(REXML::Element.new("foo")
).parent.add_element(REXML::Element.new("bar")).parent.to_s

とやると当然通ります。

このように意味が同じでありながら挙動が違うことに違和感を感じてしまうからです。
趣味の範囲ですけれどね。
なのでどうしても自分は全部括弧を補ってしまいます。

るびきちさんの仰るように
foo bar arg1は
foo(bar(arg1))と同じ
に統一してくれたら気持ちが良いのですけれどね (^^;

それでは、ありがとうございました。


[ruby-list:46158] Re: メソッドArgumentのParenthesisについて

by Tadashi Saito :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

斎藤と申します。
ちょっと興味があるので突っ込ませてください。

On Fri, 3 Jul 2009 23:24:02 +0900
"5.5" <5.5@...> wrote:

> 視覚心理学でいう“群化”によって,メソッド名と各引数がそれぞれ
> カタマリに見えるのも目にやさしいです。

自分は心理学にまったく詳しくないのですが、その「群化」というのは、
カッコでは成されないものなのでしょうか?

素人目には、「1 + 2 + 3」を「1 + (2 + 3)」とすると、「2 + 3」が「群れている」
ように感じます。
あるいは「数式だと『感じ方』より『意味』を探ってしまう」ということであれば、
「あいう(えおか)きくけこ」という例でどうでしょう。意味はなくても、「えおか」
だけ別の固まりに感じられます。

--
斎藤ただし


[ruby-list:46159] Re: メソッドArgumentのParenthesisについて

by 5.5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

5.5 です。

>> 視覚心理学でいう“群化”によって,メソッド名と各引数がそれぞれ
>> カタマリに見えるのも目にやさしいです。

斉藤さん:
> 自分は心理学にまったく詳しくないのですが、その「群化」というのは、
> カッコでは成されないものなのでしょうか?
>
> 素人目には、「1 + 2 + 3」を「1 + (2 + 3)」とすると、「2 + 3」が「群れている」
> ように感じます。
> あるいは「数式だと『感じ方』より『意味』を探ってしまう」ということであれば、
> 「あいう(えおか)きくけこ」という例でどうでしょう。意味はなくても、「えおか」
> だけ別の固まりに感じられます。

括弧も群化を引き起こすと思います。
群化の要因はいくつもあります。たとえば,日本語を知らない人がが
 
 「プログラミングのための言語」

という文字列を見たら,文字の形の特徴の類似性から,自然と

 「プログラミング」「のための」「言語」

の三つのカタマリに見えると思います。似たものがカタマリに見える
ということなので「類同の要因」といいます。

先の例

  puts a*(x1+sin(y1)), b*(x2-cos(y2))

の場合,近いもの同士がカタマリに見える「近接の要因」によって,
メソッド名,第一引数,第二引数の三つに分かれて見えます。
※いまの場合,近いもの同士というのは,スペースで隔てられてい
ない文字同士という意味です。

括弧を省略しない

  puts(a*(x1+sin(y1)), b*(x2-cos(y2)))

の場合,近接の要因によれば,「,」までと「b」以降の二つに分か
れそうですが,これは意味論と一致しません。
実際には括弧がカタマリを作るので,まずはメソソッド名と引数群の
二つに分かれて見えるでしょうか。
※括弧が群化を引き起こすのは「閉合の要因」というものにあたる
ようです。
それにしても,引数群のほうがそれ以上きれいに分解されては見え
てこない感じです。
そこで,

  puts( a*(x1+sin(y1)), b*(x2-cos(y2)) )

と書けばだいぶ見やすくなります。再び近接の要因によって,引数
それぞれがきれいにカタマリに見えます。
しかし意味論的には一塊である「puts(」と最後の「)」が視覚的に
は遠く離れてまったく別のカタマリである点が嬉しくありませんね。

(視覚的に)入れ子よりも併置が見やすいという話は,

  join(reverse(sort(array)))  # 架空の言語

よりも,メソッドチェーンを使った

  array.sort.reverse.join  # Ruby

のほうが嬉しかったり,

  array.inject(0, func(r, x){なにか})  # 架空の言語

よりも

  array.inject(0){|r, x| なにか}  # Ruby

のほうが嬉しいということにも関係すると思います。


※群化についてご興味を持たれましたら,「群化の要因」とか「ゲ
シュタルトの法則」でお調べになるとよいと思います。
サイエンス社『視覚心理学への招待』は一章を群化に割いています。

--
5.5@...


[ruby-list:46160] Re: メソッドArgumentのParenthesisについて

by Takao Kouji :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

高尾宏治です。

まったく専門外のお話なのですが、説明が分かり易く、とても興味がわきました。

On 2009/07/04, at 23:56, 5.5 wrote:
> それにしても,引数群のほうがそれ以上きれいに分解されては見え
> てこない感じです。
> そこで,
>
>   puts( a*(x1+sin(y1)), b*(x2-cos(y2)) )
>
> と書けばだいぶ見やすくなります。

たしかに。

> (視覚的に)入れ子よりも併置が見やすいという話は,
>
>   join(reverse(sort(array)))  # 架空の言語

これはLispっぽいですね。

> よりも,メソッドチェーンを使った
>
>   array.sort.reverse.join  # Ruby
> のほうが嬉しかったり,

ふむふむ。

>   array.inject(0, func(r, x){なにか})  # 架空の言語
>
> よりも
>
>   array.inject(0){|r, x| なにか}  # Ruby
>
> のほうが嬉しいということにも関係すると思います。

本当ですね。私もうれしいように思います。

> ※群化についてご興味を持たれましたら,「群化の要因」とか「ゲ
> シュタルトの法則」でお調べになるとよいと思います。
> サイエンス社『視覚心理学への招待』は一章を群化に割いています。

勉強になります。日頃、他人のコードをレビューするときなどに
コードを分かり易くするためにはどうしたらいいかを考えることがあります。
そのヒントを教えていただいたような気がしました。

---
TAKAO Kouji <kouji@...>
blog: http://d.hatena.ne.jp/kouji0625/
twitter: takaokouji / projects: ruby, s7-seven



[ruby-list:46161] Re: メソッドArgumentのParenthesisについて

by Shingo Hagiwara :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

よこやりですいませんが、なんだか違和感があったので。



> puts a*(x1+sin(y1)), b*(x2-cos(y2))

これは例として対比するならば、

puts a*(x1+sin(y1)),b*(x2-cos(y2))

と書くべきだという気がします。むしろ、
puts a*(x1+sin(y1)) b*(x2-cos(y2))
でしょうか?

> puts(a*(x1+sin(y1)), b*(x2-cos(y2)))

これも
 puts(a*(x1+sin(y1)),b*(x2-cos(y2)))
という例が適切かと思うのですが。

また
> join(reverse(sort(array)))  # 架空の言語
は大変分かりやすいかと。

> array.sort.reverse.join  # Ruby
これは「.」の意味論によるもので、
「.」が「前オブジェクトの後ラベルを実行する」という事に依存している物かと思います。引数の括弧の有無とは関係ない気もしますが。


> array.inject(0, func(r, x){なにか})  # 架空の言語
これもオブジェクトという型と、関数という型を混在させた例なので
あまり適切であるようには思えません。
任意の関数を引数に持つ場合それは高階になるので、オブジェクトのみを
引数に持つ場合に対して、理論的な隔たりが大きいように思います。


群化が作用しているかどうかと問われると、
上記例では疑問を持たざるを得ません。


[ruby-list:46162] Re: メソッドArgumentのParenthesisについて

by Masayoshi Takahashi :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

高橋征義です。

2009/07/04 14:05 に Shingo Hagiwara<rindou@...> さんは書きました:

> その僕が違和感を感じたコード(コード補完)とは
>
> REXML::Elementオブジェクトに対する補完でして、
> add_attributeに対しては
> element.add_attribute(key, value)
>
> と補完されます。しかし、add_elementでは
> element.add_element element, attrs
> と補完されました。共にNetbeans6.5.1です。
>
> おそらく補完データを書いた人が違うのでしょうね。
> それで流儀が違うと言うのかもしれません。

確認してみました。どうもREXML自体のソースで記法に
揺れがあるようですね。NetBeansの補完はそれを反映して
いるようです。ううむ。

> ちなみに気持ちが悪いなぁと思ってしまうのは、例えば
> p REXML::Element.new("hoge").add_element REXML::Element.new("foo")
> .parent.add_element(REXML::Element.new("bar")).parent.to_s
>
> とやると当然エラーですが、
>
> p REXML::Element.new("hoge").add_element(REXML::Element.new("foo")
> ).parent.add_element(REXML::Element.new("bar")).parent.to_s
>
> とやると当然通ります。
>
> このように意味が同じでありながら挙動が違うことに違和感を感じてしまうからです。

ええっと、これは要するに、

    foo bar arg1.buz

が、

    foo(bar(arg1.buz))

と解釈されているわけですよね? でも、Hagiwaraさんは、

    foo(bar(arg1).buz)

と解釈してほしかった、と。

とはいえ、これはやはりこうあるべきですよね。そうじゃないと、

p "abc".sub(/b/,"B")

みたいなものも、"aBc"とは表示されなくなりますから。

> なのでどうしても自分は全部括弧を補ってしまいます。

それでも、pメソッドの引数のカッコはわりと省略したりしません?
#そうでもなかったらごめんなさい。

pが普通のメソッドでありながら、カッコを省略できる、というのは、
Rubyの文法のおかげです。このおかげで、pがいまいちだからpp.rbの
ppメソッドを使う、といった時でも、同様に pp *foo* みたいな書き方が
できる訳です。この挙動は、普段はほとんどカッコをつけていても、
ここで省略できるのはうれしいと感じることもあります。

高橋征義 (takahashimm@...)


[ruby-list:46163] Re: メソッドArgumentのParenthesisについて

by 5.5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

5.5 です。

Shingo Hagiwara さんは書きました:

> よこやりですいませんが、なんだか違和感があったので。
>
>> puts a*(x1+sin(y1)), b*(x2-cos(y2))
>
> これは例として対比するならば、
>
> puts a*(x1+sin(y1)),b*(x2-cos(y2))
>
> と書くべきだという気がします。むしろ、
> puts a*(x1+sin(y1)) b*(x2-cos(y2))
> でしょうか?
>
>> puts(a*(x1+sin(y1)), b*(x2-cos(y2)))
>
> これも
>  puts(a*(x1+sin(y1)),b*(x2-cos(y2)))
> という例が適切かと思うのですが。

すいません,半日考えてたんですが,わかりませんでした。

> また
>> join(reverse(sort(array)))  # 架空の言語
> は大変分かりやすいかと。

分かりやすいですね。
この例はあまり適当ではありませんでした。

>> array.inject(0, func(r, x){なにか})  # 架空の言語
> これもオブジェクトという型と、関数という型を混在させた例なので
> あまり適切であるようには思えません。
> 任意の関数を引数に持つ場合それは高階になるので、オブジェクトのみを
> 引数に持つ場合に対して、理論的な隔たりが大きいように思います。

こちらも半日考えて,分かりませんでした。

最後の二つの例は,メソッド引数の括弧の省略の話からは離れ,
入れ子構造よりも横並びのほうが視覚的に把握しやすいという
話でした。少なくとも私にはそうです。

※前回まで「併置」という言葉を使いましたが,国語辞典を引
いたら意図した意味と違ってたので,とりあえず「横並び」と
言い換えました。

--
5.5@...