乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 73|回复: 6

F#-选择点和实体

[复制链接]

69

主题

875

帖子

15

银币

顶梁支柱

Rank: 50Rank: 50

铜币
1146
发表于 2015-5-5 00:58:54 | 显示全部楼层 |阅读模式
大家好,刚刚开始用F#做一些实际的工作,不知道这里的其他fsharpers会如何处理下面的情况。一个简单的场景是,我们需要向用户要求2点,他们可以随时退出,因此我们需要能够优雅地退出当前功能。有几个方法可以做到这一点,但我更愿意坚持使用功能性更强的方法,而不是if else之类的方法。下面是我对在实体的点处添加引线的看法,引线文本可能是来自所选实体的数据,以及我将id与点一起传递的原因:    let add something()= 。
让ed = AcAp,document manager . mdiactivedocument . editor 。
let entResult = ed,GetEntity("在引线起点选择一个实体:\n")。
匹配entResult,的状态。
| PromptStatus,确定--> 。
让pointResult = ed,GetPoint("选择对象文本的插入点:\n")。
匹配点结果,的状态。
| PromptStatus,确定-> doSpecialLeader entResult,ObjectId entResult。PickedPoint点结果,Value //绘制引线文本的函数。
| _ -> ()。
| _ -> ()。
您会如何做?。

本帖以下内容被隐藏保护;需要你回复后,才能看到!

游客,如果您要查看本帖隐藏内容请回复
回复

使用道具 举报

15

主题

687

帖子

169

银币

中流砥柱

Rank: 25

铜币
582
发表于 2015-5-5 01:42:07 | 显示全部楼层
嗨,在我看来,因为add在一般情况下是一个命令函数(Unit->unit),只有一个副作用(调用另一个命令函数),并且不需要其他东西,所以我会用这种简单的方式编写它:让addWhat () =。
让ed=AcAp.DocumentManager.MdiActiveDocument.Editor。
let entResult=ed.GetEntity("在领导者起始点选择一个实体:\n")。
如果entResult=PromptStatus.OK则。
let point Result=ed.GetPoint("为对象文本选择插入点:\n")。
如果指向结果=PromptStatus.OK则。
entResult.ObjectIdentResult.PickedPointpointResult.Value。
回复

使用道具 举报

69

主题

875

帖子

15

银币

顶梁支柱

Rank: 50Rank: 50

铜币
1146
发表于 2015-5-5 02:10:50 | 显示全部楼层

谢谢Gile,这很有意义,而且几乎就是我开始时的样子,只是想使用F#的FP端来掌握它的窍门。
如您所说,作为命令式函数,使用模式匹配可能没有真正的优势,除非您有多个模式要匹配(即开关情况或如果有其他序列)。
很容易想在任何地方更改和使用函数式,但我转向F#的主要原因之一是F#中的简洁和命令式编码绝对节省了一些打字。
回复

使用道具 举报

15

主题

687

帖子

169

银币

中流砥柱

Rank: 25

铜币
582
发表于 2015-5-5 06:49:13 | 显示全部楼层
我发现在某些情况下使用避免深度嵌套if-then-else子句的技术是有帮助的,有关该问题的概述,请参见例如面向铁路的规划。   //将区分的联合作为结果类型来封装任一项。
//成功,进入下一阶段,取消。
//或带有错误字符串的失败。
类型Res =。
|的下一个。
|取消。
|字符串失败。

//按照管道运算符的方式定义一个运算符,。
//它需要从PromptResult类型派生的任何内容。
//作为第一个参数,并调用secon dargument函数。
//如果成功。
let (|?>)(pr : #PromptResult) f =。
匹配pr,的状态。
| PromptStatus,确定-> f pr。
| PromptStatus,取消->取消。
| _-->失败您的示例现在变成了...    let add something()= 。
ed,GetEntity "在引线起点选择一个实体:" 。
|?> fun entResult--> 。
ed,GetPoint "选择对象文本的插入点:" 。
|?>有趣的积分结果--> 。
//您的foo放在这里...。
Next() //无值返回成功(单位)。

addSomething () | >函数。
|失败消息-> ed,WriteMessage("休斯顿,我们遇到了一个问题:{0} ",msg)。
| _ -> ()。
回复

使用道具 举报

3

主题

28

帖子

1

银币

初来乍到

Rank: 1

铜币
40
发表于 2015-5-5 08:19:21 | 显示全部楼层
谢谢凯弗,干得好
感谢您的链接!
回复

使用道具 举报

69

主题

875

帖子

15

银币

顶梁支柱

Rank: 50Rank: 50

铜币
1146
发表于 2015-5-5 17:34:44 | 显示全部楼层
嗨,另一种方式(不像kaefer的那么优雅)应该是使用成功/失败工作流程。定义通用成功/失败工作流生成器type Attempt = (unit -> 'a option)。

类型 AttemptBuilder() = 。
让成功 x = (fun () -> Some(x)) : 尝试。
let fail = (fun () -> None) : Try。
let runAttempt (a : Try) = a()。
让 bind p rest = match runAttempt p with None -> fail |一些 r -> (其余 r)。
让延迟 f = (fun () -> runAttempt (f()))。

成员 b.Bind(p, rest) = bind p rest。
成员 b.延迟(f) = 延迟 f。
成员 b.Let(p, rest) : 尝试 = rest p。
成员 b.返回(x) = 成功 。
成员 b.零() = 失败。

lettryt = new AttemptBuilder()为 PromptResult 派生类型构建尝试值:let failIfNotOk (pr : #PromptResult) = 。
尝试 { 如果 pr.状态 = PromptStatus.OK 然后返回 pr }使用函数中的工作流,假设 doSpecialLeader 返回新创建的 leader ObjectId,drawLeader 返回一个 ObjectId 选项(此处忽略): let drawLeader = try {。
let! entResult = failIfNotOk (ed.GetEntity(“在引线起始点处选择一个实体:\n”))。
let! pointResult = failIfNotOk (ed.GetPoint(“为对象文本选择插入点:\n”))。
return doSpecialLeader entResult.ObjectId entResult.PickedPoint pointResult.Value }。

drawLeader() |> ignore您可以使用工作流中的第一个PrompterResult值:让drawLeader = try {。
let! entResult = failIfNotOk (ed.GetEntity(“在引线起始点处选择一个实体:\n”))。
let opts = new PromptPointOptions(“为对象文本选择插入点:\n”)。
选择,UseBasePoint 。
选择,基点 。
let! pointResult = failIfNotOk (ed.GetPoint(opts))。
return doSpecialLeader entResult.ObjectId entResult.PickedPoint pointResult.Value }。

drawLeader() |> ignore。
回复

使用道具 举报

15

主题

687

帖子

169

银币

中流砥柱

Rank: 25

铜币
582
发表于 2015-5-9 06:32:24 | 显示全部楼层
多亏了吉尔,计算表达式(类似于单子)确实非常强大,而且非常灵活忽略。
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2025-2-5 02:42 , Processed in 0.235601 second(s), 66 queries .

© 2020-2025 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表