4

perl次のように、 のクロージャーがどのように機能するかを問題なく理解しています

use 5.012;
use strict;
use warnings;

sub countdown {
        my $start = shift;
        return sub { $start-- }
}

my $c10 = countdown(3);
say while( $_ = $c10->() );

私はJavascriptの次の部分を理解しようとしています:

var runInSandbox = (function(js, inputPath) {

  (function() {
    if ((!context.initialized__QUERY)) {
      return createContext();
    };
  })();
  (function() {
    if (typeof(inputPath) !== 'undefined') {
      (process.argv)[1] = inputPath;;
      (context)["__dirname"] = path.dirname(inputPath);;
      return (module)["filename"] = inputPath;;
    };
  })();
  return vm.runInContext(js, context, "sibilant");
});

NO CHANCE! :( PLEASE can someone rewrite the above to perl ? I know perl a bit - so for me will be extremely useful to understanding JS basics and the constructions like:

(...)() - more precisely
(function(){.....})()

double (( in the if

    if ((!context.initialized__QUERY)) {

or the next

      (context)["__dirname"] = something ;;

or

       return (module)["filename"] = inputPath;; // why double ;;?

And if someone coul'd suggest me any resource something like: Learning Javascript for perl programmers - would be very nice ;)

Ps: the JS (shortened) is from here: https://github.com/jbr/sibilant/blob/master/lib/cli.js

4

2 に答える 2

7

私は Perl のクロージャにあまり詳しくないので、少なくともこれを分かりやすく説明しようと思います。

フォーム:

(function(...) {
 ...
})();

自己呼び出しの無名関数です1。これは、無名関数を書き出して、すぐに呼び出すことを意味します。これは通常、カプセル化のために行われます2。たとえば、一連の変数を作成することになったが、グローバル名前空間を汚染したくない場合は、匿名の自己呼び出し関数内に配置できます。ただし、この場合、最初の呼び出しが必要な理由はまったくわかりません。これは単にフラグか何かをチェックしているだけだからです。さらに奇妙なのは、returnこれらの自己呼び出し関数の内部です。彼らは何にも割り当てられていません。私は変数をcreateContext()初期化する推測を危険にさらしますが、それは事実上役に立たない. 以下についても同様です。contextreturn

return (module)["filename"] = inputPath;;

((doubleとに関する限り))、それらはほとんど不要であるように思われるため、著者が最初にそれを入れた理由はわかりません。例えば:

if ((!context.initialized__QUERY)) 

と違いはありません:

if (!context.initialized__QUERY) 

また、次の括弧も不要です。二重のセミコロンも同様です。

(context)["__dirname"] = something ;;

正直なところ、それは単に不十分に書かれた Javascript か、自動生成された JavaScript のように見えます (ほとんどの場合そうです)。

次のように書き換えることができます。

var runInSandbox = function(js, inputPath) {

    if (!context.initialized__QUERY) {
       createContext();
    };

    if (typeof inputPath !== 'undefined') {
       process.argv[1] = inputPath;
       context["__dirname"] = path.dirname(inputPath);
       module["filename"] = inputPath;
    };

    return vm.runInContext(js, context, "sibilant");
};

ノート:

  1. Perl では、sub { ... }->().
  2. Perl では、{ my $var; ... }の代わりにsub { my $var; ... }->()anddo { my $var; ...; EXPR }の代わりに使用しsub { my $var; ...; return EXPR; }->()ます。
于 2013-05-09T22:43:47.570 に答える
0

これは、perl でどのように見えるべきかだと思います。

my $runInSandbox = sub {
     local($js, $inputPath) = ($_[0], $_[1]);
     sub{if (!$context.initialized_QUERY) {
         &createContext();
     }}->();
     sub{ if (defined($inputPath) {
         $process{"argv"][1] = inputPath;
         $context{"__dirname"} = &$path{"dirname"}(inputPath);
         $module["filename"] = inputPath;
     } }->();
     return &$vm{"runInContext"}($js,$context,"sibilant");
};
于 2013-05-09T23:21:20.690 に答える