言語構文について書いています。メソッド名の中にパラメータが配置される言語はありますか?


29

JavaScriptで:

function getTopCustomersOfTheYear(howManyCustomers, whichYear) {
   // Some code here.
}
getTopCustomersOfTheYear(50, 2010);

C#の場合:

public List<Customer> GetTopCustomersOfTheYear(int howManyCustomers, 
 int whichYear)
{
   // Some code here
}
List<Customer> customers = GetTopCustomersOfTheYear(50, 2010);

PHPの場合:

public function getTopCustomersOfTheYear($howManyCustomers, $whichYear)
{
   // Some code here
}
$customers = getTopCustomersOfTheYear(50, 2010);

この構文をサポートする言語はありますか?

function GetTop(x)CustomersOfTheYear(y)
{
    // Some code here
}
returnValue = GetTop(50)CustomersOfTheYear(2010);

関数を記述するより意味的で読みやすい形式ではありませんか?

更新:この質問をする理由は、新しい言語の新しい構文に関する記事を書いているからです。ただし、メソッドを宣言するためのこのような構文を使用すると、自然言語により近くなるため、開発者にとってより使いやすくなり、言語の学習曲線が減少すると考えました。この機能が既に検討されているかどうかを知りたかっただけです。


12
イディオムに慣れると読みやすくなるかもしれませんが、そのための正しいパーサーを書くのは難しいでしょう。
メイソンウィーラー

2
「プレースホルダー」とはどういう意味ですか?最後のコード例はObjective-CとSmallTalkを連想させますが、この質問は提起されたものとして理解するのは困難です。
greyfade

3
AFAIK Smalltalkは、'hello world' indexOf: $o startingAt: 6またはのような排他的にこの構文を使用した最初の言語でしたRectangle width: 100 height: 200。ところで、この質問の何が問題になっていますか?
maaartinus

8
かっこを移動すると、次のようになります。returnValue = GetTop(50, CustomersOfTheYear(2010))同じように読みやすく、実際にはより柔軟/直交しているように見えます。...そしてええ、それは普通の普通の構文です。
-dagnelies

2
@arnaud:私は完全に同意します。提案された構文は、分解されていない場合の回避策にすぎません。
back2dos

回答:


41

はい、そしてはい。はい、そのような言語があります、そして、はい、多くの人々は、慣れると、より読みやすくなります。

Objective-Cでは、メソッドは次のようになります。

- (NSArray*)getTop:(int)count customersOfTheYear:(Year)year;

それは実際には非常によく読まれていないかなり不自然な例なので、実際のコードからより良い例を示します:

+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;

赤、緑、青、およびアルファ値を使用して新しいUIColorインスタンスを返すメソッドのプロトタイプ。次のように呼び出します。

UIColor *violet = [UIColor colorWithRed:0.8 green:0.0 blue:0.7 alpha:1.0];

「Objective-Cプログラミング言語」で、パラメーターが散在したメッセージ名の詳細をご覧ください。


16
Objective CIで初めてこのことを読んだのは賢明だと思っていましたが、実際にはパラメータの名前が付けられており、管理が難しくなります。それとは別に、良い答え。
-ZJR

2
メソッドがどのように呼び出されるかの例は見逃せません。
-greyfade

3
@ZJRは、ウィキペディアの反対意見にもかかわらず、Obj-Cのスタイルは名前付きパラメーターに似ていますが、異なっています。上記の例では、メソッド名は次のとおり+colorWithRed:blue:green:alpha:です。私は、メソッドに一致するパラメータの名前を使用することが起こったが、私はのように簡単に使うことができたrbg、とa。JavaScriptオファーなどの名前付きパラメーターでは、指定された実際の名前を使用して値にアクセスします。通常、真の名前のパラメーターは任意の順序で指定でき、パラメーターはオプションです。似ていますが、はい、しかし根本的に異なります。
カレブ

2
私はpythonを考えていました:color(r=0xFF,g=0xFF,b=0x55)などcolor(b=0x32,r=0x7F,a=.5,g=0xFF)など。それでは、これらの非常に名前の付いたパラメーターを呼び出しましょう。:)
ZJR

