この事実は、トレーニングコースの変更に反映されています。 最も有名なプログラミングコースであるSICPの著者であるSassmanは次のように述べています。「 90年代半ば、さらに2000年代のエンジニアリングは、80年代のエンジニアリングとは大きく異なります。80年代、優秀なプログラマはコードはハードウェアの近くで機能し、Schemeでも機能しました-すべての段階ですべてが透明でした。抵抗器と同様に、色のマーキングを見て、定格電力、許容偏差、抵抗、V =を見つけます。 IRは、あなたが知っている必要があるすべてです6.001は シンプルなテクニックを使用して、完全に理解している小さな立方体から必要なことを行う複雑な構造を作成する方法についてエンジニアを教育するコースに進みますが、プログラミングは今までとはまったく異なります。ソフトウェアのドキュメント、誰がそれを書いたかさえも知らないので、ライブラリを徹底的に調査して、それらがどのように機能するかを調べ、異なるソースデータを試し、コードがどのように反応するかを確認する必要があります これは完全に異なる仕事であり、異なる学習コースが必要です。 」
建築用レンガは標準化されています-通常、レンガ職人はこの場所に適したレンガを選択する必要はありません。 ライブラリでは、逆のことが言えます。PDF処理を意図したものは、分散コンピューティングシステムの作成には適していません。 適切なライブラリとその中の適切な機能を見つけ、それをプログラムに統合する方法を理解する必要があります。 Googleは、他の自然言語検索エンジンと同様に、これまで少し役立ちました。 したがって、他のアプローチを検討してください。
静的に型付けされた関数の機能では、型によって推測できます。 そしてその逆-関数が何をすべきかを知って、そのタイプ(署名)を想定します。 たとえば、リストからアイテムを抽出する関数は、次の型である必要があります
[a] -> a
-ここで、「a」は現在未定義の要素タイプであり、「[a]」は「a」タイプの要素のリストタイプです。 タイプ別の検索エンジンは(一部の言語では)開発者の生活を大幅に簡素化します-これらはOCamlのocamlfind、HaskellのHoogleとHayoo、ScalaのScalexです。
動的に型付けされた言語の場合、コンパイラーによって無視されたとしても、各関数に型が割り当てられていれば、このアプローチは機能します。 時々これは自動的に行うことができます-現代のシステムはしばしばコードから型を推測できますが(これは静的に型付けされた関数型言語の多くのコンパイラが行うことです)、継承を持つ言語ではそれを実装するのが難しいです) 実際のプログラムでの関数の使用に関する統計を収集できます-これは正しく記述された一般化された型を保証するものではありませんが、検索と文書化には役立ちます(ライブラリが使用される前に誰もが文書を書くわけではありません-なぜあなたの人生を単純化しないのですか: -))。
アロン・カイ(Smalltalkの著者)の仲間であるテッド・ケーラーは、より急進的な検索技術を提供しています 。 その1つは、この関数のテストを作成し、既存のすべての関数で実行することです。 怖いように聞こえますが、個人的には、Javaライブラリからメソッドを探し、Scala REPLから名前で適切と思われるすべてを呼び出す必要がありました。 また、自動化できるものはすべて自動化する必要があります。 :-)。
2番目の手法は、すべてのライブラリ関数に可能な限り多様な注釈を付け、注釈で検索することです。 注釈は、この動物園の管理を可能にする関数およびライブラリの分類法を構築するために使用されます(「分類法」という用語は、生物学者によって非常によく造られました)。
分類学/存在論的アプローチは、Rプログラマーにさらに深く入りました( 記事 、 プレゼンテーション )。 これは驚くべきことではありません-オントロジーと同じ場所で、Rは大規模で複雑な構造化データの分析によく使用されます。
オントロジーが概念化の正確な仕様であることは誰もが知っています。 しかし、仕様と概念化とは何なのかはあまりわかりません。 私は彼らの一人ではないので、私がそれをどのように理解しているかを説明しようとします。
オントロジーは多かれ少なかれ正式に主題領域を記述します-その中にどんなオブジェクトがあり、どのような関係がそれらの間に存在します。 オントロジーには多くの言語がありますが、W3C RDF標準(より複雑なOWLの場合)が最も広く使用されています。
RDFでは、すべてが「トリプル」subject-predicate-objectによって定義されます。 F1.R is_a RFunction。 「F1.R」はR関数です。 W3Cはトリプルを記述するためにXMLを課そうとしましたが、やがてその考え方を変え、 人間の構文を開発しました。
RDFはしばしばグラフと呼ばれ、それを処理できるデータベースはグラフとして分類されます。 そのようなデータベースと通信するための主な言語は、SQLとPrologのかなり成功したハイブリッドであるSPARQLです。 典型的なクエリは、検索したいグラフのフラグメントのテンプレートとしてそれらを自分自身で表します。 この形式では、非常にエキゾチックな条件を定式化することは難しくありません。たとえば、「GPLv3で利用可能なライブラリから関数を見つけ、その結果をcreatePDFと呼ばれる関数の入力に渡すことができます」。 これは、記事の冒頭で説明したタイプテンプレートによる検索よりもやや複雑ですが、はるかに柔軟です。
型の記述が不十分な関数の引数に関するより詳細な情報を保存できます。 たとえば、org.w3.banana.SparqlEngineクラスのexecuteSelectメソッドに最初の引数であるSPARQL選択クエリ文字列があるとします。 このような注釈なしで文字列引数を受け取るすべての関数からこのような関数を見つけることは簡単ではありません。 検索エンジンに加えて、この情報はコード検証(Cのlintのアナログ)およびIDEで構文の強調表示に使用できます。
時には彼らはそのような情報をタイプに入れることができますが、検索にはあまり役立ちませんが。 これがOCaml(コンパイラレベル)で行われる方法です。
#(fun a-> Printf.sprintf a 1; a) "%d" ;; -:(int->文字列、ユニット、文字列)format = <abstr>全体を文字列テンプレートに代入する機能を見つけるために、誰もタイプの関数を探すことはないことは明らかです
(int -> string, unit, string) format -> int -> string
最高の世界では、あるプログラミング言語のライブラリを他のプログラミング言語から比較的簡単に呼び出すことができます。 現実にはそうではありませんが、夢を見ることができます。
現代の言語は非常に異なっており、一方の用語は他方の用語に簡単な方法でマッピングできます。 たとえば、一部の言語には「タイプのクラス」という概念があります。これは、共通のインターフェースが存在するタイプのセットです(OOPインターフェースとは異なり、これらのインターフェースはタイプの一部ではなく、別々に存在します)。 たとえば、関数
max :: Ord a => a -> a -> a
同じ型aの 2つのパラメーターを待機すると、同じ型の結果が返され、この型はOrdクラス(比較可能なもの)に属している必要があります。 つまり、2つの整数で呼び出して全体を取得するか、2つの実数で呼び出して実数を取得できます。 しかし、全体と現実で-それは不可能です。
型クラスは非常に便利に使用でき(検索時にも便利です)、型クラスがない言語では、それらをエミュレートする方法を考え出しました。
これらは通常、特定の型のインターフェイスの実装を含む暗黙的なパラメーターを渡すことで実装されます。 ScalaやC ++などの複雑なデフォルトでパラメーターを記述することができる言語では、これは比較的簡単です。 確かに、Haskellでは暗黙的な引数が最初に渡され(最適化のため)、ScalaおよびC ++では最後に(言語デバイスのため)渡され、言語間検索エンジンはこれを考慮する必要があります。
APIは、メソッドと関数のシグネチャだけでなく、それらの呼び出しのシーケンス(ネットワークプロトコルとほぼ同じ)も記述することができます。 上記の記事では、このためにcouldBeUsedBefore述語が導入されています。 これは、言語がErlangプロセスやScalaアクターなどの多かれ少なかれ独立したエンティティを許可する場合に特に当てはまります。 Erlangはオプションの関数の型指定を許可し、Scalaは静的に型指定されますが、プロセス/アクターにメッセージデバイスを正式に記述しません。
彼らが言うように、各ライブラリではDSLは外に座って尋ねます。 Smalltalkでサインを見つける方法を多かれ少なかれ理解している場合、Common Lispでループを見つける方法は完全に理解できません。