免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: 太平绅士
打印 上一主题 下一主题

【讨论】如果将 XXX 语言, 变成 blablabla,是不是就是一门 Functional 语言了? [复制链接]

论坛徽章:
0
11 [报告]
发表于 2009-03-25 14:55 |只看该作者
的确是。
我认为做“对比”是很好的,主要关注它们之间的差异;但是,如果想要用一方里面的概念去“类比”另一方里面的概念,就很容易出问题了。
如果你带着C语言来看函数式语言,会觉得后者只是用一种诡异的方式完成了原来C可以很直接完成的任务;如果不了解C的变量、内存模型、语句等概念,先看函数式语言,反而会觉得函数式语言很自然(之后再看C语言的话,会觉得C在用一种诡异的方式表达原来Haskell可以直接表达的意思)。

原帖由 MMMIX 于 2009-3-25 14:38 发表

agreed.

可能许多人觉得这样和自己已知的东西类似比较省力气吧,尤其是不准备深入了解的时候。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
12 [报告]
发表于 2009-03-25 15:00 |只看该作者
我随便罗列一下 Haskell 里面的几个 C 里面没有的,但是有时候却很好用的特点:
1,partial application
2,curry
3,flip
等等等等,限于篇幅,我只说一下第一个:部分应用。

这个很有用,比如做 callback 的时候,如果是 C 语言的话,那么这个 callback 的接口是什么样,之前就定死了
举个例子,比如 man ftw:
  1.        int ftw(const char *path, int (*fn)(const char *,
  2.               const struct stat *ptr, int flag), int ndirs);
复制代码

ftw 大意是说,给每个目录里的每个文件都调用一次中间那个 fn,
比如 fn 可以用下面这个函数填实:
  1. int printItem( const char *name, const struct stat *ptr, int flag )
  2. {
  3.     fprintf( stdout, "found: [%s]\n", name );
  4. }
复制代码

这很不错,看起来它也能够工作。
但是现在我要用 ftw 了,却碰到了这样的一个需求:我需要用来作为 callback 的,实际上是下面这个函数!!
  1. int printItemToFile( FILE *fp, const char *name, const struct stat *ptr, int flag )
  2. {
  3.     fprintf( fp, "found: [%s]\n", name );
  4. }
复制代码

没办法,这个信息得打印到文件里去,可惜我一开始也不知道要打印到哪个文件里去,这完全由我的调用者来决定。
这下糟糕了,ftw 工作起来似乎有些问题。
这可怎么办?

因为我只是回帖的时候临时想到了这个例子,没有仔细深入地思考过,是否有办法避免此问题,
不过我知道有许多 callback 为了实现这样的需求,设计的时候就加入了一个 void *userData 这样的参数来储存用户自己的私有数据。

但这看起来多少有些不美观。

Haskell 面对此类问题可以做得很美:

  1. foo = do
  2.     ftw "/path/to/dir" printFile .......
  3.     where printFile = printFileToHandler fp
复制代码

[ 本帖最后由 flw 于 2009-3-25 15:03 编辑 ]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
13 [报告]
发表于 2009-03-25 15:06 |只看该作者
当然了,Haskell 提供给人们的,绝对不止是一些语法糖这么简单。

论坛徽章:
0
14 [报告]
发表于 2009-03-25 15:24 |只看该作者
原帖由 flw 于 2009-3-25 15:00 发表
我随便罗列一下 Haskell 里面的几个 C 里面没有的,但是有时候却很好用的特点:
1,partial application
2,curry
3,flip
等等等等,限于篇幅,我只说一下第一个:部分应用。

这个很有用,比如做 callb ...


这个例子很有意思,忍不住再次像一把,像 c++ functor + bind参数。
无论如何,看起来形式上的确是非常优雅的, thanks!

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
15 [报告]
发表于 2009-03-25 15:30 |只看该作者
原帖由 太平绅士 于 2009-3-25 15:24 发表

这个例子很有意思,忍不住再次像一把,像 c++ functor + bind参数。
无论如何,看起来形式上的确是非常优雅的, thanks!

好奇的话,就多了解一些吧。
Haskell 远不止这些。

如果我告诉你,1 是个函数,2 也是个函数,你会怎样想?
但这的确是 lambda 演算的基础。

事实上,没有学过任何编程的人,如果不喜欢逃数学课的话,应该会对 Haskell 更有感觉。

像 C++ 还有 Python Perl 这种语言,只是有一些 FP 的影子,
但它们本质上还是命令式语言。它们最终追求的也不是全套的 FP 特性,
因此碰到有些 FP 语言很好解决的问题的时候,它们可能就会费一些周折,或者可能会增加一些新的特性来支持,
但总归不如 FP 语言里那么来得自然。

[ 本帖最后由 flw 于 2009-3-25 15:33 编辑 ]

论坛徽章:
0
16 [报告]
发表于 2009-03-30 00:04 |只看该作者
原帖由 MMMIX 于 2009-3-25 14:38 发表

agreed.

可能许多人觉得这样和自己已知的东西类似比较省力气吧,尤其是不准备深入了解的时候。


套用七剑里面一句话:要放开心灵

我好像近错地方了,好像还刷屏了,这很不好。

论坛徽章:
0
17 [报告]
发表于 2009-03-30 10:45 |只看该作者
借一句经典的话:你有两种方法学好 FP,第一种是你有一个非常聪明的脑袋,能理解它是如何思考的,第二种是看大量的代码,理解它是如何思考的。
我现在有一点点明白,FP 的思考方式和 OO ,结构化,绝对是不一样的。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
18 [报告]
发表于 2009-03-30 12:28 |只看该作者
原帖由 drunkedcat 于 2009-3-30 10:45 发表
借一句经典的话:你有两种方法学好 FP,第一种是你有一个非常聪明的脑袋,能理解它是如何思考的,第二种是看大量的代码,理解它是如何思考的。
我现在有一点点明白,FP 的思考方式和 OO ,结构化,绝对是不一样的。

那是自然。命令式编程语言的基础是图灵机,注重的是问题解决的过程和步骤。
函数式编程语言的基础是 lambda 演算,注重的是如何分解并描述问题。

虽然图灵机和 lambda 演算是等效的,但是显然它们是两种不同的抽象方法。
命令式语言中的每个动作都在影响 real world,同一个命令随着运行时刻的不同效果就会不同,
这就是为什么循环和递归会把人的脑袋搞晕的原因。
而函数式编程语言中的函数在任何时候它的求值结果都是一样的,
因此你只要搞明白输入、输出是什么,函数的语义是什么,就不会搞晕了。

当然了,实际面对工作的时候,会发现并不是所有的问题都适合用函数式语言来描述。
有些问题自身就是一步一步完成的,它们天生就适合用命令式语言解决。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP