web-dev-qa-db-ja.com

Dartで可変数の引数またはパラメーターを使用して関数を作成する

Dartで可変数の引数またはパラメーターを使用して関数を作成する方法を探しています。代わりに配列パラメーターを作成できることはわかっていますが、構文の簡潔さが重要なライブラリーで作業しているため、作成したくないと思います。

たとえば、プレーンJavaScriptでは、次のようなことができます( here から借用):

function superHeroes() {
  for (var i = 0; i < arguments.length; i++) {
    console.log("There's no stopping " + arguments[i]);
  }
}

superHeroes('UberMan', 'Exceptional Woman', 'The Hunk');

ただし、Dartでは、そのコードは実行されません。ダーツで同じことをする方法はありますか?そうでない場合、これはロードマップにあるものですか?

31
plowman

今のところそれはできません。

varargsが戻ってくるかどうかは本当にわかりません-数回前にありましたが 削除されました

ただし、varargs関数のエミュレート でエミュレートすることは可能です。以下のコードスニペットを参照してください。

typedef dynamic OnCall(List);

class VarargsFunction extends Function {
  OnCall _onCall;

  VarargsFunction(this._onCall);

  call() => _onCall([]);

  noSuchMethod(Invocation invocation) {
    final arguments = invocation.positionalArguments;
    return _onCall(arguments);
  }
}

main() {
  final superHeroes = new VarargsFunction((arguments) {
    for (final superHero in arguments) {
      print("There's no stopping ${superHero}");
    }
  });
  superHeroes('UberMan', 'Exceptional Woman', 'The Hunk');
}
21

Alexandre Ardhuinの答えを少し試してみたところ、現在のバージョンのDartでこの作業を行うためにいくつかの調整ができることがわかりました。

_class VarArgsClass {
  noSuchMethod(InvocationMirror invocation) {
    if (invocation.memberName == 'superheroes') {
      this.superheroes(invocation.positionalArguments);
    }
  }

  void superheroes(List<String> heroNames) {
    for (final superHero in heroNames) {
      print("There's no stopping ${superHero}!");
    }
  }
}

main() {
  new VarArgsClass().superheroes('UberMan', 'Exceptional Woman', 'The Hunk');
}
_

これには、次のような多くの問題があります。

  • 署名がパラメータと一致しないため、superheroes()を呼び出すと警告が生成されます。
  • スーパーヒーローに渡される引数のリストが実際に_List<String>_であることを確認するには、さらに手動でチェックする必要があります。
  • noSuchMethod()でメンバー名を確認する必要があると、メソッド名を変更した場合に「スーパーヒーロー」文字列を変更するのを忘れる可能性が高くなります。
  • リフレクションにより、コードパスの追跡が困難になります。

しかし、これらすべての問題に問題がなければ、これで作業は完了です。

5
plowman

構文の簡潔さに本当に興味がある場合は、たとえば10個のオプションの位置パラメーターを使用して関数/メソッドを宣言するだけです。誰かが10以上の引数でそれを呼び出すことはありそうにありません。

それがハックのように聞こえる場合、それはそれがisハックだからです。しかし、私はダートチームが同じことをしているのを見ました:-)

3
Ladicek

あなたが書いた例では、リストを使用するのが最善だと思います。すみません!

Dartbug.comを見ていますが、これに対する機能リクエストが表示されません。あなたは間違いなくそれを作成することを歓迎します!

2

このバージョン:

  1. 位置引数とキーワード引数の両方で機能します。
  2. 戻り値の入力をサポートします。
  3. 現代のダートで動作します。
typedef T VarArgsCallback<T>(List<dynamic> args, Map<String, dynamic> kwargs);

class VarArgsFunction<T> {
  final VarArgsCallback<T> callback;
  static var _offset = 'Symbol("'.length;

  VarArgsFunction(this.callback);

  T call() => callback([], {});

  @override
  dynamic noSuchMethod(Invocation inv) {
    return callback(
      inv.positionalArguments,
      inv.namedArguments.map(
        (_k, v) {
          var k = _k.toString();
          return MapEntry(k.substring(_offset, k.length - 2), v);
        },
      ),
    );
  }
}

main() {
    dynamic myFunc = VarArgsFunction((args, kwargs) {
      print('Got args: $args, kwargs: $kwargs');
    });
    myFunc(1, 2, x: true, y: false); // Got args: [1, 2], kwargs: {x: true, y: false}
}

ありがとう、アレクサンドル answer

0
Dev Aggarwal