Javascript 一种更为惯用的写作方法

Javascript 一种更为惯用的写作方法,javascript,functional-programming,sanctuary,Javascript,Functional Programming,Sanctuary,我编写了一个代码片段,用于提取源对象键(这些键应该是未知的,因此我添加了一个不存在的要提取的键baz)。 我提取的数组中的每个元素-我想添加从中提取元素的键,然后将结果展平以获得单个数组 我在编写代码时遇到了两个主要问题: 当尝试使用S.insert时,它总是返回一个错误,因为对象值(数字{r:***})的类型与我尝试添加到键部分的字符串的类型不同(例如{Section':***'foo'**}).我最终只是为了表达我的意图而改变了对象 我没能写一个合适的映射函数来抽象Maybe并允许我访问里面

我编写了一个代码片段,用于提取
对象键(这些键应该是未知的,因此我添加了一个不存在的要提取的键
baz
)。 我提取的数组中的每个元素-我想添加从中提取元素的键,然后将结果展平以获得单个数组

我在编写代码时遇到了两个主要问题:

  • 当尝试使用
    S.insert
    时,它总是返回一个错误,因为对象值(数字
    {r:***}
    )的类型与我尝试添加到键
    部分的字符串的类型不同(例如
    {Section':***'foo'**}
    ).我最终只是为了表达我的意图而改变了对象
  • 我没能写一个合适的映射函数来抽象
    Maybe
    并允许我访问里面的变量。所以我不得不使用
    S.maybeToNullable
    ,然后将值重新包装到
    Maybe
  • 有没有更好的方法来表达下面用
    编写的逻辑
  • 代码片段:

    const S = require('sanctuary');
    const source = {
      foo: [{ r: 1 }, { r: 2 }, { r: 3 }],
      bar: [{ r: 4 }, { r: 5 }, { r: 6 }],
    }
    
    const result =
      S.pipe([
        S.map(
          prop => {
            const nullable = S.maybeToNullable(S.value(prop)(source))
            return nullable ? S.Just(nullable.map(val => {val['Section'] = prop; return val})) : S.Nothing
          }
        ),
        S.justs,
        S.reduce(xs => x => [...xs, ...x])([])
      ])(['foo', 'bar', 'baz'])
    
    以下是我的解决方案:

    const S = require ('sanctuary');
    
    //    source :: StrMap (Array { r :: Integer })
    const source = {
      foo: [{r: 1}, {r: 2}, {r: 3}],
      bar: [{r: 4}, {r: 5}, {r: 6}],
      quux: [{r: 7}, {r: 8}],
    };
    
    //    result :: Array { r :: Integer, Section :: String }
    const result =
    S.filter (S.compose (S.flip (S.elem) (['foo', 'bar', 'baz']))
                        (S.prop ('Section')))
             (S.chain (S.pair (s => S.map (S.unchecked.insert ('Section') (s))))
                      (S.pairs (source)));
    
    有几件事需要注意:

    • 在这种情况下,我觉得不自然,因为有两个输入(
      source
      ['foo',bar',baz']
      )。使用
      S.pipe
      需要在管道中硬编码其中一个输入

    • 无法用于更新记录,但
      S.unchecked.insert
      可用于此目的。如果类型检查器认为某个我知道是正确的表达式不正确,我希望能够禁止类型检查

    • 从您的问题中,我不清楚输出顺序是否重要。您的解决方案尊重节名称数组的顺序;我的不清楚。请告诉我输出顺序是否重要

      • 以下是我的解决方案:

        const S = require ('sanctuary');
        
        //    source :: StrMap (Array { r :: Integer })
        const source = {
          foo: [{r: 1}, {r: 2}, {r: 3}],
          bar: [{r: 4}, {r: 5}, {r: 6}],
          quux: [{r: 7}, {r: 8}],
        };
        
        //    result :: Array { r :: Integer, Section :: String }
        const result =
        S.filter (S.compose (S.flip (S.elem) (['foo', 'bar', 'baz']))
                            (S.prop ('Section')))
                 (S.chain (S.pair (s => S.map (S.unchecked.insert ('Section') (s))))
                          (S.pairs (source)));
        
        有几件事需要注意:

        • 在这种情况下,我觉得不自然,因为有两个输入(
          source
          ['foo',bar',baz']
          )。使用
          S.pipe
          需要在管道中硬编码其中一个输入

        • 无法用于更新记录,但
          S.unchecked.insert
          可用于此目的。如果类型检查器认为某个我知道是正确的表达式不正确,我希望能够禁止类型检查

        • 从您的问题中,我不清楚输出顺序是否重要。您的解决方案尊重节名称数组的顺序;我的不清楚。请告诉我输出顺序是否重要


        对不起,它看起来更复杂、更不可读。我来自具有FP功能的其他语言,我确信这不是我想要的。你能解决我提到的
        1
        2
        问题吗?我很乐意先解决这些问题。
        S.value(prop)(source)
        给出了一个
        可能(数组{r::Integer})
        。要在
        {r::Integer}
        上操作,您需要映射两次。请尝试将lambda替换为
        prop=>S.map(S.map(S.unchecked.insert('Section')(prop))(S.value(prop)(source))
        。抱歉,它看起来更复杂、更不可读。我来自其他具有FP功能的语言,我确信这不是我想要的。你能解决我提到的
        1
        2
        问题吗?我很乐意先解决这些问题。
        S.value(prop)(source)
        给出了一个
        可能(数组{r::Integer})
        。要在
        {r::Integer}
        上操作,需要映射两次。请尝试将lambda替换为
        prop=>S.map(S.map(S.unchecked.insert('Section')(prop))(S.value(prop)(source))