当前位置: 首页 > 编程日记 > 正文

closurescallbacks


引用文章原文地址:(声明:文章只为自己总结知识,内容东拼西凑,版权归以下作者所有。)

1. Wikipedia: callback(computer science)

2. Implement callback routines in Java By John D. Mitchell, JavaWorld.com, 06/01/96

3. Why is Python more fun than Java? Brian M. Clapper

最近在读Eckel的Thinking in Java,读到Inner Class那一章碰到两个概念不是很清楚,一个是callback,另一个是closures,网上搜了搜,整理如下。

先说callback,粘一段wikipedia的概念。

词条:callback 来自:wikipediaIn computer programming, a callback is executable code that is passed as an argument to other code. It allows a lower-level software layer to call a subroutine (or function) defined in a higher-level layer.

(下面很多是翻译wikipedia的东西,翻译自然会加入了自己的理解,出错难免。)

为什么需要callback呢?

比如说你想对一个序列中的每个元素进行一次任意的操作,一种方案是遍历这个序列,直接对每个元素进行操作,这是最直接的,缺点是会产生代码冗余,每次遍历都要写重复的代码。另一种方案是写一个泛型的库函数,将序列传递给库函数,在函数的内部遍历操作这个序列,一定程度上消除了代码冗余,问题是使用库函数的应用程序的要求是不可预期的,不可能写出所有满足应用程序要求的库函数。第三种方案当然就是callback,应用程序对序列进行遍历,对每个元素调用callback函数,解决了上述两个问题。

一个用C写的示例:

程序功能:遍历一个整形的数组找出第一个大于5的元素,并给出索引(index)

