如何从动态镜头获得动态视图

How can I get dynamic view from a dynamic lens

动态使用R.view ...

const robotsNames = [ 'da Vinci Surgical System',  'KITT', 'The Tachikomas', 'Toyota violin-playing robot',
    'GERTY', 'Mega Man', 'Rock ‘Em Sock ‘Em Robots', 'Doraemon', 'Awesom-O', 'HK-47', 'ED-209', 'Beer-Fetching Robot',
    'Bishop', 'The Energizer Bunny', 'Clank', 'Daft Punk', 'Johnny 5', 'The Robot', 'Roboto', 'Marvin the Paranoid Android',
    'Lego Mindstorms NXT', 'Robbie', 'Astro Boy', 'The Iron Giant', 'Optimus Prime', 'Roomba', 'DJ Roomba', 'Cindi Mayweather',
    'Rosie', 'Crow T. Robot/Tom Servo', 'K-9', 'The Terminator', 'The Maschinenmensch, aka Maria', 'ASIMO', 'GLaDOS', 'HAL 9000',
    'The Final Five', 'Sojourner', 'Data', 'R2D2', 'Bender Bending Rodriguez', 'Wall-E' ];

const getRandomInt =  R.curry((min, max) => {
    return Math.floor(Math.random() * (max - min + 1)) + min;
})
const getRandomFromZero = getRandomInt(0);
const lensRandomRobot = R.pipe(R.length, getRandomFromZero, R.lensIndex);

// NOT WORK...
const randomRobot = R.pipe(lensRandomRobot, R.view);
const robot = randomRobot(robotsNames);

// THIS WORKS ..
// const robot = R.view(lensRandomRobot(robotsNames))(robotsNames) // I dont want to pass the values twiice

console.log(robot);
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.23.0/ramda.min.js"></script>

如果您想避免重复 robotsNames

,您应该在 randomRobot 中使用 R.converge 而不是 R.pipe

const robotsNames = [ 'da Vinci Surgical System',  'KITT', 'The Tachikomas', 'Toyota violin-playing robot',
    'GERTY', 'Mega Man', 'Rock ‘Em Sock ‘Em Robots', 'Doraemon', 'Awesom-O', 'HK-47', 'ED-209', 'Beer-Fetching Robot',
    'Bishop', 'The Energizer Bunny', 'Clank', 'Daft Punk', 'Johnny 5', 'The Robot', 'Roboto', 'Marvin the Paranoid Android',
    'Lego Mindstorms NXT', 'Robbie', 'Astro Boy', 'The Iron Giant', 'Optimus Prime', 'Roomba', 'DJ Roomba', 'Cindi Mayweather',
    'Rosie', 'Crow T. Robot/Tom Servo', 'K-9', 'The Terminator', 'The Maschinenmensch, aka Maria', 'ASIMO', 'GLaDOS', 'HAL 9000',
    'The Final Five', 'Sojourner', 'Data', 'R2D2', 'Bender Bending Rodriguez', 'Wall-E' ];

const getRandomInt =  R.curry((min, max) => {
    return Math.floor(Math.random() * (max - min + 1)) + min;
})
const getRandomFromZero = getRandomInt(0);
const lensRandomRobot = R.pipe(R.length, getRandomFromZero, R.lensIndex);

// CHANGE MADE HERE
const randomRobot = R.converge(R.view, [lensRandomRobot, R.identity]);
const robot = randomRobot(robotsNames);


console.log(robot);
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.23.0/ramda.min.js"></script>

两件事:

  • 达蒙的回答很好。 converge does the job as expected. But there are several alternatives to consider. converge is very Ramda-specific. Something better known to the FP world might interest you. lift 更常见。你可以这样使用它:

    const randomRobot = R.lift(R.view)(lensRandomRobot, R.identity);
    

    或者,也许最好也是 ap, which would be perfect except that the parameter order in view is opposite what ap supplies, so there needs to be a flip*:

    const randomRobot = R.ap(R.flip(R.view), lensRandomRobot);
    

    您可以在 Ramda REPL.

  • 上看到这些方法
  • 其次,引入随机源在函数式代码中是一个奇怪的想法。显然,任何使用随机值的东西都不再具有引用透明性。这就是 Ramda 不提供 random/shuffle 函数的原因。

    Ramda 曾在某一时刻尝试过随机性,尝试使用引用透明的版本。但最终它因匹配不佳而放弃,但 that code 可能会帮助您创建基于随机代码的可测试版本。


*关键是当ap应用于函数时,它的行为是这样的:

ap(f, g)(x); //=> f(x)(g(x))

对于像 Ramda 那样柯里化的函数,这等同于

ap(f, g)(x); //=> f(x, g(x))