-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.xml
3034 lines (2475 loc) · 288 KB
/
index.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>记忆和记忆的补完</title>
<link>http://longlycode.github.io/</link>
<description>Recent content on 记忆和记忆的补完</description>
<generator>Hugo -- gohugo.io</generator>
<language>en</language>
<copyright>LonglyCode</copyright>
<lastBuildDate>Mon, 16 Jul 2018 13:38:52 +0800</lastBuildDate>
<atom:link href="http://longlycode.github.io/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>About</title>
<link>http://longlycode.github.io/about/</link>
<pubDate>Mon, 16 Jul 2018 13:38:52 +0800</pubDate>
<guid>http://longlycode.github.io/about/</guid>
<description>
<h1 id="我们仍未知道那天的记忆和记忆的补完">我们仍未知道那天的记忆和记忆的补完</h1>
<blockquote>
<p>这是lonelycode的个人技术博客。主要专注于Web后端开发,涉及主要内容如下:</p>
</blockquote>
<ol>
<li>Python 和 Golang的使用</li>
<li>数据库</li>
<li>微服务</li>
<li>Emacs/Vim/Linux/CommandLine等工具分享</li>
</ol>
<p><a href="https://github.com/LonglyCode">本人Github地址</a></p>
</description>
</item>
<item>
<title>Linux使用的点点滴滴</title>
<link>http://longlycode.github.io/post/linux_note/</link>
<pubDate>Tue, 17 Jul 2018 11:48:14 +0000</pubDate>
<guid>http://longlycode.github.io/post/linux_note/</guid>
<description><blockquote>
<p>完全Linux下工作已经接近一年半的时间,中间零零碎碎记录一些好的东西和遇到的坑。有些只是为了记录而记录,网上都提到就不提了。持续更新&hellip;</p>
</blockquote>
<p></p>
<h2 id="基础">基础</h2>
<ol>
<li>查看具体某个进程TCP端口占用情况, <code>lsof -p &lt;pid&gt; -i &quot;TCP&quot;</code></li>
<li><code>tail -f file.log</code> 尾部跟踪log文件(主要是-f参数&ndash;follow),可以实时输出最后的结果,对于实时请求可以看到信息。可以监控多个文件 <code>tail -f /path/*/file.log*</code></li>
<li>source + sh 可以重启执行sh文件</li>
<li><code>grep -A -B -C</code> 参数可以指定行数,找到结果之前、之后、上下几行的信息。</li>
<li>awk 可以用于 按分割符打印输入的字符串, $1 代表参数 1, $2代表参数2,默认按空格打印,如果是其他分隔符用参数 -F</li>
<li>scp 可用于将本地代码通过ssh拷贝到目标机器(sshcopy简称)</li>
<li>增量更新两个相同的目录: <code>rsync -avz src dst</code></li>
<li>找到对应的文件进行删除: <code>find . -name '*.bill' | xargs rm -f</code></li>
<li><code>ls -li</code> 其中i用于显示列出项的inode,对于查看链接的文件或者目录有用</li>
<li>设置代理其实就是修改https_proxy变量,<code>export https_proxy=socks5://127.0.0.1:1080</code></li>
</ol>
<h2 id="有用">有用</h2>
<ol>
<li>pip可以直接从github上安装,方式是 <code>pip install git+https://.....git</code></li>
<li>zsh插件叫autojump,自动跳转目录,非常好用。</li>
<li>使用<code>sshfs</code>可以用来将远程路径映射到本地,所有本地操作都会自动同步到远程去,当然是ssh安全的。命令如右边 <code>sshfs /remote/path/ /local/path/ -o follow_symlinks -o sshfs_sync -o reconnect</code></li>
<li><strong>mycli</strong> mysql 的命令行工具,也有对应的postgresql工具</li>
<li>ssh免密码登录需要最后设置:<code>ssh-copy-id &lt;remoteIP&gt;</code></li>
<li>lsyncd 是有用的同步目录的工具,可以设置的同步延时时间: <code>lsyncd -delay 2 -rsync src dst</code></li>
<li>mysqldump 同的mysql命令几乎一样,前者重定向输出,后者重定向输入: <code>mysqldump -u &lt;user&gt; -h &lt;host&gt; &lt;dbname&gt; -p --skip-lock-tables &gt; xxx.sql</code></li>
<li>strace 用于监控某个进程的读写情况:<code>strace -p &lt;pid&gt; -e trace=open,write,read,close</code></li>
<li>redshift 用于护眼:<code>redshift -c /etc/redshift.conf &amp;</code></li>
<li>vimdiff 对于的熟悉vim的人进行两个文件临时diff简直是神器</li>
<li>tcpdump</li>
<li>dig</li>
<li>用sed命令批量替换某个路径下的字符, <code>grep 原字符串 -rl 所在目录</code> | xargs sed -i &ldquo;s/原字符串/新字符串/g&rdquo;`</li>
<li>使用<code>httpie</code>替代curl或者postman,可以将request data 通过管道导入, <code>cat xxxx.json | sudo http -b POST :8080/xxxxx/xxxx\?token=kjl\&amp;uid=uid2</code></li>
</ol>
<h2 id="备忘">备忘</h2>
<ol>
<li>emacs直接安装需要安装依赖: <code>sudo apt-get install build-essential texinfo libx11-dev libxpm-dev libjpeg-dev libpng-dev libgif-dev libtiff-dev libgtk2.0-dev libncurses-dev</code></li>
<li>svn 进行某一部分的目录单独更新:一,对父目录进行<code>svn checkout svn://svn.oa.com/SrcCodes/trunk/ --depth 'immediates'</code>,二,到对应的想更新的路径操作<code>svn up --set-depth 'infinity'</code></li>
<li>查看mysql数据库对应的用户和ip的权限: <code>select DISTINCT(</code>GRANTEE<code>) from</code>information_schema<code>.</code>USER_PRIVILEGES<code>;</code></li>
<li>设置用户mysql权限 <code>GRANT insert,update,select,delect PRIVILEGES ON &lt;dbname&gt;.* TO 'user@'192.168.%.%' identified by 'password';</code></li>
<li>mysql 安装和使用:
<ul>
<li>apt-get install mysql-server</li>
<li>apt-get install mysql-client</li>
<li>apt-get install python-mysqldb
接着使用<code>mysql -u root -p</code>进入客户端,然后输入密码,记得安装过程会提示你输入密码;<code>create database [databasename]</code>,注意mysql需要设置为中文,加后缀<code>create database [databasename] character set gbk</code></li>
</ul></li>
<li>在新的设备上把SSH密钥添加到个人github账号的方式:<code>ssh-keygen -t rsa -C [email protected]</code></li>
<li>设置autojump,一般从github上下载源码,然后在<code>.zshrc</code>文件下添加autojump插件,最重要的是要添加下面两句:
<code>shell
[[ -s /home/xxxx/.autojump/etc/profile.d/autojump.sh ]] &amp;&amp; source /home/xxxx/.autojump/etc/profile.d/autojump.sh
</code>
最后运行 <code>source .zshrc</code>。</li>
</ol></description>
</item>
<item>
<title>博客迁移到 HUGO</title>
<link>http://longlycode.github.io/post/blog/</link>
<pubDate>Mon, 16 Jul 2018 16:01:23 +0800</pubDate>
<guid>http://longlycode.github.io/post/blog/</guid>
<description><h1 id="迁移原因">迁移原因</h1>
<p>之前不明白别人的博客为什么要迁移来迁移去,迁移完还要发一篇文章简述原因。
后来换了电脑之后,原来的博客代码丢了,才知道对于自己不熟悉而且偶尔用的东西,往往累觉不爱。</p>
<h2 id="对于-hexo">对于 HEXO</h2>
<ul>
<li>几乎没接触前端,NPM 在新的环境不是强制安装的;</li>
<li>NPM 的速度和依赖对于偶尔使用的人体验太差,容易劝退。</li>
</ul>
<h2 id="对于-hugo">对于 HUGO</h2>
<ul>
<li>只要一个编译好的可执行文件,可以扔到不同的环境当中;</li>
<li>使用 go 一段时间了;</li>
<li>生成博客的速度快;</li>
<li>支持 org-mode;</li>
<li>工程结构很清晰,主题在单独的文件夹当中,直接依赖 github 项目,太棒。</li>
</ul>
<h2 id="迁移过程">迁移过程</h2>
<p>网上已经很多,下面这篇挺不错的:
<a href="http://keithmo.me/post/2016/07/20/build-your-own-blog1/" title=" GitHub + Hugo 搭建个人博客"> GitHub + Hugo 搭建个人博客</a></p>
</description>
</item>
<item>
<title>初识postgresql以及在Flask里面的关联使用</title>
<link>http://longlycode.github.io/post/%E5%88%9D%E8%AF%86postgresql%E4%BB%A5%E5%8F%8A%E5%9C%A8flask%E9%87%8C%E9%9D%A2%E7%9A%84%E5%85%B3%E8%81%94%E4%BD%BF%E7%94%A8/</link>
<pubDate>Tue, 19 Apr 2016 00:50:21 +0000</pubDate>
<guid>http://longlycode.github.io/post/%E5%88%9D%E8%AF%86postgresql%E4%BB%A5%E5%8F%8A%E5%9C%A8flask%E9%87%8C%E9%9D%A2%E7%9A%84%E5%85%B3%E8%81%94%E4%BD%BF%E7%94%A8/</guid>
<description><!-- toc -->
<blockquote>
<p>起因发现同一个服务器上面有人安装了postgresql用来跑一个大型的应用,postgresql如雷贯耳,一直没机会接触,于是好奇折腾了起来。因为牵扯众多只挑重点来讲。</p>
</blockquote>
<p></p>
<h2 id="1-安装">1.安装</h2>
<ol>
<li><p>在Ubuntu系统以及其延伸系统安装特别方便。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-sql" data-lang="sql"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-sql" data-lang="sql"><span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="k">get</span> <span class="n">postgresql</span>
<span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="k">get</span> <span class="n">postgresql</span><span class="o">-</span><span class="n">client</span>
<span class="n">sudo</span> <span class="n">apt</span><span class="o">-</span><span class="k">get</span> <span class="n">pgadmin3</span></code></pre></td></tr></table>
</div>
</div>
<p>分别为本体、客户端和一个管理postgresql的图形界面软件,非常好用,建议不熟悉命令行的新手使用。</p></li>
<li><p>在window下直接下载exe文件安装。
安装完成后将postgresql的<strong>bin</strong>目录加入到系统环境变量<code>Path</code>,譬如<code>;C:\Program Files (x86)\postgres\9.3\bin</code>加入到计算机-&gt;属性-&gt;高级环境变量-&gt;环境变量-&gt;系统变量-&gt;Path最末端。之后也可以在cmd下面操作。</p></li>
</ol>
<h2 id="2-初始化-添加用户和数据库">2. 初始化&ndash;添加用户和数据库</h2>
<p>初始化的时候让人很疑惑,postgresql的用户和系统用户不关联,它本身自己拥有一套用户管理系统,必须新建一个用户和一个和用户名同名的数据才能使用(有疑问?)。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span><span class="lnt">5</span><span class="lnt">6</span></pre></td>
<td class="lntd">
<pre class="chroma">``` sql
# 所有的命令都可以加 --help来查看用法,下面用-s参数新建一个superuser账号 hehe。
createuser -s hehe
# 新建一个同名的数据库hehe并用参数-O指定owner(所有者)。
createdb -O hehe hehe # createdb -O username databasename
```</pre></td></tr></table>
</div>
</div>
<p>值得一提的是,它自带一个postgres用户和postgres数据库。</p>
<h2 id="3-登陆和使用">3. 登陆和使用</h2>
<p><code>psql</code> 是连接postgresql的命令控制台工具。常用的几个参数选项和MySQL很相似。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span></pre></td>
<td class="lntd">
<pre class="chroma">``` sql
# 用上节新建的账号登陆
psql -h 127.0.0.1 -p 5442 -U hehe -d hehe
```</pre></td></tr></table>
</div>
</div>
<p>最常用的几个参数<code>-h</code>指定服务器,<code>-p</code>指定端口,缺省默认的为5432,<code>-U</code> 指定登陆的用户,<code>-d</code>指定数据库,缺省默认和用户名相同的数据库。如果此用户需要密码接下来还需要输入口令。</p>
<h2 id="4-登陆之后">4. 登陆之后</h2>
<blockquote>
<p>登陆之后就进入命令控制台,几乎所有操作都是在这个环境下进行的。</p>
</blockquote>
<h3 id="基本操作">基本操作</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><span class="lnt"> 1</span><span class="lnt"> 2</span><span class="lnt"> 3</span><span class="lnt"> 4</span><span class="lnt"> 5</span><span class="lnt"> 6</span><span class="lnt"> 7</span><span class="lnt"> 8</span><span class="lnt"> 9</span><span class="lnt">10</span></pre></td>
<td class="lntd">
<pre class="chroma">1. \h:查看sql命令的解释
2. \?:所有psql命令列表
3. \l:现有所有数据库列表
4. \c [databasename]:直接跳转连接到其他数据库
5. \d:列出当前数据库的表格
6. \d [tablename]:列出表格的结构,非常有用的命令
7. \du:列出所有用户
8. \conninfo:当前连接信息
9. \password:为当前用户指定一个登陆口令
10. \q:退出当前控制台</pre></td></tr></table>
</div>
</div>
<h3 id="sql操作">sql操作</h3>
<ul>
<li><p>sql命令很多而且所有数据库大多都雷同。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-sql" data-lang="sql"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span><span class="lnt">5</span><span class="lnt">6</span><span class="lnt">7</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-sql" data-lang="sql"><span class="o">#</span> <span class="err">新建表</span>
<span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">books</span><span class="p">(</span><span class="n">book_no</span> <span class="nb">integer</span><span class="p">,</span><span class="n">name</span> <span class="nb">text</span><span class="p">,</span><span class="n">price</span> <span class="n">numberic</span><span class="p">,</span><span class="k">UNIQUE</span> <span class="p">(</span><span class="n">book_no</span><span class="p">));</span>
<span class="o">#</span> <span class="err">插入数据</span>
<span class="k">INSERT</span> <span class="k">INTO</span> <span class="n">books</span><span class="p">(</span><span class="n">book_no</span><span class="p">,</span><span class="n">name</span><span class="p">,</span><span class="n">price</span><span class="p">)</span> <span class="k">VALUES</span><span class="p">(</span><span class="mi">2333</span><span class="p">,</span><span class="s1">&#39;万历十五年&#39;</span><span class="p">,</span><span class="mi">18</span><span class="p">.</span><span class="mi">5</span><span class="p">);</span>
<span class="o">#</span> <span class="err">查询</span>
<span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">books</span>
<span class="o">#</span> <span class="err">等等</span><span class="p">...</span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<h2 id="5-启动-备份和恢复">5. 启动、备份和恢复</h2>
<h3 id="启动中止状态操作">启动中止状态操作</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><span class="lnt">1</span><span class="lnt">2</span></pre></td>
<td class="lntd">
<pre class="chroma">1. Ubuntu: /etc/init.d/postgresql start (stop/status/restart)
2. Windows: /PostgreSQL/9.3/bin/pg_ctl.exe (stop/status/restart/reload)</pre></td></tr></table>
</div>
</div>
<h3 id="备份和恢复">备份和恢复</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span></pre></td>
<td class="lntd">
<pre class="chroma">1. pg_dump [databasename]:将postgresql数据导出到一个脚本文件
2. pg_dumpall:将所有的postgresql数据库导出到一个脚本文件
3. pg_restore:从以上两个命令导出脚本文件恢复
4. psql [databasename] &lt; backup.sql恢复外部数据</pre></td></tr></table>
</div>
</div>
<h2 id="6-连接flask的依赖">6. 连接Flask的依赖</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span><span class="lnt">5</span></pre></td>
<td class="lntd">
<pre class="chroma">1. Psycopg2: 一个适配连接postgres数据库的python包,windows下请选择 win-Psycopg不然会提示缺少DLL的error
2. Flask-SQLAlchemy(2.1):Flask下的SQLAlchemy拓展,以更加python的形式来写数据库结构,更容易迁移数据库
3. Flask-Migrate:Flask数据库的初始化、迁移脚本和版本管理的利器
4. Flask-Script:命令行的拓展
几乎使用Flask的用户都默认安装后三者,真正依赖是Psycopg2。</pre></td></tr></table>
</div>
</div>
<h2 id="7-最小使用">7. 最小使用</h2>
<ol>
<li><p>在Flask项目的config.py文件里面最主要设置<code>SQLALCHEMY_DATABASE_URI</code>变量就可以了</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="lnt"> 1</span><span class="lnt"> 2</span><span class="lnt"> 3</span><span class="lnt"> 4</span><span class="lnt"> 5</span><span class="lnt"> 6</span><span class="lnt"> 7</span><span class="lnt"> 8</span><span class="lnt"> 9</span><span class="lnt">10</span><span class="lnt">11</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span>
<span class="kn">from</span> <span class="nn">flask.ext.sqlalchemy</span> <span class="kn">import</span> <span class="n">SQLAlchemy</span>
<span class="n">SQLALCHEMY_DATABASE_URI</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="sa"></span><span class="s1">&#39;DATABASE_URL&#39;</span><span class="p">)</span> <span class="ow">or</span> \
<span class="sa"></span><span class="s1">&#39;postgresql://username:password@localhost:5432/databasename</span><span class="err">
</span><span class="err"></span><span class="s1">DEBUG =True</span><span class="err">
</span><span class="err">
</span><span class="err"></span><span class="s1">app=Flask(__name__)</span><span class="err">
</span><span class="err"></span><span class="s1">app.config.from_object(__name__)</span><span class="err">
</span><span class="err"></span><span class="s1">db=SQLAlchemy(app)</span></code></pre></td></tr></table>
</div>
</div>
<p>比如用之前建好的数据库<code>hehe</code>就把最后那行改成 <code>postgresql://hehe:@localhost:5432/hehe</code></p></li>
<li><p>用SQLAlchemy来建一个名为User的测试model,保存为model.py文件</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="lnt"> 1</span><span class="lnt"> 2</span><span class="lnt"> 3</span><span class="lnt"> 4</span><span class="lnt"> 5</span><span class="lnt"> 6</span><span class="lnt"> 7</span><span class="lnt"> 8</span><span class="lnt"> 9</span><span class="lnt">10</span><span class="lnt">11</span><span class="lnt">12</span><span class="lnt">13</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">config</span> <span class="kn">import</span> <span class="n">db</span>
<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
<span class="n">__tablename__</span> <span class="o">=</span> <span class="sa"></span><span class="s1">&#39;users&#39;</span>
<span class="nb">id</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">email</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">String</span><span class="p">(</span><span class="mi">64</span><span class="p">),</span> <span class="n">unique</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">index</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">username</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">String</span><span class="p">(</span><span class="mi">64</span><span class="p">),</span> <span class="n">unique</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">index</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">password_hash</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">String</span><span class="p">(</span><span class="mi">128</span><span class="p">))</span>
<span class="n">name</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">String</span><span class="p">(</span><span class="mi">64</span><span class="p">))</span>
<span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="sa"></span><span class="s1">&#39;&lt;User </span><span class="si">%r</span><span class="s1">&gt;&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">username</span></code></pre></td></tr></table>
</div>
</div></li>
<li><p>建立一个名为manage.py文件,最小化使用Flask框架。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="lnt"> 1</span><span class="lnt"> 2</span><span class="lnt"> 3</span><span class="lnt"> 4</span><span class="lnt"> 5</span><span class="lnt"> 6</span><span class="lnt"> 7</span><span class="lnt"> 8</span><span class="lnt"> 9</span><span class="lnt">10</span><span class="lnt">11</span><span class="lnt">12</span><span class="lnt">13</span><span class="lnt">14</span><span class="lnt">15</span><span class="lnt">16</span><span class="lnt">17</span><span class="lnt">18</span><span class="lnt">19</span><span class="lnt">20</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">config</span> <span class="kn">import</span> <span class="n">app</span><span class="p">,</span><span class="n">db</span>
<span class="kn">from</span> <span class="nn">flask.ext.script</span> <span class="kn">import</span> <span class="n">Manager</span>
<span class="kn">from</span> <span class="nn">flask.ext.migrate</span> <span class="kn">import</span> <span class="n">Migrate</span><span class="p">,</span><span class="n">MigrateCommand</span>
<span class="kn">from</span> <span class="nn">model</span> <span class="kn">import</span> <span class="n">User</span>
<span class="n">migrate</span><span class="o">=</span><span class="n">Migrate</span><span class="p">(</span><span class="n">app</span><span class="p">,</span><span class="n">db</span><span class="p">)</span>
<span class="n">manager</span><span class="o">=</span><span class="n">Manager</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
<span class="n">manager</span><span class="o">.</span><span class="n">add_command</span><span class="p">(</span><span class="sa"></span><span class="s1">&#39;db&#39;</span><span class="p">,</span><span class="n">MigrateCommand</span><span class="p">)</span>
<span class="nd">@app.route</span><span class="p">(</span><span class="sa"></span><span class="s1">&#39;/&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">hello</span><span class="p">():</span>
<span class="k">return</span> <span class="sa"></span><span class="s1">&#39;Hello&#39;</span>
<span class="nd">@app.route</span><span class="p">(</span><span class="sa"></span><span class="s1">&#39;/&lt;name&gt;&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">hello_user</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
<span class="k">return</span> <span class="sa"></span><span class="s2">&#34;hello {} !&#34;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
<span class="k">if</span> <span class="vm">__name__</span><span class="o">==</span><span class="sa"></span><span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
<span class="n">manager</span><span class="o">.</span><span class="n">run</span><span class="p">()</span></code></pre></td></tr></table>
</div>
</div></li>
<li><p>命令行下初始化数据库,先来到项目目录下,按顺序输入下面三个命令</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span><span class="lnt">5</span><span class="lnt">6</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="c1"># 初始化</span>
<span class="n">python</span> <span class="n">manage</span><span class="o">.</span><span class="n">py</span> <span class="n">db</span> <span class="n">init</span>
<span class="c1"># 建立迁移脚本</span>
<span class="n">python</span> <span class="n">manage</span><span class="o">.</span><span class="n">py</span> <span class="n">db</span> <span class="n">migrate</span> <span class="o">-</span><span class="n">m</span> <span class="sa"></span><span class="s2">&#34;init databasename for postgres&#34;</span>
<span class="c1"># 更新</span>
<span class="n">python</span> <span class="n">manage</span><span class="o">.</span><span class="n">py</span> <span class="n">db</span> <span class="n">upgrade</span></code></pre></td></tr></table>
</div>
</div>
<p>可以看见当前目录下面生成了一个名为<code>migrations</code>文件夹,这个文件夹是保存迁移脚本和数据库版本控制的地方,下次如果添加了新的model只要使用上面最后两条命令即可。</p></li>
<li><p>在psql下查看</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-sql" data-lang="sql"><span class="lnt"> 1</span><span class="lnt"> 2</span><span class="lnt"> 3</span><span class="lnt"> 4</span><span class="lnt"> 5</span><span class="lnt"> 6</span><span class="lnt"> 7</span><span class="lnt"> 8</span><span class="lnt"> 9</span><span class="lnt">10</span><span class="lnt">11</span><span class="lnt">12</span><span class="lnt">13</span><span class="lnt">14</span><span class="lnt">15</span><span class="lnt">16</span><span class="lnt">17</span><span class="lnt">18</span><span class="lnt">19</span><span class="lnt">20</span><span class="lnt">21</span><span class="lnt">22</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-sql" data-lang="sql"><span class="err">$</span> <span class="n">psql</span> <span class="o">-</span><span class="n">U</span> <span class="n">hehe</span>
<span class="o">#</span> <span class="err">查看当前数据库的表</span>
<span class="n">hehe</span><span class="o">=#</span> <span class="err">\</span><span class="n">d</span>
<span class="k">Schema</span> <span class="o">|</span> <span class="n">Name</span> <span class="o">|</span> <span class="k">Type</span> <span class="o">|</span> <span class="k">Owner</span>
<span class="c1">---------|-----------------|-------|--------
</span><span class="c1"></span><span class="k">public</span> <span class="o">|</span> <span class="n">alembic_version</span> <span class="o">|</span> <span class="k">table</span> <span class="o">|</span> <span class="n">hehe</span>
<span class="k">public</span> <span class="o">|</span> <span class="n">users</span> <span class="o">|</span> <span class="k">table</span> <span class="o">|</span> <span class="n">hehe</span>
<span class="k">public</span> <span class="o">|</span> <span class="n">users_id_seq</span> <span class="o">|</span> <span class="o">??????|</span> <span class="n">hehe</span>
<span class="o">#</span> <span class="err">查看</span><span class="n">users表结构</span>
<span class="n">hehe</span><span class="o">=#</span> <span class="err">\</span><span class="n">d</span> <span class="n">users</span>
<span class="k">Table</span> <span class="s2">&#34;public.users&#34;</span>
<span class="k">Column</span> <span class="o">|</span> <span class="k">Type</span> <span class="o">|</span> <span class="n">Modifiers</span>
<span class="c1">--------------|------------------------|---------------------------------------------
</span><span class="c1"></span><span class="n">id</span> <span class="o">|</span> <span class="nb">integer</span> <span class="o">|</span> <span class="k">not</span> <span class="k">null</span> <span class="n">nextval</span><span class="p">(</span><span class="s1">&#39;users_id_seq&#39;</span><span class="p">::</span><span class="n">regclass</span><span class="p">)</span>
<span class="n">email</span> <span class="o">|</span> <span class="nb">character</span> <span class="nb">varying</span><span class="p">(</span><span class="mi">64</span><span class="p">)</span> <span class="o">|</span>
<span class="n">username</span> <span class="o">|</span> <span class="nb">character</span> <span class="nb">varying</span><span class="p">(</span><span class="mi">64</span><span class="p">)</span> <span class="o">|</span>
<span class="n">password_hash</span> <span class="o">|</span> <span class="nb">character</span> <span class="nb">varying</span><span class="p">(</span><span class="mi">128</span><span class="p">)</span> <span class="o">|</span>
<span class="n">name</span> <span class="o">|</span> <span class="nb">character</span> <span class="nb">varying</span><span class="p">(</span><span class="mi">64</span><span class="p">)</span> <span class="o">|</span>
<span class="n">Indexes</span><span class="p">:</span>
<span class="s2">&#34;users_pkey&#34;</span> <span class="k">PRIMARY</span> <span class="k">KEY</span><span class="p">,</span> <span class="n">btree</span> <span class="p">(</span><span class="n">id</span><span class="p">)</span>
<span class="s2">&#34;ix_users_email&#34;</span> <span class="k">UNIQUE</span><span class="p">,</span> <span class="n">btree</span> <span class="p">(</span><span class="n">email</span><span class="p">)</span>
<span class="s2">&#34;ix_users_username&#34;</span> <span class="k">UNIQUE</span><span class="p">,</span> <span class="n">btree</span> <span class="p">(</span><span class="n">username</span><span class="p">)</span></code></pre></td></tr></table>
</div>
</div>
<p>说明成功了</p></li>
</ol>
<h2 id="8-添加数据和显示">8. 添加数据和显示</h2>
<p>还是用命令行操作,需要在manage.py文件下面添加:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">flask.ext.script</span> <span class="kn">import</span> <span class="n">Shell</span>
<span class="k">def</span> <span class="nf">make_shell_context</span><span class="p">():</span>
<span class="k">return</span> <span class="nb">dict</span><span class="p">(</span><span class="n">app</span><span class="o">=</span><span class="n">app</span><span class="p">,</span><span class="n">db</span><span class="o">=</span><span class="n">db</span><span class="p">,</span><span class="n">User</span><span class="o">=</span><span class="n">User</span><span class="p">)</span>
<span class="n">manager</span><span class="o">.</span><span class="n">add_command</span><span class="p">(</span><span class="sa"></span><span class="s1">&#39;shell&#39;</span><span class="p">,</span><span class="n">Shell</span><span class="p">(</span><span class="n">make_context</span><span class="o">=</span><span class="n">make_shell_context</span><span class="p">))</span></code></pre></td></tr></table>
</div>
</div>
<p>然后再命令行下面<code>python manage.py shell</code>进入带有app、db和User上下文环境的shell控制台。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-sql" data-lang="sql"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span><span class="lnt">5</span><span class="lnt">6</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-sql" data-lang="sql"><span class="n">u</span> <span class="o">=</span> <span class="k">User</span><span class="p">(</span><span class="n">username</span><span class="o">=</span><span class="s2">&#34;xibao&#34;</span><span class="p">)</span>
<span class="o">#</span> <span class="err">添加一个名为</span><span class="n">xibao的用户</span>
<span class="n">db</span><span class="p">.</span><span class="k">session</span><span class="p">.</span><span class="k">add</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
<span class="n">db</span><span class="p">.</span><span class="k">session</span><span class="p">.</span><span class="k">commit</span><span class="p">()</span>
<span class="o">#</span> <span class="err">退出当前控制台</span>
<span class="n">exit</span></code></pre></td></tr></table>
</div>
</div>
<p>启动服务<code>python manage runserver</code>,在浏览器上面输入<code>127.0.0.1:5000\xibao</code>会返回&rdquo;hello xibao !&ldquo;。</p>
<h2 id="9-从postgresql里面备份">9. 从postgresql里面备份</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-sql" data-lang="sql"><span class="lnt">1</span><span class="lnt">2</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-sql" data-lang="sql"><span class="o">#</span> <span class="err">使用之前</span><span class="n">pg_dump命令备份</span>
<span class="n">pg_dump</span> <span class="o">-</span><span class="n">f</span> <span class="n">backup</span><span class="p">.</span><span class="k">sql</span> <span class="n">hehe</span></code></pre></td></tr></table>
</div>
</div>
<p>当前项目目录下面会多出一个<code>backup.sql</code>文件。</p></description>
</item>
<item>
<title>emacs完全补完计划(五)——歌剧魅影Elisp</title>
<link>http://longlycode.github.io/post/emacs%E5%AE%8C%E5%85%A8%E8%A1%A5%E5%AE%8C%E8%AE%A1%E5%88%92%E4%BA%94/</link>
<pubDate>Sun, 28 Feb 2016 20:18:06 +0000</pubDate>
<guid>http://longlycode.github.io/post/emacs%E5%AE%8C%E5%85%A8%E8%A1%A5%E5%AE%8C%E8%AE%A1%E5%88%92%E4%BA%94/</guid>
<description><!-- toc -->
<h2 id="闲话elisp">闲话elisp</h2>
<blockquote>
<p>如果说emacs是一出庞大的歌剧,那么elisp则是撑起全场的主角,它犹如一道魅影,神秘、黑暗、引人入胜,在剧初以无以伦比的优雅身姿和独一无二的音色试图唤起观众的灵魂共鸣;当有人尝试接近它的时候,或许期望越大失望越大,藏在另一半面具下是人性特有的丑陋,是受世人侮辱唾弃后难掩的愤怒和敏感;而最后它高尚的选择和坚持让作为学习者的我们不断反思,什么叫做美?不是世俗的外在的可视的,是来源内在的人性之光,能够让灵魂起舞。事实上扯远了,不过大概总结了学习elisp的三个阶段,首先被洗脑认为lisp系语言如同武林传说中的秘籍邪典,迷迷糊糊建立了莫名的崇拜,后来深入学习才发现lisp系语言有固有的缺陷,致使它们在现代背景下难有立足之地,最后在完全了解它们了,发现在语言演变的历史长河它们是那么的独一无二,具有难以言表在时间的美,仿佛洞开了一个新世界。lisp相对现在很古老,在这期间有很多篇文章试图向别人灌输它的思想,这篇文章也是其中一篇,但lisp系语言太庞大,就elisp本身的官方手册都有一千多页,要在一篇文章里面完全展现它是不现实的,只能按笔者自己的有限理解来书写,可能夹杂着不恰当的比喻,希望观者有所悟。</p>
</blockquote>
<p></p>
<h2 id="七言七日七符">七言七日七符</h2>
<blockquote>
<p>中国古代只用“七言”寥寥数语就表达出了无尽的情感和哲思,简直是“少即是多”的典范。而在西方传闻上帝仅仅花了七日便创造了世界。so what?说明“七”是吉祥的数字&hellip;&hellip;传说lisp语言在创造之初也仅仅存在七个操作符。分别是 quote,atom,eq,car,cdr,cons以及 cond,如果从这七个角度出发就能化繁为简,理解lisp语言之源。之前的文章有提到三点<strong>操作符前置</strong>、<strong>数据结构</strong>以及<strong>返回机制</strong>,其实都是针对lisp语言的最大特征&ndash;<strong>括号</strong>而言的,在括号里面操作符会前置,遇到括号就执行并返回的机制,在括号外部引入引号让括号返回本身。实际上括号的只体现了lisp语言构成二分一的元素&ndash;语法。而七个操作符体现了语言的另一半组成&ndash;语义。</p>
</blockquote>
<h3 id="atom">atom</h3>
<p>atom翻译过来是原子,不可分割的意思。可以联想到古代由于科学不发达,许多人都想找到世界里最基本东西,用来理解世界的本质或者掌握其中的运行规律。一个经典的模型就是“五行”&ndash;金木水火土,世间万物的都是由这五种基本元素组成的。基本元素的概念其实就对应着atom,语言中一些基础类型是atom的一种。比如最常见的字符串、数字还有布尔值都是。之前有讲过elisp里面用后缀为<code>p</code>的函数来判断一个object的类型,比如<code>stringp</code>、<code>numberp</code>等等,可是没有<code>atomp</code>,因为atom只是一个笼统的概念,没有实际对应的类型,就干脆把atom当做判断符,用来判断一个object是否是atom。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nv">atom</span> <span class="s">&#34;hello&#34;</span><span class="p">)</span> <span class="c1">;;==&gt;t</span>
<span class="p">(</span><span class="nv">atom</span> <span class="mi">233</span><span class="p">)</span> <span class="c1">;;==&gt;t</span>
<span class="p">(</span><span class="nv">atom</span> <span class="no">nil</span><span class="p">)</span> <span class="c1">;;==&gt;t</span>
<span class="p">(</span><span class="nv">atom</span> <span class="ss">:keyword</span><span class="p">)</span> <span class="c1">;;==&gt;t</span></code></pre></td></tr></table>
</div>
</div>
<p>实际上elisp用<code>type-of</code>返回一个object的具体类型。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nv">type-of</span> <span class="s">&#34;hello&#34;</span><span class="p">)</span> <span class="c1">;;==&gt;string</span>
<span class="p">(</span><span class="nv">type-of</span> <span class="mi">233</span><span class="p">)</span> <span class="c1">;;===&gt;integer</span>
<span class="p">(</span><span class="nv">type-of</span> <span class="no">nil</span><span class="p">)</span> <span class="c1">;;===&gt;symbol</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="cons-car-cdr">cons、car、cdr</h3>
<p>不得不吐槽一下知道atom这个概念并没什么卵用,其实是为了理解cons这个概念做铺垫。cons可以翻译成序对或者点对,个人更倾向于后者。回到“五行”说,当我们手握五大元素的时候会做什么能更有趣?让它们发生关系!这就是所谓相克相生的运行体系,譬如钻木取火、水来土掩、水火不容等等&hellip;<code>cons</code>就是把两个基本元素(atom)结合的一种数据结构,让单独的atom彼此建立联系,<code>cons</code>这个字符本身就是建立这种结构的函数。如下图所示:</p>
<p>可以看出<code>cons</code>返回的形式是<code>(1 . 2)</code>,所以又可以叫做点对结构。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="c1">;;consp是用来判断是否是一个点对结构的函数。</span>
<span class="p">(</span><span class="nv">consp</span> <span class="p">(</span><span class="nv">cons</span> <span class="s">&#34;fire&#34;</span> <span class="s">&#34;water&#34;</span><span class="p">))</span> <span class="c1">;;毋庸置疑返回t</span>
<span class="p">(</span><span class="nv">consp</span> <span class="o">&#39;</span><span class="p">(</span><span class="s">&#34;fire&#34;</span><span class="o">.</span><span class="s">&#34;water&#34;</span><span class="p">))</span> <span class="c1">;;居然也返回t,说明也可以用&#39;(xx.oo)的形式构造一个点对。</span></code></pre></td></tr></table>
</div>
</div>
<p>而<code>car</code>和<code>cdr</code>是对cons最基本的操作,比如<code>(car (cons &quot;阴&quot; &quot;阳&quot;))</code>会返回<strong>阴</strong>,cons的头部;<code>(cdr (cons &quot;阴&quot; &quot;阳&quot;))</code>则返回<strong>阳</strong>,cons的尾部;相当于一个负责“采阴”,另一个负责“取阳”。
<code>cons</code>犹如雌雄、阴阳、黑白、天地等相互对立又相互依存的统一矛盾体,不禁让人联想到太极,也如同太极能够演化出两仪四象八卦万物一样,<code>cons</code>理论上也能构造出任何的数据结构,简单而强大。不信请看:
之前常常提到的list(列表)也是一种特殊的cons,上面第三个例子就是list的结构图,不仅要有“你和我”而且还要大家围在一起手牵手。<code>(cons 1 (cons 2 (cons 3 (cons 4 nil))))</code>这样生成list方式太麻烦所以创造了一个<code>list</code>的函数。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span><span class="lnt">5</span><span class="lnt">6</span><span class="lnt">7</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="c1">;;下面两个表达式是完全相等的</span>
<span class="p">(</span><span class="nv">cons</span> <span class="mi">1</span> <span class="p">(</span><span class="nv">cons</span> <span class="mi">2</span> <span class="p">(</span><span class="nv">cons</span> <span class="mi">3</span> <span class="p">(</span><span class="nv">cons</span> <span class="mi">4</span> <span class="no">nil</span><span class="p">))))</span> <span class="c1">;;==&gt;(1 2 3 4)</span>
<span class="p">(</span><span class="nv">list</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span><span class="p">)</span> <span class="c1">;;==&gt;(1 2 3 4)</span>
<span class="c1">;;将233加入到一个list的头部,并返回加入之后的新list</span>
<span class="p">(</span><span class="nv">cons</span> <span class="mi">233</span> <span class="p">(</span><span class="nv">list</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span><span class="p">))</span> <span class="c1">;;==&gt;(233 1 2 3 4)</span>
<span class="c1">;;用consp来判断</span>
<span class="p">(</span><span class="nv">consp</span> <span class="p">(</span><span class="nv">list</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span><span class="p">))</span> <span class="c1">;;==&gt; t</span></code></pre></td></tr></table>
</div>
</div>
<p>由于cons存在无限的可能,<code>car</code>和<code>cdr</code>这种一次只取一步的操作显然就不合时宜。于是乎创造出各种延伸变异版本的car和cdr,简直丧心病狂。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span><span class="lnt">5</span><span class="lnt">6</span><span class="lnt">7</span><span class="lnt">8</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="c1">;;X代表某种cons复合结构。</span>
<span class="p">(</span><span class="nv">caar</span> <span class="nv">X</span><span class="p">)</span> <span class="c1">;;Return the car of the car of X.</span>
<span class="p">(</span><span class="nv">cddr</span> <span class="nv">X</span><span class="p">)</span> <span class="c1">;;Return the cdr of the cdr of X.</span>
<span class="o">.</span>
<span class="o">.</span>
<span class="o">.</span>
<span class="p">(</span><span class="nv">caaaar</span> <span class="nv">X</span><span class="p">)</span> <span class="c1">;;Return the `car&#39; of the `car&#39; of the `car&#39; of the `car&#39; of X.</span>
<span class="p">(</span><span class="nv">cddddr</span> <span class="nv">X</span><span class="p">)</span> <span class="c1">;;Return the `cdr&#39; of the `cdr&#39; of the `cdr&#39; of the `cdr&#39; of X.</span></code></pre></td></tr></table>
</div>
</div>
<p>实际上,<code>cons</code>更常用于表示概念名称和具体实物之间的关联,像<code>(cons key value)</code>或者<code>'(key . value)</code>便可以表达一个物体。更实际的是,虽然cons结构能千变万化,但是对内存的效率却不高,所以lisp方言们都吸取了其他语言的数据结构,比如数组(array)、哈希表(hash table)等等来提高操作数据的效率,诚然,这样会让lisp方言们摇身一变成了“通用性的语言”,更易于其他程序猿的接受和自身的推广,但点对结构不该被遗忘或抛弃,它是lisp纯粹本质的体现之一。</p>
<h3 id="quote">quote</h3>
<p><code>quote</code>在之前已经提到过了,其实等同于<code>'</code>,引号是quote的简写,<code>(quote a)</code>完全等同于<code>'a</code>。之前还提到过因为lisp语法只要遇到括号就会根据前置的“操作符”求值返回,<code>quote</code>的存在就是对抗这种固化的机制而存在的。可以说没有quote的lisp里面都是“一个求值过程”,quote不求值只返回,数据就很容易构造出来,说到底quote 的存在是由于lisp代码和数据都是都用统一的S表达式带来了困扰。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span><span class="lnt">5</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nv">quote</span> <span class="p">(</span><span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span><span class="p">))</span>
<span class="c1">;;等同于</span>
<span class="o">&#39;</span><span class="p">(</span><span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span><span class="p">)</span>
<span class="c1">;;等同于</span>
<span class="p">(</span><span class="nv">list</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span><span class="p">)</span></code></pre></td></tr></table>
</div>
</div>
<p>这种不求值只返回的机制不仅仅用于构建数据,自然还可以让代码不求值返回,让代码之上又有的一层机制,为神奇的宏的出现埋好了伏笔。</p>
<h3 id="eq">eq</h3>
<p>判断相等的,我至今不明白为什么eq会位列七个操作符之内,它看起来并不是很重要。它的定义是:(eq x y),如果x和y是同一个原子(atom)或者空表(cons),则返回t,否则返回nil。eq是最表面的判断,equal才是更深入的判断,之后会罗列elisp里面所以和判断相等有关的函数。</p>
<h3 id="cond">cond</h3>
<p>cond是控制结构,类似其他语言里面的select-case控制功能,为什么七个操作符里面没有if,大概cond可以判断一种或者多种条件进行跳转,if只能一个或者两个条件,多种条件要不停的嵌套。
形如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span><span class="lnt">5</span><span class="lnt">6</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nv">cond</span>
<span class="p">((</span><span class="nv">条件1</span><span class="p">)</span> <span class="nv">表达式1</span><span class="p">)</span>
<span class="p">((</span><span class="nv">条件2</span><span class="p">)</span> <span class="nv">表达式2</span><span class="p">)</span>
<span class="p">((</span><span class="nv">条件3</span><span class="p">)</span> <span class="nv">表达式3</span><span class="p">)</span>
<span class="p">((</span><span class="nv">条件4</span><span class="p">)</span> <span class="nv">表达式4</span><span class="p">)</span>
<span class="p">)</span></code></pre></td></tr></table>
</div>
</div>
<p>从上到下依次执行,直到遇到条件表达式返回值为t,则将该条件后面表达式的值当做整个cond表达式的返回值。</p>
<h2 id="elisp的基本数据类型">elisp的基本数据类型</h2>
<blockquote>
<p>回到elisp,基本数据类型有些和其他语言差不多,限于篇幅,挑重点讲。</p>
</blockquote>
<h3 id="integer">integer</h3>
<p>整型,#bNNN表示二进制数,同理有#o(八进制数)、#x(十六进制数)。</p>
<h3 id="float">float</h3>
<p>INF表示无穷大。</p>
<h3 id="char">Char</h3>
<p>Char其实就是integer,字符型用整数型对应的编码表示了而已。可以用<code>?字母</code>来打印字面量。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nv">prin1</span> <span class="nv">?a</span><span class="p">)</span> <span class="c1">;;==&gt;97</span>
<span class="p">(</span><span class="nv">prin1</span> <span class="nv">?A</span><span class="p">)</span> <span class="c1">;;==&gt;65</span></code></pre></td></tr></table>
</div>
</div>
<p>也和其他语言的一样,<code>\n</code>来表示空一行,<code>\t</code>表示TAB键等等,elisp里面多了几个:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt"> 1</span><span class="lnt"> 2</span><span class="lnt"> 3</span><span class="lnt"> 4</span><span class="lnt"> 5</span><span class="lnt"> 6</span><span class="lnt"> 7</span><span class="lnt"> 8</span><span class="lnt"> 9</span><span class="lnt">10</span><span class="lnt">11</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="nv">?\a</span> <span class="c1">;=&gt; 7 ; control-g, `C-g&#39;</span>
<span class="nv">?\b</span> <span class="c1">;=&gt; 8 ; backspace, &lt;BS&gt;, `C-h&#39;</span>
<span class="nv">?\t</span> <span class="c1">;=&gt; 9 ; tab, &lt;TAB&gt;, `C-i&#39;</span>
<span class="nv">?\n</span> <span class="c1">;=&gt; 10 ; newline, `C-j&#39;</span>
<span class="nv">?\v</span> <span class="c1">;=&gt; 11 ; vertical tab, `C-k&#39;</span>
<span class="nv">?\f</span> <span class="c1">;=&gt; 12 ; formfeed character, `C-l&#39;</span>
<span class="nv">?\r</span> <span class="c1">;=&gt; 13 ; carriage return, &lt;RET&gt;, `C-m&#39;</span>
<span class="nv">?\e</span> <span class="c1">;=&gt; 27 ; escape character, &lt;ESC&gt;, `C-[&#39;</span>
<span class="nv">?\s</span> <span class="c1">;=&gt; 32 ; space character, &lt;SPC&gt;</span>
<span class="nv">?\\</span> <span class="c1">;=&gt; 92 ; backslash character, `\&#39;</span>
<span class="nv">?\d</span> <span class="c1">;=&gt; 127 ; delete character, &lt;DEL&gt;</span></code></pre></td></tr></table>
</div>
</div>
<h2 id="elisp的容器类型">elisp的容器类型</h2>
<blockquote>
<p>也是基础的数据结构,因为具有容纳的作用,而且彼此之间是有联系的,所以独起一章。这么多的容器式数据类型,区别它们的无非两点:存储的数据类型和底层的存储形式。关系如下图:</p>
</blockquote>
<p>Sequence(序列)是hash-table外所有容器类型的总称了。用<code>(length aSequence)</code>获取Sequence的长度,<code>(elt sequence N)</code>来获取第N个元素,对任何一种序列都有用。</p>
<h3 id="list">List</h3>
<p>list是特殊的cons点对结构,是emacs里面最常见的数据类型。</p>
<ol>
<li>创建list:使用list函数<code>(list 1 2 3 4)</code>或者<code>'(1 2 3 4)</code></li>
<li>获取list里面的元素</li>
</ol>
<table>
<thead>
<tr>
<th>函数</th>
<th>功能</th>
</tr>
</thead>
<tbody>
<tr>
<td>(car X)</td>
<td>first element</td>
</tr>
<tr>
<td>(nth n X)</td>
<td>nth element (start from 0)</td>
</tr>
<tr>
<td>(car (last X))</td>
<td>last element</td>
</tr>
<tr>
<td>(cdr X)</td>
<td>2nd to last elements</td>
</tr>
<tr>
<td>(nthcdr n X)</td>
<td>nth to last elements</td>
</tr>
<tr>
<td>(butlast X n)</td>
<td>without the last n elements</td>
</tr>
</tbody>
</table>
<ol>
<li>在list头部添加元素:(cons element mylist)</li>
<li>合并两个list:(append list1 list2)</li>
<li>判断list是否为空:<strong>null</strong></li>
<li>判断某个元素是否存在:<code>(member element X)</code></li>
<li>返回元素所在的位置:<code>(position element X)</code></li>
</ol>
<h4 id="alist-association-list">alist(association list)</h4>
<p>alist是elisp里面非常重要的概念,理解了点对结构之后,alist其实是把一组cons组织成一个列表,每个元素就是一个cons。形如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span><span class="lnt">5</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nv">list</span>
<span class="o">&#39;</span><span class="p">(</span><span class="nv">key1</span> <span class="o">.</span> <span class="nv">value1</span><span class="p">)</span>
<span class="o">&#39;</span><span class="p">(</span><span class="nv">key2</span> <span class="o">.</span> <span class="nv">value2</span><span class="p">)</span>
<span class="o">&#39;</span><span class="p">(</span><span class="nv">key3</span> <span class="o">.</span> <span class="nv">value3</span><span class="p">)</span>
<span class="p">)</span></code></pre></td></tr></table>
</div>
</div>
<p>emacs里面组织存放一组变量的最常见的形式。值得一提的是alist里面的元素是顺序的,且允许重复键值。
一个非常有用的函数<strong>assoc</strong>,用key来寻找value,key的匹配使用的是equal。这么用:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt"> 1</span><span class="lnt"> 2</span><span class="lnt"> 3</span><span class="lnt"> 4</span><span class="lnt"> 5</span><span class="lnt"> 6</span><span class="lnt"> 7</span><span class="lnt"> 8</span><span class="lnt"> 9</span><span class="lnt">10</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="c1">;;构建一个alist,并把它赋给dict</span>
<span class="p">(</span><span class="nv">setq</span> <span class="nv">dict</span>
<span class="o">&#39;</span><span class="p">((</span><span class="nv">pine</span> <span class="o">.</span> <span class="nv">cones</span><span class="p">)</span>
<span class="p">(</span><span class="nv">oak</span> <span class="o">.</span> <span class="nv">acorns</span><span class="p">)</span>
<span class="p">(</span><span class="nv">maple</span> <span class="o">.</span> <span class="nv">seeds</span><span class="p">)))</span>
<span class="c1">;;使用assoc,找到对应的cons并返回</span>
<span class="p">(</span><span class="nv">assoc</span> <span class="ss">&#39;oak</span> <span class="nv">dict</span><span class="p">)</span> <span class="c1">;;==&gt;(oak . acorns)</span>
<span class="c1">;;结合car、cdr可以把cons里面key和value分别取出来</span>
<span class="p">(</span><span class="nv">car</span> <span class="p">(</span><span class="nv">assoc</span> <span class="ss">&#39;oak</span> <span class="nv">dict</span><span class="p">))</span> <span class="c1">;;==&gt;oak</span>
<span class="p">(</span><span class="nv">cdr</span> <span class="p">(</span><span class="nv">assoc</span> <span class="ss">&#39;oak</span> <span class="nv">dict</span><span class="p">))</span> <span class="c1">;;==&gt;acorns</span></code></pre></td></tr></table>
</div>
</div>
<h4 id="plist-property-list">plist(Property list)</h4>
<p>顾名思义,属性列表,其作用和alist相似,不过语法更加清晰些。形如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="o">&#39;</span><span class="p">(</span><span class="ss">:key1</span> <span class="nv">value1</span> <span class="ss">:key2</span> <span class="nv">value2</span> <span class="ss">:key3</span> <span class="nv">value3</span><span class="p">)</span></code></pre></td></tr></table>
</div>
</div>
<p>注意<code>:</code>是不能省略的,而且key的值必须是唯一的。用plist-get取出值,plist-put来加入新的值。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="c1">;;构建一个plist,并把它赋给plst</span>
<span class="p">(</span><span class="nv">setq</span> <span class="nv">plst</span> <span class="p">(</span><span class="nv">list</span> <span class="ss">:buffer</span> <span class="p">(</span><span class="nv">current-buffer</span><span class="p">)</span> <span class="ss">:line</span> <span class="mi">10</span> <span class="ss">:pos</span> <span class="mi">2000</span><span class="p">))</span>
<span class="c1">;;plist-get取出值</span>
<span class="p">(</span><span class="nv">plist-get</span> <span class="nv">plst</span> <span class="ss">:pos</span><span class="p">)</span> <span class="c1">;;==&gt;2000</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="array">Array</h3>
<p>创建Array需要指定一个固定长度,除了char-table,这点限制了它的使用。
除了从sequence继承过来的<strong>length</strong>和<strong>elt</strong>函数,array本身也有几个函数,对下属的类型都有效。
设置元素位置和值:<code>(aset array index value)</code></p>
<h4 id="vector">Vector</h4>
<ol>
<li>创建一个Vector:两种形式<code>[v1 v2 v3 ...]</code>和<code>(vector v1 v2 v3 ...)</code>,显然引入了<code>[]</code>,在一堆括号里面也另类。</li>
<li>将多个sequence合并成为一个vector:<code>(voncat seq1 seq2)</code></li>
<li>vector和list的转换:<code>(append vector nil)</code></li>
</ol>
<h4 id="bool-vector">bool-vector</h4>
<ol>
<li>bool-vector是vector的子集,只能用来存放nil或t。</li>
<li>创建 bool-vector:<code>(make-bool-vector LENGTH INIT)</code>。</li>
</ol>
<h4 id="char-table">char-table</h4>
<h4 id="string">string</h4>
<ol>
<li>string是不可变的,这点和大部分的语言一致</li>
<li>string可以包含文本属性properties,形如<code>#(&quot;str&quot; property-data)</code>,property-data是以plist形式包含了string的一些属性。</li>
<li>string用<code>string=</code>和<code>string&lt;</code>进行对比。</li>
</ol>
<h3 id="hash-table-哈希表">Hash Table(哈希表)</h3>
<blockquote>
<p>在其他语言比较常见的类型,数据容量到达一定级别速度依旧非常快,没有特殊的顺序要求,但不能重复。如果是小型数据装载还是建议用list,大集合用哈希表。</p>
</blockquote>
<ol>
<li><p>创建的哈希表时候可以根据一些关键字<code>:key</code>来指定初始属性。</p>
<ul>
<li>:test 因为哈希表里面的key值要求不能重复,所以key值需要比较,这个关键字指定key值比较的函数,可以是<code>eq</code>、<code>eql</code>、<code>equal</code>,默认是<code>eql</code>。</li>
<li>:size 指定初始容量大小</li>
</ul></li>
<li><p>访问hash table相关的函数:</p>
<ul>
<li>(gethash KEY TABLE)</li>
<li>(puthash KEY VALUE TABLE)</li>
<li>(remhash KEY TABLE):移除某个元素</li>
<li>(clrhash TABLE):清理hash table</li>
<li>(maphash FUNCTION TABLE):对每个元素都应用FUNCTION</li>
</ul></li>
<li><p>拷贝:<code>(copy-hash-table table)</code></p></li>
<li><p>个数:<code>(hash-table-count table)</code></p></li>
</ol>
<h2 id="emacs基本数据类型小结">emacs基本数据类型小结</h2>
<h3 id="数据类型间的转换">数据类型间的转换</h3>
<ol>
<li>number-to-string/string-to-number</li>
<li><p>concat可以将序列转换成字符串:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nv">concat</span> <span class="o">&#39;</span><span class="p">(</span><span class="nv">?a</span> <span class="nv">?b</span> <span class="nv">?c</span> <span class="nv">?d</span> <span class="nv">?e</span><span class="p">))</span> <span class="c1">; =&gt; &#34;abcde&#34;</span>
<span class="p">(</span><span class="nv">concat</span> <span class="nv">[?a</span> <span class="nv">?b</span> <span class="nv">?c</span> <span class="nv">?d</span> <span class="nv">?e]</span><span class="p">)</span> <span class="c1">; =&gt; &#34;abcde&#34;</span></code></pre></td></tr></table>
</div>
</div></li>
<li><p>vconcat 把字符串转换成向量</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nv">vconcat</span> <span class="s">&#34;abcde&#34;</span><span class="p">)</span> <span class="c1">;;==&gt;[97 98 99 100 101]</span></code></pre></td></tr></table>
</div>
</div></li>
<li><p>append原来是用来拼接两个list或者向list添加元素的,这里也可以把字符串转换成一个列表。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nv">append</span> <span class="s">&#34;abcdef&#34;</span> <span class="no">nil</span><span class="p">)</span> <span class="c1">; =&gt; (97 98 99 100 101 102)</span></code></pre></td></tr></table>
</div>
</div></li>
<li><p>字母大小写:downcase、upcase、capitalize</p></li>
<li><p>转换数字为float类型:<code>(float number)</code></p></li>
<li><p>float转integer:ceiling、round</p></li>
</ol>
<h3 id="对比相等">对比相等</h3>
<ol>
<li><code>(eq OBJ1 OBJ2)</code>:只是简单的对比两个object是否相等。</li>
<li><p><code>(eql OBJ1 OBJ2)</code>:比eq高级一个点,遇到数字的时候还会判断数字的类型和大小。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="c1">;;除了数值为1,一个为整数一个为浮点数,所以为nil</span>
<span class="p">(</span><span class="nv">eql</span> <span class="mi">1</span> <span class="mf">1.0</span><span class="p">)</span> <span class="c1">;;==&gt;nil</span>
<span class="c1">;;类型和数值都一样才返回t</span>
<span class="p">(</span><span class="nv">eql</span> <span class="mf">1.0</span> <span class="mf">1.0</span><span class="p">)</span> <span class="c1">;;==&gt;t</span></code></pre></td></tr></table>
</div>
</div></li>
<li><p><code>(equal O1 O2)</code>:因为比上面两个都长,所以更加深入,比较类型、数值以及结构全部相等情况,最常用的比较。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="c1">;;下面左右两个都是cons结构的生成方式,所以返回t</span>
<span class="p">(</span><span class="nv">equal</span> <span class="o">&#39;</span><span class="p">(</span><span class="mi">1</span> <span class="o">.</span> <span class="mi">2</span><span class="p">)</span> <span class="p">(</span><span class="nv">cons</span> <span class="mi">1</span> <span class="mi">2</span><span class="p">))</span> <span class="c1">;;==&gt;t</span></code></pre></td></tr></table>
</div>
</div></li>
<li><p><code>=</code>:数字比较,主要针对值,<code>(= 2 2.0)</code>返回t。</p></li>
<li><p><code>string=</code>和<code>string-equal</code>:两者是一样的,前者是后者的别名,比较字符串是否相等。</p></li>
</ol>
<h3 id="正则表达式">正则表达式</h3>
<p>之前已经讲到正则常用的函数<code>string-match</code>和<code>look-at</code>,前者必须指定正则表达式和需要匹配的字符串,而look-at则是从此buffer的光标开始出进行匹配。
elisp的正则语法和其他语言基本一致,但有一点特别丑陋,像<code>(,) {,} \</code>等都需要转义才能使用,因为&rdquo;\&ldquo;也需要转义所以需要以&rdquo;\&ldquo;形式转义其他字符,比如匹配四位数字的正则&rdquo;[0-9]\{4\}&ldquo;。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="c1">;;匹配2016这个数字</span>
<span class="p">(</span><span class="nv">string-match</span> <span class="s">&#34;[0-9]\\{4\\}&#34;</span> <span class="s">&#34;欢迎2016的到来&#34;</span><span class="p">)</span>
<span class="c1">;;中间参数0代表第0分组,也就是所有分组。</span>
<span class="p">(</span><span class="nv">match-string</span> <span class="mi">0</span> <span class="s">&#34;欢迎2016的到来&#34;</span><span class="p">)</span> <span class="c1">;;==&gt;&#34;2016&#34;</span></code></pre></td></tr></table>
</div>
</div>
<h2 id="symbol-符号">Symbol(符号)</h2>
<h3 id="概述">概述</h3>
<p>理解symbol是理解elisp的关键。当初在elisp成形的时候,面向对象的思想还没这么盛行,这种思想用继承和实例化的方式结构化地梳理代码间的关系,尤为重要的是对象状态的组织和存储以一种非常合理的形式呈现。elisp没有包含面向对象的思想,所以不现代很落后。就像用对象来指代一切很多现代语言一样,symbol是elip 里面的通用货币。symbol可以<strong>同时</strong>拥有下面四种值:
1. &ldquo;name&rdquo;,symbol-name符号名字
2. &ldquo;value&rdquo;,存储的变量值
3. &ldquo;function&rdquo;,存储的函数或者宏
4. &ldquo;property list&rdquo;,存储的属性列表</p>
<h3 id="symbol定义">symbol定义</h3>
<p>symbol具有唯一的名字,它拥有四个Cell,cell应该翻译成“槽”或者“域”,作用就是存储指向以上四个值的“指针”。symbol 名字定义的规则很简单,就是<code>(quote name)</code>或者<code>'name</code>,单引号+普通字符,遇到特殊的字符该转义的还是得转义,比如:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nv">symbolp</span> <span class="ss">&#39;+1</span><span class="p">)</span> <span class="c1">;;==&gt;nil</span>
<span class="p">(</span><span class="nv">symbolp</span> <span class="ss">&#39;\+1</span><span class="p">)</span> <span class="c1">;;==&gt;t</span>
<span class="c1">;;使用symbol-name获得名字</span>
<span class="p">(</span><span class="nv">symbol-name</span> <span class="ss">&#39;\+1</span><span class="p">)</span> <span class="c1">;;==&gt;&#34;+1&#34;</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="求值规则和symbol">求值规则和symbol</h3>
<p>现在完全总结一下elisp里面的求值规则,一共三种:
1. 第一种就是自求值,数字、字符串、cons以及nil、t等会直接返回它所拥有的值。
2. 第二种是本节讨论的符号,符号虽然是使用了单引号这种形式,但它会根据不同环境或者“操作符”从cells里面返回不同值。
3. 第三种是列表求值,之前说的“遇到括号就返回”,如果在括号外围有quote或者单引号只会返回列表本身。
也可以用<code>(eval 表达式)</code>方式来主动求值(evaluation),相当于抵消quote的作用。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="c1">;;下面两个表达式是完全相等的</span>
<span class="p">(</span><span class="nv">+</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span> <span class="mi">5</span><span class="p">)</span> <span class="c1">;;==&gt;14</span>
<span class="p">(</span><span class="nv">eval</span> <span class="o">&#39;</span><span class="p">(</span><span class="nv">+</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span> <span class="mi">5</span><span class="p">))</span> <span class="c1">;;==&gt;14</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="symbol组成">symbol组成</h3>
<p>用<code>(set (quote sym) val)</code>可将值赋给一个符号,看起来太麻烦了,用<code>(setq sym val)</code>是同样的效果,其中val不能是自求值类型,占有一个符号中的cell只能是一个不能自求值类型。如果是自求值类型的话symbol不再是symbol而只是一个<strong>变量</strong>。
1. value cell的存储和取出</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt"> 1</span><span class="lnt"> 2</span><span class="lnt"> 3</span><span class="lnt"> 4</span><span class="lnt"> 5</span><span class="lnt"> 6</span><span class="lnt"> 7</span><span class="lnt"> 8</span><span class="lnt"> 9</span><span class="lnt">10</span><span class="lnt">11</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="c1">;;如果是基本类型直接赋值的话,根本不会当符号处理,因为它们返回自求值</span>
<span class="p">(</span><span class="nv">setq</span> <span class="nv">num</span> <span class="mi">123</span><span class="p">)</span>
<span class="p">(</span><span class="nv">symbol-value</span> <span class="nv">num</span><span class="p">)</span> <span class="c1">;;==&gt;*** Eval error *** Wrong type argument: symbolp,123</span>
<span class="p">(</span><span class="nv">symbolp</span> <span class="nv">num</span><span class="p">)</span> <span class="c1">;;==&gt;nil</span>
<span class="p">(</span><span class="nv">type-of</span> <span class="nv">num</span><span class="p">)</span> <span class="c1">;;==&gt;integer</span>
<span class="c1">;;但是将num这个变量使用quote的话,就变成一个符号</span>
<span class="p">(</span><span class="nv">setq</span> <span class="nv">sym</span><span class="err">—</span><span class="nv">num</span> <span class="ss">&#39;num</span><span class="p">)</span>
<span class="p">(</span><span class="nv">symbolp</span> <span class="nv">sym-num</span><span class="p">)</span> <span class="c1">;;==&gt;t</span>
<span class="c1">;;symbol-value 的作用是从cell里面取出符号并进行eval</span>
<span class="p">(</span><span class="nv">symbol-value</span> <span class="nv">sym-num</span><span class="p">)</span> <span class="c1">;;==&gt;123</span>
<span class="c1">;;也可以先判断一个symbol是否已经绑定一个变量值</span></code></pre></td></tr></table>
</div>
</div>
<ol>
<li>function cell 的存储和取出
<code>lisp
;;使用symbol-function取出操作
(symbol-function 'car) ;;==&gt; #&lt;subr car&gt;
;;使用fset将上节sym-num这个符号的function cell存储一个函数
(fset sym-num 'car) ;;==&gt;car
;;fboundp来判断是否有绑定函数
(fboundp sym-num) ;;==&gt;t
;;用funcall来调用
(funcall sym-num '(a . b)) ;;==&gt;a
</code></li>
<li><p>property list属性列表,属性列表为了变量和函数存在的,用来存储附加属性或者状态。形如(pro1 value1 pro2 value2&hellip;)。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt"> 1</span><span class="lnt"> 2</span><span class="lnt"> 3</span><span class="lnt"> 4</span><span class="lnt"> 5</span><span class="lnt"> 6</span><span class="lnt"> 7</span><span class="lnt"> 8</span><span class="lnt"> 9</span><span class="lnt">10</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="c1">;;使用put 和 get 分配或者取出操作,貌似一次只能分配一次</span>
<span class="p">(</span><span class="nv">put</span> <span class="nv">sym-num</span> <span class="ss">:key</span> <span class="s">&#34;value1&#34;</span><span class="p">)</span>
<span class="p">(</span><span class="nv">put</span> <span class="nv">sym-num</span> <span class="ss">:color</span> <span class="s">&#34;blue&#34;</span><span class="p">)</span>
<span class="c1">;;&#34;:key&#34;是一种特殊的符号,一般用在property list 和hash table 里面</span>
<span class="p">(</span><span class="nv">get</span> <span class="nv">sym-num</span> <span class="ss">:color</span><span class="p">)</span> <span class="c1">;;==&gt;&#34;blue&#34;</span>
<span class="c1">;;symbol-plist获取整个属性列表</span>
<span class="p">(</span><span class="nv">symbol-plist</span> <span class="nv">sym-num</span><span class="p">)</span> <span class="c1">;;==&gt;(group-documentation &#34;The X Window system.&#34; :key &#34;value1&#34; :color &#34;blue&#34;)</span>
<span class="c1">;;把symbol-plist单独提取出来自然可以用plist-get和plist-put操作</span>
<span class="p">(</span><span class="nv">setq</span> <span class="nv">my-plist</span> <span class="p">(</span><span class="nv">symbol-plist</span> <span class="nv">sym-num</span><span class="p">))</span>
<span class="p">(</span><span class="nv">plist-get</span> <span class="nv">my-plist</span> <span class="ss">:color</span><span class="p">)</span> <span class="c1">;;==&gt;&#34;blue&#34;</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="string-和symbol转换">string 和symbol转换</h3>
<p>值得一提的是,字符串和符号之间可以直接转换。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="lnt">1</span><span class="lnt">2</span><span class="lnt">3</span><span class="lnt">4</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-lisp" data-lang="lisp"><span class="c1">;;将symbol 转换成string</span>
<span class="p">(</span><span class="nv">symbol-name</span> <span class="ss">&#39;sym-num</span><span class="p">)</span>
<span class="c1">;;将string 转换成symbol</span>
<span class="p">(</span><span class="nv">intern</span> <span class="s">&#34;minecraft&#34;</span><span class="p">)</span></code></pre></td></tr></table>
</div>
</div>
<p>未完待续&hellip;&hellip;</p></li>
</ol></description>
</item>