V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
pythonee
V2EX  ›  程序员

怎么理解函数式编程中的"变量也是函数"

  •  
  •   pythonee · 2014-04-15 14:09:36 +08:00 · 6745 次点击
    这是一个创建于 3657 天前的主题,其中的信息可能已经有所发展或是发生改变。
    在大多数函数式编程语言中,大多数都强调一切都是函数,函数式一等公民。
    那么 "变量" 也是 "函数"

    var foo = "hello world"

    那么"foo"这个变量也是一个函数?

    是不是可以说等价于下面的函数写法

    def foo() = { "hello world" }

    即变量名是方法名,变量值是返回值。
    那么这样说的话,函数式和命令式的本质区别是什么呢?只是表示形式上的区别吗
    40 条回复    2017-07-25 10:08:07 +08:00
    min
        1
    min  
       2014-04-15 14:22:21 +08:00
    函数==变量说明函数的参数和返回值也可以是函数,这点很重要
    zzNucker
        2
    zzNucker  
       2014-04-15 14:26:23 +08:00
    说法有问题吧,不是“变量也是函数”。
    是“函数”可以赋给变量。

    延伸出去就是函数可以作为返回值,可以作为参数,可以作为XXXXX。
    otakustay
        3
    otakustay  
       2014-04-15 14:27:32 +08:00
    应该是“变量可以是函数”吧?
    walleL
        4
    walleL  
       2014-04-15 14:33:21 +08:00
    walleL
        5
    walleL  
       2014-04-15 14:34:11 +08:00
    楼上各位真快 。。。
    jsonline
        6
    jsonline  
       2014-04-15 14:36:29 +08:00 via Android
    没听说过这句话
    ibudao
        7
    ibudao  
       2014-04-15 14:37:28 +08:00
    有点意思,不过我觉得本质是:数据即代码,代码即数据。所谓代码,就是可以被执行的,或者说加上了可eval的标记,但其实也是一种数据。
    变量实际上是一种标识符,函数名也是一种标识符,而标识符通常被解析为一个内存地址,这个内存地址可以存放数据,也可以存放代码。
    命令式语言中,通常变量类型的标识符存放的是数据;而函数式语言则都可存放。
    NemoAlex
        8
    NemoAlex  
       2014-04-15 14:37:58 +08:00
    听说过一切都是对象,没听说一切都是函数...
    求出处,需要研读一下
    ibudao
        9
    ibudao  
       2014-04-15 14:40:25 +08:00
    @NemoAlex 一切都是0和1...
    NovemberEleven
        10
    NovemberEleven  
       2014-04-15 14:51:40 +08:00
    就像数学,y可以是一个函数,也可以是一个数字。
    zhy0216
        11
    zhy0216  
       2014-04-15 15:13:45 +08:00
    常量函数
    pengyang
        12
    pengyang  
       2014-04-15 15:16:48 +08:00 via Android
    学习了,谢谢
    pythonee
        13
    pythonee  
    OP
       2014-04-15 15:29:05 +08:00
    @NemoAlex 出处找不到了,记得是看haskell还是lisp提到的
    standin000
        14
    standin000  
       2014-04-15 15:44:31 +08:00
    是数据也是函数。在其它语言里,数据和函数是区分的。

    最直观的就是代码本身在LISP中也是可以eval的。
    Kabie
        15
    Kabie  
       2014-04-15 16:22:02 +08:00
    ...给成员变量设getter和setter倒是面向对象语言经常提的吧。。。
    dun2
        16
    dun2  
       2014-04-15 16:22:23 +08:00
    > 那么这样说的话,函数式和命令式的本质区别是什么呢?只是表示形式上的区别吗

    严格的函数式编程强调不使用mutable的变量。
    即变量一旦赋值以后就无法更改。

    这样就不存在状态的争抢,利于实现并发和分布式的场景了。
    plprapper
        17
    plprapper  
       2014-04-15 16:32:15 +08:00
    fordo(){
    commond=$1
    for i in `seq 100`
    do
    $commond
    sleep 1s
    done
    }

    。。。
    flypiggy
        18
    flypiggy  
       2014-04-15 17:34:41 +08:00
    函数式编程就没有变量....
    pythonee
        19
    pythonee  
    OP
       2014-04-15 17:41:43 +08:00
    @flypiggy 是的,我也就是这个意思,变量不过是表现的像个变量,其实是个无参函数。但是这句话没有说清我那个疑问啊
    simpx
        20
    simpx  
       2014-04-15 18:15:05 +08:00   ❤️ 2
    [OT]
    少年,过去我也像你这样,被一些优雅的概念吸引,尤其是“万物皆函数”、“数据即代码”这一类的大一统的概念。
    但后来我刨根问底后发现,这些优雅的概念仅仅是复杂现实的一个理想性封装,比如拥有这些“特性”的语言,底层实现也是非常dirty的,真正的优雅,只能存在数学里。
    这些人造概念的坏处,被你说中了,有些就是”形式上的区别“,它底层逃不开笨拙的机器
    所以,不用纠结于这些人造的概念,要么多看算法,要么,多写代码。
    pythonee
        21
    pythonee  
    OP
       2014-04-15 18:29:48 +08:00
    @simpx 嗯,不纠结,只是闲来给自己点思考的东西。不过还是谢谢这位同样"过来的少年",继续写代码去,另外发现scala这货挺适合拿来玩的
    otbzi
        22
    otbzi  
       2014-04-15 18:30:12 +08:00   ❤️ 1
    @simpx

    如果你认为java中的lambda这种feature的就是你眼中的函数式语言的话,那的确可以说得上是「非常dirty」的了。

    如果你看过Paul Graham写的 the root of lisp: http://www.paulgraham.com/rootsoflisp.html

    就会知道,lisp语言是如何在几个非常少的special form之上构造出一门语言的。

    在lisp中,的确是如上文某位同学所说的,「函数式语言是没有变量的」。

    在这个时候,如果你还要说,「计算机都是应用科学,数学才是最叼!」。如果你抱着这种想法,这个世界上我们做了这么多工作,就是为了通过思考抽象出一些概念和工具用来解决问题。你非要每个point都还「刨根问底」,把数学跟工程学科排序一下,得出一个谁谁誰是「笨拙」的结论。那真的就无解了。

    前人做了那么多工作。就是让我们做的事情一步一步更加抽象。解决越来越多的问题。「一句数学最叼」,你对人类做出了什么贡献了么?这么粗暴的下结论,就明显给人智力上的懒惰的感觉。
    hhkbp2
        23
    hhkbp2  
       2014-04-15 19:12:15 +08:00
    "变量也是函数"?
    出处在哪?
    jiyinyiyong
        24
    jiyinyiyong  
       2014-04-15 19:23:32 +08:00
    大多数函数式编程语言 - - - - 错, 这是函数式语言的关键, 不是大多数, 是所有
    一切都是函数 - - - - 错!
    函数式一等公民 - - - - "式" 改成 "是" 的话是对的
    那么 "变量" 也是 "函数" - - - - 错!

    一般说区分函数式编程看到是一个函数 a, a 能不能像一般的变量一样随意传递
    纯函数语言里, 比如 Haskell, String, Char, Number, Bool 都是很明确的.
    pythonee
        25
    pythonee  
    OP
       2014-04-15 19:48:57 +08:00
    @hhkbp2 我想起应该可以用丘奇运算(或者叫lambda运算?)来表示出处吧,在丘奇的体系中,0和1也是函数,而不是变量。
    pythonee
        26
    pythonee  
    OP
       2014-04-15 19:50:53 +08:00
    @jiyinyiyong 之所以说大多数,是因为我不敢确定其他的语言是什么情况。"式"的确打错了,应该是"是"。如果函数式的重点是,函数像值一样传递的,那么内涵是不是太少了点
    hhkbp2
        27
    hhkbp2  
       2014-04-15 20:25:31 +08:00
    @pythonee 数学定义和计算机编程语言还是有比较多区别的,不能因为lambda运算如何如何就推定函数式编程也如此
    函数式编程虽然有高阶函数(可以将函数赋值给变量),但值语义是比较常见的,不推荐命令式语言中的变量用法
    hhkbp2
        28
    hhkbp2  
       2014-04-15 20:34:42 +08:00
    @jiyinyiyong
    @pythonee
    讲到函数式编程内涵,并非只是常常被人提到的函数式风格,我理解至少有2层意义
    1. 函数式风格(包括高阶函数,对无副作用,可重入的强调等)
    2. 函数式数据结构和函数式算法

    第1点广为人知,第2点则较少人讲到。其中函数式数据结构(值语义),奠定了函数式在大并发时代的优势,详细可以参考erlang或clojure的设计
    Ricepig
        29
    Ricepig  
       2014-04-15 20:40:13 +08:00
    @hhkbp2 其实优势不如想象的大。所谓值语义,immutable,还是无法避免并发的核心问题。还是需要我们自己发挥聪明才智,如履薄冰地解决。
    pythonee
        30
    pythonee  
    OP
       2014-04-15 22:21:15 +08:00
    @hhkbp2 你说的函数式数据结构和算法是指将传统数据结构如:树、队列等这些用函数式来实现吗?我觉得Toplanguage组里有个liuxinyu前辈用haskell做了一些研究。不知道你指的是不是那个,另外,你说的值语义是什么?

    erlang在大并发时代的优势应该是它的actor模型和轻量级线程、热部署等特性。但是这些好像我无法将他们与值语义联系起来。不过听说热部署特性在函数式中比在命令式语言中较容易实现
    hhkbp2
        31
    hhkbp2  
       2014-04-15 23:20:40 +08:00
    @Ricepig
    你所说并发的核心问题是指?
    hhkbp2
        32
    hhkbp2  
       2014-04-15 23:25:47 +08:00
    @pythonee
    liuxinyu从拼音来看,没猜错的话,应该就是同我认识的同一个人
    functional算法和数据结构,之前就有人研究过,并且出过书的

    值语义是指immutable,clojure里面有一整套的persistent data structure。有兴趣的话可以找些相关的书或资料深入了解一下它里面的实现
    pythonee
        33
    pythonee  
    OP
       2014-04-16 09:31:26 +08:00
    @hhkbp2 我理解的并发核心应该是现有使用共享状态来进行多线程通信时导致的锁争用、线程等待这些问题,erlang通过消息传递和变量不可变解决了这个问题,但是又引进了另外的问题
    pythonee
        34
    pythonee  
    OP
       2014-04-16 09:32:06 +08:00
    @hhkbp2 "clojure里面有一整套的persistent data structure" 这个第一次听说,有相关资料看吗,最好入门级的
    simpx
        35
    simpx  
       2014-04-16 09:58:27 +08:00
    [OT]
    @otbzi 我只同意你”在这个时候“之前的话,因为我并没有试图得出哪种思想更笨拙、或者没有意义。限于篇幅,我也没办法让你觉得我不是在粗暴的下结论。

    实际上,我认真学习过lisp,也分别用python、javascript自己实现过不完备的lisp解释器,我反而根本不会Java :)

    但当我深入下去,试图实现纯粹的万物皆函数,比如用邱奇数来表示数字,我发现我实现的这门lisp方越来越徒有其表,只能算用各种dirty模拟了一个完美的概念,毕竟我是在图灵机上实现,而不是Lisp machine。我也不得不造出一些二流的概念,误导后人,当然,如果有人用我的方言的话。

    保留个人观点,纯粹的函数式思想是用来带给我们MapReduce这样的运算架构的,而不是用来在图灵机上实现的。在现实的函数式语言中寻找纯粹的概念,是白费力气,要么接受dirty,要么钻研纸上完美的lisp。
    edison0951
        36
    edison0951  
       2014-04-16 10:15:36 +08:00
    函数式编程和函数式语言还是有些许出入的吧。
    zinking
        37
    zinking  
       2014-04-16 12:13:29 +08:00
    其实还是个蛮有意思的哲学话题 静跟动的关系

    比如一开始学习线性空间的时候,我们能够理解先行空间里的点的意思。 突然有一天,说函数也是线性空间里的点的时候,突然就产生了像楼主这样的冲击感。 不过深入下去很快就理解了
    pythonee
        38
    pythonee  
    OP
       2014-04-16 12:46:36 +08:00
    @zinking 线性空间我就记得矩阵了,矩阵是描述线性空间运动的极好工具,其他的都忘了。不过听你这么一说,好像有点印象
    wity_lv
        39
    wity_lv  
       2014-04-16 14:30:13 +08:00
    从数学的角度理解.
    函数. f(x) = x + 1;
    普通理解, x = 1,2,3,4,5 .... 整数.
    f(2) = 2 + 1; 计算结果为3.


    如果 x 是另外一个函数.
    x = f(a, b) = a + b;
    f(x) = f(2, 3) + 1 = (2 + 3) + 1 = 5 + 1; 输出结果为6


    再说一个不好理解的case:
    y = f(a, b) = a + b;
    x = f(a) = y(a, 4);
    f(x) = x + 1 = f(a) + 1 = a + 4 + 1

    1. 函数可以用来计算
    2. 函数可以作为参数(变量也是函数)
    3. 函数可以用来生成函数(变量也是函数)

    用mit-scheme实现.
    1. 函数可以用来计算
    (define plus1(x) (+ x 1)
    (plus1 2) #> 输出3

    2. 函数可以作为参数(变量也是函数)
    (define plus-both(a b) (+ a b)
    (plus1 (plus-both 2 3) ) #> 输出 6

    3. 函数可以用来生成函数(变量也是函数)
    (define generated_fun(a) (plus1 (plus-both a 4) ) #> a + 4 + 1
    (generate_fun 1) #> 1 + 4 + 1 输出 6


    函数式编程语言能够很容易使用数学的方式来思考。
    Cbdy
        40
    Cbdy  
       2017-07-25 10:08:07 +08:00
    只是先求值和后求值的区别
    一切都是对象(值,先求值),一切都是函数(后求值)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   854 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 21:43 · PVG 05:43 · LAX 14:43 · JFK 17:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.