Microsoft Power Fx 概述

Power Fx 是用于 Microsoft Power Platform 的低代码语言。 它是一种强类型、声明性、一般用途的函数式编程语言。

Power Fx 以人性化的文本表达。 它是一种低代码语言,制作者可以直接在类似 Excel 的公式栏或 Visual Studio Code 文本窗口中使用。 低代码中的“低”是由于语言的简洁性和简单性,让制作者和开发人员都可以轻松进行一般的编程任务。 它可以进行从面向没有编程经验的用户的无代码到面向经验丰富的专业人士的“专业代码”的全面开发,无需通过学习或重写来解决二者之间的差异,从而使不同的团队可以协作并节省时间和费用。

备注

  • Microsoft Power Fx 是 Power Apps 中画布应用的公式语言的新名称。 当我们从画布应用中提取语言,将其与其他 Microsoft Power Platform 产品集成并使其作为开放源代码提供时,此概述和相关文章还在撰写。 要现在了解此语言的更多信息并体验此语言,请从 Power Apps 文档中的开始使用画布应用中的公式开始,并注册免费的 Power Apps 试用
  • 在本文中,当我们描述可能在编程技能范围的任一端使用的功能时,我们指的是制作者。 如果功能更高级并且可能超出典型 Excel 用户的范围,我们所说的用户是指开发人员

Power Fx 将对象与声明性的电子表格式公式绑定在一起。 例如,将 UI 控件的 Visible 属性视为 Excel 工作表中的单元格,它具有基于其他控件的属性来计算其值的关联公式。 公式逻辑会自动重新计算该值,这与电子表格的方式类似,这会影响控件的可见性。

此外,Power Fx 还可以在需要时提供命令性逻辑。 工作表通常没有可以将更改提交到数据库的按钮,但是应用通常会有。 相同的表达式语言用于声明性和命令性逻辑。

Power Fx 将作为开源软件提供。 它目前已集成到画布应用中,我们正在从 Power Apps 中提取它以用于其他 Microsoft Power Platform 产品并用作开源软件。 详细信息:GitHub 上的 Microsoft Power Fx

本文概述了语言及其设计原则。 要了解有关 Power Fx 的详细信息,请参阅以下文章:

视为电子表格

假如您可以像在 Excel 中构建工作表一样轻松地构建应用会怎样?

假如您可以利用现有的电子表格知识会怎样?

这些问题启发了 Power Apps 和 Power Fx 的创建。 每天有亿万用户使用 Excel 创建工作表;让我们来为他们带来轻松的应用创建,使用他们已经知道的 Excel 概念。 通过将 Power Fx 从 Power Apps 中分离出来,我们将针对楼宇自动化、虚拟代理或其他领域回答这些问题。

所有编程语言,包括 Power Fx,都有表达式:一种表示对数字、字符串或其他数据类型的计算的方法。 例如,在大多数语言中,mass * acceleration 表示 massacceleration 的乘法。 表达式的结果可以放置在变量中、用作过程的参数或嵌套在较大的表达式中。

Power Fx 推进了这一步。 表达式本身并不能说明计算的内容。 是由制作者来决定将其放在变量中还是传递给函数。 在 Power Fx 中,不是只编写一个没有特定含义的表达式,而是编写一个将表达式绑定到标识符的公式。 您编写 force = mass * acceleration 作为计算 force 的公式。 当 massacceleration 发生更改时,force 会自动更新为新值。 表达式描述了一个计算,公式为该计算给出一个名称,将该计算用作方法。 这是我们为何将 Power Fx 称为公式语言的原因。

例如,此来自 Stack Overflow 的公式以相反顺序搜索字符串。 在 Excel 中,它看起来类似下图。

反向搜索

