我怎样才能在这个函数中保持数学顺序?

Posted

技术标签:

【中文标题】我怎样才能在这个函数中保持数学顺序?【英文标题】:How can I keep the mathematical order in this function? 【发布时间】:2022-01-05 21:00:39 【问题描述】:

我有这个函数返回错误的结果

def calc(a): return lambda op: 
    '+': lambda b: calc(a+b),
    '-': lambda b: calc(a-b),
    '*': lambda b: calc(a*b),
    '/': lambda b: calc(a/b),
    '=': a[op]

calc(1)('+')(2)('*')(10)('=') # 30 -> should be 21

有谁知道如何保持函数式风格并遵循正确的数学顺序?

【问题讨论】:

如果你正在寻找柯里化,Haskell 基本上是围绕这个概念构建的,而 Python 则完全没有。您可能可以自己实现它,但它不值得痛苦,IMO add(1, mul(2, 10))。不要试图在你的表达式中镜像中缀符号。 (addmul 是在 operator 模块中预定义的,以及其他运算符的函数。) Python 不是函数式语言。您可以使用lambda 函数和mapreduce 编写一些功能性代码,但仅此而已。如果您想要一种纯函数式的方法,那么您正在寻找 Haskell。我认为还有其他纯函数式语言,但 Python 不是其中之一。同样,您可以在 Python 中模拟函数式样式,但这就像用叉子吃汤一样 - 不是非常有效或富有成效。 @KellyBundy,我不确定柯里化是否与运算符优先级有很大关系。 AFAIK,运算符优先级是在解析期间完成的,但currying是在运行时完成的。如果您以正确的顺序调用柯里化函数,您将获得正确的运算符优先级。 因为a 也可以是一个子表达式,你可以简单地写成calc(1)('+')(calc(2)('*')(10)('='))('=')。否则,您需要为每个运算符分配优先级并累积传递给calc 的所有运算符(在评估之前),以按优先级确定的顺序排列它们。此外,您还必须将括号作为复合运算符引入。对于一个有趣的项目来说,这可能是太多工作了.. 【参考方案1】:

请注意,我对 Python 缺乏深入的了解,因此答案将在 JS 中。希望它仍然有帮助。

一个合适的解决方案需要涵盖以下属性:

运算符优先级 运算符关联性(左/右/无) 运算符数量(一元/二元) 圆括号

运算符关联性不得与数学属性相混淆。运算符必须是左、右或根本不关联。后者意味着操作符是不可组合的。

优先级决定了不同运算符的计算顺序,如果相同则关联。

a + b - c = a + (b - c) :: - exceeds precedence of +
a - b - c = (a - b) - c :: - is left associative

这个解决方案只是一个粗略的草图。它不使用字符串符号作为运算符,但可以轻松更改。更重要的是,它既不考虑运算符结合性也不考虑括号,而是始终假定左结合性和二元运算符。这只是开始了解预期的复杂性:

const prec = n => o => (o.prec = n, o);

const prec1 = prec(1);
const prec2 = prec(2);
const prec3 = prec(3);
const prec4 = prec(4);

const add = prec1(x => prec1(y => x + y));
const sub = prec2(x => prec2(y => x - y));
const mul = prec3(x => prec3(y => x * y));
const div = prec4(x => prec4(y => x / y));

const infix = x => f => infix_(f(x));

const infix_ = partialF => y => 
  const go = g => 
    if (partialF.prec >= g.prec)
      return infix_(g(partialF(y)));

    else 
      const partialG = g(y);
      return infix_(z => partialF(partialG(z)));
    
  ;

  Object.defineProperty(
  go,
  "run",
  get() return partialF(y)); // lazy property getter
  
  return go;
;

const r1 = infix(2) (mul) (3) (sub) (4) (add) (5) (div) (2); // 2*3-4+5/2 = 4.5
const r2 = infix(2) (add) (3) (sub) (4) (mul) (5) (div) (2); // 2+3-4*5/2 = -5

console.log(r1.run);
console.log(r2.run);

【讨论】:

以上是关于我怎样才能在这个函数中保持数学顺序?的主要内容,如果未能解决你的问题,请参考以下文章

按顺序连锁不同的功能[关闭]

我怎样才能顺序淡入几个div?

轮询:页面被刷新,任何指定的过滤器/排序顺序也被重置。我怎样才能防止这种情况发生?

浅谈顺序存储结构

硬盘逻辑分区应该怎么排序,物理顺序是啥,怎样让C盘保持在最佳顺序上

excel表格中的数字有一位数、两位数、三位数,可是排序只按第一位数排,怎样才能按1到10000的自然顺序排呢