- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图将this转换为F#,但由于错误消息(标题中)的错误太大,无法搜索,因此我无法弄清楚自己在做什么,因此我没有找到解决方法。
这是代码:
let getIP : string =
let host = Dns.GetHostEntry(Dns.GetHostName())
for ip in host.AddressList do
if ip.AddressFamily = AddressFamily.InterNetwork then
ip.ToString() // big fat red underline here
"?"
最佳答案
F#中的for
循环用于运行命令式代码,其中for
循环内的代码不会产生结果,而是会产生某种副作用。因此,预期F#for
循环中的expression块将产生unit
类型,这是副作用函数应返回的类型。 (例如printfn "Something"
返回unit
类型)。另外,无法在F#的早期退出for
循环。这是设计使然,也是for
循环并不是执行您要执行的操作的最佳方法的另一个原因。
您要做的是一次列出一个项目,找到符合条件的第一个项目,然后返回该项目(如果找不到该项目,则返回一些默认值)。 F#为此具有特殊的功能: Seq.find
(如果List.find
是F#列表,则为host.AddressList
;如果Array.find
是数组,则为host.AddressList
。这三个函数采用不同的输入类型,但从概念上讲,它们的工作方式相同,因此从现在开始,我将重点介绍在Seq.find
上,它接受任何IEnumerable
作为输入,因此很可能是您在此处所需要的)。
如果您在F#文档中查看Seq.find
函数的类型签名,您将看到它是:
('T -> bool) -> seq<'T> -> 'T
'T -> bool
和
seq<'T>
并返回
'T
。
'T
语法的意思是“这是一个称为T的通用类型”:在F#中,撇号表示其后是通用类型的名称。
'T -> bool
类型的意思是一个函数,它接受一个
'T
并返回一个布尔值。即谓词为“是,这与我要查找的内容相匹配”或“否,请继续查找”。
Seq.find
的第二个参数是
seq<'T>
;
seq
是F#的
IEnumerable
的缩写,因此您可以将其读为
IEnumerable<'T>
。结果是
'T
类型的项目。
Seq.find
的结果返回。
Seq.find
将引发异常,这可能不是您要查找的行为。这就是
Seq.tryFind
函数存在的原因:除了返回值外,它的函数签名看起来类似于
Seq.find
:它返回
'T option
而不是
'T
。这意味着您将得到类似于
Some "ip address"
或
None
的结果。对于您的情况,如果未找到该项目,则打算返回
"?"
。因此,您想将
Some "ip address
或
None
的值转换为
"ip address"
(不包括
Some
)或
"?"
。这就是
defaultArg
函数的作用:如果您的值是
'T option
,则它需要一个
'T
和一个
None
来表示默认值,并且它返回一个简单的
'T
。
Seq.tryFind
接受谓词函数和序列,并返回'T option
。在您的情况下,这将是string option
defaultArg
接受'T option
和默认值,并返回普通的'T
(在您的情况下为string
)。 let getIP : string = (code)
。似乎您打算将
getIP
用作一个函数,但没有给它提供任何参数。编写
let something = (code block)
将通过立即(仅一次)运行代码块,然后将其结果分配给名称
something
来创建一个值。而编写
let something() = (code block)
将创建一个函数。它不会立即运行该代码块,但会在每次调用该函数时运行该代码块。所以我认为您应该写
let getIP() : string = (code)
。
getIP
函数:
let getIP() = // No need to declare the return type, since F# can infer it
let isInternet ip = // This is the predicate function
// Note that this function isn't accessible outside of getIP()
ip.AddressFamily = AddressFamily.InterNetwork
let host = Dns.GetHostEntry(Dns.GetHostName())
let maybeIP = Seq.tryFind isInternet host.AddressList
defaultArg maybeIP "?"
ip
中
isInternet
参数的类型。从代码中可以明显看出,它必须是带有
.AddressFamily
属性的某个类,但是F#编译器无法(在代码的这一点上)不知道要将哪个类传递给此谓词函数。这是因为F#编译器是
单遍编译器,它以自顶向下,从左到右的顺序在代码中工作。为了能够推断
ip
参数的类型,您可能需要重新排列一下代码,如下所示:
let getIP() = // No need to declare the return type, since F# can infer it
let host = Dns.GetHostEntry(Dns.GetHostName())
let maybeIP = host.AddressList |> Seq.tryFind (fun ip -> ip.AddressFamily = AddressFamily.InterNetwork)
defaultArg maybeIP "?"
Seq.tryFind
或其他类似函数时,F#中最常见的样式是使用
fun
关键字将该谓词声明为匿名函数。这就像C#中的lambdas一样工作(在C#中,谓词为
ip => ip.AddressFamily == AddressFamily.InterNetwork
)。另一个常见的事情是将
|>
运算符与
Seq.tryFind
等带有谓词的事物一起使用。
|>
运算符*基本上采用
|>
运算符之前的值,并将其作为运算符之后函数的
最后参数传递。因此,
foo |> Seq.tryFind (fun x -> xyz)
类似于编写
Seq.tryFind (fun x -> xyz) foo
,只是
foo
是您在那行中首先阅读的内容。由于
foo
是您要查找的序列,而
fun x -> xyz
是您的查找方式,因此感觉更自然:用英语,您会说“请在我的壁橱里找一件绿色衬衫”,所以这个概念“壁橱”出现在“绿色衬衫”之前。在惯用的F#中,您将编写
closet |> Seq.find (fun shirt -> shirt.Color = "green")
:同样,概念“壁橱”出现在“绿色衬衫”之前。
host.AddressList
之前将先遇到
fun ip -> ...
,因此它将知道名称
ip
是
host.AddressList
中的一项。并且由于它知道
host.AddressList
的类型,因此可以推断
ip
的类型。
|>
运算符在幕后进行了很多操作,涉及
currying和
partial application。但是,对于初学者而言,只需将其视为“在函数的参数列表的末尾输入一个值”,便会拥有正确的想法。
关于f# - 该表达式应具有类型“unit”,但此处具有类型“string”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51760327/
如果您想使用 String.Concat() 连接 5 个或更多字符串,则它会使用 Concat(String[])。 为什么不一直使用 Concat(String[]) 而不再需要 Concat(S
今天在使用 String 时,我遇到了一种我以前不知道的行为。我无法理解内部发生的事情。 public String returnVal(){ return "5";
似乎在我所看到的任何地方,都有一些过时的版本,这些版本不再起作用。 我的问题似乎很简单。我有一个Java类,它映射到derby数据库。我正在使用注释,并且已经成功地在数据库中创建了所有其他表,但是在这
一、string::size_type() 在C++标准库类型 string ,在调用size函数求解string 对象时,返回值为size_type类型,一种类似于unsigned类型的int 数据
我正在尝试将数据保存到我的 plist 文件中,其中包含字符串数组的定义。我的plist - enter image description here 我将数据写入 plist 的代码是 -- let
我有一个带有键/值对的 JavaScript 对象,其中值是字符串数组: var errors = { "Message": ["Error #1", "Error #2"], "Em
例如,为了使用相同的函数迭代 List 和 List> ,我可以编写如下内容: import java.util.*; public class Test{ public static voi
第一个Dictionary就像 Dictionary ParentDict = new Dictionary(); ParentDict.Add("A_1", "1")
这是我的 jsp 文件: 我遇到了错误 The method replace(String, String, String) in the type Functions is not appl
我需要一些帮助。我有一个方法应该输出一个包含列表内容的 txt 文件(每行中的每个项目)。列表项是字符串数组。问题是,当我调用 string.Join 时,它返回文字字符串 "System.Strin
一位同事告诉我,使用以下方法: string url = "SomeURL"; string ext = "SomeExt"; string sub = "SomeSub"; string s
给定类: public class CategoryValuePair { String category; String value; } 还有一个方法: public
我正在尝试合并 Stream>>对象与所有 Streams 中的键一起映射到单个映射中. 例如, final Map someObject; final List>> list = someObjec
在这里使用 IDictionary 的值(value)是什么? 最佳答案 使用接口(interface)的值(value)始终相同:切换到另一个后端实现时,您不必更改客户端代码。 请考虑稍后分析您的代
我可以知道这两个字典声明之间的区别吗? var places = [String: String]() var places = [Dictionary()] 为什么当我尝试以这种方式附加声明时,只有
在 .NET 4.0 及更高版本中存在 string.IsNullOrWhiteSpace(string) 时,在检查字符串时使用 string.IsNullOrEmpty(string) 是否被视为
这个名字背后的原因是什么? SS64在 PowerShell 中解释此处的字符串如下: A here string is a single-quoted or double-quoted string
我打算离开 this 文章,尝试编写一个接受字符串和 &str 的函数,但我遇到了问题。我有以下功能: pub fn new(t_num: S) -> BigNum where S: Into {
我有一个结构为 [String: [String: String]] 的多维数组。我可以使用 for 循环到达 [String: String] 位,但我不知道如何访问主键(这个位 [String:
我正在尝试使用 sarama(管理员模式)创建主题。没有 ConfigEntries 工作正常。但我需要定义一些配置。 我设置了主题配置(这里发生了错误): tConfigs := map[s
我是一名优秀的程序员,十分优秀!