Excel 中带有公式的公式栏的屏幕截图:=RIGHT(A1,LEN(A1)- FIND("|", SUBSTITUTE(A1," ","|", LEN(A1)-LEN(SUBSTITUTE(A1," ","")))) 单元格 A1 包含文本“Hello, World! It is great to meet you!”单元格 A2 包含文本“you!”

Power Fx 使用相同的公式,将单元格引用替换为控件属性引用:

Power Fx 反向搜索。

Power Apps 中 Power Fx 公式栏的屏幕截图。 公式为 =RIGHT(Input.Text,Len(Input.Text)- FIND("|", SUBSTITUTE(Input.Text," ","|", Len(Input.Text)-Len(Substitute(Input.Text," ","")))) 在公式下方的“输入”框中,输入文本“Hello, World! It is great to meet you!”逐个字母地出现。 同时在“标签”框中,最后一个单词的字母出现。 当完整文本出现在“输入”框中时,单词“you!”出现在“标签”框中。

当更改 Input 控件值时,Label 控件将自动重新计算公式并显示新值。 此处没有在其他语言中常见的 OnChange 事件处理程序。

另一个示例是针对屏幕的 Fill 颜色使用公式。 当控制红色、绿色和蓝色的滑块发生更改时,背景颜色会自动更改,因为它在被重新计算。

颜色滑块。

没有在其他语言中常见的用于滑块控件的 OnChange 事件。 完全没有办法显式设置 Fill 属性值。 如果颜色未按预期工作,您需要查看此公式来了解它为什么不工作。 您无需在应用中进行搜索来查找在意外时间设置属性的代码片段;没有时间元素。 正确的公式值始终会保留。

当滑块设置为深色时,“红色”、“绿色”和“蓝色”的标签将更改为白色以进行补色。 这通过每个标签控件的 Color 属性上的简单公式完成。

Power Fx 颜色滑块。

这样做的一大好处是,它与 Fill 颜色发生的行为是独立的:它们是两个完全不同的计算。 Power Fx 逻辑通常由很多独立的较小公式组成,而不是大型的整体过程。 这让它们更易于理解,并且可以在不干扰现有逻辑的情况下支持功能增强。

Power Fx 是一种声明性语言,就像 Excel 一样。 制作者定义他们需要的行为,但是由系统确定和优化如何以及何时完成该行为。 为了可以实际应用,大多数工作通过没有副作用的纯函数完成,使 Power Fx 也可以充当一种函数语言(同样与 Excel 一样)。

始终实时

工作表的一个定义的方面是它们始终是活动的,并且更改会立即反映出来。 工作表中没有编译或运行模式。 修改公式或输入值后,会立即重新计算工作表来反映这些更改。 检测到的任何错误都会立即呈现,不会干扰工作表的其余部分。

通过 Power Fx 实现了相同的目的。 增量编译器用于让程序与正在运行的数据持续保持同步。 更改会在程序的图中自动传播,影响相关计算的结果,这可能会驱动控件的属性(如颜色或位置)。 增量编译器还提供丰富的公式编辑体验,包括 IntelliSense、建议、自动完成和键入检查。

在下面的动画中,订单号显示在依赖于滑块控件的标签控件中,即使它下面的标签上存在两个错误。 该应用非常活跃,并且具有交互性。 通过输入 .InvalidName 结果修复公式的第一次尝试应该会立即显示一条红线并显示错误,但应用会保持运行。

始终实时。

当输入 .Employee 时,这将导致 Data 窗格添加“员工”表,检索此表的元数据,并立即提供有关列的建议。 我们刚刚演练了从一个表到另一个表的关系,系统对应用的引用进行了必要的调整。 添加 .Customer 时会发生相同的情况。

每次更改后,滑块将继续其最后一个值,并且所有变量都保留其值。 在整个过程中,订单号按预期继续显示在顶部标签中。 应用保持实时状态,一直处理实际数据。 我们可以在保存后离开,其他人可以像使用 Excel 一样打开并使用它。 没有构建步骤,没有编译步骤,只有发布步骤来确定为用户准备好的应用版本。

低代码

Power Fx 使用简洁而强大的公式描述业务逻辑。 大多数逻辑都可以简化为一行,其中包含丰富的表达能力和控制以满足更复杂的需求。 目标是将制作者需要了解的概念数降到最低—在理想情况下,不超过 Excel 用户已知的概念数。

例如,要查找订单中员工的名字,您可以编写 Power Fx,如下面的动画所示。 除 Excel 概念外,此处使用的唯一增加的概念是点 "." 表示法,用它来钻取数据结构,在本例中为 .Employee.'First Name'。 此动画演示了 Power Fx 公式的各个部分与需要在等效 JavaScript 中显式编码的概念之间的映射。

低代码 JavaScript。

我们来更深入地了解一下 Power Fx 为我们所做的所有事情,以及由于公式是声明性的,它必须优化的自由度:

  • 异步:Power Fx 中的所有数据操作都是异步的。 制作者不需要对此进行指定,也不需要在调用结束后同步操作。 制作者根本不需要知道此概念,也不需要了解什么是 promise 或 lambda 函数。

  • 本地和远程:Power Fx 对内存中的本地数据和数据库或服务中的远程数据使用相同的语法和函数。 用户不需要考虑此区别。 Power Fx 会自动将它可以完成的任务委派给服务器,以更有效地处理筛选器和排序。

  • 关系数据:订单和客户是两个不同的表,具有多对一关系。 OData 需要“$expand”以及有关外键(类似于 SQL 中的联接)的知识。 公式中没有此内容,实际上,数据库密钥是制作者无需了解的另一个概念。 制作者可以使用简单的点表示法从记录中访问关系的整个图形。

  • 投影:编写查询时,很多开发人员会编写 select * from table,这会返回所有数据列。 Power Fx 会分析整个应用中使用的所有列,甚至跨公式依赖项分析。 投影会自动优化,同样,制作者不需要知道“投影”的含义。

  • 仅检索所需内容:在此示例中,LookUp 函数意味着只应检索一条记录,这就是返回的全部内容。 如果使用 Filter 函数请求更多记录—可能有数千条记录符合条件,一次将仅返回一页数据,每页大约 100 条记录。 用户必须对库或数据表进行手势操作来查看更多数据,系统会自动为他们引入数据。 制作者可以推出大型数据集,而无需考虑将数据请求限制为可管理的区块。

  • 仅在需要时运行:我们为标签控件的 Text 属性定义了一个公式。 当所选变量发生更改时,LookUp 将自动重新计算并且标签将更新。 制作者不需要为“选择”编写 OnChange 处理程序,也不需要记住此标签依赖于它。 这是如前所述的声明性编程:制作者指定他们想要在标签中包括哪些内容,而没有指定获取它的方式或时间。 如果此标签不可见是因为它在屏幕上不可见,或者它的 Visible 属性为 false,我们可以将此计算推迟到标签可见之后,来有效地消除这种情况(如果这种情况很少发生)。

  • Excel 语法翻译:很多用户都使用 Excel,其中大多数人都知道与号 (&) 用于字符串连接。 JavaScript 使用加号 (+),其他语言使用点 (.)。

  • 显示名称和本地化First Name 在 Power Fx 公式中使用,而 nwind_firstname 在 JavaScript 等效项中使用。 在 Microsoft Dataverse 和 SharePoint 中,除了唯一的逻辑名称外,还有列和表的显示名称。 在这种情况下,显示名称通常要对用户友好得多,但是它们还有另一个重要的品质,就是它们可以本地化。 如果您有一个多语言团队,每个团队成员都可以使用自己的语言查看表和字段名称。 在所有用例中,Power Fx 会确保正确的逻辑名称被自动发送到数据库。

无代码

您不必读写 Power Fx 即可开始表达逻辑。 可以通过简单切换和 UI 生成器表达许多自定义和逻辑。 这些无代码工具用于读写 Power Fx,以确保有足够的空余空间让用户可以进一步操作,同时确认无代码工具永远不会提供完整语言的所有表达能力。 即使与无代码构建器一起使用,公式栏也位于 Power Apps 的前面和中心,以训练制作者在代表他们做什么,让他们可以开始学习 Power Fx。

让我们来看看一些示例。 在 Power Apps 中,属性窗格为控件的属性提供无代码切换和旋钮。 实际上,大多数属性值都是静态值。 您可以使用颜色生成器来更改 Gallery 的背景颜色。 请注意,公式栏将反映此更改,将公式更新为其他 RGBA 调用。 您随时可以转到公式栏,进一步进行操作—在本示例中,是使用 ColorFade 调整颜色。 颜色属性仍会显示在属性面板中,但是将鼠标悬停在上面时会显示 fx 图标,您将被定向到公式栏。 这可以通过两种方式完全实现:删除 ColorFade 调用将使颜色返回到属性面板可以理解的内容,您可以再次使用它来设置颜色。

无代码颜色。

下面是一个更复杂的示例。 库显示来自 Dataverse 的员工列表。 Dataverse 提供表数据的视图。 我们可以选择这些视图之一,公式将更改为使用包含此视图名称的 Filter 函数。 两个下拉菜单可用于拨入正确的表和视图,而无需接触公式栏。 但是,假设您需要进一步处理,添加排序。 我们可以在公式栏中执行此操作,属性面板将再次显示 fx 图标并将修改定向到公式栏。 同样,如果我们将公式简化为属性面板可以读取和写入的内容,可以再次使用它。

无代码排序。

这些都是简单的示例。 我们认为 Power Fx 是描述无代码交互的理想语言。 该语言简明、强大且易于分析,并提供对低代码“无差异”所需的常用净空。

专业代码

低代码制作者有时会构建需要专家帮助或由专业开发人员接管的东西,以进行维护和增强。 专业人士也赞同,与生成专业工具相比,低代码开发更容易、更快速且成本更低。 并非所有情况都需要 Visual Studio 的完整功能。

专业人士希望使用专业工具来提高效率。 Power Fx 公式可以存储在 YAML 源文件中,这样可以方便使用 Visual Studio Code、Visual Studio 或任何其他文本编辑器进行编辑,并让 Power Fx 可以置于 GitHub、Azure DevOps 或任何其他源代码管理系统的源代码管理之下。

专业代码 Visual Studio Code。

专业代码 GitHub。

Power Fx 支持基于公式的组件进行共享和重用。 我们宣布了支持组件属性的参数,支持创建纯用户定义的函数,并在此过程中进行更多增强。

此外,Power Fx 擅长将专业人员构建的组件和服务拼接在一起。 现成可用的连接器提供对数百个数据源和 Web 服务的访问,自定义连接器使 Power Fx 能够与任何 REST Web 服务通信,代码组件使 Power Fx 能够与屏幕和页面上的完全自定义 JavaScript 交互。

设计原则

简单

Power Fx 主要面向未受过开发人员培训的制作者受众。 如果可能,我们使用此访问群体已知或者可以快速汲取的知识。 成功所需的概念数将降到最低。

设计简单对开发人员也有益。 对于开发人员访问群体,我们旨在设计一种可以减少生成解决方案所需时间的低代码语言。

Excel 一致性

Microsoft Power Fx 语言大量借用 Excel 公式语言。 我们寻求利用很多也使用 Excel 的制作者的 Excel 知识和经验。 类型、运算符和函数语义尽可能与 Excel 接近。

如果 Excel 没有答案,我们接下来会期待 SQL。 在 Excel 之后,SQL 是下一种最常用的声明性语言,它可以提供有关 Excel 不提供的数据操作和强键入的指导。

声明性

制作者描述他们希望自己的逻辑做什么,而不是确切的如何何时做。 这让编译器可以通过并行执行操作,将工作推迟到需要时以及预取和重用缓存的数据来进行优化。

例如,在 Excel 工作表中,作者定义单元格之间的关系,但是 Excel 决定何时以及以什么顺序对公式进行求值。 类似地,应用中的公式可以根据需要基于用户操作、数据库更改或计时器事件,被视为的“recalc-ing”。

函数式

我们偏爱没有副作用的纯函数。 这样可以使逻辑更容易理解,并为编译器提供最大的优化自由。

与 Excel 不同,应用本质上确实会改变状态—例如,应用具有将更改保存到数据库中记录的按钮。 因此,某些函数确实有副作用,尽管我们已尽可能限制它。

组合

在可能的情况下,添加的功能可以与现有功能很好地结合在一起。 强大的函数可以分解为较小部分,它们更易于单独使用。

例如,控件没有单独的 SortFilter 属性。 相反,SortFilter 函数将组合成一个 Items 属性。 表达 SortFilter 行为的 UI 通过为此属性使用双向编辑器,被放置在 Items 属性的上层。

强类型

所有值的类型在编译时已知。 这允许在创作时及早检测到错误并提供丰富的建议。

支持多态类型,但是必须先将其类型固定为静态类型,并且必须在编译时知道该类型,才能够使用它们。 提供 IsTypeAsType 函数以测试和转换类型。

类型推理

类型从其使用中派生,不需要声明。 例如,将变量设置为数字会导致变量的类型被建立为数字。

类型使用冲突会导致编译时错误。

区域设置相关小数分隔符

世界上有些区域使用点 (.) 作为小数点分隔符,而其他区域使用逗号 (,)。 这也是 Excel 功能。 其他编程语言通常不会这样做,这些语言通常为全球所有用户使用公认的点 (.) 作为小数点分隔符。 为了尽可能使所有级别的制作者都可以上手使用,对于一生中一直使用该语法的一个法国人来说,3,14 是一个十进制数字很重要。

选择小数分隔符对用于函数调用参数的列表运算符和链接运算符具有级联影响。

作者的语言小数分隔符 Power Fx 小数分隔符 Power Fx 列表分隔符 Power Fx 链接运算符
. (点) . (点) ,(逗号) ;(分号)
,(逗号) ,(逗号) ;(分号) ;;(双分号)

详细信息:全球支持

不面向对象

Excel 不是面向对象的,Power Fx 也不是。 例如,在某些语言中,字符串的长度表示为字符串的属性,例如 JavaScript 中的 "Hello World".length。 就函数而言,Excel 和 Power Fx 将此表示为 Len( "Hello World" )

具有属性和方法的组件是面向对象的,Power Fx 可以轻松使用它们。 但是,如果可能,我们更愿意使用函数式方法。

可扩展

制作者可以使用 Power Fx 本身来创建组件和功能。 开发人员可以通过编写 JavaScript 创建其组件和函数。

对开发人员友好

虽然制作者是我们的主要目标,但我们也尝试尽可能对开发人员友好。 如果与前面描述的设计原则不冲突,那么我们将以开发人员喜欢的方式来设计。 例如,Excel 没有添加注释的功能,因此我们使用类似于 C 的行和内联注释。

语言演变

不断发展的编程语言既必要又棘手。 每个人—都有理由担心更改可能破坏现有代码,而且需要用户学习新模式,无论更改的背后有多大的好意。 Power Fx 非常重视后向兼容性,但我们也确实认为我们不能总是在第一次就做好,我们会一同去了解一个社区怎样做是最好的。 我们必须继续发展,Power Fx 从一开始就设计了对语言发展的支持。

每个保存的 Power Fx 文档都带有一个语言版本标记。 如果我们要进行不兼容的更改,我们会编写称之为“反向兼容转换器”的功能,在下次公式被编辑时自动重写该公式。 如果更改是我们需要培训用户的主要内容,我们还将显示一条消息,其中包含指向文档的链接。使用此功能,我们仍然可以加载多年前使用 Power Apps 预览版构建的应用,不管那之后发生了多少更改。

例如,我们引入了 ShowError 函数来显示带有红色背景的错误横幅。

显示错误。

虽然用户喜欢它,但他们还请求我们提供一种显示成功横幅(绿色背景)或信息性横幅(蓝色背景)的方法。 因此,我们提出了一个更通用的 Notify 函数,来为通知类型获取第二个参数。 我们本来可以添加 Notify 并按原样保留 ShowError,但是我们改为用 Notify 代替 ShowError。 我们删除了以前一直使用的函数,用其他函数代替了它。 由于有两种方法可以做同一件事,因此,这会引起混乱—特别是对于新用户,最重要的是,这会增加复杂性。 没有人抱怨,所有人都赞成此更改,然后迁移到下一个通知功能。

这是相同的应用在加载到最新版本的 Power Apps 中时的外观。 用户无需执行任何操作即可进行此转换,它将在打开应用时自动发生。

Notify 函数替代 ShowError。

有了此服务,Power Fx 可以比大多数编程语言发展得更快、更积极。

无未定义值

有些语言(如 JavaScript)对未初始化的变量或缺少的属性使用未定义值的概念。 为了简单起见,我们避免了这个概念。 其他语言的未定义的实例将被视为错误或空值。 例如,所有取消初始化的变量以空值开头。 所有数据类型均可以使用空值。

Data types
运算符和标识符

变量
命令性逻辑
全球支持
表达式语法
YAML 公式语法
画布应用中的公式