99种用Racket说I love you的方式
99种用Racket说I love you的方式
来源 https://www.tuicool.com/articles/qiyeAz
原文 http://www.soimort.org/posts/145/
今天是3月14日,也就是传说中的 白色情人节 (据说是个被表白一方向表白方回赠礼物以表示心意的好日子,蕴含着人们对天下有情人终成眷属的 良好祝愿 )。
作为一个技术宅,应该在这一天准备什么样的礼物给妹子捏?99朵玫瑰?还是巧克力?可不要被这些 商家营销手段 给骗了——就像Sheldon家Amy说的一样,Nerds们过一个真正属于自己的“No dinner, no romance, no gifts”的情人节才是正道啊;这种时候,只要像往常那样写写代码,用代码来说出“I love you”就好了。当然,为了表示诚意,我们要用99种——没错,是用99种不同的方式来写同一句话。
用什么语言写好捏?当然是 满满的都是爱 的 Racket 咯ヽ(♡´ω`♡)ノ
(先放上一段忘了从哪偷来的代码……在DrRacket里运行,就能看到一颗doki~doki跳动的红心哦)
#lang racket(require 2htdp/universe 2htdp/image) (define scale-factor 10) (define window-size (* scale-factor 20)) (define (lobe shape size) (shape (* size scale-factor) 'solid 'red)) (define • (lobe circle 4)) (define •• (overlay/offset • (* 7 scale-factor) 0 •)) (define ▼ (rotate 180 (lobe triangle 14))) (define ♥ (overlay/offset •• 0 (* 8 scale-factor) ▼)) (define amplitude 1/10) (define speed 1/2) (define (☺♥ n) (overlay (scale (add1 (* (sin (* n speed)) amplitude)) ♥) (empty-scene window-size window-size))) (animate ☺♥)
下面开始,进入正题。
以前,穷屌丝书生喜欢发问,茴香豆的茴字有几种写法?而高富帅则会问,I love you里面的love有几种make法?不管做任何一件事情,方法上的选择总是很重要——对于敲代码的程序猿来说也一样。
在Python里,做任何事,通常有且仅有一种正确的方法;Pythonic教的传教士说:只有一种姿势最优雅,其他的体位都是邪恶的。但是Rubyists们却不以为然。他们是一群奉行自由主义的嬉皮,不需要Python里面那种类似 哲♂学 一样的教条束缚;在解决同一个最基本的问题上有时也会跟随feeling写出新奇而孑然不同的代码。
记得刚开始接触Ruby那会,试着 用Ruby解过 那套经典的 P-99(99个Prolog问题) 。前面好几十个问题差不多都是关于list的操作:做过一遍之后立刻就感觉到,Ruby单从表达问题的灵活性上来说,的确不是现有的其他主流语言所能够比拟的——显然,作为Perl的继任者,Ruby很好地发扬光大了这一点。
嘛,当然,要说到表达能力,基于 抖S前入式 、把数据和代码结构高度统一起来的Lisp才是编程语言中真正的总攻(虽然这也让一部分Lisper养成了光说空话不干实事+吹嘘自己造车轮造得多么的好+不合作不贡献社区的 坏毛病 )。话说回来,在Lisp里,哪怕是做最简单的一件事情——构造一个list,也能凭空造出千般万般变化。不信?继续看下去。
为了帮助童鞋们更好地理解Racket语言中的核心概念,Univ of Utah的CS系教授Matthew Might写了这篇 《99 ways to say '(I love you)
》 。你不仅能够从中领略到Lisp那无与伦比的表达能力,还能借此复习一下Scheme/Racket中的那些基础知识点:lambdas,higher-order function,pattern matching,delayed evaluation,macros,等等——当然,后者才是此文的主要目的。
下面奉上原文翻译。(其实文字部分也就几句话)
Original Article: 99 ways to say '(I love you) by Matthew Might
(Chinese Translation by Mort Yao )
99 ways to say '(I love you)
虽说其具有本质上的简单性,有关list的那些事儿仍然会常常让Racket程序员们困惑不已。
除开list结构本身之外,Racket程序中各种运算的表达方式更需要花上不少时间来发掘和掌握。
为了更好地强调这些重点,我写了99个不超过一条推长度的Racket表达式,它们求值的结果均得到同样的一个list: '(I love you)
。
这些表达式中大约有一半用来展示构建或操作list的方法,剩下来的则展示了Racket中表述计算的各色方式。
所涉及到的关键知识点包括:
- 用cons连接单元(cons cells)
- 字面list记号(literal list notation)
- 加点list记号(dotted list notation)
- 反引号表示list(quasiquoted lists)
- let绑定形式(let-binding forms)
- vector和stream(vectors and streams)
- 匿名函数(anonymous functions)
- 高阶list操作(higher-order list operations)
- 条件式(conditionals)
- 结构化模式匹配(structural pattern-matching)
- 哈希表(hash maps)
- 续延(continuations)
- 异常(exceptions)
- 诺言(promises)
- 变更(mutation)
- 宏(macros)
- 端口(ports)
- 未来(futures)
- 参数(parameters)
以下是具体的99种方式。
如果读到任何一条不能理解的话,不妨在DrRacket的REPL里面尝试摸索一番,直到你彻底弄懂它。
99种方式
下面的每一枚Racket表达式,求值的结果均得到一个list '(I love you)
:
(原文里面没有给这99条归类,小标题是翻译君擅自加的,看的时候请注意鉴别……)
1. 构造list的基本手段: quote
和 list
;;;
'(I love you)
;;;
(quote (I love you))
;;;
(list 'I 'love 'you)
;;;
(list (quote I) (quote love) (quote you))
2. 用 cons
连接单元
;;;
(cons 'I (cons 'love (cons 'you '())))
;;;
(cons 'I (cons 'love (list 'you)))
;;;
(cons 'I (list 'love 'you))
;;;
(cons 'I '(love you))
3. 加点list记号(Dotted list notation)
;;;
'(I love . (you))
;;;
'(I . (love . (you)))
;;;
'(I . (love . (you . ())))
;;;
'(I . (love you))
4. 反引号表示list(Quasiquoted lists)
;;;
`(I love you)
;;;
`(I ,'love you)
;;
(quasiquote (I ,'love you))
;;
(quasiquote (I (unquote 'love) you))
;;;
`(I ,`love you)
;;;
(let ([verb 'love]) `(I ,verb you))
;;;
`(I ,(string->symbol "love") you)
;;;
`(I ,(string->symbol (list->string '(#\l #\o #\v #\e))) you)
;;;
`(I love . (you))
;;;
`(I love . ,(list 'you))
;;;
`(I love ,@'(you))
;;;
`(I love (unquote-splicing '(you)))
;;;
`(I ,@(list 'love 'you))
;;;
`(,@(list 'I 'love) you)
;;;
`(,@'(I love you))
;;;
`,'(I love you)
;;;
`(I love you . ,'())
5. car
和 cdr
;;;
(car (list '(I love you)))
;;;
(cdr '(Hark! I love you))
6. let
绑定形式( let
-binding forms)
;;;
(let ([words '(love you I)]) (list (car (cdr (cdr words))) (car words) (car (cdr words))))
;;;
(let ([words '(love you I)]) (list (caddr words) (car words) (cadr words)))
;;;
(let* ([c '(you)] [b (cons 'love c)] [a (cons 'I b)]) a)
;;;
(let () '(I love you not) '(I love you))
7. vector
;;;
(vector->list (vector 'I 'love 'you))
;;;
(vector->list #(I love you))
8. stream
;;;
(stream->list (stream 'I 'love 'you))
9. 匿名函数(Anonymous functions)
;;;
((lambda args args) 'I 'love 'you)
;;;
((lambda (one two . rest) rest) 'You 'believe 'I 'love 'you)
;;;
((lambda (a c b) (list a b c)) 'I 'you 'love)
;;;
(apply (lambda (a c b) (list a b c)) (list 'I 'you 'love))
;;;
((lambda (a b [c 'you]) (list a b c)) 'I 'love)
;;;
((lambda (#:foo b #:bar c #:baz a) (list a b c)) #:baz 'I #:bar 'you #:foo 'love)
;;;
((lambda (a b #:key [c 'me]) (list a b c)) #:key 'you 'I 'love)
10. 柯里化(Currying)
;;;
(let ([f (λ (x) (λ (y) (λ (z) (list x y z))))]) (((f 'I) 'love) 'you))
11. case-lambda
;;;
(let ([f (case-lambda [() 'I] [(x) 'love] [(x y) 'you])]) (list (f) (f 1) (f 1 2)))
12. 基础list操作
;;;
(append '(I love) '(you))
;;;
(append '(I) '(love) '(you))
;;;
(flatten '((I) (love you)))
;;;
(flatten '((I) (love) (you) ()))
;;;
(reverse '(you love I))
;;;
(remove 'cannot '(I cannot love you))
;;;
(remove-duplicates '(I love love love you))
;;;
(take '(I love you not) 3)
;;
(take-right '(I think I love you) 3)
;;;
(drop '(She knows I love you) 2)
;;;
(drop-right '(I love you no more) 2)
13. 高阶list操作(map、filter和reduce)
;;;
(map (lambda (x) (if (eq? x 'hate) 'love x)) '(I hate you))
;;;
(map (λ (i) (vector-ref #(love you I) i)) '(2 0 1))
;;;
(map (λ (k) (hash-ref #hash(("foo" . I) ("baz" . you) ("bar" . love)) k)) '("foo" "bar" "baz"))
;;;
(map string->symbol (sort (list "love" "you" "I") string<?))
;;;
(map string->symbol (string-split "I-love-you" "-"))
;;;
(flatten (map (λ (a b) (cons a b)) '(I love you) '(() () ())))
;;;
(filter (lambda (x) (not (eq? x 'cannot))) '(I cannot love you))
;;;
(foldr cons '() '(I love you))
;;;
(foldl cons '() '(you love I))
14. 迭代(Iterations)
;;;
(for/list ([word #(I love you)]) word)
15. 条件式(Conditionals)
;;;
(cond [(even? 3) '(Not me)] [(odd? 3) '(I love you)])
;;;
(cond [(even? 3) '(Not me)] [(odd? 2) '(Nor I)] [else '(I love you)])
;;;
(case 1 [(a b c) '(Not me)] [(3 2 1) '(I love you)])
16. 结构化模式匹配(Structural pattern-matching)
;;;
(match #t [#f '(Not me)] [#t '(I love you)])
;;;
(match #t [#f '(Not me)] [_ '(I love you)])
;;;
(match 'you ['me '(Not me)] [x `(I love ,x)])
;;;
(match '(foo bar) ['(foo bar) '(I love you)])
;;;
(match '(I cannot lift you) [(list 'I 'cannot _ c) `(I love ,c)])
;;;
(match '(2 3 1) [(list-no-order 3 1 2) '(I love you)])
;;;
(match '(love you I) [(list-no-order 'I 'love foo) `(I love ,foo)])
;;;
(match '(3 . 4) [(cons 3 4) '(I love you)])
;;;
(match '(3 love 1) [(cons 3 (cons x (cons 1 '()))) `(I ,x you)])
;;;
(match '(3 love 1) [(cons 3 (cons x (cons 1 '()))) `(I (unquote x) you)])
;;;
(match 3 [(? symbol?) '(Not me)] [(? string?) '(Me neither)] [(? number?) '(I love you)])
;;;
(match 3 [(not 4) '(I love you)] [3 'unreachable])
;;;
(match '(you love I) [`(,c love ,a) `(,a love ,c)])
;;;
(match '(We love you) [`(,_ . ,rest) `(I . ,rest)])
;;;
(match '(We love you) [`(,_ ,rest ...) `(I ,@rest)])
;;;
(match '(We love you) [(list _ rest ...) `(I ,@rest)])
;;;
(match #(1 love 3) [(vector (? number?) b (? number?)) `(I ,b you)])
;;;
(match #hash((1 . I) (3 . you) (5 . love)) [(hash-table (1 a) (5 b) (3 c)) (list a b c)])
;;;
(match 'you [(and x (? symbol?)) `(I love ,x)])
;;;
(match '100 [(app (λ (n) (- n 1)) 99) '(I love you)])
17. 续延(Continuation)
;;;
(list 'I (call/cc (λ (cc) (error (cc 'love)))) 'you)
18. 异常(Exceptions)
;;;
(with-handlers ([symbol? (lambda (p) `(I ,p you))]) (raise 'love))
19. 延迟求值(Delayed evaluation)
;;;
(let ([problem (delay (car '()))]) '(I love you))
;;;
`(I ,(force (delay 'love)) you)
;;;
(letrec ([x (delay (list a b c))] [a 'I] [c 'you] [b 'love]) (force x))
20. 变更(Mutation)
;;;
(let ([word 'know]) (set! word 'love) `(I ,word you))
;;;
(let ([word-box (box 'know)]) (set-box! word-box 'love) `(I ,(unbox word-box) you))
21. 宏(Macros)
;;;
(let-syntax ([un-yoda-list (syntax-rules () [(_ c a b) (list 'a 'b 'c)])]) (un-yoda-list you I love))
22. 端口(Ports)
;;;
(let ((in (open-input-string "I love you"))) (cons (read in) (cons (read in) (cons (read in) '()))))
23. 未来(Futures)
;;;
(list (touch (future (λ () 'I))) 'love 'you)
24. 参数化(Parameterization)
;;;
(let ([a (make-parameter "a")] [b (make-parameter "b")] [c (make-parameter "c")]) (parameterize ([a 'i] [b 'love] [c 'you]) (list (a) ((parameterize ([b 'dislike]) (λ () (b)))) (c))))
来自其他人的贡献
由 David Van Horn 提供:
(define `λ (λ 'love 'I 'you)) ((λ λ λ) `(λ (⊙ λ ∪) λ) `(λ (λ ⊙ ∪) λ) `(λ (∪ ⊙ λ) λ))
由Bruce Bolick提供:
(define (stream-take s n) (if (= n 0) '() (cons (stream-first s) (stream-take (stream-rest s) (- n 1))))) (define U 3) (define I stream-take) (define ♥ (stream 'I 'love 'you)) (I ♥ U)
(原文完)
(我表示诸位看官到这里可以直接无视以下内容了……看可以,请一笑了之。)
因为文章里提到的99种方式都没有涉及到logic programming,我觉得很有必要写一个自己的版本。用谓词逻辑来推导出“I love you”这种设定会很有趣的不是么……
于是就有了下面这段蛋疼的产物(用到了 Racklog ,一个仿Prolog的逻辑式编程扩展),最终的结果也是一样一样的 '(I love you)
:
我要做一只合格的脑残偶像厨WOTA \(^o^)/
#lang racket
(require racklog) (define %love (%rel () [('I 'AKB48)] [('I 'you)] [('you 'I)])) (define first-love (%which (who) (%and (%is who 'AKB48) (%love 'I who) (%love who 'I)))) (define not-that-much-but-still-love (%which (who) (%and (%love 'I who) (%love who 'I)))) (define (♡˙︶˙♡) `(I love, (cdr (car not-that-much-but-still-love)))) (♡˙︶˙♡)
====================== End
转载于:https://www.cnblogs.com/lsgxeva/p/10155529.html
99种用Racket说I love you的方式相关推荐
- 芯盾时代:一种会思考的新一代安全身份认证方式
喂,有没有想过你在互联网上的"身份证"是什么?更通俗地讲,在互联网中,什么能证明"你是你"? 当我们登录一个银行APP时,是不是只凭"用户名+口令&q ...
- 抛砖引玉,孢子,一种另类的WP7第三方应用数据交换方式
孢子,一种另类的WP7第三方应用数据交换方式 <孢子>这个游戏玩过的人应该对里面的模型很有印象,尤其会对里面只靠一张PNG就能在游戏中还原成3D很感兴趣,今天要介绍的就是这种技术:在PNG ...
- 贝叶斯优化: 一种更好的超参数调优方式
简介 本文受 浅析 Hinton 最近提出的 Capsule 计划 启发,希望以更通俗的方式推广机器学习算法,让有数学基础和编程能力的人能够乐享其中. 目前人工智能和深度学习越趋普及,大家可以使用开源 ...
- 哪种副业挣钱多?副业通过什么方式赚钱的呢?
哪种副业挣钱多?副业通过什么方式赚钱的呢? 你是通过什么方式赚钱的呢? 在这里我们把它分为主业赚钱和副业赚钱,并且更多的是针对个人! 主业:大部分人的主业是通过工作打工带来的收入: 副业:业余时间兼职 ...
- java按空格分字符串,两种用空格分隔的java字符串的方式
两种用空格分隔的java字符串的方式 两种方式: 1. String str = "123 456 789 111"; String [] strArray = str.split ...
- 在Windows, Mac, Linux三种系统中分别获取wifi密码的方式
在Windows, Mac, Linux三种系统中分别获取wifi密码的方式 1. Windows netsh wlan show profile name=wifi名称 key=clear | fi ...
- 几种不需要戴眼镜的立体成像方式
http://www.4dshijue.com/4dedu/2010/0605/126.html 3D技术的迅速发展,摘下眼镜看3D已经成了民心所向,也是3D技术发展的大势所趋,相信这一天很快就会到来 ...
- 能听懂口音的开源语音系统来了:OpenAI出品,支持99种语言,英文识别能力直逼人类...
点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 羿阁 发自 凹非寺 量子位 | 公众号 QbitAI 逼近人类水平的 ...
- [搜索]一种改进的召回率准确率公式计算方式
在信息检索系统中,召回率和准确率的定义为: 召回率:(Recall Ratio,简称R)是衡量信息检索系统在实施某一检索作业时检出相关文献能力的一种测度指标,其计算方法为:Recall=检出的相 ...
最新文章
- dos2unix install on mac_mac2019新品唇釉来啦!MAC有色唇油试色
- 如何安装jdk_Java JDK下载与安装教程
- 对git的使用日常问题及解决
- python pywin32 微信_python win32con安装_python-2.7 – 安装pywin32
- 有机化学芳烃 芳香性
- mysql 开启守护进程_[求助]Linux上MySQL Server 5.6 安装后无法启动守护进程
- 少走弯路,给Java 1~5 年程序员的建议
- ubuntu16.04 + kinetic +turtlebot2配置
- 放大缩小保证div对齐_NFS Write IO 不对齐深度分析
- linux修改默认python版本_Linux 升级 Python 并修改默认版本
- php页面设置密码,PHP页面输入密码才能访问加密代码
- vue-resource插件使用
- Joomla源代码解析(十九) JController
- 【LeetCode】【数组】题号:*665,非递减数列
- SiTime 硅晶振抖动定义和测量方法
- Computer:路由器连接交换机怎么建立局域网
- mark:x264编译选项
- Win10重装win7时一直显示windows启动中,不要慌
- RFID标签的基础知识(3)--了解芯片(之超高频标签芯片篇)
- 移动端和pc端的区别