我终于找到了榆树功能编程的优秀切入点,男孩,我喜欢它,但我仍然缺乏一些关于一些概念的基本优雅。
我经常发现自己编写的代码类似于下面的代码,它似乎正在做它应该做的事情,但如果有经验的人可以提出更紧凑和直接的方法,我相信这可以提供一些有价值的见解,所以(u)的rcery。
我认为这可以归结为,如下所示
(<->
是向量减法运算符):
edgeDirections : List Vector -> List Vector
edgeDirections corners = List.map2 (\p v -> p <-> v) corners (shiftr 1 corners)
但我对一个能做shiftr
的方法的方法并不满意。
但是stackoverflow的规则要求它,这是我尝试过的。我写了一个关于shiftr
的可能用法的丑陋示例(我绝对不喜欢Debug.crash
而我对Maybe
感到不满):
给定矢量列表(多边形的角点),通过计算每个角矢量与其前一个矢量的差值来计算方向矢量,从列表中第一个和最后一个条目之间的差异开始。
[v1,v2,v3] -> [v1-v3,v2-v1,v3-v2]
这里是:
edgeDir : Vector -> ( Maybe Vector, List Vector ) -> ( Maybe Vector, List Vector )
edgeDir p ( v, list ) =
case v of
Nothing ->
Debug.crash ("nono")
Just vector ->
( Just p, list ++ [ p <-> vector ] )
edgeDirections : List Vector -> List Vector
edgeDirections corners =
let
last =
List.head <| List.reverse corners
in
snd <| List.foldl edgeDir ( last, [] ) corners
main =
show <| edgeDirections [ Vector -1 0, Vector 0 1, Vector 1 0 ]
我很欣赏有关如何以更直接的方式实现此结果的任何见解,可能使用我尚未了解的现有语言结构,或者有关如何使用Maybe
减轻痛苦的任何指示。后者可能Just
是不可能的,但我确信前者将a)打击我并且b)让我刮挠我的头几次:))
谢谢你,非常感谢这种恰到好处的语言!
答案 0 :(得分:2)
如果Elm具有内置init
and last
功能,这可能更清晰。
你可以通过做一些模式匹配来远离所有Maybes。这是我尝试使用模式匹配和累加器。
import List exposing (map2, append, reverse)
shiftr list =
let shiftr' acc rest =
case rest of
[] -> []
[x] -> x :: reverse acc
(x::xs) -> shiftr' (x::acc) xs
in shiftr' [] list
edgeDirections vectors =
map2 (<->) vectors <| shiftr vectors
另请注意(<->)
的映射函数的缩写,相当于(\p v -> p <-> v)
。
假设Elm 具有init
和last
功能 - 让我们在这里快速定义:
init list =
case list of
[] -> Nothing
[_] -> Just []
(x::xs) -> Maybe.map ((::) x) <| init xs
last list =
case list of
[] -> Nothing
[x] -> Just x
(_::xs) -> last xs
然后您的shiftr
功能可缩短为:
shiftr list =
case (init list, last list) of
(Just i, Just l) -> l :: i
_ -> list
答案 1 :(得分:0)
在我“挂断”之后,我想出了这个,但我确信这仍然可以大大改进,如果它甚至是正确的(它只适用于n = 1)
shiftr : List a -> List a
shiftr list =
let
rev =
List.reverse list
in
case List.head rev of
Nothing ->
list
Just t ->
[ t ] ++ (List.reverse <| List.drop 1 rev)
main =
show (shiftr [ 1, 2, 3, 4 ] |> shiftr)