質問
Ruby 関数を次のように定義すると:
def ldap_get ( base_dn, filter, scope=LDAP::LDAP_SCOPE_SUBTREE, attrs=nil )
最初の 2 つと最後の引数だけを指定して呼び出すにはどうすればよいですか?なぜそうではないのか
ldap_get( base_dn, filter, , X)
可能ですか、または可能である場合、どうすれば実現できますか?
解決
これは現在ルビーでは不可能です。 「空の」属性をメソッドに渡すことはできません。最も近いものはnilを渡すことです:
ldap_get(base_dn, filter, nil, X)
ただし、これにより、LDAP :: LDAP_SCOPE_SUBTREEではなくnilにスコープが設定されます。
できることは、メソッド内でデフォルト値を設定することです:
def ldap_get(base_dn, filter, scope = nil, attrs = nil)
scope ||= LDAP::LDAP_SCOPE_SUBTREE
... do something ...
end
上記のようにメソッドを呼び出すと、動作は期待どおりになります。
他のヒント
ほとんどの場合、オプションハッシュを使用する方が良いでしょう。
def ldap_get(base_dn, filter, options = {})
options[:scope] ||= LDAP::LDAP_SCOPE_SUBTREE
...
end
ldap_get(base_dn, filter, :attrs => X)
時間が移動し、バージョン2以降、Rubyは名前付きパラメーターをサポートしています:
def ldap_get ( base_dn, filter, scope: "some_scope", attrs: nil )
p attrs
end
ldap_get("first_arg", "second_arg", attrs: "attr1, attr2") # => "attr1, attr2"
ldap_get
を定義した方法で実行することはできません。ただし、次のように ldap_get
を定義した場合:
def ldap_get ( base_dn, filter, attrs=nil, scope=LDAP::LDAP_SCOPE_SUBTREE )
次のことができます。
ldap_get( base_dn, filter, X )
ただし、最初の2つの引数と最後の引数では呼び出せないという問題があります(以前と同じ問題ですが、最後の引数は異なります)。
この理由は簡単です。Rubyのすべての引数にデフォルト値を設定する必要はないため、指定した方法で呼び出すことはできません。たとえば、最初の2つの引数にはデフォルト値がありません。
1) メソッドをオーバーロードすることはできません (なぜRubyはメソッドのオーバーロードをサポートしないのでしょうか?) では、まったく新しいメソッドを作成してみてはいかがでしょうか?
2) 長さ 0 以上の配列に対して splat 演算子 * を使用して、同様の問題を解決しました。次に、パラメータを渡したい場合は配列として解釈されますが、パラメータなしでメソッドを呼び出したい場合は何も渡す必要はありません。見る Ruby プログラミング言語 186/187ページ
最近、これを回避する方法を見つけました。配列の要素を保持または破棄するために、オプションのパラメーターを使用して配列クラスにメソッドを作成したかった。
これをシミュレートする方法は、パラメータとして配列を渡し、そのインデックスの値がゼロかどうかを確認することでした。
class Array
def ascii_to_text(params)
param_len = params.length
if param_len > 3 or param_len < 2 then raise "Invalid number of arguments #{param_len} for 2 || 3." end
bottom = params[0]
top = params[1]
keep = params[2]
if keep.nil? == false
if keep == 1
self.map{|x| if x >= bottom and x <= top then x = x.chr else x = x.to_s end}
else
raise "Invalid option #{keep} at argument position 3 in #{p params}, must be 1 or nil"
end
else
self.map{|x| if x >= bottom and x <= top then x = x.chr end}.compact
end
end
end
異なるパラメーターでクラスメソッドを試す:
array = [1, 2, 97, 98, 99]
p array.ascii_to_text([32, 126, 1]) # Convert all ASCII values of 32-126 to their chr value otherwise keep it the same (That's what the optional 1 is for)
output: [&quot; 1&quot;、&quot; 2&quot;、&quot; a&quot;、&quot; b&quot;、&quot; c&quot;}&quot;
さて、予定どおりに動作するクールです。次に、配列の3番目のパラメーターオプション(1)を渡さない場合に何が起こるかを確認します。
array = [1, 2, 97, 98, 99]
p array.ascii_to_text([32, 126]) # Convert all ASCII values of 32-126 to their chr value else remove it (1 isn't a parameter option)
output: [&quot; a&quot;、&quot; b&quot;、&quot; c&quot;]
ご覧のとおり、配列の3番目のオプションが削除されたため、メソッドの別のセクションが開始され、範囲(32-126)にないすべてのASCII値が削除されました
代わりに、パラメーターでnilとして値を発行することもできました。次のコードブロックのようになります。
def ascii_to_text(top, bottom, keep = nil)
if keep.nil?
self.map{|x| if x >= bottom and x <= top then x = x.chr end}.compact
else
self.map{|x| if x >= bottom and x <= top then x = x.chr else x = x.to_s end}
end
可能です:) 定義を変更するだけ
def ldap_get ( base_dn, filter, scope=LDAP::LDAP_SCOPE_SUBTREE, attrs=nil )
to
def ldap_get ( base_dn, filter, *param_array, attrs=nil )
scope = param_array.first || LDAP::LDAP_SCOPE_SUBTREE
scopeは最初の場所で配列になります。 3つの引数を指定すると、base_dn、filter、attrsが割り当てられ、param_arrayは[]になります 引数が4つ以上の場合、param_arrayは[argument1、or_more、および_more]
になります欠点は...それは明確な解決策ではなく、本当にreallyいことです。これは、rubyの関数呼び出しの途中で引数を省略することができると答えることです:)
もう1つ必要なことは、スコープのデフォルト値を書き換えることです。
名前付き変数を使用すると間違いなくコードが読みやすくなりますが、部分的なアプリケーションでこれを実行できます。 John Resigは2008年にJavaScriptでそれを行う方法についてブログ記事を書きました: http:// ejohn.org/blog/partial-functions-in-javascript/
Function.prototype.partial = function(){
var fn = this, args = Array.prototype.slice.call(arguments);
return function(){
var arg = 0;
for ( var i = 0; i < args.length && arg < arguments.length; i++ )
if ( args[i] === undefined )
args[i] = arguments[arg++];
return fn.apply(this, args);
};
};
Rubyで同じ原則を適用することはおそらく可能です(プロトタイプの継承を除く)。