3
@ZJR、あなたのpythonの例はまさにその通りです。それがまさに「名前付きパラメーター」と呼ぶものです。私は、Obj-Cが本当にそれをあなたに全く与えないと言っているだけです。メソッドは複数の部分に分割され、各部分にはコロンが付いているため、構文 JavaScriptの名前付きパラメーターによく似ています、実際にそうではありません。Obj-Cの名前はメソッド名の一部であり、実装内のパラメーターを参照するために使用できる名前ではありません。順序が重要です。パラメーターはオプションではありません。私たちはおそらく同意するのではないでしょう。
カレブ

25

回答:smalltalk

http://en.wikipedia.org/wiki/Smalltalk

'hello world' indexOf: $o startingAt: 6 Javaのようなものです "hello world".indexOfStartingAt(o, 6)

Rectangle width: 100 height: 200 Javaのようなものです new Rectangle(100, 200)

構文は... expression word1: parm1 word2: parm2 word3: parm3 ...呼び出されるメソッドの名前は、すべての単語の連結です。


17

「流interfaceなインターフェース(@Jesperが元々作成したコメントを「答え」に上げる)と呼ばれる抽象化を探していると思います。現在、この一般的なパターンは多くの言語で正常に実装されており、Objective-Cはそのうちの1つです。

これはかなりきれいな例です:

Person bo = new Person();
bo.Set.FirstName("Bo").LastName("Peep").Age(16).Size("Little").LostHerSheep();

Randy PattersonHow to design fluent interfaceで、このようなものをどのように実装できるかを見ることができます

Andre Viannaが簡単な歴史を述べた後、有用な情報を含む2つの記事で、可能な実装について説明します。Viannaは、「カスケード」と呼ばれるSmalltalk 80で最初に出会った古い考え方をさかのぼります。これは、同じオブジェクトに複数のメッセージを送信することを可能にしました。このように見えた:

aThing one: 'one';
  two: 'two';
  other.

その後「へと進化し、カスケード方式チェーン我々は、」「修飾方法は、複数の修飾子が単一の式に呼び出すことができるように、ホストオブジェクトを返してください。」メソッドが後になるために育ったチェーニング流れるようなインターフェイスの私たちが知っている概念で、今日頻繁に使用します。あなたがやろうとしていることは非常に似ています。

Ayende Rahienは、「流fluentなインターフェイス」が「メソッドチェーン」とは大きく異なり、独自の名前に値する可能性があることを説明します。

流interfacesなインターフェイスは、ビヘイビアドリブン開発(BDD)で使用されるいくつかの新しいツールでよく見られ、新しいConstraint-Based Assert Modelで主要な.NETユニットテストツールであるNUnitにも使用されています

これらの基本的なアプローチは、その後、Ruby、Python、C#、Objective-C、Javaなどの他の言語で実装されました。似たようなものを実装するには、連鎖と流prettyさの基本である「クロージャ」の概念を勉強する必要があります。

おそらく、これらのモデルを改善できます。それが私たちが素晴らしい新しい言語を得る方法です。それでも、メソッドチェーンと流なインターフェイスを完全に理解すると、アイデアを発展させるための素晴らしい出発点になると思います!


2
これまでに調査されたほとんどの回答に対して+1。
ヘイレム

@haylem、私に戻って例ともう少し詳細を追加してくれてありがとう!
ジョントブラー

3
流なスタイルの良い説明であるために賛成ですが、これはOPが求めているものではないことに注意してください。私が読んだように、質問は、単一の関数またはメソッドの名前の一部を持つパラメーターの散在に関連しています。提案された関数宣言に注意してくださいfunction GetTop(x)CustomersOfTheYear(y)。これは単一の関数であり、2つの異なる関数への連鎖呼び出しではありません。
カレブ

@Calebここで彼は、これらの挿入パラメータが、流interfaceなインターフェース(この答え)または名前付きパラメータ(別の答え)を実行するための柔軟性のない方法であることを指摘しようとしていると思います。 これまでのところ、流interfaceなインターフェイス/名前付きパラメーターではうまくいかないという利点はありません。
イズカタ14

16

Objective-Cはそれを行います。典型的なプロトタイプは次のとおりです。

- (void) areaWithHeight: (float) height andWidth: (float) width;

このようなメソッドを呼び出す方法は次のとおりです。

float area = [self areaWithHeight: 75 andWidth: 20];

Objective-Cは主にMac OS XのCocoaおよびiOSのCocoa Touchで使用されますが、gccはgccが動作するほぼすべてのプラットフォームでObjective-Cコードを構築します。


