【Clojure】在loop-recur中实现多重循环
2016-07-09 01:14
405 查看
问题
在loop-recur中实现多重循环(里:如何造一个轮子)描述
在loop-recur中使用一个N重循环是很痛苦的(脑细胞在燃烧),这时候可以使用一个生成N重循环下标列表的工具,在loop-recur中实现多重循环代码
(defn smooth [cur config] (let [cur (reverse cur) config (reverse config) ps (map #(list % %2) cur config)] (loop [carry 0 head (first ps) tail (rest ps) ret '()] (if (nil? head) ret (let [[x y] head the-carry (quot (+ carry x) y) the-rest (mod (+ carry x) y)] (recur the-carry (first tail) (rest tail) (conj ret the-rest))))))) ; only for test! (smooth (map + [1 2 3] [3 9 9]) [10 10 10]) (smooth (map + [1 2 3] [1 1 1]) [10 10 10]) (smooth [0 2 2] [2 2 2]) (defn smooth-ex [numbers limits] (let [numbers (reverse numbers) limits (reverse limits) pairs (map #(list % %2) numbers limits)] (loop [carry 0 head (first pairs) tail (rest pairs) ret '()] (if (nil? head) ret (let [[number limit] head the-carry (quot (+ carry number) limit) the-rest (mod (+ carry number) limit)] (recur the-carry (first tail) (rest tail) (conj ret the-rest))))))) (defn looper-unit [looper] (if (= (count looper) 0) '() (let [zero-cnt (dec (count looper))] (into '(1) (repeat zero-cnt 0))))) (defn is-looper-end? [looper looper-end] (= (map inc looper) looper-end)) (defn looper-next [looper looper-end] (smooth (map + looper (looper-unit looper)) looper-end)) (defn looper-demo [looper-end] (loop [looper (repeat (count looper-end) 0) ret []] (let [[i j] looper looper-string (str "row:" i " " "col:" j)] (if (is-looper-end? looper looper-end) (ret conj looper-string) (recur (looper-next looper looper-end) (conj ret looper-string)))))) ; just for test! (map println (looper-demo [3 3]))
说明
smooth: 类似大数加法中的进位操作,处理循环中下标的进位操作
smooth-ex:
smooth的容易阅读的版本 …
looper-unit: 生成循环的递增单位,即一个形如
(0 ... 0 1)的列表, 可能不含0
其他函数顾名思义,不解释了
核心思想即产生一系列列表,例如一个二重循环:
for(int i = 0; i < 2; ++i) for(int j = 0; j < 2; ++j) { /* excuse me */}
其下标对应的序列为:
[ (0 0) (0 1) (1 0) (1 1) ]
那么对于任意循环,我们只需要生成该列表组就可以进行循环操作, 那么在哪里可以买到呢:
注意
(0 0)到
(0 1)的变化过程:
(= '(0 1) (map + '(0 0) '(0 1)))
而
(0 1)到
(1 0)的变化过程则较为复杂,但这一变化可以看作二进制下
01 + 01 => 10的过程
宗上可以看出,生成列表的过程可以看作是一个N进制数字自增的过程,特别的是这里的每一个位可能对应不同的进制(比如上面那个循环把j的限制改成
j < 100, 就变成了i是2进制,j是100进制的自增过程)
利用这一性质产生了如上的编码(轮子),具体使用方法参考
looper-demo, 配合解构操作可以顺利获得各循环变量, 然后瞎鸡巴乱搞
最后需要注意的是,对循环的限制是左闭右开区间,
(looper-end [5 5])得到的是一个 0-4 的二重循环
clojure多行注释太麻烦了,最后补上
(map println (looper-demo [3 3]))的输出结果
; 不是代码 仅供参考 => (map println (looper-demo [3 3])) row:0 col:0 row:0 col:1 row:0 col:2 row:1 col:0 row:1 col:1 row:1 col:2 row:2 col:0 row:2 col:1 row:2 col:2 (nil nil nil nil nil nil nil nil nil) ; 最后的一串nil是prinln的返回值被map收集了, 因为这里我们需要的是副作用
相关文章推荐
- 常用的linux命令
- 青鸟租房网站-登录验证 房屋列表显示
- Linux HugePages及MySQL 大页配置
- 启动TOMCAT报错 java.util.zip.ZipException: invalid LOC header (bad signature)
- CentOS如何查看端口是被哪个应用/进程占用
- Windows Remote Shell(WinRM)使用介绍
- 设置centos 和win文件共享
- 腾讯云linux系统yum安装软件——以nginx为例
- Centos PHP 扩展Xchche的安装教程
- Java 操作 excel 文档 用 apache poi 来解决。
- 我们如何获取数据并分析数据?
- 谈一谈国内的积分激励
- linux awk命令
- 大型网站架构不得不考虑的10个问题
- linux下pear安装
- Linux内存管理
- 使用nologin用户启动tomcat进程
- Docker学习笔记四 镜像
- Ubuntu下Apache建立虚拟主机
- CentOS安装桌面环境