这是使用现代javascript的简单链式表达式,用于查找位于包含逗号分隔的键值对列表的字符串中的特定键的值,该键值对用=
分隔。
如果源为null或未找到密钥,这会下降,在我看来,这对于Maybe monad而言似乎是一项艰巨的任务。
// Grab the tag with key in `tag`
const getTag = (product, tag) =>
product.Tags
.split(',')
.find(t => t.startsWith(`${tag}=`))
.split('=')[1]
getTag({Tags: 'a=y,b=z'}, 'a') // returns 'y'
getTag({Tags: 'a=y,b=z'}, 'z') // returns boom (desired null)
getTag({Tags: null}, 'a') // returns boom (desired null)
因此,我npm安装了避难所,并开始使用功能性解决方案。据我所知,这是很丑陋的,它告诉我我一定做错了什么或使用了错误的工具。
const getk = S.map(S.filter(S.test(/=/)))(S.splitOn(','))
S.map(S.map(S.map(S.splitOn('='))))(S.map(getk))(S.toMaybe(null))
// Nothing
S.map(S.map(S.map(S.splitOn('='))))(S.map(getk))(S.toMaybe('a=y,b=z'))
//Just ([["a", "y"], ["b", "z"]])
我不希望这成为“为我解决此问题”的问题,但是我很难传达我实际上需要帮助的内容。
我仍在尝试“弄清楚” FP,所以这肯定是一个熟悉的问题。
答案 0 :(得分:1)
我们可以使用S.map
转换内部值,并使用S.join
删除不需要的嵌套:
func main() {
fs := http.FileServer(http.Dir("static"))
http.Handle("/", fs)
bs := http.FileServer(http.Dir("public"))
http.Handle("/public/", http.StripPrefix("/public/", bs))
http.HandleFunc("/show", show)
http.HandleFunc("/db", getDB)
r := mux.NewRouter()
r.HandleFunc("/loc/{id}", getLoc)
log.Println("Listening 3000")
if err := http.ListenAndServe(":3000", nil); err != nil {
panic(err)
}
}
func getLoc(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
http.Error(w, http.StatusText(405), http.StatusMethodNotAllowed)
return
}
id := r
fmt.Println("URL")
fmt.Println(id)
}
const S = require ('sanctuary');
const $ = require ('sanctuary-def');
// getTag :: String -> Object -> Maybe String
const getTag = tag => S.pipe ([
S.get (S.is ($.String)) ('Tags'), // :: Maybe String
S.map (S.splitOn (',')), // :: Maybe (Array String)
S.map (S.map (S.stripPrefix (tag + '='))), // :: Maybe (Array (Maybe String))
S.map (S.head), // :: Maybe (Maybe (Maybe String))
S.join, // :: Maybe (Maybe String)
S.join, // :: Maybe String
]);
getTag ('a') ({Tags: 'a=y,b=z'}); // => Just ('y')
getTag ('z') ({Tags: 'a=y,b=z'}); // => Nothing
getTag ('z') ({Tags: null}); // => Nothing
后跟S.map
始终等于S.chain
:
S.join
此方法通过不短路来完成一些不必要的工作,但是S.stripPrefix
允许我们在单个步骤中检查标签是否存在并提取标签的值。 :)
使用S.justs
选择第一个匹配项的更新版本:
// getTag :: String -> Object -> Maybe String
const getTag = tag => S.pipe ([
S.get (S.is ($.String)) ('Tags'), // :: Maybe String
S.map (S.splitOn (',')), // :: Maybe (Array String)
S.map (S.map (S.stripPrefix (tag + '='))), // :: Maybe (Array (Maybe String))
S.chain (S.head), // :: Maybe (Maybe String)
S.join, // :: Maybe String
]);
答案 1 :(得分:0)
这里是仅使用现代JavaScript的Sanctuary代码的替代方法:
const stripPrefix = e =>
e.startsWith(`${tag}=`)
&& e.replace(`${tag}=`, "")
const getTag = tag => product =>
product?.Tags
?.split(",")
.map(stripPrefix)
.filter(Boolean)
[0]
|| null
getTag("b")({ Tags: "a=y,b=c" }) // returns 'y'
getTag("z")({ Tags: "a=y,b=z" }) // returns null
getTag("a")({ Tags: null }) // returns null
如果找不到标记,stripPrefix
函数将返回false
,然后将其filter
编辑。
您可以使用optional chaining运算符({ Tags: null }
)处理?.
。