申し訳ありませんが、箇条書きはハイフンになっているはずです。回答テキストのハイフンはマークアップと見なされます。Objective-Cのハイフンは、オブジェクトに属するメソッドを宣言するために使用されます-[foo bar:x]ここで、fooはオブジェクトまたはクラスインスタンスです-プラス記号はクラスメソッドに使用され、C ++は静的メンバー関数と呼ばれます。
マイククロフォード

13

Common lispでは、次のような関数のキーワード引数を定義できます。

(defun area (&key width height)
    (* width height))

関数は次のように呼び出されます。

(area :width 2 :height 3)

Adaでは、特別な宣言は必要ありません。引数を順番にリストするか、次のように引数に名前を付けることで、任意のプロシージャまたは関数を呼び出すことができます。

a := area(width => 2, height => 3);

最後に、ブーストライブラリには、C ++に機能を追加するためのハッキング層が含まれています。http//www.boost.org/doc/libs/release/libs/parameter/doc/html/index.html


5

私はその名前を見つけることができませんでしたが、同様のことを達成するためのデザインパターンがあり、関数呼び出しは説明したように変更された新しいオブジェクトを返します。例えば:

query = db.getTopCustomers(50).forYear(2010);

内部で管理できない複雑さを避けるためにデータは非常に直交している必要があるため、あまり頻繁には使用されませんが、適切な状況では役立つ場合があります。


6
これは、流interfaceなインターフェイスデザインスタイルと呼ばれます
ジェスパー

@Jesper、私が見るものはjQueryチェーンと非常に似ています。私は正しいですか?
サイードネアマティ

はい、@ Saeed、jQueryはこのスタイルを使用します。
カールビーレフェルト

5

Pythonにはキーワードパラメータがあります。関数定義の例

def getTopCustomers(count,year):
...

関数呼び出しの例

x = getTopCustomers(year=1990, count=50)

(私はこれが元の質問の精神ではないことを理解していますが、lispのキーワードパラメータが適格であれば、そうします。SmalltalkとObjective-Cでは、引数間のキーワードは実際には関数名/ルックアップの一部です)


私は個人的にはこの方が好きです。これは、パラメーターの順序がわかっている場合にパラメーター名なしで関数を呼び出すオプションを提供するためです
パブロメッシャー

4

Agdaにはmixfix表記があります

if_then_else x y z = case x of
                     True -> y
                     False -> z

 if cond then x else y

関数にアンダースコアを付けて名前を付けると、その間に引数を挟んで2つの部分に分割できます


4

プログラミング言語自体ではありませんが、Cucumberは関数名の途中でパラメーターを取ります。これにはスペースを含めることができ、英語のように見えます。

ただし、「関数」はRubyで定義されています

# definition
Given /^I calculate (.*) times (.*)$/ do |x, y|
    @result = x.to_i * y.to_i
end

Then /^the result should be (.*)$/ do |v|
    @result.should == v.to_i
end

# usage
Scenario:
    Given I calculate 6 times 9
    Then the result should be 42

4

TeXでは、基本的に呼び出しプロトコルが無料であることを意味する「引数パターン」を持つマクロを定義できます。あなたの特定の例については、使用することができます

\def\getTopCustomers#1OfTheYear#2;{%
  The #1 top customers of the year #2.
}
\getTopCustomers 50 OfTheYear 2010;

;レジスターでプレイすることに同意する場合は、削除することもできます。

\newcount\customers
\newcount\year
\def\getTopCustomers#1OfTheYear{%
  \customers#1\relax
  \afterassignment\reallyGetTopCustomersOfTheYear
  \year
}
\def\reallyGetTopCustomersOfTheYear{%
  The {\the\customers} top customers of the year {\the\year}.
}
\getTopCustomers 50 OfTheYear 2010

TeXを使用すると、レクサーを再構成できます。\afterassignment上記で使用したマクロのおかげで、ビルトインプロシージャを使用してlex番号を指定できます。非常に簡潔な呼び出しプロトコルを定義すると非常に便利です。たとえば、テーブルのマークダウン表記法を理解するTeXマクロを記述することは非常に妥当です。

「顧客がTeXから保存されているデータベースにどのようにアクセスしますか?」と尋ねますが、これは別の質問です。:)

Common lispでは、これqueryを書くことを可能にするマクロを定義することは間違いなく可能です

(query getTopCustomers 50 OfTheYear 2010)