遍历的方案:

 1  int i;
 2  
 3  for (i = 0; i < length; i++)
 4  {
 5      if (array[i] > 5
 6      { 
 7          break;
 8      }
 9  }
10  
11  if (i < length) 
12  {
13      printf("Item %d\n", i);
14  }
15  else
16  {
17      printf("Not found\n");
18  }


callback的方案:

 1 /* LIBRARY CODE */
 2  int traverseWith(int array[], size_t length, 
 3                   int (*callback)(int index, int item, void *param), 
 4                   void *param)
 5  {
 6      int exitCode = 0;
 7      for (int i = 0; i < length; i++) {
 8          exitCode = callback(i, array[i], param);
 9          if (exitCode != 0) { 
10              break;
11          }
12      }
13      return exitCode;
14  }
15  
16  /* APPLICATION CODE */
17  int search (int index, int item, void *param)
18  {
19      if (item > 5) {
20          *(int *)param = index;
21          return 1;
22      } else {
23          return 0;
24      }
25  }
26  
27  /* (in another function) */
28  int index;
29  int found;
30  found = traverseWith(array, length, &search, &index);
31  if (found) {
32      printf("Item %d\n", index);
33  } else {
34      printf("Not found\n");
35  }
36 
37

注意 search函数的最后一个参数param,callback函数通常用这样一个指针参数来操作它的scope之外的数据,在这里是用来存放索引的值。只有statically scoped language的语言(如C/C++)才需要这样的参数,Lexically scoped languages的语言(如Lisp)支持closure因而不需要这个参数,closure是一个可以调用的对象,它可以保留创建它的那个scope里的信息,Java中的Inner Class就是一个面向对象的closure,因为它可以通过一个内置的引用访问包含它类的所有成员,包括private成员。

可以看到上面的callback函数是通过一个函数指针实现的,Java不支持函数指针,那么再Java中如何来实现 callback函数呢?

Jave支持Interface,利用它我们可以实现callback的效果。技巧就是把我们要调用的callback函数封装在一个简单的接口里。任何实现这个接口的object都可以用来callback. 下面我写的Java版的callback.

 1 import java.util.ArrayList;
 2 import java.util.Collections;
 3 import java.util.List;
 4 import java.util.Arrays;
 5 
 6 interface Matcher<T>
 7 {
 8     //test if t meets certain requirement, index is the index of t in a List
 9     public boolean matches(int index, T t);
10 }
11 class MyLib
12 {
13     //Find the fisrt item in list that meets the requirement of matcher
14     public static <T> boolean findFirstMatch(List<T> list, Matcher<T> matcher)
15     {
16         boolean found = false;
17         for(int i = 0; i < list.size(); i++)
18         {
19             if(matcher.matches(i,list.get(i)))
20             {
21                 found = true;
22                 break;
23             }
24         }
25         return found;
26     }
27 }
28 class Value
29 {
30     int val;
31     public Value(int val)
32     {
33         this.val = val;
34     }
35 }
36 public class CallbackAndColsureExample
37 {
38     public static final List<Integer> NUMBERS = 
39         Collections.unmodifiableList(Arrays.asList(1,4,6,10,3,9,7));
40     public static void main(String[] args)
41     {
42         final int base = 5;
43         final Value index = new Value(-1);
44         Matcher<Integer> biggerThanBaseMatcher = new Matcher<Integer>()
45         {
46             public boolean matches(int idx, Integer val)
47             {
48                 if(val > base)
49                 {
50                     index.val = idx;
51                     return true;
52                 }
53                 else return false;
54             }
55         };
56         boolean found = MyLib.findFirstMatch(CallbackAndColsureExample.NUMBERS, biggerThanBaseMatcher);
57         if(found) System.out.println("item found at index " + String.valueOf(index.val));
58         else System.out.println("item not found");
59     }
60 }

我们用Matcher<T>这个接口封装了一个callback函数,在类CallbackAndColsureExample的内部我们用了一个匿名的Inner Class实现了Matcher<T>接口,并定义了一个对象biggerThanBaseMatcher,通过biggerThanBaseMatcher我们就可以调用callback函数了。注意这个Inner Class形成了一个closure, 所以在它的内部可以访问在Outer calss里定义的index.

转载于:https://www.cnblogs.com/sirkay777/archive/2008/12/12/1353844.html

相关文章:

吴恩达老师深度学习视频课笔记:卷积神经网络

计算机视觉&#xff1a;包括图像分类(image classification)、目标检测(object detection)、风格迁移(neural style transfer)等等。边缘检测示例&#xff1a;神经网络的前几层可以检测边缘&#xff0c;然后后面几层可能检测到物体的部分&#xff0c;接下来靠后的一些层可能检测…

COCO 2019挑战赛,旷视研究院拿下三项计算机识别冠军 | ICCV 2019

出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;10月27日&#xff0c;两年一度的国际计算机视觉大会ICCV 2019&#xff08;InternationalConference on Computer Vision&#xff09;在韩国首尔开幕。作为ICCV 2019重头戏&#xff0c;COCO 是人工智能领域最具影响力的…

runners学习

runners是由salt-run命令调用的&#xff0c;一般我用的到就是jobs和manage模块。源代码是在./site-packages/salt/runners/下的。当然我们可以自定义runners。先谈谈jobs模块。包含active、lookup_jid、list_job、list_jobs、print_job五种方法。salt-run jobs.active ->返回…

Swift基础 - - 高德地图实践

高德地图开发需要自己到官网http://lbs.amap.com/console/ 注册一个ak&#xff0c;新建一个swift工程&#xff0c;然后在Info.plist中添加一个NSLocationAlwaysUsageDescription或者NSLocationWhenInUseUsageDescription。 高德地图的库以及依赖库加入到项目里面 需要的库如下…

Shell脚本示例代码

1. echo_printf_usage.sh: echo和printf的用法 #! /bin/bash# echo和printf的用法# echo是用于终端打印的基本命令.在默认情况下,echo在每次调用后会添加一个换行符 echo "hello, beijing" echo "$(pwd)" echo $(pwd) # 结果并不是希望得到的,将会输出: $…

「2019嵌入式智能国际大会」 399元超值学生票来啦,帮你豪省2600元!

2019 嵌入式智能国际大会即将来袭&#xff01;购票官网&#xff1a;https://dwz.cn/z1jHouwE物联网是继计算机、互联网和移动通信之后的又一次信息产业的革命性发展&#xff0c;在互联网和移动互联网高速发展的时代&#xff0c;几乎所有行业都有数据联网的需求。无论是国外的科…

ThinkPHP学习笔记之Model操作

2019独角兽企业重金招聘Python工程师标准>>> 1. 3种实例化model模型方法 a) new 命名空间GoodsModel(); b) D([“模型标志Goods”]) (之前版本会实例化自定义model对象&#xff0c;目前都实例化Model基类对象) i. 没有参数实例化一个Model对象、有参数也实例化一…

Ubuntu 14.04 64位上配置JDK操作步骤

1. 从 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 下载jdk-8u172-linux-x64.tar.gz; 2. 解压缩&#xff1a; tar -xvzf jdk-8u172-linux-x64.tar.gz 3. 创建/usr/jdk目录&#xff1a; sudo mkdir -p /usr/jdk 4. 将解压缩后的jd…

Swift语言实现代理传值

需求&#xff1a;利用代理实现反响传值&#xff08;以下例子采用点击第二个视图控制器中的按钮来改变第一个视图控制器中的Label的内容&#xff09; 一、创建RootViewController import Foundation import UIKitclass RootViewController:UIViewController,ChangeWordDelegate{…

亚马逊马超:如何使用DGL进行大规模图神经网络训练?

演讲嘉宾 | 马超&#xff08;亚马逊应用科学家&#xff09;整理 | 刘静 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;与传统基于张量&#xff08;Tensor&#xff09;的神经网络相比&#xff0c;图神经网络将图 (Graph) 作为输入&#xff0c;从图结构中学习潜在的知…

Python学习系列(六)(模块)

Python学习系列&#xff08;六&#xff09;(模块) Python学习系列&#xff08;五&#xff09;(文件操作及其字典) 一&#xff0c;模块的基本介绍 1&#xff0c;import引入其他标准模块 标准库&#xff1a;Python标准安装包里的模块。 引入模块的几种方式&#xff1a; i&#xf…

Ubuntu14.04 64位上配置终端显示git分支名称

之前在Ubuntu14.04上在终端上显示git分支名称基本上都使用oh-my-zsh&#xff0c;可以参考 https://blog.csdn.net/fengbingchun/article/details/77803322 &#xff0c;由于限制了权限&#xff0c;使得不能安装oh-my-zsh&#xff0c;显示错误如下&#xff1a;在 https://githu…

创建UITextField对象

//创建UITextField对象 UITextField * tf[[UITextField alloc]init];//设置UITextField的文字颜色tf.textColor[UIColor redColor];//设置UITextField的文本框背景颜色tf.backgroundColor[UIColor grayColor];//设置UITextField的边框的风格tf.borderStyleUITextBorderStyleRou…

non-local神经网络:通过非局部操作解决深度神经网络核心问题

译者 | 李杰出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;回想一下我们熟悉的CNN、RNN。如下图所示&#xff0c;这些神经网络模型都是基于局部区域进行操作&#xff0c;属于local operations。为了获得长距离依赖&#xff0c;也就是图像中非相邻像素点之间的关系&a…

fgets()用法笔记

为了避免缓冲区溢出&#xff0c;从终端读取输入时应当用fgets()代替gets()函数。但是这也将带来一个问题&#xff0c;因为fgets()的调用格式是&#xff1a; fgets (buf, MAX, fp)fgets (buf, MAX, stdin) buf是一个char数组的名称&#xff0c;MAX是字符串的最大长度&#xff0c…

iOS 上常用的两个功能:点击屏幕和return退出隐藏键盘和解决虚拟键盘

原文地址&#xff1a;http://blog.csdn.net/xiaotanyu13/article/details/7711954 iOS上面对键盘的处理很不人性化&#xff0c;所以这些功能都需要自己来实现&#xff0c; 首先是点击return和屏幕隐藏键盘 这个首先引用双子座的博客 http://my.oschina.net/plumsoft/blog/42545…

深度学习可解释性问题如何解决?图灵奖得主Bengio有一个解

作者 | Yoshua Bengio, Tristan Deleu等译者 | 刘畅&#xff0c;编辑 | Just出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;自 2012 年以来&#xff0c;深度学习的发展有目共睹&#xff0c;今年 3 月&#xff0c;为此做出巨大贡献的 Yoshua Bengio、Yann Lecun和Geo…

zepto打造一款移动端划屏插件

效果图 样式1 样式2 调用 正常情况下应该是后台生成的html代码&#xff0c;但还是写了一套操作tab页的方法 调用简便如下&#xff1a; <link rel"stylesheet" href"kslider.css" type"text/css"/> <script type"text/javascript&q…

swift使用xib绘制UIView

目标&#xff1a;用xib绘制一个UIView&#xff0c;在某个ViewController中调用。 三个文件&#xff1a;ViewController.swift DemoView.swift DemoView.xib 首先&#xff0c;可以专心将DemoView.xib画出来&#xff0c;别忘记DemoView.xib中UIView的一处设置 然后&#x…

吴恩达老师深度学习视频课笔记:深度卷积网络

Why look at case studies?&#xff1a;过去几年&#xff0c;计算机视觉研究中的大量研究都集中在如何把卷积层、池化层以及全连接层这些基本构件组合起来形成有效的卷积神经网络。找感觉最好的方法之一就是去看一些案例&#xff0c;就像很多人通过看别人的代码来学习编程一样…

测试工程师的好日子来啦?Testin发布AI测试产品,提升易用性和自动化效率

2019年10月26日&#xff0c;以"AI未来"为主题的第二届NCTS中国云测试行业峰会在北京国际会议中心正式开幕。在本次大会上&#xff0c;Testin 总裁徐琨正式发布测试业务Testin云测的全新AI产品iTestin。作为 Testin 人工智能战略中的重要一环&#xff0c;iTestin 融合…

Discuz DB层跨库映射关系表名前缀BUG修复后产生的新bug

新的逻辑引入了新的bug&#xff0c;会导致在跨多库连接时&#xff0c;产生表名前缀映射混乱&#xff0c;需要再做逻辑上的修复。 function table_name($tablename) {if(!empty($this->map) && !empty($this->map[$tablename])) {$id $this->map[$tablename];…

swift语言的Block

[cpp] view plaincopy// // blockDemo.swift // swiftDemo // // Created by apple on 14-6-29. // Copyright (c) 2014年 fengsh. All rights reserved. // import Foundation //无参无返回值 typealias funcBlock () -> () //或者 () -> …

吴恩达老师深度学习视频课笔记:目标检测

目标定位&#xff1a;如下图,图像分类任务就是算法遍历图像&#xff0c;判断其中的对象是不是car。图像定位分类(classification with localization)不仅要用算法判断图像中的是不是car&#xff0c;还要在图像中标记出car的位置。图像分类的思路可以帮助学习分类定位&#xff0…

国际顶级学界业界大咖云集,9 场技术论坛布道,2019 嵌入式智能国际大会强势来袭!...

2019 嵌入式智能国际大会即将来袭&#xff01;购票官网&#xff1a;https://dwz.cn/z1jHouwE2019年12月6日-8日&#xff0c;2019嵌入式智能国际大会将在深圳华侨城洲际大酒店举行。本次大会由哈尔滨工业大学&#xff08;深圳&#xff09;、清华大学国际研究生院、CSDN、嵌入式视…

Linux简介总结

1. Linux 就是Unix, 但是Unix 并不一定是Linux.2. 三种软件模式&#xff1a;商业软件&#xff0c;共享软件&#xff0c;自由软件。3. 为什么使用Linux? 它是一个自由软件。第一&#xff1a;可免费提供给任何用户使用。第二&#xff1a;它的源代码公开和可自…

Swift中编写单例的正确方式

本文由CocoaChina译者leon(社区ID)翻译自krakendev 原文&#xff1a;THE RIGHT WAY TO WRITE A SINGLETON 转载请保持所有内容和链接的完整性。 在之前的帖子里聊过状态管理有多痛苦&#xff0c;有时这是不可避免的。一个状态管理的例子大家都很熟悉&#xff0c;那就是单例。使…

C语言中的弱符号与强符号介绍

弱符号(Weak symbol)是链接器(ld)在生成ELF(Executable and Linkable Format,缩写为ELF&#xff0c;可执行和可链接格式&#xff0c;是一种用于可执行文件、目标文件、共享库和核心转储的标准文件格式。ELF文件有两种索引&#xff1a;程序标头中记载了运行时所需的段&#xff0…

Simple Transformer:用BERT、RoBERTa、XLNet、XLM和DistilBERT进行多类文本分类

作者 | Thilina Rajapakse译者 | Raku编辑 | 夕颜出品 | AI科技大本营&#xff08;ID: rgznai100&#xff09;【导读】本文将介绍一个简单易操作的Transformers库——Simple Transformers库。它是AI创业公司Hugging Face在Transformers库的基础上构建的。Hugging Face Transfor…

StarUML中时序图添加小人

转载于 http://blog.csdn.net/longyuhome/article/details/9011629 在看时序图的例子的时候&#xff0c;发现有些的时序图上有小人的图标&#xff0c;可是一些UML工具却没有找到小人的图标&#xff0c;这让我很闹心&#xff0c;一直没解决&#xff0c;今天终于将该问题给解…