面试交易员时需要注意哪些常规问题?
私募分支机构管理人员,不打广告,不说观点,只分享个人生活经历。希望能对有缘人有所帮助。本公众号不定期更新。
【本公众号已委托“维权骑士”rightknights.com进行维权行动,禁止抄袭、转载,违者必究】
前两天是几个网友问的我这个问题,而且这几年中国经济不好,恩,可以告诉大家,现在只是刚开始,明后两年,大家做好准备,该屯粮屯粮,以后地主家都没有余粮了。正是因为经济不好,所以中国目前社会上的金融公司,那是遍地开花,吸金手段颇多,为了给金融小白们的提个醒,也为了大家少受骗,才决定回答这个问题。至于答案,我太有发言权了,废话不多说,上干货。
操盘手这个职位,从去年十月份左右,我面试到今年的三四月份,从北京,辗转至上海。中间少说我面试的公司加起来有上百家(君无戏言)。要说这里面的套路,我是太清楚了。
给大家列个目录吧。
一、名义为招操盘手实为拉拢客户
二、名义为招操盘手实为配资公司
三、名义为招操盘手实为平台操控
四、名义为招操盘手实为统计数据
目前见到的各种公司,基本上是以第一种第二种居多,而且这两种分为很多方式,先说第一种。
名义为招操盘手实为拉拢客户
这种公司的运作方式非常简单,市面上打着XX资产管理公司等旗号,其实内部运作跟资产管理有毛线关系。看过我个人经历的人都知道,我再简单给大家说一下我的亲身经历。这是真事,这样你们也能完全能理解这些公司的套路了。去年面试的北京某公司,也是在我股票配资爆仓之后几个月开始面试的,他问我的做过股票没,我说做过,做过一年,吃了个牛市,翻了十二倍左右,最后1:3配资,爆仓。我说我有爆仓经历,而且我一定能好好做,我现在对风险很厌恶。然后对方来了句,你都爆过仓了我凭什么要你?然后他说你走吧,我木讷。但是当天下午我接到了前台给我打的电话,说我面试成功了,那个时候,我是感激涕零,觉得这是上天给我的好机会,我要好好珍惜。
(这里其实就是心理战,对方先给你一巴掌,再给颗糖,比喻有些不恰当,但是情况确实是这样。这时候,你就会心存感激。)可是结果呢,我去了之后,发现那两天去面试的人几乎全部都被录用,然后到了之后把我们安排在一个大教室里,先告诉我们现在是实习期,一天工资100,等正式录用了,再随当月工资一并发放,大家好好表现,最后择优录取。教室有老师讲课,K线、均线、MACD、KDJ这些技术指标,然后再开开玩笑,和实习生们拉近一些关系,每日均是如此,讲课讲了一个星期,下班很早,三点下班。第二周开始让我们分组安排在交易室,每个交易室大概有10-15人左右,每个人配备一台电脑,老师给我们申请模拟盘,然后我们开始简单的操作,他们才不在乎你的收益率是多少,不过在你模拟操盘的这个星期里,他们会经常说,XX学员今天这笔做的不错,如果是实盘,那这一笔交易就赚了多少多少,对于不懂交易的人来说,这些好像就是分分钟的事情,让学员们有一种假象。不过我当时做过一年多交易了,深知没有这么简单。第三周,老师们会单独找我们聊天,套路都一样,但分两种:先拉家常,来一线城市多么不容易,我以前也是这样等等的话,然后你如果模拟盘期间做的收益不错,对方会说,交易这个东西,模拟和实盘是两码事,有的人模拟做得很好,但实盘不一定行,不过我们觉得你可以,但是为了谨慎起见,公司会对你在进行一项考核,你拿自己的钱在公司做,盈利全部归你自己,公司只是看一下你的交易能力。如果你模拟盘期间做的不好,对方会说,交易这个东西,拟和实盘是两码事,有的人模拟做得不好,但实盘不一定比别人做得差,不过我们觉得你可以,但是为了谨慎起见,公司会对你在进行一项考核,你拿自己的钱在公司做,盈利全部归你自己,公司只是看一下你的交易能力。这样的话,无论你交易能力怎么样,对方都有办法让你开户入金做这件事,当然作为一个实习生,首先是肯定想成为正式员工然后奔着年入百万去的,其次就是一些学员做模拟盘分分钟盈利几千上万块,这样的事情,对于交易小白来说,也是及其有诱惑力的。
当然,一旦你开户入金,对方会给你设定一个期限,比如两个月到三个月的实盘考核期,在这期限里,对于交易小白来说,你不停交易贡献的手续费,也够他们给几个员工发工资了。
名义为招操盘手实为配资公司
配资公司,简单解释一下,比如说你有10万块钱,要炒股(或者期货或者外汇等,只要跟交易有关即可,但大部分配资都是股票配资,因为股票无杠杆),你嫌自己的钱太少,想多借点钱炒股,在亲戚朋友那里你又张不开口,OK,配资公司来帮你(去年行情好的时候配资公司非常赚钱),假如你有10万想借30万,这个配资比例就是1:3,你的钱加上配资公司借给你的30万块钱,总共40万块钱,你可以拿着40万开始炒,如果满仓打一个涨停板,当然,你就赚了4万块钱,比你10万块钱满仓打一个涨停板,多赚了3万。当然了,如果亏损起来,也是非常可怕的。你借配资公司的钱,是要收利息的,行情好的时候,每个月可能两三个点,行情一般的时候,每个月也就一个多点。(业内人士都懂,说这么多就是想给不明白的人解释的更清楚)。
这其实就是心理战,大家试想一下,行情好的时候,配资公司几乎是坐等客户上门。行情不好的时候呢,配资公司就要想办法了,怎么想办法呢?很简单,一般的客户是不会轻易去配资的,那什么样的客户会去配资呢?喜欢交易这一行的人去配资的可能性才会比较大,那怎样才能找到喜欢交易的人呢?发个招聘信息,XX公司招募操盘手,年薪多少多少,门槛低一些,社会上很多抱着高薪幻想的人蜂拥而至,他们装作很高冷的样子,表面上让你认为这种公司非常难进,如果你进来了,那年入百万指日可待,其实则不然。这种公司,以招操盘手为由,面试通过很简单,然后接下来一般是先让你模拟,模拟之后找一堆理由让你小资金实盘,当然了,来面试的人,大部分都是没多少钱的,这个时候公司会给出一些说辞,会告诉你我们现在有什么什么业务,如果你相信自己的能力,当然公司可以借钱给你做,这样的话你自己的盈利也很多了。我们知道,每个人的内心其实都是相对比较自信的,尤其是来做交易的人,内心那是无比自信,总觉得百万年薪就在自己眼前,只要自己愿意付出。当然我们也知道,这样的话,你入了套,公司愿意借钱给你, 是要收取利息的,不过在和你商量期间,公司的人员会有意无意向你说明:这一点利息,跟你几分钟的盈利比起来都是小数目。一般不太聪明的人,也都会欣然接受公司这种方案了。这样的话,你就成功的成为了一名配资客户,在你不断交易然后亏损的期间(相信我,除非你是真正的操盘手,不然不可能不断盈利),公司每月收取你的配资利息,直到你把自己的本金快亏损完了,公司才会站出来说:你不适合做操盘手,然后打发你走人。当然了,如果你稳定盈利了,那更好,你赚多少,我无所谓,我每月收你的利息,如果你做的时间长,确实能稳定盈利,我后台也可以看你的及时交易情况,跟单做。
(现在很多公司都是以上两种业务一起做,既让你开户入金做交易收取你的佣金,又旁敲侧击让你配资收取利息。)
名义为招操盘手实为平台操控
这个我还没遇到过,因为之前被骗过一次,所以后来找工作都很谨慎,但这种公司的模式听前辈说过,你去面试,很容易又面试上了,然后让你在他们的交易平台做模拟盘交易,而且你发现,在你做模拟交易期间,几乎次次都是盈利的,感觉自己无比自信,是命中注定的操盘手,中国的利弗莫尔。然后公司给你*说你这么牛啊,但是我们还是想看你的实际盈利能力,然后自信的你上了实盘,然后没想到一段时间你自己确实也是盈利的,然后这个时候,公司要么督促你加大资金(公司会说以后给你的操盘资金的多少完全看你现在的自有资金有多少,其中有一个比例),或者公司觉得你没钱,然后你会发现,在你满仓做多或者满仓做空的时候,一两跟大阴线或者大阳线把你干到爆仓,没错,就是这么给力。然后要么你继续入金做,要么滚蛋,所谓的“实习”结束。当然自信你的觉得这是意外,又开始找钱来投入,因为之前的盈利笔数很多,给你造成了一个假象,循环往复,直到你完全失去信心走人。
(恩,在这里插一段。其实还有一种比较头疼的,也是最气人的,你入金入了10万块,其实他们给你的是模拟盘,而你自己全然不知,当你账面形成所谓的亏损的时候,老板从你入金的账户里面扣除,赚了钱想撤资的时候,千方百计不让你退金。)
他们给你提供的交易平台,类似于邮币卡、贵金属、原油、现货黄金白银、伦敦金、伦敦银等等,当然,在公共视野里的肯定是真的,也是人为无法控制的,除非你有巨大的资金。他们的平台都是市场上没听说过的。这种公司最主要的盈利模式就是通过做平台操控来获取利润,什么叫平台操控呢,简单一点,就是平台就是他家的,他说什么就是什么,横竖你都是个死,这种公司,赚钱那叫一个暴力。
名义为招操盘手实为统计数据
这个,本来不想说的,因为我上海有朋友公司就搞这个,很新鲜吧?我也不让你入金,你过来面试就上,直接给你账户,里面的钱少的可怜,期货市场就是一手一手的做,几千块钱,一个账户几千,够你买什么沥青、豆粕之类的一手。大量招人,然后让你做三四个月,三四个月后,稳定盈利的,他们还不要你(变态不变态),总之就是为了统计大量的交易数据,招人一招都是几十上百的。具体他们拿这个数据来做什么,这个我之前问过,但人家也没有向我具体透露。总之,真实实盘数据嘛,在市场里肯定会有一些我们不知道的用途的。
其实我只是简单罗列了一下,前两条是目前市场上最多的,而且现在的手段和方法不知道又发展到了多先进的地步。大家一定擦亮眼睛,只要让你交钱,分分钟撤退。相信我,在金融这个行业,万万不可太自信,在这个行业里,无论做什么,都要一定要谨慎。
俗话说:金融行业骗子多。祝大家好运。
明天周六啦,开心。哈哈哈哈哈哈。
上一篇: tencent cloud
推荐阅读
-
纯干货分享 | 研发效能提升——敏捷需求篇-而敏捷需求是提升效能的方式中不可或缺的模块之一。 云智慧的敏捷教练——Iris Xu近期在公司做了一场分享,主题为「敏捷需求挖掘和组织方法,交付更高业务价值的产品」。Iris具有丰富的团队敏捷转型实施经验,完成了企业多个团队从传统模式到敏捷转型的落地和实施,积淀了很多的经验。 这次分享主要包含以下2个部分: 第一部分是用户影响地图 第二部分是事件驱动的业务分析Event driven business analysis(以下简称EDBA) 用户影响地图,是一种从业务目标到产品需求映射的需求挖掘和组织的方法。 在软件开发过程中可能会遇到一些问题,比如大家使用不同的业务语言、技术语言,造成角色间的沟通阻碍,还会导致一些问题,比如需求误解、需求传递错误等;这会直接导致产品的功能需求和要实现的业务目标不是映射关系。 但在交付期间,研发人员必须要将这些需求实现交付,他们实则并不清楚这些功能需求产生的原因是什么、要解决客户的哪些痛点。研发人员往往只是拿到了解决方案,需要把它实现,但没有和业务侧一起去思考解决方案是否正确,能否真正的帮助客户解决问题。而用户影响地图通常是能够连接业务目标和产品功能的一种手段。 我们在每次迭代里加入的假设,也就是功能需求。首先把它先实现,再逐步去验证我们每一个小目标是否已经实现,再看下一个目标要是什么。那影响地图就是在这个过程中帮我们不断地去梳理目标和功能之间的关系。 我们在软件开发中可能存在的一些问题 针对这些问题,我们如何避免?先简单介绍做敏捷转型的常规思路: 先做团队级的敏捷,首先把产品、开发、测试人员,还有一些更后端的人员比如交互运维的同学放在一起,组成一个特训团队做交付。这个团队要包含交付过程中所涉及的所有角色。 接着业务敏捷要打通整个业务环节和研发侧的一个交付。上图中可以看到在敏捷中需求是分层管理的,第一层是业务需求,在这个层级是以用户目标和业务目标作为输入进行规划,同时需要去考虑客户的诉求。业务人员通过获取到的业务需求,进一步的和团队一起将其分解为产品需求。所以业务需求其实是我们真正去发布和运营的单元,它可以被独立发布到我们的生产环境上。我们的产品需求其实就是产品的具体功能,它是我们集成和测试的对象,也就是我们最终去部署到系统上的一个基本单元。产品需求再到了我们的开发团队,映射到迭代计划会上要把它分解为相应的技术任务,包括我们平时所说的比如一些前端的开发、后端的开发、测试都是相应的技术任务。所以业务敏捷要达到的目标是需要去持续顺畅高质量的交付业务价值。 将这几个点串起来,形成金字塔结构。最上层我们会把业务目标放在整个金字塔的塔尖。这个业务目标是通过用户的目标以及北极星指标确立的。确认业务目标后再去梳理相应的业务流程,最后生产。另外产品需求包含了操作流程和业务规则,具需求交付时间、工程时间以及我们的一些质量标准的要求。 谈到用户影响的地图,在敏捷江湖上其实有一个传说,大家都有一个说法叫做敏捷需求的“任督二脉”。用户影响地图其实就是任脉,在黑客马拉松上用过的用户故事地图其实叫督脉。所以说用户影响地图是在用户故事地图之前,先帮我们去梳理出我们要做哪些东西。当我们真正识别出我们要实现的业务活动之后,用户故事地图才去梳理我们整个的业务工作流,以及每个工作流节点下所要包含的具体功能和用户故事。所以说用户影响地图需要解决的问题,我们包括以下这些: 首先是范围蔓延,我们在整张地图上,功能和对应的业务目标是要去有一个映射的。这就避免了一些在我们比如有很多干系人参与的会议上,那大家都有不同想法些立场,会提出很多需求(正确以及错误的需求)。这个时候我们会依据目标去看这些需求是否真的是会影响我们的目标。 这里提到的错误需求,比如是利益相关的人提出的、客户认为产品应该有的、某个产品经理需求分析师认为可以有的....但是这些功能在用户影响地图中匹配不到对应目标的话,就需要降低优先级或弃掉。另外,通常我们去制定解决方案的时候,会考虑较完美的实现,导致解决方案括很多的功能。这个时候关键目标至关重要,会帮助我们梳理筛选、确定优先级。 看一下用户影响到地图概貌 总共分为一个三层的结构: 第一层why,你的业务目标哪个是最重要的,为什么?涉及到的角色有哪些? 第二层how ,怎样产生影响?影响用户角色什么样的行为? (不需要去列出所有的影响,基于业务目标) 第三层what,最关键的是在梳理需求时不需一次把所有细节想全,这通常团队中经常遇到的问题。 我们用这个例子来看一下 这是一个客服中心的影响地图,业务目标是 3个月内不增加客服人数的前提下能支持1.5倍的用户数。此业务目标设定是符合 smart 原则的,specific非常的具体,miserable 是可以衡量的,action reoriented是面向活动的, real list 也是很实际的。 量化的目标会指引我们接下来的行动,梳理一个业务目标,尽量去量化,比如 :我们通过打造一条什么样的流水线,能够提高整个部署的效率,时间是原来的 1/2 。这样才是一个能量化的有意义的目标。 回到这幅图, how 层级识别出来的内容,客服角色:想要对它施加的影响,把客户引导到论坛上,帮助客户更容易的跟踪问题,更快速的去定位问题。初级用户:方论坛上找到问题。高级用户:在论坛上回答问题。通过我们这些用户角色,进行活动,完成在不增加客户客服人数的前提下支持更多的用户数量。 最后一个层级,才是我们日常接触比较多的真正的功能的特性和需求,比如引导到客户到论坛上,其实这个产品就需要有一个常见问题的论坛的链接。这个层次需要我们团队进一步地在交付,在每个迭代之前做进一步的梳理,细化成相应的用户故事。 这个是云智慧团队中,自己做的影响地图的范例,可以看下整个的层级结构。序号表示优先级。 那我们用户影响地图可以总结为:
-
面试交易员时需要注意哪些常规问题?
-
腾讯视频直播 02-推流-美颜滤镜 同样,腾讯云提供了 setBeautyFilter 方法来设置美颜风格、磨皮程度、美白程度和泛红程度 //style 磨皮风格:0:平滑 1:自然 2:朦胧 //美容级别:0-9。值为 0 时关闭美颜效果。默认值:0,关闭美颜效果。 //美白级别:取值 0-9。值为 0 时,将关闭美白效果。默认值:0,关闭美白效果。 //ruddyLevel:取值范围为 0-9。值为 0 时关闭美白效果。默认值:0,关闭美白效果。 public boolean setBeautyFilter(int style, int beautyLevel, int whiteningLevel, int ruddyLevel);; public boolean setBeautyFilter(int style, int beautyLevel, int whiteningLevel, int ruddyLevel) 滤镜 setFilter 方法可以设置滤镜效果,滤镜本身是一个直方图文件。setSpecialRatio 方法可以设置滤镜的程度,从 0 到 1,越大滤镜效果越明显,默认值为 0.5。 Bitmap bitmap = BitmapUtils.decodeResource(getResources, R.drawable.langman); if (mLivePusher) if (mLivePusher ! = null) { mLivePusher.setFilter(bmp); } 控制摄像头 腾讯云 sdk 默认为前置摄像头(可以通过修改 TXLivePushConfig 的配置函数 setFrontCamera 来修改默认值),调用一次 switchCamera 就切换一次,注意切换摄像头前要确保 TXLivePushConfig 和 TXLivePusher 对象已经初始化。 mLivePushConfig.setFrontCamera(true); // 默认前置摄像头。 mLivePusher.switchCamera; //切换摄像头。 ⑦ 设置徽标水印 腾讯视频云目前支持两种设置水印的方式:一种是在流媒体 SDK 中设置水印,原理是在 SDK 中对视频进行编码前在画面中设置水印。另一种方式是在云端设置水印,即由云端解析视频并添加水印标识。 建议使用 SDK 添加水印,因为在云端添加水印会有问题。下面是添加水印的 SDK 介绍: //设置视频水印 mLivePushConfig.setWatermark(BitmapFactory.decodeResource(getResources,R.drawable.watermark), 10, 10); // 最后两个参数是视频的水印。 //最后两个参数是水印位置的 X 轴和 Y 轴坐标。 mLivePusher.setConfig(mLivePushConfig); 如果需要对水印图像的位置进行模型适配,则需要调用水印规范化接口。 /设置视频水印 mLivePushConfig.setWatermark(mBitmap, 0.02f, 0.05f, 0.2f); //参数为水印图像。 //参数包括水印图像的位图、水印位置的 X 轴坐标、水印位置的 Y 轴坐标和水印宽度。后三个参数的范围是 [0,1]。 // 最后两个参数是水印位置的 X 轴坐标和 Y 轴坐标。 mLivePusher.setConfig(mLivePushConfig); TXLivePushConfig 中的 setHardwareAcceleration 方法可以启用或禁用硬件编码。 if (mHWVideoEncode){ if (mLivePushConfig ! = null) { if (Build.VERSION.SDK_INT < 18){ Toast.makeText(getApplicationContext, "Hardware acceleration failed, current phone API level is too low (min 18)"、 Toast.LENGTH_SHORT).show; mHWVideoEncode = false; } } } } mLivePushConfig.setHardwareAcceleration(mHWVideoEncode ? TXLiveConstants.ENCODE_VIDEO_HARDWARE : TXLiveConstants.ENCODE_VIDEO_SOFTWARE); mLivePusher.setConfig(mLivePushConfig); // 如果您不确定何时启用硬件加速,建议将其设置为 ENCODE_VIDEO_AUTO。 // 默认情况下启用软件编码,但如果手机的 CPU 使用率超过 80% 或帧速率为 10,SDK 将自动切换到硬件编码。 ⑨ 后台推流 在常规模式下,一旦应用程序进入后台,摄像头捕捉数据的能力就会被 Android 禁用,这意味着 SDK 无法继续捕捉和编码音频和视频数据。如果我们什么都不做,故事就会按照下面的脚本发展: 阶段 1(背景剪切后 10 秒 ->)- CDN 无法将视频流传输给观众,因为没有数据,观众看到的是主帧。 阶段 2(10 秒-> 70 秒)--观众一方的播放器因无法接收到直播流而退出,房间里空无一人。 第 3 阶段(70 秒后)--服务器直接断开了推送流媒体的 RTMP 链接,主播需要重新打开直播才能继续。 主播可能只是短暂地接了一个紧急电话,但各云提供商的安全措施会迫使主播的直播提前结束。 1) 设置 setPauseFlag 在开始推流之前,使用 TXLivePushConfig 的 setPauseImg 接口设置一个等待图像,其含义建议为 "主播将暂时离开,稍后再回来"。
-
F#探险之旅(二):函数式编程(上)-函数式编程范式简介 F#主要支持三种编程范式:函数式编程(Functional Programming,FP)、命令式编程(Imperative Programming)和面向对象(Object-Oriented,OO)的编程。回顾它们的历史,FP是最早的一种范式,第一种FP语言是IPL,产生于1955年,大约在Fortran一年之前。第二种FP语言是Lisp,产生于1958,早于Cobol一年。Fortan和Cobol都是命令式编程语言,它们在科学和商业领域的迅速成功使得命令式编程在30多年的时间里独领风骚。而产生于1970年代的面向对象编程则不断成熟,至今已是最流行的编程范式。有道是“*代有语言出,各领风骚数十年”。 尽管强大的FP语言(SML,Ocaml,Haskell及Clean等)和类FP语言(APL和Lisp是现实世界中最成功的两个)在1950年代就不断发展,FP仍停留在学院派的“象牙塔”里;而命令式编程和面向对象编程则分别凭着在商业领域和企业级应用的需要占据领先。今天,FP的潜力终被认识——它是用来解决更复杂的问题的(当然更简单的问题也不在话下)。 纯粹的FP将程序看作是接受参数并返回值的函数的集合,它不允许有副作用(side effect,即改变了状态),使用递归而不是循环进行迭代。FP中的函数很像数学中的函数,它们都不改变程序的状态。举个简单的例子,一旦将一个值赋给一个标识符,它就不会改变了,函数不改变参数的值,返回值是全新的值。 FP的数学基础使得它很是优雅,FP的程序看起来往往简洁、漂亮。但它无状态和递归的天性使得它在处理很多通用的编程任务时没有其它的编程范式来得方便。但对F#来说这不是问题,它的优势之一就是融合了多种编程范式,允许开发人员按照需要采用最好的范式。 关于FP的更多内容建议阅读一下这篇文章:Why Functional Programming Matters(中文版)。F#中的函数式编程 从现在开始,我将对F#中FP相关的主要语言结构逐一进行介绍。标识符(Identifier) 在F#中,我们通过标识符给值(value)取名字,这样就可以在后面的程序中引用它。通过关键字let定义标识符,如: let x = 42 这看起来像命令式编程语言中的赋值语句,两者有着关键的不同。在纯粹的FP中,一旦值赋给了标识符就不能改变了,这也是把它称为标识符而非变量(variable)的原因。另外,在某些条件下,我们可以重定义标识符;在F#的命令式编程范式下,在某些条件下标识符的值是可以修改的。 标识符也可用于引用函数,在F#中函数本质上也是值。也就是说,F#中没有真正的函数名和参数名的概念,它们都是标识符。定义函数的方式与定义值是类似的,只是会有额外的标识符表示参数: let add x y = x + y 这里共有三个标识符,add表示函数名,x和y表示它的参数。关键字和保留字关键字是指语言中一些标记,它们被编译器保留作特殊之用。在F#中,不能用作标识符或类型的名称(后面会讨论“定义类型”)。它们是: abstract and as asr assert begin class default delegate do donedowncast downto elif else end exception extern false finally forfun function if in inherit inline interface internal land lazy letlor lsr lxor match member mod module mutable namespace new nullof open or override private public rec return sig static structthen to true try type upcast use val void when while with yield 保留字是指当前还不是关键字,但被F#保留做将来之用。可以用它们来定义标识符或类型名称,但编译器会报告一个警告。如果你在意程序与未来版本编译器的兼容性,最好不要使用。它们是: atomic break checked component const constraint constructor continue eager event external fixed functor global include method mixinobject parallel process protected pure sealed trait virtual volatile 文字值(Literals) 文字值表示常数值,在构建计算代码块时很有用,F#提供了丰富的文字值集。与C#类似,这些文字值包括了常见的字符串、字符、布尔值、整型数、浮点数等,在此不再赘述,详细信息请查看F#手册。 与C#一样,F#中的字符串常量表示也有两种方式。一是常规字符串(regular string),其中可包含转义字符;二是逐字字符串(verbatim string),其中的(")被看作是常规的字符,而两个双引号作为双引号的转义表示。下面这个简单的例子演示了常见的文字常量表示: let message = "Hello World"r"n!" // 常规字符串let dir = @"C:"FS"FP" // 逐字字符串let bytes = "bytes"B // byte 数组let xA = 0xFFy // sbyte, 16进制表示let xB = 0o777un // unsigned native-sized integer,8进制表示let print x = printfn "%A" xlet main = print message; print dir; print bytes; print xA; print xB; main Printf函数通过F#的反射机制和.NET的ToString方法来解析“%A”模式,适用于任何类型的值,也可以通过F#中的print_any和print_to_string函数来完成类似的功能。值和函数(Values and Functions) 在F#中函数也是值,F#处理它们的语法也是类似的。 let n = 10let add a b = a + blet addFour = add 4let result = addFour n printfn "result = %i" result 可以看到定义值n和函数add的语法很类似,只不过add还有两个参数。对于add来说a + b的值自动作为其返回值,也就是说在F#中我们不需要显式地为函数定义返回值。对于函数addFour来说,它定义在add的基础上,它只向add传递了一个参数,这样对于不同的参数addFour将返回不同的值。考虑数学中的函数概念,F(x, y) = x + y,G(y) = F(4, y),实际上G(y) = 4 + y,G也是一个函数,它接收一个参数,这个地方是不是很类似?这种只向函数传递部分参数的特性称为函数的柯里化(curried function)。 当然对某些函数来说,传递部分参数是无意义的,此时需要强制提供所有参数,可是将参数括起来,将它们转换为元组(tuple)。下面的例子将不能编译通过: let sub(a, b) = a - blet subFour = sub 4 必须为sub提供两个参数,如sub(4, 5),这样就很像C#中的方法调用了。 对于这两种方式来说,前者具有更高的灵活性,一般可优先考虑。 如果函数的计算过程中需要定义一些中间值,我们应当将这些行进行缩进: let halfWay a b = let dif = b - a let mid = dif / 2 mid + a 需要注意的是,缩进时要用空格而不是Tab,如果你不想每次都按几次空格键,可以在VS中设置,将Tab字符自动转换为空格;虽然缩进的字符数没有限制,但一般建议用4个空格。而且此时一定要用在文件开头添加#light指令。作用域(Scope)作用域是编程语言中的一个重要的概念,它表示在何处可以访问(使用)一个标识符或类型。所有标识符,不管是函数还是值,其作用域都从其声明处开始,结束自其所处的代码块。对于一个处于最顶层的标识符而言,一旦为其赋值,它的值就不能修改或重定义了。标识符在定义之后才能使用,这意味着在定义过程中不能使用自身的值。 let defineMessage = let message = "Help me" print_endline message // error 对于在函数内部定义的标识符,一般而言,它们的作用域会到函数的结束处。 但可使用let关键字重定义它们,有时这会很有用,对于某些函数来说,计算过程涉及多个中间值,因为值是不可修改的,所以我们就需要定义多个标识符,这就要求我们去维护这些标识符的名称,其实是没必要的,这时可以使用重定义标识符。但这并不同于可以修改标识符的值。你甚至可以修改标识符的类型,但F#仍能确保类型安全。所谓类型安全,其基本意义是F#会避免对值的错误操作,比如我们不能像对待字符串那样对待整数。这个跟C#也是类似的。 let changeType = let x = 1 let x = "change me" let x = x + 1 print_string x 在本例的函数中,第一行和第二行都没问题,第三行就有问题了,在重定义x的时候,赋给它的值是x + 1,而x是字符串,与1相加在F#中是非法的。 另外,如果在嵌套函数中重定义标识符就更有趣了。 let printMessages = let message = "fun value" printfn "%s" message; let innerFun = let message = "inner fun value" printfn "%s" message innerFun printfn "%s" message printMessages 打印结果: fun value inner fun valuefun value 最后一次不是inner fun value,因为在innerFun仅仅将值重新绑定而不是赋值,其有效范围仅仅在innerFun内部。递归(Recursion)递归是编程中的一个极为重要的概念,它表示函数通过自身进行定义,亦即在定义处调用自身。在FP中常用于表达命令式编程的循环。很多人认为使用递归表示的算法要比循环更易理解。 使用rec关键字进行递归函数的定义。看下面的计算阶乘的函数: let rec factorial x = match x with | x when x < 0 -> failwith "value must be greater than or equal to 0" | 0 -> 1 | x -> x * factorial(x - 1) 这里使用了模式匹配(F#的一个很棒的特性),其C#版本为: public static long Factorial(int n) { if (n < 0) { throw new ArgumentOutOfRangeException("value must be greater than or equal to 0"); } if (n == 0) { return 1; } return n * Factorial (n - 1); } 递归在解决阶乘、Fibonacci数列这样的问题时尤为适合。但使用的时候要当心,可能会写出不能终止的递归。匿名函数(Anonymous Function) 定义函数的时候F#提供了第二种方式:使用关键字fun。有时我们没必要给函数起名,这种函数就是所谓的匿名函数,有时称为lambda函数,这也是C#3.0的一个新特性。比如有的函数仅仅作为一个参数传给另一个函数,通常就不需要起名。在后面的“列表”一节中你会看到这样的例子。除了fun,我们还可以使用function关键字定义匿名函数,它们的区别在于后者可以使用模式匹配(本文后面将做介绍)特性。看下面的例子: let x = (fun x y -> x + y) 1 2let x1 = (function x -> function y -> x + y) 1 2let x2 = (function (x, y) -> x + y) (1, 2) 我们可优先考虑fun,因为它更为紧凑,在F#类库中你能看到很多这样的例子。 注意:本文中的代码均在F# 1.9.4.17版本下编写,在F# CTP 1.9.6.0版本下可能不能通过编译。 F#系列随笔索引页面