【问题标题】:Why is printf() an impure function?为什么 printf() 是一个不纯的函数?
【发布时间】:2012-08-08 19:57:47
【问题描述】:

据我所知,不纯函数是指那些在使用相同参数调用时并不总是返回相同值的函数(我一定是遗漏了什么,或者可能是错误的,如果我错了,请纠正我)。

那么为什么printf() 被认为是一个不纯函数呢?

【问题讨论】:

    标签: c printf purely-functional


    【解决方案1】:

    “纯”函数也没有副作用

    换句话说,无论你调用多少次,一个纯函数只会影响任何东西,除了它的输出

    例如,foo 是不纯的即使它返回零

    int x;
    int foo() { x++; return 0; }
    int bar() { return x; }
    

    如果foo 是纯的,调用它不会影响bar() 的结果。

    printf 不纯,因为它的结果有“副作用”——具体来说,它会在屏幕上(或文件等)打印一些东西。
    如果它是纯的,那么你可以调用它十亿次,并确保不会发生任何不好的事情。
    但是,如果您真的调用printf 一百万次,那么对于用户来说肯定不同的- 它填满了他的屏幕(或磁盘空间,或其他)。很明显它不是纯的。

    此外:如果您的输出被重定向为您自己的输入(有点没用,但仍然如此),那么调用printf 会影响您从getchar 收到的内容。 :) 所以它也可以直接观察到。

    【讨论】:

    • 虽然正确,但这个答案与printf 无关。它也没有解决 WHY printf 不纯(外部 - 相对于内部 - 副作用)。
    • 所有函数都是不纯的。他们是时候执行(哲学)了!顺便说一句 - bar 返回 x
    • @Mehrdad:我查看了 wiki。它认为是不纯的。无论如何,谢谢你启发我。在您发帖之前,我肯定会将此 foo 视为 pure 函数。
    • @DavidTitarenco:我将问题从“Is printf () an impure”编辑为“为什么 printf...”。所以他基本上是在上下文中回答的:)
    【解决方案2】:

    成为纯函数有两个部分。首先,正如您所说,该函数必须始终为相同的输入参数返回相同的值。 printf 不满足的第二个标准是函数不能有 I/O 或对象突变等副作用。

    【讨论】:

    • printf 甚至不满足第一个条件:它返回成功打印的多个字符。
    • @Vladimir: 每当您提供相同的输入参数时,它总是会返回相同的值(即成功打印的字符数)。那么它是如何满足第一个条件的呢?
    • 返回值可能会有所不同,具体取决于 a) printf 的实现和 b) 写入过程中发生的错误。想象一下如果标准输出是关闭的。这是一个例子:pastebin.com/HAtCm2Jh
    • @Vladimir 好点,我忘记了 C/C++ 中的返回值。我花了太多时间编写 Java,其中 PrintStream.printf 的返回值是 this
    【解决方案3】:

    简单地说,printf 是不纯的,因为它确实是 I/OI/O 根据定义是不纯的,因为存在 I/O 设备的外部状态(状态可能因执行而异)。

    【讨论】:

      【解决方案4】:

      printf() 不纯,因为它会导致输出到 I/O 设备作为副作用.....

      【讨论】:

        【解决方案5】:

        纯函数在编程中的意义在于,如果它已经有了以相同参数调用该函数的结果,则该实现可以优化该纯函数的调用。显然,调用 printf 无法做到这一点。

        附:即使按照您的定义,printf 也是不纯的,因为它可以在成功时返回一个值,而在出现 I/O 错误(例如,输出设备上的空间不足)时返回另一个值。

        【讨论】:

          【解决方案6】:

          很多答案都说明printf 有I/O 作为副作用,但printf 也可能有其他副作用。例如,%n 说明符允许 printf 写入到指定地址(并且是一些安全漏洞的原因)。

          【讨论】:

            猜你喜欢
            • 2012-08-04
            • 1970-01-01
            • 2022-06-13
            • 1970-01-01
            • 2020-06-09
            • 2013-11-15
            • 1970-01-01
            • 2015-08-27
            • 1970-01-01
            相关资源
            最近更新 更多