如何将这些代码和我的想法转换为功能思维(Clojure)
How do convert this code and my thinking to a functional mindset (Clojure)?
如何将此JavaScript代码转换为Clojure?
我正试图绘制一个(x,y)世界,其中的单元格根据填充属性打开或关闭。在下面的示例中,我尝试先打印行,然后打印列,但下一步是移动fill属性(向上、向下、向左、向右)。所以,如果我不打印数据结构,我不想要一个无效的答案。
我的目标是了解如何以功能的方式思考这个问题。对我来说,用JavaScript中的可变状态很容易解决这个问题。在开发解决方案时,我能够很容易地思考如何用JavaScript编写代码,但当我在Clojure中做同样的事情时,我不知所措。所以,我觉得这个问题的一个好答案是帮助我理解如何以功能的方式思考这类问题。
我看过很多关于Clojure和函数式编程的演讲和文章,但当涉及到编写代码时,我很难开始。
var world = [
[{ x: 1, y: 4, fill:0 }, { x: 2, y: 4, fill:0 }, { x: 3, y: 4, fill:0 }, { x: 4, y: 4, fill:0 }],
[{ x: 1, y: 3, fill:0 }, { x: 2, y: 3, fill:0 }, { x: 3, y: 3, fill:0 }, { x: 4, y: 3, fill:0 }],
[{ x: 1, y: 2, fill:0 }, { x: 2, y: 2, fill:0 }, { x: 3, y: 2, fill:0 }, { x: 4, y: 2, fill:0 }],
[{ x: 1, y: 1, fill:0 }, { x: 2, y: 1, fill:0 }, { x: 3, y: 1, fill:1 }, { x: 4, y: 1, fill:0 }]
];
function printworld(world) {
var out = "";
for(var row=0; row<world.length; row++) {
for(var col=0; col<world[row].length; col++) {
out += "["+world[row][col].fill+"]";
}
out += "'n"
}
console.log(out);
}
printworld(world);
输出看起来像:
[0][0][0][0]
[0][0][0][0]
[0][0][0][0]
[0][0][1][0]
编辑:在4clojure.com上花时间解决这些问题后,我意识到我正试图解决一个比我准备解决的更大的问题(例如Clojure的国际象棋游戏)。在4clojure.com上创建最基本的函数一直很困难,但它正在积累如何使用函数方法来处理解决方案的稳定知识。
如何开始以功能性的方式思考?没有捷径和快速的答案。您必须投入大量的时间来尝试以功能方式进行编码。
您可以从变形简单的算法开始。但重要的是要记住,在函数式编程中,你关心的是数据流,而不是如何指示CPU做这做那。
了解语言中的核心功能是很重要的。从这些核心功能中,您可以开始转换数据。如果你愿意的话,可以是乐高或DNA条纹。
如果你对Clojure特别感兴趣,那么我建议你花点时间在4Clojure和Lisp之地上。
Clojure IRC是向Rockstar Clojure开发人员学习的好地方。友好的社区和乐于助人的肯定。
永远记住:"OOP默认情况下并不容易,FP默认情况下也不难"。
数据看起来或多或少是一样的:
(def world [[{:x 1, :y 2, :fill 0}, {:x 2, :y 2, :fill 0}]
[{:x 1, :y 1, :fill 0}, {:x 2, :y 2, :fill 1}]])
但对于打印功能,您可以使用doseq
(defn print-world [world]
(doseq [row world]
(doseq [cell row]
(print (str "[" (:fill cell) "]")))
(println)))
(print-world world)
;; outputs
;; [0][0]
;; [0][1]
以及改变元件assoc-in
或update-in
; move the filled cell 'up'
(print-world
(-> world
(assoc-in [1 1 :fill] 0) ; set bottom-right fill to 0
(assoc-in [0 1 :fill] 1))) ; set top-right fill to 1
;; outputs
;; [0][1]
;; [0][0]
Clojure不是最适合这种编程的,但它是有用的东西。
编辑:就功能性思维而言,这不是一种可以通过堆叠式答案轻松传达的技能。它需要大量的代码编写和阅读他人的代码。一个很好的在线起点是Clojure for the Brave and True。让我从功能上思考的是"为美好的未来学习哈斯克尔"!。
当试图进入"功能思维方式"时,有时查看代码并思考如何分离可分离的部分会有所帮助。在这个例子中,有三个逻辑阶段:
- 将数据更改为仅包含筛选字段
- 以矢量形式(使用
[]
s) - 打印得很好
如果我们将它们分离成自己的Clojure表达式,那么也许你可以在其他地方重用其中一个,或者编写更好的测试等,而不是在同一个矩阵中执行这两个操作(诚然,效率略高)
user> (def world [[{:x 1, :y 4, :fill 0 }, {:x 2, :y 4, :fill 0 }, {:x 3, :y 4, :fill 0 }, {:x 4, :y 4, :fill 0 }],
[{:x 1, :y 3, :fill 0 }, {:x 2, :y 3, :fill 0 }, {:x 3, :y 3, :fill 0 }, {:x 4, :y 3, :fill 0 }],
[{:x 1, :y 2, :fill 0 }, {:x 2, :y 2, :fill 0 }, {:x 3, :y 2, :fill 0 }, {:x 4, :y 2, :fill 0 }],
[{:x 1, :y 1, :fill 0 }, {:x 2, :y 1, :fill 0 }, {:x 3, :y 1, :fill 1 }, {:x 4, :y 1, :fill 0 }]])
#'user/world
user> (defn filter-fill [world] (map #(map :fill %) world))
#'user/filter-fill
user> (filter-fill world)
((0 0 0 0) (0 0 0 0) (0 0 0 0) (0 0 1 0))
user> (defn vector-world [world] (mapv #(mapv vector %) world))
#'user/vector-world
user> (clojure.pprint/pprint (vector-world (filter-fill world)))
[[[0] [0] [0] [0]]
[[0] [0] [0] [0]]
[[0] [0] [0] [0]]
[[0] [0] [1] [0]]]
nil
这个草图生成世界的状态,而不是改变内存中的结构。用Rich Hickey的话说,它生成下一个值,而不是在同一个旧地方存储不同的东西。
// world is an object with the world's state
var world = function(tl, tr, bl, br){
this.state = {topLeft: tl, topRight: tr, bottomLeft: bl, bottomRight: br};
};
// screen is an object with internal state that represents
// the state of the of the world
var screen = function(aWorld){
this.state = [[{fill: aWorld.state.topLeft},
{fill: aWorld.state.topRight}],
[{fill: aWorld.state.bottomLeft},
{fill: aWorld.state.bottomRight}]];
};
// showScreen is a function in which all side
// effects occur.
function showScreen(aScreen){
var out = "";
for (var line = 0; line < aScreen.state.length; line++){
for (var pix = 0; pix < aScreen.state[line].length; pix++){
out += "[" + aScreen.state[line][pix].fill + "]";
}
out += "'n"
}
console.log(out);
}
// here is the heart of functional style programming:
// generating the next value instead of changing
// some existing state
function nextWorld(tr,tl,br,bl){
showScreen(new screen(new world(tr,tl,br,bl)))
}
// turn off screen
function screenOff(){
nextWorld(0,0,0,0)
}
// make a forward slash
function forwardSlash(){
nextWorld(1,0,0,1)
}
- 如何分解jQuery"toggle”;函数转换为separate“;显示“;以及“;隐藏“;功能
- 将自定义Google Sheets功能转换为附加组件
- 是否有将基于字符串的JSON转换为Mongoose Schema对象实例的本地功能
- 这个javascript代码有什么错误,它有将数字转换为单词的功能
- 修复Javascript代码以将文本中的所有Youtube链接转换为Youtube ID功能
- 是否有一种功能齐全的范式语言可以转换为JavaScript
- 将复选框转换为图像,需要添加拖动功能才能更改图像
- 下拉菜单转换为单选按钮,不再触发特定功能
- 如何将这些代码和我的想法转换为功能思维(Clojure)
- 将 SVG 转换为图像时画布到 URL 功能出现问题
- 将现有的jQuery从点击功能转换为延迟自动显示
- JavaScript 温度转换功能将不起作用
- 如何使用HSL到RGB转换功能
- 合并指令'将功能转换为Angular表单验证
- 将searchlogic的搜索功能转换为transakrails 3
- 如何将“media.setVolume”功能转换为进度条或搜索栏
- 将功能转换为开关
- Ajax:将复选框功能转换为Wordpress中的输入字段和更新按钮
- 将javascript方法的功能转换为c#
- 将 DRY 放大 ibox 内容功能转换为动态功能