【问题标题】:is it possible to add some new syntax in javascript?是否可以在 javascript 中添加一些新语法?
【发布时间】:2013-12-30 00:19:06
【问题描述】:

是否可以在 javascript 中添加一些新语法?就像我希望它有一个类似的语法:

mul>10>20 结果为 200 或者如果说 mul(2)(3) 结果为 6 ?有可能的?我在某处看到类似的问题来做到这一点?所以我不确定这是否可能?如果不是在 JS 中,是否可以在 C、Java、Python 等其他语言中使用?我的理解是,所有这些语言都只能为新对象添加一些功能,甚至那些新对象也只能具有语言本身已经具有的运算符和语法?那么我是正确的还是可以为这些语言添加新语法?

【问题讨论】:

  • 你可以在本地做第二个(currying),而不是第一个,除非你做一些不必要的eval解析。
  • 如果你试图以某种方式解析它,它看起来会很丑。但是检查一下 Coffeescript 或其他使 JavaScript 具有新语法的语言。你可以分叉和扩展。
  • 我相信你可以用 Lisp 宏来做到这一点... :-)
  • 看看一本好的 lisp 书。我想你会喜欢你所看到的。

标签: javascript python operator-overloading


【解决方案1】:

您更广泛的问题的答案是将写入您正在使用的语言,这意味着旨在使用您可用的工具解决您的问题。

但是,您给出的第二个示例实际上已经是一种相当常见的模式,称为 currying。您可以通过以下方式扩展 Javascript 来实现此目的:

Function.prototype.curry = function() {
    var fn = this, args = Array.prototype.slice.call(arguments);
    return function() {
      return fn.apply(this, args.concat(
        Array.prototype.slice.call(arguments)));
    };
  };

所以假设mul(a, b) 是:

function mul(a, b) {
    return a * b;
}

你可以使用mul.curry(2)(3)

这是Fiddle

有关此设计模式的更深入解释,请查看http://ejohn.org/blog/partial-functions-in-javascript/

【讨论】:

  • 不好意思挑剔,但偏应用!=咖喱。
  • 如果有人想看看 Array.prototype.slice.call() 是如何工作的,那么可以在stackoverflow.com/questions/7056925/…看到它
  • 但它怎么能独立于参数范围呢?意味着我不知道是mul(2)(3)还是mul(2)(3)(1)(9)
【解决方案2】:

在 Python 中

mul(2)(3)

表示使用参数2调用mul,然后使用参数3调用return(假设它是一个函数)。您无法重新定义该语法,但可以让您的函数使用它:

def mul(arg):
    return lambda x: x * arg

为了允许链接(即mul (2)(3)(4)),我会选择class

import operator

class op(object):

    def __init__(self, op, arg):
        self.op = op
        self.value = self._get_val(arg)

    def _get_val(self, arg):
        try:
            return arg.value
        except AttributeError:
            return arg

    def __repr__(self):
        return str(self.value)

    def __call__(self, arg):
        self.value = self.op(self.value, 
                             self._get_val(arg))
        return self

    def __getitem__(self, key):
        self.value = self.op(self.value, 
                             -1 * self._get_val(key))
        return self


class mul(op):

    def __init__(self, arg):
        super(mul, self).__init__(operator.mul, arg)

我添加了一个额外功能,方括号使参数变为负数 (mul(2)[3] == -6)。这只是假装return 一个数字;我将实现其余必要的magic methods 作为练习留给读者。

除了返回x > yTrueFalse)之外,您不能让mul>x>y 执行任何操作,因为函数对象mul 的计算结果将大于任何整数。

【讨论】:

  • 如果我希望这些参数是递归的而不仅仅是两个呢?
  • 好问题;答案已编辑。请注意,这一切都意味着您需要做更多的工作和更难阅读的代码!
  • 它说 super() 至少接受一个参数 0 给定
  • 我的代码是针对 Python 3.x 的,你可能需要为 2.x 做一些调整
  • 对于 2.x(mul.__init__())只需要一项更改,我现在已经完成了
【解决方案3】:

Currying 将允许您这样做:

function mul(num1) {
  return function (num2) {
    return num1 * num2;
  }
}

mul(2)(3); // 6

多参数版本(需要用空括号指定参数的结尾):

function mul (num1) {
  var vals = [num1];
  var fn = function (num2) {
    if (num2) {
      vals.push(num2);
      return fn;
    }else{
      var res = 1;
      vals.forEach(function (el) {
        res *= el;
      });
      return res;
    }
  }

  return fn;
}

console.log(mul(2)(3)(4)()); // 24

【讨论】:

  • 我已经这样做了,但它永远不会知道它何时是最后一个参数,所以永远不能做任何最后需要的事情。 :)
  • 你的意思是你想要超过 2 个参数?如果是这样,我进行了编辑以展示您如何做到这一点。
猜你喜欢
  • 2016-05-24
  • 1970-01-01
  • 2021-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-06
  • 1970-01-01
相关资源
最近更新 更多