web-dev-qa-db-ja.com

静的型付けと動的型付けの両方をサポートするプログラミング言語はありますか?

静的または動的であることは、言語で完全にサポートされるものでなければなりません。静的と動的は、基本的に2つの言語を切り替えて、オンとオフを切り替える必要があるものではありません。

私はこのような本格的な混合型タイピングの狂気を話している:

class MyClass {
  function myMethod(x: int, y: int){        # one parameter is typed, the other not
    return <cast_to_int> y.return_integer(x); #casting to guarantee the contract
  }    
}

MyClass static_obj = MyClass();  #statically typed instantiation;
var dynamic_obj = {};   #dynamically typed instantiation
dynamic_obj.return_integer = (function (x) {return x*2}) #dynamic method creation

static_obj.myMethod(3, dynamic_obj)     # This returns 6

dynamic_obj.return_integer = (function (x) {return x+1}); # dynamic member reassignment

static_obj.myMythod(3, dynamic_obj)   # this returns 4


static_obj.myMethod('asdf', dynamic_obj) # This can't compile, because of typing

# and also this crazy thing; Notice that the static interface of the method is respected
if (<user input> == 2){
    static_obj.myMethod = (function (x: int, y){return x + y.yet_some_other_method(x);})
}

# but when the static contract is not respected, it doesn't compile
static_obj.myMethod = (function (a, b, c) {return 'asdf'}) # Compile time error

このトピックに興味があるのは、静的言語でのAPIの発見可能性が素晴らしい(Java、C#、およびABAPについてしばらく好きだった)ので本当に気に入っていますが、実行時のテスト、サルのパッチ、REPL、再割り当ても好きです。 、そしてクレイジーなリフレクションマジック(JavaScriptとPythonについて私が気に入った)。

私はDartの静的型チェッカーを知っていますが、実際の静的な保証を提供しないため、それだけでは十分ではありません。

また、型推論には興味がありません。真の動的動作の次に真の静的実行が必要です。私はまた、Pythonのdict、JSオブジェクト、またはJavaのHashMapなどのマッピングタイプを使用してデータ(または関数)を渡すことができることも知っていますが、Javaのマッピングはそれらにメソッドを運ぶことができません。 dictsには(すぐに)メソッドを含めることはできません。JSはあらゆる種類の静的な制限を単純に笑っていますが、thisキーワードを介してコンテキストオブジェクトにアクセスできるメソッドを実行時に追加すると、本当にクールなもの(Pythonは、クラスインスタンスにではなく、クラスオブジェクトに関数を追加するときにも実行します)を知っています)。

私の好奇心はこの論文によっても引き起こされました: 可能な場合は静的型付け、必要な場合は動的型付け

そして、APIの発見可能性の議論は私自身の経験から来ましたが、このペーパーはそれをサポートしているようです: http://personales.dcc.uchile.cl/~rrobbes/p/ICPC2014-idetypes.pdf

16
vlad-ardelean

はい。 4.0以降のC#は、dynamicキーワードを使用した最も一般的な例です。私が忘れている、または知らない他の良い例がおそらくあります。

30
Telastyn

この良い例が Dylan です。あなたはディランで静的および動的タイピングを使用することができます、例えば、

define method double(a :: <integer>) => (result :: <integer>)
    2 * a
end

または

define method double(a) => (result)
    2 * a
end

これは変数などにも適用されます。別のより穏やかな例はREBOLですが、その関数定義のみで、たとえば、

double: func [a [integer!]] [a * 2]
double: func [a] [a * 2]

関数パラメーターは、R​​EBOL内で唯一、あらゆる種類の型チェック(または、宣言)が許可されています。

9
Gregory Higley

クラシックVisual BasicとVBAは、この機能を最初から備えています。

VB.NETには、リリース(1.0)からもこの機能があり、プロジェクトプロパティのコードファイルまたはプロジェクト全体でOption Strict Onステートメントを使用して「スイッチを切る」オプションがありました。これは実際にはオフに切り替えないため、これがオンの場合、遅延バインディングステートメントをコンパイルしません。

C#は最終的にバージョン4.0の後半に追いつきましたが、動的キーワードを使用して「許可」する必要があるという違いがあります。

3
Matt Wilko

JavaはこれをObjectクラスで持っています。

int myMethod(int x, Object y) {
  return x > 0 ? x : (int)y;
}

void go() {
  Object obj;
  if(Math.random() > 0.5)
    obj = 3;
  else
    obj = "hello";
  myMethod(-5, obj); // throws ClassCastException if obj is a String
}

Java 8では、ラムダ関数が導入されているため、関数をマップ内に配置できますが、少し扱いに​​くいです。

Map myObj = new HashMap();
myObj.put("add",
          (BiFunction) (Object x, Object y) -> ((Number) x).intValue() + ((Number) y).intValue());
BiFunction addition = (BiFunction) myObj.get("add");
int apply = (int) (Number) addition.apply(3, 2.2);
0
Ypnypn