[英]How do I fix this code smell?
我有一些代码执行显式递归,最重要的是,它在不需要时两次调用同一函数。 我认为我可以修复后者,但在前者方面需要帮助。
yesodIdentifier :: Text -> [LDAPEntry] -> Text
yesodIdentifier name ((LDAPEntry _ attributes):_) =
let (Just eMail) = L.lookup "proxyAddresses" attributes
partedEmail = L.map (S.splitOn "@") eMail -- now we have
-- [["garbage:name","domain"]]
in yesodIdentifier' name partedEmail -- the secondary function is the problem
where yesodIdentifier' :: Text -> [[String]] -> Text
yesodIdentifier' nameToMatch ((name:[domain]):rest) =
if ((unpack nameToMatch) == (sanitized name))
then (pack (sanitized name)) `append`
(pack "@") `append`
(pack domain)
else yesodIdentifier' nameToMatch rest
where sanitized :: String -> String
sanitized dirty =
let (garbage:[cleanedName]) = S.splitOn ":" dirty
in cleanedName
yesodIdentifier' name _ = pack "empty identifier"
我想做的是从LDAPEntry中获取(String,[String]),并将其缩减为与给定名称匹配的电子邮件地址。
您可以看到递归在哪里。 如果可以解决此问题,则无需担心yesodIdentifier' name _ = pack "empty identifier"
因为如果用户不在LDAP数据库中,则根本不会调用此代码。 我只是把它放在那里完成。 我认为这可以更好地表现为折痕,但我无法完全正确地表达出来。 有任何想法吗?
这可以表示为过滤器。 这并非易事,因为如果您进行递归,那么您将在休息时递归并丢弃较早的条目。 您仍然必须处理空列表:
yesodI nameToMatch list = let result = filter (match(unpack nameToMatch)) list match s1 (s2:[domain]) = s1 == s2 in case result of [] -> "empty identifier" res -> repack (head res) repack arg@(name:[domain]) = (pack (sanitized name)) `append` (pack "@") `append` (pack domain)
来自ja的答案,重写为使用find:
yesodI name l = intercalate "@" <$> (find ((name ==) . head) $ filter (not . null) l)
更具可读性的版本
yesodI name list = repack <$> find matchName list'
where list' = filter (not . null) list
repack = intercalate "@"
matchName = (name ==) . head
您可以消毒的电子邮件地址(name, domain)
第一对,使用find
找到的第一个具有匹配的名称,然后maybe
来决定,如果你做什么做/ DO-找不到匹配:
yesodIdentifier :: Text -> [LDAPEntry] -> Text
yesodIdentifier name ((LDAPEntry _ attributes):_) =
let (Just eMail) = L.lookup "proxyAddresses" attributes
name' = T.unpack name
sanitizedEmail = concatMap sanitize eMail -- now we have [("name","domain")]
empty = "empty identifier"
nonEmpty (name, domain) = concat [name, "@", domain]
sanitize s = do
(dirtyName:[domain]) <- [S.splitOn "@" s]
(garbage:[cleanedName]) <- [S.splitOn ":" dirtyName]
return (cleanedName, domain)
in T.pack . maybe empty nonEmpty . L.find ((name' ==).fst) $ sanitizedEmail
这是未经测试的,因为我还没有所有可用的类型...我希望这能引起您的santize
,在List Monad
中将丢弃无法分解为garbage:name@domain
邮件的电子邮件地址garbage:name@domain
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.