一天,艾伦·埃利亚森读了一个放屁的笑话,非常生气,他发明了一种编程语言。20年后,Frink成为处理单元的最佳专用语言之一。
“但是,为什么我们只需要一种处理单位的语言呢?”很高兴你问了!
单位是数字表示的物理属性,如距离或时间。我们几乎总是在谈论国际单位,或国际系统。这是像米、秒、公斤这样的东西,还有像千和兆克这样的前缀。一公里=1000米,1厘米=1/100米。
单位可以有指数:M²表示平方米,m³表示立方米,m*s-1表示速度。这些形成了新的物理属性或尺寸。我们可以将不同维数的数字相乘和除法,但不能相加。我可以加1米+1米,但不能加1米+1公斤。支持单位的语言需要能够跟踪单位,并确保不添加不兼容的维度。它还应该确保我将正确的单元传递给依赖于单元的函数。压力计算需要面积和力,而不是频率和安培。
首先,单位有多种不同的表示法。有SI系统,所有理智、正确思维的国家都在使用,然后是美国系统。1英尺和米都是距离。把脚和米混在一起可以吗?这就是摧毁火星气候轨道器的虫子。但是也有一些有效的用例,您可能希望将它们混合在一起!当我做饭时,我使用公制重量和美国体积的混合,比如1杯水和128克面粉。在英国,啤酒是用品脱来计量的,但它的酒精体积是用SI来计量的。
不同的尺寸并不总是意味着单位是不兼容的。有一套非标准的单位叫做“高斯单位”,用于物理学的某些领域。在SI中,以法拉为单位测量电容,法拉的尺寸为A²s⁴kg-1 m−2。以高斯单位为单位,以厘米为单位测量电容。如果您明确表示要做什么,则可以添加这些看似不兼容的维度。
维度不是唯一的,两个不兼容的物理量可以具有相同的维度。典型的例子是能量和角力都是以牛顿米为单位测量的。2还有大量特定于领域的示例。当您进入重力井时,重力的变化率有N/m。表面张力也是以N/m为单位测量的。
200°+360°是什么?它可以是200°或560°,这取决于我们有一个“圆角”或一个“旋转角”(就像拧进螺钉一样)。
有些量是无单位的。20°+1弧度是多少?它们都是尺寸相容的无量纲的量。加两个比率怎么样?把弧度加到比率上怎么样?
单位可以有其他限制。您可以互相减去时间戳,但不能将它们相加。
单位可以具有不同的历史值。一英尺被定义为正好0.3048米。然而,在1959年之前,这是0.3048006米。这意味着所有的历史文献都有不同的脚的度量。有一段时间,我们在不同的地方使用了这两种定义!
不确定因素。如果你使用物理测量,你所有的测量都会有一定的不确定性。当你加两米,加或减一厘米时会发生什么?
如果你想了解更多关于邪恶单位的信息,请查看比尔·肯特的测量数据报告。
向一种语言添加度量单位是一件棘手的事情。这不仅仅是因为有许多硬域问题,在解决方案上也有不同的权衡。我们需要编译时还是运行时的正确性?单位应该是类型系统的一部分,还是有更好的表示法?我们如何处理派生单元?我们如何处理泛型?这里很好地概述了设计挑战,讨论了为Ada提出的一些解决方案。
本页介绍了各种语言如何进行度量。在很大程度上,他们将问题转嫁给预处理器和库,从而限制了他们能为您提供的帮助。唯一内置支持度量单位的主流语言是F#。F#专注于在编译时捕获所有错误。所有单位之间的换算都必须明确,因此不能意外添加英尺和米。这样做的代价是灵活性:您也不能添加厘米和米。
//质量,克。[<;Measure>;]键入g//质量,千克。[<;Measure>;]键入kg//定义转换常数。设grasPerKilgram:Float<;g kg^-1>;=1000。0<;g/kg>;//定义转换函数。设ConvertGramsToKilgram(x:Float<;g>;)=x/grasPerKilgram
对于F#的目标来说,这是一个很好的设计选择。它添加了样板文件,但不会让您的软件陷入混乱。这适用于工业软件,因为在工业软件中,很多人可能会受到bug的影响。
它不太适合低风险、小规模的工作。样板使交互使用变得更加困难。如果我想知道泰坦尼克号在米饭中的重量,我不想花十分钟写单位换算。为此,最常用的工具是Units,这是一个用于转换的GNU程序:
您有:12英尺+3英寸+3英寸|8英寸您想要:FT*12.28125/0.081424936。
Units是一款优秀的软件,但它不是一种编程语言。我想要一种语言,它有内置的量纲分析,但不需要太多的样板。比单位更强大但不像F#那么严格的东西。
这就是弗林克的用武之地。在Frink中,任何数字都可以使用单位进行标记。弗林克将阻止你添加不兼容的单位,与F#相同。
>;1米1米(长度)>;1米+2公斤添加时出错:米+2公斤原因:一致性异常:不能添加不同尺寸的单位。尺寸类型:M(长度)kg(质量)。
语法被设计成看起来像“自然”的数学运算,因此空格被算作乘法。1米实际上是1*米。这看起来可能会引起一些问题,但实际上挺不错的。这使得将方程式转换为Frink变得更容易。
通过使用->;运算符,我们可以在两个单位之间转换值。我们可以选择是否将单位名称包括在转换中,方法是将其放在引号中。
Frink附带了大量预定义的单位;它的默认单位文件超过5000行。
//如何测量,哦,测量一年?>;525600分钟->;年0.99933688171353600106>;525600分钟->;历史分析0.9992981356527034257>;525600分钟->;高斯0.99926355644744010579>;525600分钟->;日历1。
玉米特价销售:=0.25美元//如果我们有生活工资,你一天的劳动能买多少穗/玉米//?>;15美元/小时*8小时->;";玉米特价销售";480;玉米待售&>15美元/小时-&>#34;玉米待售/(8小时)";480.0玉米待售/(8小时)。
Frink中的前缀只是乘数。我可以写千英尺,它会自动知道这意味着“1000英尺”。弗林克还知道一些常见的术语,比如“一半”和“正方形”。
>;1公里->;[";千英尺&34;,";英尺#34;,";英寸&34;]3千英尺,280英尺,1280/127(约。10.078740157480315)英寸&>;1公里-&>[";千英尺&34;,";英尺&34;,";英寸";,0]3千英尺,280英尺,10英寸。
Frink函数的工作方式与预期不谋而合,但您需要强制参数符合尺寸和前提条件。
>;spherVolume[半径为长度]:=4/3圆周率半径^3>;spherVolume[2]调用函数spherVolume[2]时出错。体积:不满足约束--值必须具有长度尺寸。
>;HMS[1天]24小时0分0秒>;(10英里)/(3英里每小时)->;HMS3小时20分0秒
Frink真的在它的负担能力上大放异彩。如果人们要互动地使用它,它需要是令人愉快和合理的。弗林克做了很多小事来帮助做这件事。一些例子:
>;长度:->;[英尺,英寸,0]//现在所有长度都以英尺和英寸为单位,>;1米3,3//面积不受影响>;2 m*2 m4 m^2(面积)。
>;人口=!=人>;270万人/(5平方英里)->;(平方英尺)/人警告:倒数换算51.6266666666666665。
通过使用?str,您可以获得所有以str开头的现有单元的列表。通过使用??它还可以给出单位的价值。
?Foot[acreFoot,arabicFoot,assyrianFoot,BoardFoot,CordFoot,doricFoot,Early Roman Foot,Foot,Foalfield,Foot蜡烛,Foot Lambert,FrenchFoot,GreekFoot,NethernFoot,IrishFoot,LateromanFoot,NorthernFoot,olympicFoot,RomanFoot,ScotsFoot,SumerianFoot,TimberFoot]>;?footarabicFoot=0.270256米(。
有用于表示时间戳的特殊语法,这使得转换日期和时间变得很容易。
//会议是明天,巴黎时间下午3点,纽约是什么时间?>;#3pm巴黎#+1天-纽约#34;AD2020-07-10上午09:00:00.000(星期五)东部夏令时。
埃利亚森喜欢烹饪,所以弗林克有很多食物尺寸。很多烘焙食谱都需要大量的“过筛面粉”,但过筛既凌乱,又烦人,又不精确。我们应该用质量来衡量它们:
>;?面粉[面包粉_勺子,面包粉筛子,面包粉勺子,蛋糕面粉勺,蛋糕面粉筛子,蛋糕面粉勺,面粉勺,面粉筛子,面粉勺子]>;2.5杯面粉_筛分->;gram 283.49523125。
让我们做一些更复杂的事情。像埃利亚森一样,我也喜欢烹饪。虽然我主要做美味的菜肴,但我也擅长巧克力制作。我一直对我的每块巧克力有多少卡路里有一点好奇,所以让我们试着用Frink来计算一下。
在这个例子中,我将使用CIA书中的柴茶配方。3以下是配料表:
我从标签上拿出了每种配料的卡路里,除了牛奶巧克力,因为我是批量购买的。相反,我在这里找到了在线信息。不是同一种牛奶巧克力,不过估计一下就行了。
:->;更改默认单位表示。如果没有它,比能量将以基本国际单位表示,即每公斤焦耳。接下来,我把所有的测量结果都输入字典。我没有费心将每个测量值转换成国际单位,因为弗林克可以为我计算比率。
KCG=new dict//kcal/gram kcg@";hc";=50千卡/(汤匙重奶油)kcg@";cs&34;=120千卡/(2汤匙玉米糖浆)kcg@";黄油";=100千卡/(14克)kcg@";mc";=235千卡/(1.55盎司)配方=new dict//。mc";=460个语法配方@";黄油";=20个语法=[";hc";,";cs";,";mc";,";黄油";]total_cals=0kcalfor x=ing total_cals=total_cals+reecipe@x kcg@x。
根据外壳的不同,这足以容纳80到100块巧克力。我们可以用一个区间来模拟这种不确定性:
我们不是有一个确切的数字,而是有一个数字的上下限。所有使用该间隔完成的数学运算都会更改界限。4.
>;x=new Interval[80,100][80,100]//Frink执行区间数学>;x+2[82,102]>;x*2[160,200]>;x-new Interval[80,100][-20,20]。
但是巧克力不仅仅是它的馅料。它周围还有外壳,它会有不同于填充物的比能量。为了计算出每块巧克力有多少壳,我称了10块巧克力的重量,然后取平均值。每块巧克力给我9克。我大概知道每个巧克力有多少馅料,这是基于我用馅料做了多少巧克力。从巧克力的质量中减去馅料的质量,就得到了外壳的质量。
DICRSUM[d]:=SUM[MAP[{|x|x@1},d]]//每种巧克力的克数=新的DICROGPC@";配方";=DISTSUM[配方]/madespc@";dc";=9克-gpc@";配方";
从那时起,一个简单的计算方法就是计算出贝壳和馅料总共有多少卡路里。这就给了我巧克力的总卡路里。
这告诉我,每块巧克力的热量是40-50千卡,这和我预期的差不多。
如果你对弗林克感兴趣,你可以在这里下载。至少,我建议您查看默认的单元文件;这是一个有趣而有洞察力的介绍,介绍了单元可以有多奇怪。我将给你们留下他对坎德拉的一些评论:
我认为烛台是个骗局,我完全反对。一些一无是处的照明“工程师”或心理学家很可能把这种在感知上被操纵的可憎之处带入了整个原本是科学的努力中。
多么令人难以置信的没用和愚蠢的单位。540.00000001 x 10^12 Hz(或任何其他频率)的光是零坎德拉吗?这会是这个频率下的脉冲函数吗?哦,等等,海森堡不确定原理让这一切变得不可能。没有提及其他波长的校正(理想情况下沿着黑体曲线)?去你的,16点CGPM!你们都去死吧!
感谢朱比利·杨拍摄了开场白。合成图片来自Zardoz的肖恩·康纳利(Sean Connery)和艾伦·埃利亚森(Alan Eliasen)的主页。
怪罪罗纳德·里根吧。我们本该在90年代完成计量的,但是里根扼杀了这个项目。[返回]。
它们的维度并不完全相同,因为能量是标量,扭矩是矢量。但是扭矩的矢量分量具有相同的维度,并且是标量。[返回]。
Frink将间隔视为间隔内的单个未知值,而不是范围本身。这意味着对于任何间隔x,x-x=0。[返回]