ここで、getCustomersとOfTheYearはシンボルとして解釈されます。その場合、それを理解するのはマクロの仕事です。Common Lispは、コードの読みやすさの領域で優れています(そうです、そうです!)。マクロシステムにより、アプリケーション用に調整された擬似言語を簡単に作成できるためです。(アプリケーション言語と呼ばれると思います。)

PS:C ++を引用した人はいないようです。(プリプロセッサなしで)取得できる最も近いものは

query.getTopCustomers(50).OfTheYear(2010):

秘theは、を実装getTopCustomersするquery(またはその他の)参照を返すようにすることですOfTheYear。この例を小さなクエリ言語まで作成できますが、最終的なプロパティを特定する(値を返す)か、finaliseメソッドを追加する(ルックアップを実行して値を返す)必要があります。気になったら、STLのストリームコントローラーを模倣して、次のようなものを書くこともできます。

query << getTopCustomers(50) << OfTheYear(2010) << flush;

しかし、これは再びアプリケーション言語の方向に向かっています。

編集:Common LispとC ++(TeXではない!)も引用している@hanの回答を見落としました。


2

JavaScriptまたはクロージャーをサポートする他の言語では、次のような関数をカリー化できます。

function getTopCustomersFunc(count) {
    return function(year) {
       // run some query, return count customers from year
    }
}
var top20Func = getTopCustomersFunc(20);
var top20Customers2005 = top20Func(2005);
var top20Customers2008 = top20Func(2008);

1
これは興味深いので+1ですが、top20Funcの「20」はパラメーターではなく、パラメーターを思い出させる名前の一部であることに注意してください。同じように簡単に言うことができますvar top5Func = getTopCustomersFunc(37);。「5」はここでは誤解を招きますが、コードは変数に名前が付けられた場合とまったく同じように機能しますtop37Func
カレブ

1

これは「言語」の定義に依存しますが、ロボットフレームワークのテストフレームワークでは、この方法でキーワードを定義できます。埋め込み引数に関するドキュメントから:

Select ${animal} from list | Open page | pet selection
                            | Select item from list | animal_list | ${amimal}

上記は、「$ {animal}」がパラメーターである「select $ {animal} from list」という名前の新しいキーワード(基本的には関数)を宣言しています。「リストから猫を選択」のように呼び出します


これはSQLステートメントのように思えます。+1
サイードネアマティ

1

通知7。

To create (employee - a person) being paid (salary - a number):
    say "Welcome to your new job, [name of employee]!";
    choose a blank row from the table of employees;
    now the paid entry is the salary;
    now the name entry is the name of the employee.

等々。


3
これは、言語の構文がどのように機能するかを正確に説明していません。多くの人はInform言語に精通しておらず、パラメーターを呼び出しまたはコードの他の領域での使用と区別できません。

この言語には興味があります。未回答のコードサンプルだけで回答はかなり短くなりましたが、OPによって提供されたサンプルもそうでした(ただし、より従来の言語では)。Wikiには、それについて読むべき素晴らしい記事があります。
ヨーヨー

0

Common Lispのキーワードについては既に述べましたが、Common Lispのマクロもこれをかなり簡単に許可します。

(defmacro get-my-element (from list at index)
  `(nth ,index ,list))

これは次のように呼び出すことができます:

(get-my-element from '(a b c) at 1) ;returns B

もう一つ注意すべきは、しかし、用語ということであるfromとはat適用されません。そこに何かがなければなりません、それらを完全にスキップするとエラーになりますが、マクロはそれらを破棄するだけなので、それらが読みやすさを超えているかどうかは重要ではありません(重要です):

(get-my-element from '(a b c) 3 1) ;also returns B

-2

Clojureでは、このような状況でキーワード引数を使用するのが一般的です。例えば:

(get-customers :top 50 :year 2010)

キーワード引数はかなり柔軟で、オプションでデフォルトを指定することなどができます。


-4

Pythonでこれをエミュレートできます。例えば、

def GetTop(customers, ofYear):
  #write some code here to get the customers

print GetTop(customers=50 ofYear=2010)

あるいは

def GetTop(**args):
  #write some code here using the same parameter names as above

print GetTop({customers: 50, ofYear: 2010})

1
2番目の例の構文は間違っています。また、誰かがすでにこれを投稿しました。
ウィンストンイーバート

これは単にポイントがで行われた(そしてより良い説明)を繰り返す。この前の答え 3年前に投稿されました
ブヨ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.