2011年8月27日星期六

【挖一挖】levelup.cn的论坛ACG小说版的某些内容

去年的时候从bingj.com的页面存档里挖出来的,现转过来做纪念。
挖取的目标是http://archive.bbs.levelup.cn/showforum-67-(\d+).aspx
挖取的结果是http://www.uudisc.com/group/10240/topic/37165
以下的便是当初挖取结果的内容,不过那里也快挂了。
话说levelup也出过此方面的杂志,也已经早早的挂了,仅还可以搜索到目录。

[轻小说]《月兔的银色方舟》作者:[日]鴨志田一
[轻小说]《白山同学与黑色手提袋》第一卷 作者:[日铃木铃
[轻小说]《攻壳机动队——宇宙生化人》作者:[日]远藤明范
[游戏小说]《水仙》全一卷 作者:[日]片冈とも
[轻小说]《がく×ぶる》(第一卷)作者:[日]本田 透
[杂书?]《征服世界有可能的吗》作者:[日]冈田斗司夫
[轻小说]《莱茵河的囚徒》作者:[日]田中芳树
雛形
[轻小说]《杀×爱》作者:风见周(0~4)
[轻小说]《魔女宅急便》作者:角野荣子(全)
[轻小说]《新本格魔法少女莉丝佳》作者:西尾维新(1~2)
[輕小說]《狼與辛香料》作者:[日]支仓冻沙 (13+短篇)12/17更新
[轻小说] 《文学少女》作者:野村美月 (1-8+短篇 完)12/17日更新
[轻小说]《仰望半月的夜空》作者:桥本纺 (1-8卷+2短篇完结)
[轻小说]《离别的钢琴奏鸣曲 1~2》作者:杉井光 12/9更新第2卷
[轻小说] 这本轻小说真厉害!2009年前10名作品集合!
[轻小说]《超人家族一家和乐!? 》作者:桥本和也 (1~4)12/9更新第4卷
[轻小说]《电波系彼女 三卷全》作者:片山宪太郎
[轻小说]《冰箱上的洞》作者:KOMUGI
[轻小说]《初恋魔法电击》作者:明日香正太(1-9完整版 未完)
[排行榜] 这本轻小说真厉害2010
[轻小说]《电波男》作者:本田透(适合宅人群= =)
求书~~~~知道三毛的进来哈
[轻小说]《魔法少女奈叶》作者:都筑真纪(全)
[日本小说]《人间失格》作者:太宰治
[遊戲劇本]《真月譚月姬》作者:[日]奈须きのこ (完整版)
[遊戲小說]《格蘭蒂亞》作者:[日]細江ひろみ
[轻小说]《圣魔之血长篇+短篇》 作者:吉田直在
[轻小说] 《便·当 味噌炖青花鱼290元》作者:朝浦(第1卷未完)
[輕小說]《百花缭乱》作者:すずきぁきら(2卷未)11/30更新
[轻小说]《影≒光 Shadow Light》作者:影名浅海 (1~5)
[游戏相关] 《潜龙谍影 - Metal Gear Solid 官方小说》
[轻小说]《银盘万花筒》作者:海原零 (1~9)
[推理侦探]《白夜行》作者:东野圭吾
[轻小说]《神样家族》作者:桑岛由一 (1~7)
[合集小说]乙一作品集[共32篇]
[轻小说]《风之圣痕》作者:山门敬宏(1~6+短篇)
[轻小说]《空罐少女!》作者:蓝上陆/铃平ひろ (1~4)
[轻小说]《骷髅恋人》作者: 平坂读(1~5)
[轻小说]《眼镜男与断头少女》作者: 藤原祐 (1~2)
[妖怪小说]《巷说百物语》作者:京极夏彦(1~4完结)
[国产轻小说]《長安幻夜》原作:面堂兄 漫画:韩露(漫友人气连载)
[輕小說]《虚轴少女ResinCastMilk》作者:[日]藤原佑(1-5)
[漫画改编]《黑血》 原案/漫画:赵佳
[輕小說]《触摸魔女》作者:[日]镜裕之
银河铁道之夜
哈里7:哈里波特与死圣
[遊戲相關]《Tales of Symphonia 拉塔特斯克的骑士 世界之愿》作者:[日]矢島さら
[輕小说] 《乃木坂春香的秘密》作者:[日]五十岚雄策(10卷)11/09更新

[輕小說]《IS》作者:[日]弓弦イズル
[轻小说]《电波女与青春男01》作者:入间人间
[轻小说]《奇诺之旅》作者:时雨泽惠一(1-12+外+PS2剧本)11/6更新
[动漫相关]《云之彼端约定之地》 原作:新海诚
[轻小说]《打工魔法师》作者:椎野美由贵 (1~8)10/25更新第8卷
给寺院拍照 照片出来后我惊呆了(恐怖)
[輕小說]《Campione!神不值得信奉》作者:[日]丈月城
[轻小说]《灼眼的夏娜 》作者:高桥弥七郎 10/21更新19卷
[轻小说]谷川流作品集(部分附插画),纳米盘
[推理小说]《魔术的耳语》作者:宫部美雪
[轻小说]《亲亲坏老爹》作者:野村美月(1-4卷)9/22更新
[畅销经典]《肖申克的救赎》作者:斯蒂芬·金
[轻小说]《听到涛声》作者:冰室冴子(1~2+番外篇)
[轻小说]《MAMA》作者:红玉ぃづき
[推理小说]《猎捕史奈克》作者:宫部美雪
[轻小说]《超妹大战》作者:古桥修之(1~2)
[动漫相关]《名侦探柯南 江神原的魔女》 作者:平良隆久
[推理小说]《火车》作者:宫部美雪
[轻小说]《幻影父亲》作者:深泽美潮
[輕小說]《Resin Cast Milk 虚轴少女的日常》作者:[日]藤原佑
[轻小说]《吊线木偶症候群》作者:乾久留美
[轻小说]《不適合少女的職業》作者:櫻庭一樹
[轻小说]《镇魂练习曲》作者:北泽大辅 (1~3)
[动漫相关]《L改变世界 洛杉矶BB连续杀人案件》作者:西尾维新
[动漫小说] 《反逆的鲁路修官方小说朱之轨迹》作者:岩佐守(完)
[动漫相关]《空中杀手》作者:森博嗣 (完)
[2009]这本轻小说最厉害TOP50!
[轻小说]《在暗夜中寻找羔羊》作者:穗史贺雅也 (1~3完结)
[輕小說]《我甜蜜的苦涩委内瑞拉》作者:[日]森田季节
[輕小說]《机巧魔神》作者:[日]三雲岳斗
[輕小說]《東京吸血鬼金融》作者:[日]真藤順丈
[輕小說]《闲狼作家是美少女妖怪?》作者:[日]杉井光
[輕小說]《梅格&賽隆》作者:[日]时雨泽惠一
[轻小说]《盖棺论定!》作者:文冈あちら
[剧情小说]《流行之神》作者:不详
[轻小说]《凛子与昭介の故事&Yaorozu》作者:土塀赋之 古户真智子
[轻小说]《此处前方是荒野》作者:水无神知宏
[轻小说]《串刺少女》作者:木村航 (1~3完结)
[輕小說]《幸运机会!》作者:[日]有泽真水
《精子战争》
两本工具书:完全复仇手册,完全失踪手册
[推理小说]《他人事》作者:平山梦明
[遊戲相關]《命运传奇 命运传承者》作者:[日]矢島さら(上下全)9/19更新
[轻小说]《心灵侦探八云》作者:神永学 (1~2)
[惊悚小说]《ZOO》作者:[日]乙一
[轻小说]《疾走!青春期的帕拉贝伦》作者:深见真(1~2)
[推理小說]《狂骨之夢》作者:[日]京极夏彦(上下全)
[轻小说]《MM一族》作者:松野秋鸣(1-8未) 9/12更新
[轻小说]《9S》作者:[日]叶山透(1-9+Memories+SS,未完结)
[短篇轻小说]《辉石之花》作者:河屋 一

[轻小说]《七人武器店》(1-2)作者:[日]大乐绚太(未完结)
[轻小说]《魔法战士李维》作者:[日]水野良(未完结)
[轻小说]《春季限定草莓塔事件》作者:米泽穗信
[推理小说]《铁鼠之槛》作者:京极夏彦
[輕小說]《學生會的日常》作者:[日]葵せきな(1卷未)
[资料收集]英雄无敌生物背景考究
[輕小說]《佰物語》广播剧全对话翻譯. 作者:[日]西尾維新
[轻小说]《壳中少女》作者:冲方丁(全)
[科幻军事]《光晕》(1~4全)作者:[美] 埃里克·尼伦德&威廉·C·迪茨 [中
[轻小说]《终焉的年代记》作者:川上稔(1-3上 未完) 8/24更新
《灵异知识普及资料》作者:不详
[轻小说]《在遙遠彼方的小千》作者:日日日(全一卷)
[轻小说]《拯救你的最初咒语》作者:须堂项(1~2未完)
[轻小说]《捨棄在八月的路上》作者:伊藤たかみ(全一卷)
[幻想小说]《妖藩记鬼剑众》作者:菊地秀行
[剧情小说]《最终幻想VI》 作者:不详
[官方小说]《怪物猎人2G魂之继承者1-5》 作者:冰上惠一
[轻小说]《神灯女仆1-4》作者:夏绿
[奇幻经典]被遗忘的国度系列(包含部分英文原著)更新《血脉+无星之夜》
[游戏相关]《秋之回忆1-3+从今以后》 作者:不详
[轻小说]《七姬物语1-4》作者:高野和
[轻小说]《狂恋声优宝贝》作者:木本雅彦
[轻小说]《彈珠汽水》作者:[日]鴻野貴光 (全一卷)
[輕小說]《小齒輪!》作者:[日]樋口司
[热门小说]《凉宫春日的忧郁》作者:谷川流
【科幻】《光晕三部曲》 作者:[美] 埃里克·尼伦德 威廉·C·迪茨
[轻小说]《女帝·龍凰院麟音的初恋 第一卷》作者:[日]风见周
[动漫相关]《晴空之Air1-6》作者:不详
[轻小说]《学校的阶梯》作者:櫂末高彰 (1~9+短篇 未完)8/8更新
[剧情小说]《寄生前夜2》作者:不详
强烈推荐《战神
[轻小说]《神样灵感少女+传说灵感少女》作者:松原真琴/小畑健(8/1更新完结)
城寨书房版规
电子书资源获取流程及阅读、排版工具
[轻小说]《抱歉咯?二之宫同学》作者:铃木大辅(1卷未)
求书求助专贴
[轻小说]《重回那天》作者:健速(全一卷)
[灵异小说]《怪谈新耳袋》 作者:木原浩胜、中山市朗
[轻小说]《请别忧伤了,二之宫君1-10全》作者:钤木大辅
[轻小说]《流星慢舞》作者:桥本纺
【奇幻】《被遗忘的国度》系列:伊尔明斯特之旅
[轻小说]《放学后的征服世界》作者:わかつきひかる
[短篇轻小说]《可疑的少女与危险的少年》作者:深见真
[轻小说]《新罗德斯岛战记》作者:【日】水野良(全)
[轻小说]《七都市物语 (全)》作者:田中芳树
[轻小说]《XXXHOLIC兰德尔特环的粉尘]》作者:西尾维新
[动漫相关]《L改变世界+外传》 作者:西尾维新
[轻小说]《Black Blood Brother》作者:あざの耕平(1-5+外) 7/7更新
[轻小说]《郭德堡变奏曲》作者:五代ゆぅ
[轻小说]《逃离学校!》作者:谷川流

[轻小说]《郭德堡变奏曲》作者:五代ゆぅ
[轻小说]《逃离学校!》作者:谷川流
[轻小说]《电击!!神盾5少女》作者:谷川 流 (1~2 全)
[轻小说]《铁拳灵感少女》作者:松原真琴/小畑健
[游戏相关]《潜龙谍影4官方小说 下》(已完结)作者:伊藤计划
[轻小说]《我的亲爱主人!?》作者:鹰野佑希(1-5完) 7/4更新
[轻小说]《斩鬼夜鸟子1-3》作者:树田省治
[轻小说]《单恋的麒麟1-2》 作者:志村一矢
[轻小说]《神曲奏界 異色協奏》作者:淺井ラボ、あざの耕平、神野奧那、三田誠
[轻小说]《欢迎来到NHK!》作者:滝本竜彦
[短篇小说]《月之雨物语》作者:古茶(全)
[轻小说]《云霄飞车》作者:山田悠介(全)
[轻小说]《某一天,炸弹从天而降》作者:古桥秀之 (全)
[游戏小说]《最终幻想Ⅶ~On the way to a smile》( 那那岐篇 神罗篇 尤菲篇)
[轻小说]《罗德岛战记+罗德岛传说+新罗德斯岛战记》 作者:水野良
[轻小说]《替身伯爵系列 1》作者:清家未森
[轻小说]《天空之钟 响彻惑星》作者:渡濑草一郎(1-9)
皆杀的田中芳树!二十枚入~
[轻小说]《晴空之下,突然……(全)》作者:田中芳树
[轻小说]《自卫队三部曲第一部 盐之街》作者:有川浩
[恐怖小说]《第十三种人格的恐怖》作者:贵志祐介
[轻小说]《虚轴少女1-5 Resin Cast Milk》作者:藤原祐
[轻小说]《虫之歌》作者:岩井恭平(9卷+BUG系列+外传)
[轻小说]《我的爱马很凶恶》作者:新井辉
[轻小说]《Bad!Daddy 亲亲坏老爹1-3》作者:不詳
[畅销小说]《天竺热风录》作者:田中芳树(波澜壮阔的盛唐再现)
[轻小说]《三月.七日》作者:森桥ビソゴ (1~2 全)
[轻小说]《本格推理委员会》作者:日向正道 (全)
[动漫相关]《闪光的哈萨维》 作者:不详
[轻小说]《绯弹的亚里亚1~3》作者:赤松中学
[轻小说]《战斗司书与虚言者的宴会 》作者:山形石雄
[日本科幻]《寄生前夜》作者:濑名秀明
[游戏剧本]《最终幻想X-2外传 你所吹响的口哨》作者:ベニー松山
阴阳师第①-⑧卷全集》作者:[日]梦枕貘 TXT
[短篇轻小说]《夏天,真纪子与MD-WalkMan的故事》作者:紅玉いづき
[轻小说]《幽灵恋人1~4》作者:平坂 读
[轻小说]《一切终将远去》作者:山本文绪
[轻小说]《幽灵少女与科学少年1~2》作者:飞田甲
[轻小说]《烟囟町的赤魔与绝望少年 1 》作者:ゆうきりん
[推理小说]《“犀川&萌绘”系列》作者:森博嗣 (1~2未完)
[轻小说]《虎跃龙笑 狮王争霸!》作者:嬉野秋彦 (1~2未完)
[推理小说]《姑获鸟之夏》作者:京极夏彦
[轻小说]《消极的快乐、电锯的边缘》作者:泷本龙彦 (全)
[轻小说]《快打城市 slum online》作者:樱坂洋
[轻小说]《ALL YOU NEED IS KILL》作者:樱坂 洋
[轻小说]《青叶君与宇宙人1~3》作者:松野秋鸣
[轻小说]《加速世界 第一卷》作者:不詳
[轻小说]《吉永家的石像怪1-11》作者:田口仙年堂
[轻小说]《无头骑士异闻录 DuRaRaRa!!1-2》作者:成田良悟
[流行小说]药师寺凉子怪奇事件簿(1~7卷) 作者:田中芳树

[轻小说]《莉莉亚&特雷兹》作者: 时雨泽惠一 (全)
[游戏相关]《寂静岭》 作者:山下定
[动漫相关]《战斗妖精·雪风》 作者:神林长平
[輕小說]《抽签勇者1-8》 作者:清水文化
[动漫相关]《今日起是魔王17-20》 作者:乔林 知
[轻小说]《DoubleDown—以小博大的勘缲郎》作者:西尾维新(全)
[轻小说]《艾莉森》作者: 时雨泽惠一 (全)
[轻小说]《自卫队三部曲第二部 空之中》作者:有川浩(全)
[轻小说]《淑女骑士团 Lady General》作者:千田诚行(未完)
[动漫相关]《君吻》作者:日暮茶坊 (未完)
[架空都市]《波罗的海复仇记 (全)》作者:田中芳树
[架空都市]《梦幻都市(全)》作者:田中芳树
[轻小说]《黑龙潭异闻 短篇集(全)》作者:田中芳树
[历史傳记]《海嘯》作者:田中芳树
[轻小说]《狂乱家族日记》作者:日日日
[轻小说]《钢铁白兔骑士团》作者:舞阪洸 (1-6卷未完)5/31日更新
[日系耽美]《三千世界鸦杀1-13+番外前传+090601更新丧神之碑》 作者:津守时生
[轻小说]《复仇之虎(全)》作者:田中芳树
[轻小说]《风翔万里 (全)》作者:田中芳树
[轻小说]《绞缬城绮谭(全)》作者:田中芳树
[轻小说]《灼热的龙骑兵(3本全)》作者:田中芳树
[轻小说] 《圣诞节的恐怖分子》作者:佐藤友哉(全一卷)
[轻小说]《神的记事本》作者:杉井光(1-3卷未完)
[历史傳记]《奔流》作者:田中芳树
[历史傳记]《红尘》作者:田中芳树
[動漫相关]《星之声》作者:新海诚
[影视相关]《变形金刚电影版 前傳 昨日幽靈 》作者:不詳
[轻小说]《我的狐仙女友1-4》 作者:西野胜海
[剧情小说]《潜龙谍影4爱国者之枪》作者:不详
[轻小说]《你我崩坏的世界》作者:西尾纬新
[轻小说]《DDD》作者:奈须きのこ(1-2卷未完)
[轻小说]《侵略少女与谎言庭院》作者:清水マリコ(1卷全)
[轻小说]《公主+天国》作者:風見周(第1卷未完)
[推理小说] 《秋叶原@DEEP》作者:石田衣良 (全)
[动漫相关]《PHANTOM OF INFERNO 无间地狱》作者:虚渊玄
[轻小说]《战斗司书 1-7》作者:山形石雄
[轻小说]《碧阳学园学生会议事錄1-3+外傳》作者:葵せきな
[轻小说]《伊里野的天空 UFO的夏天》作者:秋山瑞人(1-4+短篇 全)
[动漫小说] 《魍魉之匣》 作者:京极夏彦(全)
[轻小说]《黑猫1-2》作者:大崎知仁
[轻小说]《我的世界守护者》作者:谷川流
[轻小说]《轻小说的快乐写法》作者:本田透
[轻小说]《学院人体练金术 一卷全》作者:筱崎一夜
[官方小说]《女神侧身像 希尔梅丽娅2》作者:梅村崇 翻译:YULA、翔月
[轻小说]《伯爵与妖精11-16+短篇》 作者:谷瑞惠
[轻小说]《临界杀机》作者:神崎紫电(1-2未完)
[轻小说]《魔法目录》作者:鎌池和马 (1-8卷)
[轻小说] 《空之轨迹长篇同人 炎の轨迹》作者:夏木の友人帐
[動漫相關]《女王之刃 独角兽之剑》 作者:冲田荣次
[轻小说]《惡女來敲門》作者:织田兄第

[轻小说]《高校女仆警察1-4》作者:沢上水也
[轻小说]《风之圣痕 1-6卷+外传》作者:山门敬弘(靈異類)
[官方小说]《JOJO的奇妙冒险》 作者:乙一
[动漫相关]《灼眼的夏娜17、18》作者:高桥弥七郎
[轻小说]《狼与辛香料》作者:支仓冻砂 (1-10卷)
[轻小说]《绝望的世界1~腐蚀篇》作者:宫谷俊二
[轻小说]《永生之酒》作者:成田良悟(1-6未完)
[轻小说]《对某个飞行员的追忆》 作者:犬村小六 翻译:demongod
[人物传记]《德川家康》 作者:山冈庄八
[剧情小说]《零~月蚀的假面》 作者:不详
[官方小说]《失落的奥德赛 番外 塞丝、敏篇》作者:重松清 翻译:夜蓝
[游戏剧本]《奥丁领域》 作者:不详(DOC下载 慎入!)
[剧情小说]《聖女之歌》作者:不详
[同人小说]《恶魔城 审判 时之缝隙》 作者:有须hideki
[游戏剧本] 《CLANNAD》中文剧本 作者:不详
[剧情小说]《合金装备》作者:不详
[剧情小说]《晓之女神》作者:不详
[剧情小说]《莎木》作者:不详
[军事小说]《环形世界》作者:菲立普·狄克(光环原案)
[动漫小说] 《女王之刃》TV版很黄很暴力 作者:不知道 (1-3未完)
[轻小说]《月兔公主》 作者:野村美月
[轻小说] 《扉之外~the outside of door》 作者:土桥真二郎(1-3全)
[剧情小说]《王国之心2》作者:不详
[剧情小说]《荒野兵器4 上》作者:不详
[剧情小说] 《王国之心Ⅱ》序章剧情小说 作者:LightLucifer
[官方小说]《战国basara2》作者:不详
[轻小说]《新橙路》作者:松本泉 寺田宪史
[轻小说]《银之镇魂歌》作者:吉原理惠子
[动漫相关]《苍穹之巨龙》 作者:冲方丁
[动漫相关]《钢壳都市雷吉欧斯1-7+番外》 作者:雨木シュウスケ
[中文剧本]《最终幻想战略版》 作者:天幻
[剧情小说]《银河游侠》 作者:不详
[动漫相关]《今日起是魔王1-16》 作者:乔林 知
[动漫相关]《最终兵器彼女 全》 作者:不详
[游戏相关]《最终幻想11 官方小说-守护之剑》 作者:不详
[D&D]《时光之轮:世界之眼1-5》作者:罗伯特·乔丹
[剧情小说]《大神》作者:不详
[轻小说]《图书馆战争1~4全》 作者:有川 浩(09年2月2更新番外)
[官方小说]《女神侧身像 两卷全》 作者:梅村崇
[游戏小说]《北欧女神》作者:不详
[游戏小说]《女神侧身像 希尔梅丽娅》 作者:不详
[动漫相关]《天是红河岸 外传 魔之时代的黎明》 作者:筱原千绘
[轻小说]《我家有个狐仙大人1-6》作者:柴村仁 译者:张信儀
[动漫相关]《攻壳机动队 宇宙生化人》 作者:远藤明范 翻译:赵玲
[轻小说]《寒蝉鸣泣之时1-5》作者:龙骑士07
[动漫相关]《真·天地无用_魉皇鬼1-2》 作者:不详
[轻小说]《风之大陆1-9》作者:河竹圣
[轻小说]《黑执事 上》作者:不详
[官方小说]《宿命传说 苍黑的追忆》原作:矢島さら 翻译:子云
[轻小说]《悖德之城 (全)》作者:桑原水菜


此外,还有 个城寨书房 的 全区资源索引帖 ,放在下面:
A
[轻小说]《艾莉森》作者: 时雨泽惠一 (全)
[轻小说]《阿妮丝与爱摆臭脸的魔法使》1-3卷 作者:[日]花房牧生
[轻小说]《ALL YOU NEED IS KILL》作者:樱坂 洋 (全)
[轻小说]《莉莉亚&特雷兹》作者: 时雨泽惠一 (全)
[游戏相关]《奥丁领域 古温托丽篇》作者:不详
[游戏剧本]《奥丁领域》 作者:不详(DOC下载 慎入!)

B
[轻小说] 《便·当 味噌炖青花鱼290元》作者:朝浦(第1卷未完)
[轻小说]《白山同学与黑色手提袋》第一卷 作者:[日铃木铃
[推理侦探]《白夜行》作者:东野圭吾
[轻小说]《不適合少女的職業》作者:櫻庭一樹
[轻小说]《凛子与昭介の故事&Yaorozu》作者:土塀赋之 古户真智子
[輕小說]《佰物語》广播剧全对话翻譯. 作者:[日]西尾維新话
[轻小说]《冰箱上的洞》作者:KOMUGI
[轻小说]《抱歉咯 二之宫同学》作者:铃木大辅(1卷未)
[輕小說]《百花缭乱》作者:すずきぁきら(1卷未)
[轻小说]《本格推理委员会》作者:日向正道 (全)
[轻小说]《Black Blood Brother》作者:あざの耕平(1-3+外)
[架空都市]《波罗的海复仇记 (全)》作者:田中芳树
[历史傳记]《奔流》作者:田中芳树
[影视相关]《变形金刚电影版 前傳 昨日幽靈 》作者:不詳
[轻小说] 《笨蛋,测验,招唤兽》 作者:井上坚二 (1-5+外传 未完)
[游戏小说]《北欧女神》作者:不详
[轻小说]《悖德之城 (全)》作者:桑原水菜
[游戏相关]《薄暮传说剧情小说》 作者:沙下夜雪
[奇幻经典]《被遗忘的国度系列(包含部分英文原著)》更新《血脉+无星之夜》
[官方小说]《瀞灵庭的阴谋之秋 》作者:不详
[动漫相关]《Black Blood Brothers S1》作者:あざの耕平
[日本文学]《白夜的吊钟》 作者:田中芳树
[轻小说]《伯爵与妖精1-10》 作者:谷瑞惠
[轻小说]《伯爵与妖精11-16+短篇》 作者:谷瑞惠
[奇幻合集]《被遗忘国度—短篇集》 作者:[美]R·A·萨尔瓦多
[轻小说]《伯爵与妖精》作者:谷瑞惠(日)(1-7卷,同名动漫原著)
[资料典故]《本能寺三劫之变的传说》作者:青树秀吉
[奇幻合集]《被遗忘国度》系列:伊尔明斯特之旅
C
[游戏剧本] 《CLANNAD》中文剧本 作者:不详
[动漫相关]《出包王女 危险的闺房私语》作者:[日]若月光
[动漫相关]《初恋限定 冬季写真》作者:[日]平林佐和子
[輕小說]《创立!?三星学生会》作者:[日]佐々原史绪
[游戏小说]《尘骸魔京》作者:[日]海法纪光
[轻小说]《超钢女雪拉》1~9未完+番外 作者:寺田とものり
[轻小说]《菖蒲的少女革命!》第一卷 作者:[日]志茂文彦
[輕小說]《触摸魔女》作者:[日]镜裕之
[轻小说]《超妹大战》作者:古桥修之(1~2)
[轻小说]《此处前方是荒野》作者:水无神知宏
[轻小说]《超人家族一家和乐!? 》作者:桥本和也 (1~3)
[轻小说]《串刺少女》作者:木村航 (1~3完结)
[轻小说]《春季限定草莓塔事件》作者:米泽穗信 (1+解说)
[轻小说]《重回那天》作者:健速(全一卷)
[轻小说]《初恋魔法电击》作者:明日香正太(1-9完整版 未完)
[轻小说]《虫之歌》作者:岩井恭平(9卷全+BUG系列+外传)
[輕小說]《抽签勇者1-8》 作者:清水文化
[动漫相关]《苍穹之巨龙》 作者:冲方丁
[畅销小说]《创龙传1-13卷》作者:田中芳树
[剧情小说]《超级机器人大战OG》作者:不详
[轻小说]《彩云国物语1-14+番外+特典+外传》 作者:雪乃纱衣
[轻小说]《铳姬1-4》作者:高殿円
[轻小说]《传说中勇者的传说1-4+外传 总而言之的传勇传1-2》作者:镜贵也
[动漫相关]《超时空要塞 边界》官方小说第1、2卷 作者:小太刀右京
[轻小说]《纯情罗曼史》 作者:藤崎都(BL,慎入)
[剧情小说]《重生传说》作者:卡伦
[轻小说]《虫师官方小说》 原作:漆原友纪 脚本:大友克洋
[国轻小说]《長安幻夜》原作:面堂兄 漫画:韩露(漫友人气连载)
[轻小说]《穿越时空的少女》作者:筒井康隆(短篇全)
D
[轻小说]《单恋的麒麟1-2》 作者:志村一矢
[轻小说]《电波女与青春男01》作者:入间人间
[轻小说]《吊线木偶症候群》作者:乾久留美
[輕小說]《刀語》作者:[日]西尾維新(未完)
[輕小說]《東京吸血鬼金融》作者:[日]真藤順丈
[轻小说]《彈珠汽水》作者:[日]鴻野貴光 (全一卷)
[轻小说]《电波系彼女 三卷全》作者:片山宪太郎
[恐怖小说]《第十三种人格的恐怖》作者:贵志祐介
[轻小说]《打工魔法师》作者:椎野美由贵 (1~6)
[轻小说]《电波男》作者:本田透(适合宅人群= =)
[轻小说]《DoubleDown—以小博大的勘缲郎》作者:西尾维新(全)
[轻小说]《DDD》作者:奈须きのこ(1-2卷未完)
[轻小说]《对某个飞行员的追忆》 作者:犬村小六 翻译:demongod
[动漫相关]《地狱少女-彼岸花》作者:天羽沙夜
[畅销小说]《达·芬奇密码、天使与魔鬼、数字城堡、骗局》 作者:丹·布朗
[剧情小说]《大神》作者:不详
[台湾戏剧]《大霹雳》 作者:不详
[侦探推理]《东野圭吾推理小说合集》作者:东野圭吾
[人物传记]《德川家康》 作者:山冈庄八
[人物传记]《德川家康》 作者:[曰]松本清张 译者:高仁
E
[游戏小说]《恶魔城 审判 时之缝隙》 作者:有须hideki (未完待译)
[轻小说]《恶魔同盟》作者:うえお久光 (1~5)
[轻小说]《惡女來敲門》作者:织田兄第

F
[动漫小说] 《反逆的鲁路修官方小说朱之轨迹》作者:岩佐守(完)
[轻小说]《风之圣痕》作者:山门敬宏(1~6+短篇)
[轻小说]《放学后的征服世界》作者:わかつきひかる
[轻小说]《绯弹的亚里亚1~3》作者:赤松中学
[轻小说]《复仇之虎(全)》作者:田中芳树
[轻小说]《风翔万里 (全)》作者:田中芳树
[轻小说] 《扉之外~the outside of door》 作者:土桥真二郎(1-3全)
[轻小说]《风之大陆1-9》作者:河竹圣
[轻小说]《风之圣痕》第一卷 作者:山门敬弘
[轻小说]《废气公主》作者:榊一郎
[轻小说]《FATE ZERO》
G
[轻小说]《公主+天国》作者:風見周(第1卷未完)
[轻小说]《攻壳机动队——宇宙生化人》作者:[日]远藤明范
[遊戲小說]《格蘭蒂亞》作者:[日]細江ひろみ
[轻小说]《钢铁白兔骑士团》作者:舞阪洸 (1-6卷未完)5/31日更新
[轻小说]《盖棺论定!》作者:文冈あちら
[轻小说]《管家后宫学园》作者:上月司 (1卷未)
[推理小说]《姑获鸟之夏》作者:京极夏彦(京极堂系列01)(世界上没有不可思议的事)
[轻小说]《高校女仆警察1-4》作者:沢上水也
[动漫相关]《攻壳机动队 宇宙生化人》 作者:远藤明范 翻译:赵玲
[动漫相关]《高达系列八部合集》
[动漫相关]《钢壳都市雷吉欧斯1-7+番外》 作者:雨木シュウスケ
[轻小说]《钢壳都市雷吉欧斯》作者:雨木シュウスケ (1-8+外,前传,短篇 未完)
[轻小说]《钢壳都市雷吉欧斯》作者:雨木シュウスケ (1-8+外,前传,短篇 未完)
[游戏相关]《光明之泪 双龙骑士》 作者:加纳新太
[游戏相关]《薄暮传说剧情小说》 作者:沙下夜雪
[灵异小说]《怪谈新耳袋》 作者:木原浩胜、中山市朗
[动漫相关]《钢の錬金术师》作者:井上真
[游戏相关]《光明之泪 双龙骑士》 作者:未知
[动漫相关]《高达W外传 左手持镰,右手拥你》 作者:皆川由佳
[动漫相关]《高达OO P(前传)第一卷》 作者:矢立肇
[官方小说]《高达00之二 捕获高达》作者:木村畅
[官方小说]《高达00 天人组织》作者:木村畅
[游戏相关]《鬼泣4剧情小说》 作者:不详
[游戏相关]《鬼哭街》 作者:虚渊玄
[轻小说] 《谷川流作品集》(部分附插画),纳米盘
[畅销小说]《鬼吹灯Ⅱ之黄皮子坟&南海归墟&怒晴湘西&巫峡棺山》(全)作者:天下霸唱
[畅销小说]《鬼吹灯精绝古城&龙岭迷窟&云南虫谷&昆仑神宫》作者:天下霸唱
[官方小说]《怪物猎人官方小说1~4》作者:ゆうきりん
[科幻军事]《光晕》(1~4全)作者:[美] 埃里克·尼伦德&威廉·C·迪茨
[科幻军事]《光晕三部曲》 作者:[美] 埃里克·尼伦德 威廉·C·迪茨
H
[轻小说]《虎跃龙笑 狮王争霸!》作者:嬉野秋彦 (1~2未完)
[輕小說]《欢迎你!美少女游戏的世界》作者:[日]田尾典丈
[推理小说]《黑死馆杀人事件》作者:小栗虫太郎(日本推理四大奇书)
[轻小说]《欢迎来到血吸村》第一卷 作者:[日]阿智太郎
[轻小说]《幻兽少年》1-2卷 作者:[日]梦枕貘
[推理小说]《火车》作者:宫部美雪
[轻小说]《幻影父亲》作者:深泽美潮
[短篇轻小说]《辉石之花》作者:河屋 一
[轻小说]《黑魂少女》作者:[日]上月雨音(未完结)
[輕小說]《化物語》作者:西尾維新(上卷未)
[轻小说]《紅》作者:片山憲太郎
[历史傳记]《红尘》作者:田中芳树
[轻小说]《 黄昏色的咏使》作者:细音启(1-6卷)
[历史傳记]《海嘯》作者:田中芳树
[轻小说]《黑龙潭异闻 短篇集(全)》作者:田中芳树
[轻小说]《黑猫1-2》作者:大崎知仁
[军事小说]《环形世界》作者:菲立普·狄克(光环原案)
[轻小说]《欢迎来到NHK!》作者:滝本竜彦
[剧情小说]《合金装备2》作者:不详
[剧情小说]《荒野兵器4 上》作者:不详
[轻小说]《黑执事 上》作者:不详
[日系耽美]《海盗风云》作者:松冈夏树
[轻小说]《寒蝉鸣泣之时1-5》作者:龙骑士07
[轻小说]《寒蝉鸣泣之时》 鬼隐篇作者:龙骑士070
[日本文学]《红蔷薇新娘1-3》 作者:田中芳树
[游戏相关]《火焰之纹章 暗黑龙与光之剑》 作者:不详
[漫画改编]《黑血》 原案/漫画:赵佳
[游戏相关]《幻想传说 沉寂的历史》原作:祭紀 りゅーじ 翻译:子云、清雨
[动漫相关]《《横行霸道4(GTA4)》剧情小说》作者:不详
[英国童话]《哈尔的移动城堡中英两版》作者:DianaWynneJones
[奇幻合集]《哈利·波特全集》(HTML格式电子书全7本中文合辑收藏版)[附下载]
[畅销小说]《黑质三部曲 黄金罗盘&魔法神刀&琥珀望远镜》作者:菲利普·普尔曼
[轻小说]《欢迎加入HNK》作者:滝本龙彦
[现代神话]《河图洛书》作者:不动(来自新干线的超人气连载)
I

[輕小說]《IS》作者:[日]弓弦イズル

J

[轻小说]《吉永家的石像怪1-11》作者:田口仙年堂
[輕小說]《娇蛮猫娘大横行!》作者:[日]松智洋
[轻小说]《静流姐与无言的公主们》作者:[日]上远野浩平
[輕小說]《机巧魔神》作者:[日]三雲岳斗
[轻小说]《疾走!青春期的帕拉贝伦》作者:深见真(1~2)
[轻小说]《将花束献给月亮与你》作者:[日]志村一矢
[动漫相关]《机动战士高达UNICORN 0096》作者:[日]福井晴敏(1-6)
[轻小说]《9S》作者:[日]叶山透(1-9+Memories+SS,未完结)
[轻小说]《静流姐与执拗的死者们》作者:上远野浩平
[轻小说]《加速世界 第一卷》作者:不詳
[动漫相关]《机动战舰大和號 琉璃由A到B的故事》 作者:不詳
[动漫相关]《君吻》作者:日暮茶坊 (未完)
[轻小说]《绞缬城绮谭(全)》作者:田中芳树
[剧情小说]《莎木》作者:不详
[剧情小说]《寄生前夜2》作者:不详
[动漫相关]《今日起是魔王1-16》 作者:乔林 知
[动漫相关]《今日起是魔王17-20》 作者:乔林 知
[官方小说]《JOJO的奇妙冒险》 作者:乙一
[日本科幻]《寄生前夜》作者:濑名秀明
[侦探惊忪]《金田一全集》作者:横沟正史
[官方小说]《寂静岭》 作者:山下定
[官方小说]《寂静岭2》 作者:山下定
[推理侦探]《金田一少年的事件薄》作者:天树征丸
[日本文学]《甲贺忍法帖》作者:山田风太郎
[官方小说]《机动战士高达0080口袋里的战争》作者:山口宏、结城恭介
[官方小说]《机动战士高达0079+外传-密会》作者: 富野由悠季
[历史典故]《剑与禅:宫本武藏》
[合集汇总]《九州实体书汇总》
K
[轻小说]《空之境界》作者:奈须きのこ(全)
[轻小说]《看着月亮说着谎话》第一卷 作者:[日]日日日
[轻小说]科学超电磁炮特典小说,全八话
[轻小说]《矿物质超女》作者:冬樹忍 (1~6)
[轻小说]《骷髅恋人》作者: 平坂读(1~5)
[轻小说]《空罐少女!》作者:蓝上陆/铃平ひろ (1~4)
[推理小說]《狂骨之夢》作者:[日]京极夏彦(上卷未)
[轻小说]《壳中少女》作者:冲方丁(全)
[短篇轻小说]《可疑的少女与危险的少年》作者:深见真
[轻小说]《肯普法》作者:筑地俊彦(1-3未)
[轻小说]《肯普法10.5》作者:筑地俊彦
[轻小说]《快打城市 slum online》作者:樱坂洋 (全)
[轻小说]《空之中》作者:有川浩(全)
[轻小说]《狂乱家族日记1-6》 作者:日日日
[轻小说] 《空之轨迹长篇同人 炎の轨迹》作者:夏木の友人帐
[轻小说]《狂恋声优宝贝》作者:木本雅彦
[动漫相关]《空中杀手》作者:森博嗣 (完)

L
[轻小说]《罗德岛战记+罗德岛传说+新罗德斯岛战记》 作者:水野良
[轻小说]《莱茵河的囚徒》作者:[日]田中芳树
[轻小说]《离别的钢琴奏鸣曲 1》作者:杉井光
[推理小说]《猎捕史奈克》作者:宫部美雪
[輕小說]《狼與辛香料》作者:[日]支仓冻沙 (11,12卷)
[輕小說]《蘿球社!》作者:[日]蒼山サグ
[轻小说]《流星慢舞》作者:桥本纺
[轻小说]《铁拳灵感少女》作者:松原真琴/小畑健
[剧情小说]《流行之神》作者:不详
[轻小说]《临界杀机》作者:神崎紫电(1-2未完)
[轻小说]《零之使魔1-16+外传》作者:ヤマグチノボル
[动漫相关]《L改变世界+外传》 作者:西尾维新
[动漫相关]《L改变世界+外传》 作者:西尾维新
[动漫相关]《龙虎斗1-6》 作者:未知
[轻小说]《龙眠》 作者:宫部美幸
[轻小说]《LUCK*STAR杀人事件》作者:竹井10日
[轻小说]《狼與辛香料1-9》 作者:支仓冻砂
[轻小说]《狼与辛香料》作者:支仓冻砂 (1-10卷)
[动画外传]《另一个冰轮丸》 作者:松永真琴 译者:Youyuan
[日本文学]《柳生忍法帖》 作者:山田风太郎
[剧情小说]《龙背上的骑士1+2》作者:不详
[动漫相关]《L改变世界 洛杉矶BB连续杀人案件》作者:西尾维新
[热门小说]《凉宫春日的忧郁》八部全
[游戏小说]《零~月蚀的假面》 作者:不详
[游戏小说]《零·ZERO》作者:不详
[游戏小说]《零·红蝶》作者:不详
[游戏小说]《零·刺青之声》作者:不详
[轻小说]《罗德斯岛战记》
[轻小说]《零之使魔 ゼロづ使い魔小说1-14+番外》作者:ヤマグチノボル(更新到第12卷)
[轻小说]《凉宫春日的忧郁》

M
[轻小说]《魔法目录1-6+ss+外传》 作者:镰池和马
[一般小说]《魔王》作者:[日]伊坂幸太郎
[轻小说]《魔女宅急便》作者:角野荣子(全)
[推理小说]《魔术的耳语》作者:宫部美雪
[轻小说]《MAMA》作者:红玉ぃづき
[輕小說]《梅格&賽隆》作者:[日]时雨泽惠一
[轻小说]《魔法战士李维》作者:[日]水野良(未完结)
[轻小说]《魔法**目录》作者:镰池和马(9.10卷)
[轻小说]《某一天,炸弹从天而降》作者:古桥秀之 (全)
[轻小说]《MM一族》作者:作者:松野秋鸣(1-5卷)
[架空都市]《梦幻都市(全)》作者:田中芳树
[轻小说]《魔法目录》作者:鎌池和马 (1-8卷)
[动漫相关]《名侦探柯南 江神原的魔女》 作者:平良隆久
[畅销小说]《暮光之城 1-4部(英文版)》作者:斯蒂芬妮·梅尔
[轻小说]《魔法人力派遣公司》第1~2卷 作者:三田诚
[日本文学]《麻辣教师GTO 颠覆北海道》 作者:不详
[动漫游戏]《魔界战记迪斯凯亚1-6全》作者:神代创
[动漫相关]《秒速五厘米》 作者:新海诚
[轻小说]《魔法少女奈叶》作者:都筑真纪(全)
[资料分享]《魔法书与恶魔学》
[游戏小说]《魔兽世界官方小说+同人》作者:多人
[游戏相关]魔兽世界小说三部曲

N
[轻小说]《你我崩坏的世界》作者:西尾纬新
[推理小说]《脑髓地狱》作者:梦野久作 (日本推理四大奇书)
[轻小说]《女帝·龍凰院麟音的初恋 第一卷》作者:[日]风见周
[动漫小说] 《女王之刃》TV版很黄很暴力 作者:不知道 (1-3未完)
[動漫相關]《女王之刃 独角兽之剑》 作者:冲田荣次
[轻小说] 《乃木坂春香的秘密》作者:五十岚雄策(0-9卷未完) 5/14日更新
[官方小说]《女神侧身像 两卷全》 作者:梅村崇
[官方小说]《女神侧身像 负罪者》作者:不详
[游戏小说]《女神侧身像 希尔梅丽娅》 作者:梅村崇
[官方小说]《女神侧身像 希尔梅丽娅2》作者:梅村崇 翻译:YULA、翔月
[剧情小说]《逆转裁判4》翻译:清雨(游小说)
[奇幻经典]《纳尼亚传奇2 凯斯宾王子》作者:[英] C·S·刘易斯
O
[动漫相关]《one piece》 作者:不详
P
[动漫相关]《PHANTOM OF INFERNO 无间地狱》作者:虚渊玄
[轻小说]《pulp》作者:森桥ビソゴ(1~3)
Q
[轻小说]《七姬物语1-4》作者:高野和
[轻小说]《轻小说社》作者:平坂读(1~2)
[轻小说]《企鹅之夏(ペンギン·サマー)》全一卷 作者:[日]六塚光
[轻小说]《犬神》作者:有沢まみず (1~12)
[轻小说]《七人武器店》(1-2)作者:[日]大乐绚太(未完结)
[轻小说]《亲亲坏老爹》作者:野村美月(1-3卷)
[轻小说]《青叶君与宇宙人1~3》作者:松野秋鸣 (全)
[轻小说]《七都市物语 (全)》作者:田中芳树
[轻小说]《晴空之下,突然……(全)》作者:田中芳树
[轻小说]《侵略少女与谎言庭院》作者:清水マリコ(1卷全)
[剧情小说]《潜龙谍影4爱国者之枪》作者:不详
[轻小说]《轻小说的快乐写法》作者:本田透
[游戏相关] 潜龙谍影 - Metal Gear Solid [官方小说] (1卷全)
[推理小说] 《秋叶原@DEEP》作者:石田衣良 (全)
[动漫相关]《晴空之Air1-6》作者:不详
[游戏相关]《秋之回忆1-3+从今以后》 作者:不详
[轻小说]《奇诺之旅》作者:时雨泽惠(1-11+外+PS2剧本)
[轻小说]《奇诺之旅1-10全》作者:时雨沢恵一
[游戏相关]《潜龙谍影4官方小说》(下)作者:伊藤计划
[轻小说]《[欢迎加入NHK》 作者:泷本龙彦
[游戏相关]《潜龙谍影4官方小说》(上) 作者:伊藤计划
[动漫相关]《全金属狂潮短片集》作者:贺东招二 等
[动漫相关]《全金属狂潮1-11》作者:贺东招二
[游戏剧情]《寄生前夜2》 作者:不详

R
[轻小说]《人间系列》作者:西尾纬新 (第3卷)
[轻小说] 《ROOM NO.1301》 作者:新井辉(1-7卷未完)9/13更新
[轻小说] 《R.O.D》作者:仓田英之(第1卷未完)
[历史研究]《日本战国史》作者:赤军(国产)
[日本小说]《人间失格》作者:太宰治
[资料收集]《日本战国明将用兵哲学》 作者:不详

S
[轻小说]《三坪房间的侵略者!?第一卷》作者:健速
[推理小说]《世纪末的侦探神话》作者:清凉院流水
[輕小說]《SH@PPLE》作者:[日]竹岡葉月
[游戏小说]《水仙》全一卷 作者:[日]片冈とも
[轻小说]《杀×爱》作者:风见周(0~4)
[轻小说]《神样家族》作者:桑岛由一 (1~7)
[轻小说]《神之游戏1~3》作者:宮崎柊羽
[輕小說]《428被封锁的涩谷》作者:[日]北岛行德
[恐怖小说]《尸鬼》作者:[日]小野不由美 (完结)
[轻小说]《捨棄在八月的路上》作者:伊藤たかみ(全一卷)
[輕小說]《傷物語》作者:[日]西尾維新
[轻小说]《神样灵感少女》作者:松原真琴/小畑健
[轻小说]《神曲奏界 異色協奏》作者:淺井ラボ、あざの耕平、神野奧那、三田誠
[轻小说] 《圣诞节的恐怖分子》作者:佐藤友哉(全一卷)
[轻小说]《淑女骑士团 Lady General》作者:千田诚行(未完)
[轻小说]《神的记事本》作者:杉井光(1-3卷未完)
[轻小说]《神灯女仆1-4》作者:夏绿
[轻小说] 《ROOM NO.1301》 作者:新井辉(1-7卷+番外未完)
[轻小说]《说谎的男孩与坏掉的女孩》作者:入间人间(1-3未完)
[剧情小说]《聖女之歌》作者:不详
[动漫相关]《闪光的哈萨维》 作者:不详
[轻小说]《少年阴阳师1~20》 作者:结城光流
[D&D]《时光之轮:世界之眼1-5》作者:罗伯特·乔丹
[动漫相关]《水星领航员ARIA四季之风的赠礼》作者:岡田麿里 藤咲ぁゅな 浦畑达彦 吉田玲子
[日系耽美]《三千世界鸦杀1-13+番外+前传》 作者:津守时生
[官方小说]《生化危机官方小说(Resident Evil)(1-8)》原著:S·D·Perry
[官方小说]《宿命传说 苍黑的追忆》原作:矢島さら 翻译:子云
[游戏相关]《失落的奥德赛番外篇》作者:松重清 翻译:夜蓝
[官方小说]《失落的奥德赛 番外 塞丝、敏篇》作者:重松清 翻译:夜蓝
[官方小说]《宿命传说官方小说 苍黑的思念》原作:矢島さら 翻译:子云
[轻小说]《死后文》作者:雨宫谅
[百合向耽美]《圣母在上1-12》 作者:今野绪雪
[轻小说]《水星领航员水之都与哀伤的歌姬》作者:藤咲ぁゅな
[动漫相关]《死神的歌谣》作者:长谷川启介
[游戏小说]《失落的奥德赛 千年之梦 永远的旅人》原作:重松 清 翻译:夜蓝
[人文历史]《十字军骑士》作者:显克维支(EXE,TXT双版本)
[轻小说]《十二国记全集+外传》作者:小野不由美
[轻小说]《少年残像》原作:由贵香织里
[轻小说]《圣魔之血》作者:吉田直

T
[轻小说]《同居五重奏!》作者:越后屋铁舟(1卷未完)
[轻小说]《他能在那天逃过死亡吗》作者:[日]小木君人
[遊戲相關]《Tales of Symphonia 拉塔特斯克的骑士 世界之愿》作者:[日]矢島さら
[推理小说]《铁鼠之槛》作者:京极夏彦
[推理小说]《他人事》作者:平山梦明
[轻小说]《TIGER X DRAGON》作者:竹宫ゆゆこ(9卷)
[轻小说]《听到涛声》作者:冰室冴子(1~2+番外篇)
[轻小说]《逃离学校!》作者:谷川流 (1~6全)
[轻小说]《替身伯爵系列 1》作者:清家未森
[轻小说]《天空之钟 响彻惑星》作者:渡濑草一郎(1-9)
[军事小说]《汤姆克兰西部分军事小说》作者:汤姆克兰西
[动漫相关]《天是红河岸 外传 魔之时代的黎明》 作者:筱原千绘
[动漫相关]《太空堡垒-麦克罗斯传奇》作者:未知
[畅销小说]《马法尔年代记1-3全》作者:田中芳树
[轻小说]《图书馆战争1~4全》 作者:有川 浩(09年2月2更新番外)
[动漫相关]《太空堡垒-南十字军》作者:[美] 杰克·麦金尼【上、下册完整版】
[漫画相关]《天使迷梦1-6全+番外+前传》作者:游素兰(台湾)
[影视文学]《跳跃大搜查线》 作者:不详
[畅销小说]《天竺热风录》作者:田中芳树(波澜壮阔的盛唐再现)
U

V

W
[轻小说]《无头骑士异闻录 DuRaRaRa!!1-2》作者:成田良悟
[轻小说]《我们的蔬菜不够》作者:浅沼广太(1~4)
[轻小说]《我的朋友很少 第二卷》作者:平坂読
[轻小说]《我的腐女友》作者:ぺんたぶ(1~2)
[轻小说]《我的朋友很少》(第一卷)作者:[日]平坂読
[轻小说]《伪物语(下)》作者:[日]西尾维新
[輕小說]《無頭騎士異聞錄DuRaRaRa!!》作者:[日]成田良悟(3卷未)
[悬疑小说]《无人生还》 作者:阿加莎·克里斯蒂
[輕小說]《偽物語》作者:[日]西尾維新(上卷未)
[輕小說]《我甜蜜的苦涩委内瑞拉》作者:[日]森田季节
[輕小說]《物質幽靈》作者:[日]葵せきな(未完)
[轻小说]《我的亲爱主人!?》作者:鹰野佑希(1-5完) 7/4更新
[轻小说]《我们的田村同学》作者:竹宫ゆゆこ (1~2+短篇)
[轻小说]《我的爱马很凶恶》作者:新井辉
[轻小说]《“文学少女”见习生の、初恋》作者:野村美月
[轻小说] 《我的妹妹不可能那么可爱》作者:伏见司(1+短篇未完)
[轻小说]《我的世界守护者》作者:谷川流
[轻小说]《我的狐仙女友1-4》 作者:西野胜海
[轻小说] 《文学少女》作者:野村美月 (1-8+番外 完)5/6日更新
[动漫小说] 《魍魉之匣》 作者:京极夏彦(全)
[剧情小说] 《王国之心Ⅱ》序章剧情小说 作者:LightLucifer
[剧情小说]《王国之心2》作者:不详
[轻小说]《我家有个狐仙大人1-6》作者:柴村仁 译者:张信儀
[现代文学]《五百年吸血鬼惊世传奇》作者:伊丽莎白·科斯托娃
[影视相关]《我是传奇 英文版》作者:理查德·马瑟森
[日本耽美]《王朝春宵罗曼史1-4》 作者:不详
[日本小说]《为夜空的双子座衬上深红蔷薇》作者:冈崎裕信 原案:田中芳树
[轻小说]《万岁系列1-8全》作者:三浦勇雄
[悬疑恐怖]《午夜凶铃1-4》作者:铃木光司
[资料收集]《五轮书:地之卷》 作者:宫本武藏
[资料收集]《五轮书:火之卷》作者:宫本武藏

X
[短篇轻小说]《夏天,真纪子与MD-WalkMan的故事》作者:紅玉いづき
[推理小说]《献给虚无的供物》作者:中井英夫 (日本推理四大奇书)
[推理小说]《匣中的失乐》作者:竹本键治 (日本推理四大奇书)
[轻小说]《新本格魔法少女莉丝佳》作者:西尾维新(1~2)
[妖怪小说]《巷说百物语》作者:京极夏彦(1~4完结)
[輕小說]《虚轴少女ResinCastMilk》作者:[日]藤原佑(1-5)
[輕小說]《闲狼作家是美少女妖怪?》作者:[日]杉井光
[輕小說]《Resin Cast Milk 虚轴少女的日常》作者:[日]藤原佑
[輕小說]《幸运机会!》作者:[日]有泽真水
[轻小说]《心灵侦探八云》作者:神永学 (1~2)
[輕小說]《學生會的日常》作者:[日]葵せきな(1卷未)
[輕小說]《小齒輪!》作者:[日]樋口司(1卷未)
[轻小说]《学生会的一己之见》作者:[日]葵せきな(1-3+外 未完)
[轻小说]《掀起世界危机!》 作者: 佐藤了
[轻小说]《学校的阶梯》作者:櫂末高彰 (1~8+短篇 未完)
[推理小说]《“犀川&萌绘”系列》作者:森博嗣 (1~2未完)
[動漫相关]《星之声》作者:新海诚
[轻小说]《消极的快乐、电锯的边缘》作者:泷本龙彦 (全)
[轻小说]《戏言系列》作者:西尾维新 (1-10完结)
[轻小说]《学院人体练金术 一卷全》作者:筱崎一夜
[剧情小说]《晓之女神》作者:不详
[游戏对话]《仙剑奇侠传四》作者:上海软星
[轻小说]《新橙路》作者:松本泉 寺田宪史
[轻小说]《吸血鬼骑士1-4》作者:藤咲あゆな
[推理侦探]《嫌疑犯X的献身》作者:东野圭吾 (神探伽利略系列)
[轻小说]《吸血鬼猎人D》 作者:菊地秀行 插话:天野喜孝
[剧情小说]《新鬼武者 梦之黎明》作者:不详
[轻小说]《XXXHOLIC兰德尔特环的粉尘]》作者:西尾维新
[畅销经典]《肖申克的救赎》作者:斯蒂芬·金
[轻小说]《星界系列》 作者:森冈浩之
[轻小说]《幸运☆星 ONLINE》原作:美水かがみ 著:竹井10日
[军事科幻]《星之海洋》全 作者:charlesp
[国产耽美]《希露芙斯战记(5中篇) 》作者:七月
[轻小说]《新罗德斯岛战记》作者:【日】水野良(全)

Y


[轻小说]《幽灵恋人1~4》作者:平坂 读 (全)
[轻小说]《阴沉少女与黑魔法之恋》作者:熊谷雅人(1~3)
[轻小说]《遥仰凰华》番外+游戏剧本 作者:冈田留奈
[轻小说]《月兔的银色方舟》作者:[日]鴨志田一
[轻小说]《眼镜男与断头少女》作者: 藤原祐 (1~2)
[合集小说]乙一作品集[共32篇]
[轻小说]《影≒光 Shadow Light》作者:影名浅海 (1~5)
[轻小说]《银盘万花筒》作者:海原零 (1~9)
[轻小说]《仰望半月的夜空》作者:桥本纺 (1-8卷+2短篇完结)
[遊戲相關]《命运传奇 命运传承者》作者:[日]矢島さら(上卷未)
[轻小说]《云霄飞车》作者:山田悠介(全)
[短篇小说]《月之雨物语》作者:古茶(全)
[轻小说]《一切终将远去》作者:山本文绪 (全)
[轻小说]《幽灵少女与科学少年1~2》作者:飞田甲
[轻小说]《烟囟町的赤魔与绝望少年 1 》作者:ゆうきりん
[幻想小说]《妖藩记鬼剑众》作者:菊地秀行 (全)
[轻小说]《伊里野的天空 UFO的夏天》作者:秋山瑞人(1-4+短篇 全)
[轻小说]《银之镇魂歌》作者:吉原理惠子
[剧情小说]《银河游侠》 作者:不详
[轻小说]《月兔公主》 作者:野村美月
[魔幻小说]《夜访吸血鬼》作者:安妮·赖斯
[宇宙战争]《铁达尼亚1-3卷》 作者:田中芳树
[轻小说]《银魂 3年Z班的银八老师1-3》 作者:不详
[轻小说]《银河铁道之夜》
[游戏人]《樱花大战3 前传巴黎前夜· 北大路花火篇》 作者:赤堀悟
[游戏人]《樱花大战3 前传巴黎前夜·古妮西露篇》 作者:赤堀悟
[游戏人]《樱花大战3 前传巴黎前夜·艾莉卡篇》 作者:赤堀悟
[动漫相关]《云之彼端约定之地》 原作:新海诚
[游戏剧本]《XENOGEARS(异度装甲)》+《世界观解疑》
[英国童话]《哈尔的移动城堡中英两版》作者:DianaWynneJones
[轻小说]《永生之酒》作者:成田良悟 (更新1~8)
[轻小说]《亚普菲兰特》作者:田中芳树
[日本文学]《亚也日记》作者:木藤亚也(又名:一公升的眼泪)
[流行小说]药师寺凉子怪奇事件簿(1~7卷) 作者:田中芳树
[科幻经典]《银河英雄传说》
[轻小说]《BACCANO(永生之酒)第1-6卷》作者:]成田良悟
[轻小说]《阴阳师物语 1》

Z
[轻小说]《斩鬼夜鸟子1-3》作者:树田省治
[轻小说]《战斗!暴风少女!》作者:佐佐原始绪(1~2)
[轻小说]《最后大魔王》作者:水城正太郎(1~5)
[杂书?]《征服世界有可能的吗》作者:[日]冈田斗司夫
[轻小说]《战斗司书与终章猛兽》作者:山形石雄 (系列第八作)
[轻小说]《在暗夜中寻找羔羊》作者:穗史贺雅也 (1~3完结)
[轻小说]《镇魂练习曲》作者:北泽大辅 (1~3)
[惊悚小说]《ZOO》作者:[日]乙一
[轻小说]《在遙遠彼方的小千》作者:日日日(全一卷)
[轻小说]《拯救你的最初咒语》作者:须堂项(1~2未完)
[轻小说]《终焉的年代记》作者:川上稔(1-2未完)
[轻小说]《战斗司书与虚言者的宴会 》作者:山形石雄
[游戏小说]《最终幻想Ⅶ~On the way to a smile》( 那那岐篇 神罗篇 尤菲篇)
[轻小说]《灼热的龙骑兵(3本全)》作者:田中芳树
[官方小说]《战国basara2》作者:不详
[轻小说]《自卫队三部曲第一部》作者:有川浩
[动漫相关]《真·天地无用_魉皇鬼1-2》 作者:不详
[剧情小说]《战争机器》 作者:不详
[动漫相关]《最终兵器彼女 全》 作者:不详
[剧情小说]《战神:奥林匹斯之链》作者:城寨某人(-,-!)
[人物传记]《织田信长》 作者:山冈庄八
[剧情小说] 最终幻想系列剧情小说》
[港漫相关]《中华英雄》 作者:不详
[历史记载]《中国武将列传》 作者:田中芳树
[中文剧本]《最终幻想战略版》 作者:天幻
[剧情小说]《最终幻想VI》 作者:不详
[剧情小说]《最终幻想XII》作者:不详
[游戏相关]《最终幻想11 官方小说-守护之剑》 作者:不详
[游戏相关]《最终幻想7游戏剧本+剧情小说》 作者:不详
[游戏剧本]《最终幻想10剧情小说》 作者:慕容非
[剧情小说]《最终幻想IX》作者:不详
[官方小说]《FF7AC On The Way to a Smile丁塞尔篇/蒂法篇》作者:ベニー松山
[游戏剧本]《最终幻想X-2外传 你所吹响的口哨》作者:ベニー松山
[轻小说]《灼眼的夏娜 》作者:高桥弥七郎 (0~16卷、附加S卷)0
[专题收集]《战国趣闻录(番外篇*2)》.


嘛...娱乐而已的东西嘛...这里是一个链接也没有的...

lightnovel.cn曾打包放出过东西,不过风格有些区别。
ed2k://|file|%5B%E8%BD%BB%E4%B9%8B%E5%9B%BD%E5%BA%A6%5D%E8%BD%BB%E5%B0%8F%E8%AF%B4%E5%90%88%E9%9B%86VOL.1%5B2009-09%5D%5Blightkingdom.lightnovel.collection.vol1%5D.zip|183888376|98448761c16748b1742080b7953db837|h=sa2xcobe5uypgofn4fnfdyfvlx66it3c|/
ed2k://|file|%5B%E8%BD%BB%E4%B9%8B%E5%9B%BD%E5%BA%A6%5D%E8%BD%BB%E5%B0%8F%E8%AF%B4%E5%90%88%E9%9B%86VOL.2%5B2009-10%5D%5Blightkingdom.lightnovel.collection.vol2%5D.7z|2222403|c659f06bc7ecfc05219fc63117bd4872|h=ffr6ennkgx534gjt6ijih5ag755ycheb|/
ed2k://|file|%5B%E8%BD%BB%E4%B9%8B%E5%9B%BD%E5%BA%A6%5D%E8%BD%BB%E5%B0%8F%E8%AF%B4%E5%90%88%E9%9B%86VOL.3%5B2009-11%5D%5Blightkingdom.lightnovel.collection.vol3%5D.7z|2824935|bf6f16910e9f11945d84cf155dd5aaf9|h=45iw2wmhyognkkxpwwc67fzoxdeu46dc|/


相关的站点的话自己能想到的还有
http://bbs.levelup.im/forum-38-1.html
book.sky-fire.com
comic.92wy.com
www.ffsky.com
www.hgamecn.com
www.imdb.com
类似站点去找一下也能发现些,这里名字有些杂乱了,况且ACG内容还是好找的。
此外呢,有些考古性质的企划文对于搜索而言是有辅助作用的,例如维基百科。

这年头有dangdang在,还是纸质顺眼来着,也觉得存放起来踏实一点。
曾有的版权问题的正在发展出适合的解决途径,目前不必要无视已有的关注度。

2011年7月7日星期四

静态类型函数式语言Objective Caml/ML的简要介绍【程序语言介绍】

下面拿OCaml手册的导论部分的前两章缩译了一下,这里涵盖了核心语言和模块系统两方面的内容。

* Chapter 1 The core language

这部分是OCaml语言的简明教程,需要有某一编程语言的使用基础,但不一定是函数式语言。

** 1.1 Basics

下面将在交互模式中演示,“#”开头的行表示用户输入。输入以“;;”终止,交互系统会随即解析表达式或定义语句并返回执行结果。

#1+2*3;;
- : int = 7

#let pi = 4.0 *. atan 1.0;;
val pi : float = 3.14159265358979312

#let square x = x *. x;;
val square : float -> float = <fun>
 
#square(sin pi) +. square(cos pi);;
- : float = 1.

值和类型会被执行,函数中未显式声明的参数系统会根据其定义中的语句来推断。要注意整数和浮点数是不同的类型,前者用“+”和“*”而后者用“+.”和“*.”。

#1.0 * 2;;
Error: This expression has type float but an expression was expected of type int

递归函数有“let rec”绑定:

#let rec fib n =
   if n < 2 then n else fib(n-1) + fib(n-2);;
val fib : int -> int = <fun>
 
#fib 10;;
- : int = 55

** 1.2 Data types

除了整数和浮点数,Caml中还提供了其他的常用基本类型:布尔型、字符型、字符串型。

#(1 < 2) = false;;
- : bool = false
 
#’a’;;
- : char = ’a’
 
#"Hello world";;
- : string = "Hello world"

预定义的数据结构包括元组、数组、列表,此外也可创建自定义类型。列表是由“[”和“]”包裹“;”分割,或者由空表“[]”(读作nil)前面用“::”操作符添加元素构成。

#let l = ["is"; "a"; "tale"; "told"; "etc."];;
val l : string list = ["is"; "a"; "tale"; "told"; "etc."]
 
#"Life" :: l;;
- : string list = ["Life"; "is"; "a"; "tale"; "told"; "etc."]

列表的内存管理将自动进行,不需要显式地分配或回收。指针由Caml编译器负责,也不需要显式的处理。

列表(以及大部分Caml数据结构)的检查和解析通过模式匹配进行。列表的模式与列表的定义形式相同,以标识符表示列表中未定义的部分。以下是用列表进行插入排序的例子:

#let rec sort lst =
   match lst with
     [] -> []
   | head :: tail -> insert head (sort tail)
 and insert elt lst =
   match lst with
     [] -> [elt]
   | head :: tail -> if elt <= head then elt :: lst else head :: insert elt tail
 ;;
val sort : ’a list -> ’a list = <fun>
val insert : ’a -> ’a list -> ’a list = <fun>
 
#sort l;;
- : string list = ["a"; "etc."; "is"; "tale"; "told"]

这里sort推断得到的类型是“’a list -> ’a list”,表示作用于任意类型的列表并返回相同类型的列表。其中“’a ”是类型变量,代表任意类型。之所以sort可以用于任意类型列表,是因为比较操作(“=”“<=”等等)在Caml中是多态的。

#sort [6;2;5;3];;
- : int list = [2; 3; 5; 6]
 
#sort [3.14; 2.718];;
- : float list = [2.718; 3.14]

上面的sort函数没有修改它的输入列表,而是创建并返回一个元素个数相同的递增列表。列表创建后是无法在原地修改的,在Caml中列表是不可变的结构。大部分Caml中的数据结构是不可变的,而少部分(如数组)是可变的(可以在任何时候原地修改)。

** 1.3 Functions as values

Caml是一种函数式语言,支持数学意义上的函数并可以和其他数据片段一样被自由地传递。例如这里的deriv函数以浮点函数为参数并返回它的导函数的逼近函数:

#let deriv f dx = function x -> (f(x +. dx) -. f(x)) /. dx;;
val deriv : (float -> float) -> float -> float -> float = <fun>
 
#let sin’ = deriv sin 1e-6;;
val sin’ : float -> float = <fun>
 
#sin’ pi;;
- : float = -1.00000000013961143
Even function composition is definable:

#let compose f g = function x -> f(g(x));;
val compose : (’a -> ’b) -> (’c -> ’a) -> ’c -> ’b = <fun>
 
#let cos2 = compose square cos;;
val cos2 : float -> float = <fun>

以其他函数作为参数的函数称为“泛函數”(functionals)或者“高阶函数”(higher-order functions)。泛函数可用于对数据结构的迭代或类似的操作。例如Caml的标准库中提供“List.map”将给定函数应用于列表中的每个元素并返回结果列表:

#List.map (function n -> n * 2 + 1) [0;1;2;3;4];;
- : int list = [1; 3; 5; 7; 9]

常用的列表和数组相关的函数已经定义好了,或者也可以按照下面的方式自行定义。

#let rec map f l =
   match l with
     [] -> []
   | hd :: tl -> f hd :: map f tl;;
val map : (’a -> ’b) -> ’a list -> ’b list = <fun>

** 1.4 Records and variants

用户定义的数据结构包括记录和变体。它们都通过类型声明来定义。这里我们声明了一个表示有理数的记录类型。

#type ratio = {num: int; denum: int};;
type ratio = { num : int; denum : int; }
 
#let add_ratio r1 r2 =
   {num = r1.num * r2.denum + r2.num * r1.denum;
    denum = r1.denum * r2.denum};;
val add_ratio : ratio -> ratio -> ratio = <fun>
 
#add_ratio {num=1; denum=3} {num=2; denum=5};;
- : ratio = {num = 11; denum = 15}

变体类型的声明列出了该类型所有值的形状。每种情况用一个名称作为标识符,称为构造器,既用来在构造那种变体类型的值,也用来在模式匹配中检查它们。构造器的首字母大写,用来和变量名区分(必须以小写字母开头)。例如这里是一个用来进行混合运算(整数和浮点)的变体类型:

#type number = Int of int | Float of float | Error;;
type number = Int of int | Float of float | Error

这个声明表示number类型的值或者是一个整数,或者是一个浮点数,或者是表示无效运算结果的常量Error(比如被零除)。

枚举类型是变体类型的一种特殊情况,是当所有的选择支都是常量的时候:

#type sign = Positive | Negative;;
type sign = Positive | Negative
 
#let sign_int n = if n >= 0 then Positive else Negative;;
val sign_int : int -> sign = <fun>

要定义number类型的算数运算,我们需要对用到的两个number使用模式匹配:

#let add_num n1 n2 =
   match (n1, n2) with
     (Int i1, Int i2) ->
       (* Check for overflow of integer addition *)
       if sign_int i1 = sign_int i2 && sign_int(i1 + i2) <> sign_int i1
       then Float(float i1 +. float i2)
       else Int(i1 + i2)
   | (Int i1, Float f2) -> Float(float i1 +. f2)
   | (Float f1, Int i2) -> Float(f1 +. float i2)
   | (Float f1, Float f2) -> Float(f1 +. f2)
   | (Error, _) -> Error
   | (_, Error) -> Error;;
val add_num : number -> number -> number = <fun>
 
#add_num (Int 123) (Float 3.14159);;
- : number = Float 126.14159

变体类型的最常见的用途是描述递归的数据结构。考虑二叉树的例子:

#type ’a btree = Empty | Node of ’a * ’a btree * ’a btree;;
type ’a btree = Empty | Node of ’a * ’a btree * ’a btree

该定义这样来读:一个包含类型'a(任意类型)的值二叉树或者是空的或者是一个节点,节点有一个类型'a的值和两个也包含类型'a的子树(即两个 'a btree)。

二叉树上的操作的操作依照其定义自身很自然的用递归函数表达出来。例如这里的函数用来在有序二叉树(元素又左至右递增)上查找和插入。

#let rec member x btree =
   match btree with
     Empty -> false
   | Node(y, left, right) ->
       if x = y then true else
       if x < y then member x left else member x right;;
val member : ’a -> ’a btree -> bool = <fun>
 
#let rec insert x btree =
   match btree with
     Empty -> Node(x, Empty, Empty)
   | Node(y, left, right) ->
       if x <= y then Node(y, insert x left, right)
                 else Node(y, left, insert x right);;
val insert : ’a -> ’a btree -> ’a btree = <fun>

** 1.5 Imperative features

尽管目前的例子都写为纯函数的风格,Caml也具有命令式的特性。这包括了常见的while和for循环,以及可变的数据结构比如数组。数组用“[|”“|]”包围的形式来书写,或者通过“Array.create”函数来分配并初始化然后再赋值。例如,下面的函数即求两个向量(实现为浮点数组)的部分的和。

#let add_vect v1 v2 =
   let len = min (Array.length v1) (Array.length v2) in
   let res = Array.create len 0.0 in
   for i = 0 to len - 1 do
     res.(i) <- v1.(i) +. v2.(i)
   done;
   res;;
val add_vect : float array -> float array -> float array = <fun>
 
#add_vect [| 1.0; 2.0 |] [| 3.0; 4.0 |];;
- : float array = [|4.; 6.|]

通过来定义中声明为可变的,记录的字段也可以通过赋值操作来修改:

#type mutable_point = { mutable x: float; mutable y: float };;
type mutable_point = { mutable x : float; mutable y : float; }
 
#let translate p dx dy =
   p.x <- p.x +. dx; p.y <- p.y +. dy;;
val translate : mutable_point -> float -> float -> unit = <fun>
 
#let mypoint = { x = 0.0; y = 0.0 };;
val mypoint : mutable_point = {x = 0.; y = 0.}
 
#translate mypoint 1.0 2.0;;
- : unit = ()
 
#mypoint;;
- : mutable_point = {x = 1.; y = 2.}

Caml没有内置变量(可以通过赋值改变当前值的标识)的概念。(let绑定不是赋值,它在新作用域里建立了新的标识。)不过标准库中通过间接地使用可变字段(或者单元素数组)来提供了引用类型,并可通过操作符“!”获取引用的当前内容以及“:=”来赋值。变量可以通过绑定一个引用来模拟。例如,这里是一个数组的原地插入排序的例子:

#let insertion_sort a =
   for i = 1 to Array.length a - 1 do
     let val_i = a.(i) in
     let j = ref i in
     while !j > 0 && val_i < a.(!j - 1) do
       a.(!j) <- a.(!j - 1);
       j := !j - 1
     done;
     a.(!j) <- val_i
   done;;
val insertion_sort : ’a array -> unit = <fun>

函数也可用于书写需要维持两次调用中的当前状态的函数。例如下面的伪随机数生成器通过引用记录了最后返回的数值:

#let current_rand = ref 0;;
val current_rand : int ref = {contents = 0}
 
#let random () =
   current_rand := !current_rand * 25713 + 1345;
   !current_rand;;
val random : unit -> int = <fun>

再次说明,引用没什么特别的:它们是通过下面这样的一个可变字段的记录来实现的。

#type ’a ref = { mutable contents: ’a };;
type ’a ref = { mutable contents : ’a; }
 
#let (!) r = r.contents;;
val ( ! ) : ’a ref -> ’a = <fun>
 
#let (:=) r newval = r.contents <- newval;;
val ( := ) : ’a ref -> ’a -> unit = <fun>

有时会需要在数据结构中存放多态函数并保持多态。除非用户提供类型标记,不然是不允许的,因为多态仅在全局类型中引入。不过你可以给记录的字段给出显式的多态类型。

#type idref = { mutable id: ’a. ’a -> ’a };;
type idref = { mutable id : ’a. ’a -> ’a; }
 
#let r = {id = fun x -> x};;
val r : idref = {id = <fun>}
 
#let g s = (s.id 1, s.id true);;
val g : idref -> int * bool = <fun>
 
#r.id <- (fun x -> print_string "called id\n"; x);;
- : unit = ()
 
#g r;;
called id
called id
- : int * bool = (1, true)

** 1.6 Exceptions

Caml提供异常机制用来指示和处理例外的状况。异常也可用于通用的非局部控制结构。异常通过异常构造来声明,并用raise操作符来指示。例如,下面这个取列表头的函数使用异常来指示遇到空表的情况。

#exception Empty_list;;
exception Empty_list
 
#let head l =
   match l with
     [] -> raise Empty_list
   | hd :: tl -> hd;;
val head : ’a list -> ’a = <fun>
 
#head [1;2];;
- : int = 1
 
#head [];;
Exception: Empty_list.

在标准库中异常用来指示库函数不能被正常完成的情况。例如,“List.assoc”函数,用来返回一个“(键, 数据)”对的列表中给定键关联的值,在键没有在列表中出现的时候将引起预定义的异常"Not_found":

#List.assoc 1 [(0, "zero"); (1, "one")];;
- : string = "one"
 
#List.assoc 2 [(0, "zero"); (1, "one")];;
Exception: Not_found.
Exceptions can be trapped with the try…with construct:

#let name_of_binary_digit digit =
   try
     List.assoc digit [0, "zero"; 1, "one"]
   with Not_found ->
     "not a binary digit";;
val name_of_binary_digit : int -> string = <fun>
 
#name_of_binary_digit 0;;
- : string = "zero"
 
#name_of_binary_digit (-1);;
- : string = "not a binary digit"

with部分其实是异常值的正则模式匹配。因此,若干异常可以用一个try...with结构来捕获。此外,终止可以通过捕获所有的异常来进行,执行终止操作,然后再次引起该异常:

#let temporarily_set_reference ref newval funct =
   let oldval = !ref in
   try
     ref := newval;
     let res = funct () in
     ref := oldval;
     res
   with x ->
     ref := oldval;
     raise x;;
val temporarily_set_reference : ’a ref -> ’a -> (unit -> ’b) -> ’b = <fun>

** 1.7 Symbolic processing of expressions

我们通过一个较完整的例子来结束这次介绍:使用Caml进行符号处理,形式化的操作包含变量的算术表达式。下列的变体类型描述了我们将操作的表达式:

#type expression =
     Const of float
   | Var of string
   | Sum of expression * expression (* e1 + e2 *)
   | Diff of expression * expression (* e1 - e2 *)
   | Prod of expression * expression (* e1 * e2 *)
   | Quot of expression * expression (* e1 / e2 *)
 ;;
type expression =
    Const of float
  | Var of string
  | Sum of expression * expression
  | Diff of expression * expression
  | Prod of expression * expression
  | Quot of expression * expression

我们首先定义一个函数在所给变量由名称映射到值的环境下计算表达式的值。为了简化,环境用关联列表表示。

#exception Unbound_variable of string;;
exception Unbound_variable of string
 
#let rec eval env exp =
   match exp with
     Const c -> c
   | Var v ->
       (try List.assoc v env with Not_found -> raise(Unbound_variable v))
   | Sum(f, g) -> eval env f +. eval env g
   | Diff(f, g) -> eval env f -. eval env g
   | Prod(f, g) -> eval env f *. eval env g
   | Quot(f, g) -> eval env f /. eval env g;;
val eval : (string * float) list -> expression -> float = <fun>
 
#eval [("x", 1.0); ("y", 3.14)] (Prod(Sum(Var "x", Const 2.0), Var "y"));;
- : float = 9.42

现在为了进行真正的符号处理,我们定义关于变量dv的表达式的导数:

#let rec deriv exp dv =
   match exp with
     Const c -> Const 0.0
   | Var v -> if v = dv then Const 1.0 else Const 0.0
   | Sum(f, g) -> Sum(deriv f dv, deriv g dv)
   | Diff(f, g) -> Diff(deriv f dv, deriv g dv)
   | Prod(f, g) -> Sum(Prod(f, deriv g dv), Prod(deriv f dv, g))
   | Quot(f, g) -> Quot(Diff(Prod(deriv f dv, g), Prod(f, deriv g dv)),
                        Prod(g, g))
 ;;
val deriv : expression -> string -> expression = <fun>
 
#deriv (Quot(Const 1.0, Var "x")) "x";;
- : expression =
Quot (Diff (Prod (Const 0., Var "x"), Prod (Const 1., Const 1.)),
 Prod (Var "x", Var "x"))

** 1.8 Pretty-printing and parsing

上面的例子显示,表达式的内部结构(通常也称为抽象语法)在表达式变长的时候很快就难以读写。我们需要打印和解析过程在抽象语法和具体语法(这里指表达式用熟悉的代数符号,例如“2*x+1”)之间来回转换。

在打印函数中,我们考虑通常的优先规则(比如*比+绑定地更紧)来避免打印不必要的括号。在实现上,我们记录当前操作符的优先级并只当操作符的优先级低于当前优先级的时候在周围打印出括号。

#let print_expr exp =
   (* Local function definitions *)
   let open_paren prec op_prec =
     if prec > op_prec then print_string "(" in
   let close_paren prec op_prec =
     if prec > op_prec then print_string ")" in
   let rec print prec exp = (* prec is the current precedence *)
     match exp with
       Const c -> print_float c
     | Var v -> print_string v
     | Sum(f, g) ->
         open_paren prec 0;
         print 0 f; print_string " + "; print 0 g;
         close_paren prec 0
     | Diff(f, g) ->
         open_paren prec 0;
         print 0 f; print_string " - "; print 1 g;
         close_paren prec 0
     | Prod(f, g) ->
         open_paren prec 2;
         print 2 f; print_string " * "; print 2 g;
         close_paren prec 2
     | Quot(f, g) ->
         open_paren prec 2;
         print 2 f; print_string " / "; print 3 g;
         close_paren prec 2
   in print 0 exp;;
val print_expr : expression -> unit = <fun>
 
#let e = Sum(Prod(Const 2.0, Var "x"), Const 1.0);;
val e : expression = Sum (Prod (Const 2., Var "x"), Const 1.)
 
#print_expr e; print_newline();;
2. * x + 1.
- : unit = ()
 
#print_expr (deriv e "x"); print_newline();;
2. * 1. + 0. * x + 0.
- : unit = ()

解析(将具体语法转换为抽象语法)通常更精巧些。Caml提供若干工具来帮助编写解析器:一方面,Caml版本的Lex词法生成器和Yacc解析生成器,可以使用下推自动机处理啦LALR(1)语言。另一方面,预定义的(字符或标志)流类型和流的模式匹配,可以为LL(1)语言方便地编写递归下降的解析器。后面的章节中有使用ocamllex和ocamlyacc的例子。这里我们将使用流解析器。流解析器的语法支持由Camlp4预处理器提供,它可以在交互模式中由下面的“#load”指令载入。

##load "camlp4o.cma";;
Characters -1–1:
Error: Reference to undefined global ‘Dynlink’
 
#open Genlex;;
 
 let lexer = make_lexer ["("; ")"; "+"; "-"; "*"; "/"];;
val lexer : char Stream.t -> Genlex.token Stream.t = <fun>

在词法分析阶段(将输入文本转换为标志流),我们使用标准库中Genlex模块的“通用”的词法解析器。“make_lexer”接受关键词列表并返回“标志化”字符输入流的词法解析函数。标志是标识符、关键词或者是字面义(整数、浮点、字符、字符串)。空白和评论跳过。

#let token_stream = lexer(Stream.of_string "1.0 +x");;
val token_stream : Genlex.token Stream.t = <abstr>
 
#Stream.next token_stream;;
- : Genlex.token = Float 1.
 
#Stream.next token_stream;;
- : Genlex.token = Kwd "+"
 
#Stream.next token_stream;;
- : Genlex.token = Ident "x"

解析器通过在在标志流上执行自身的操作。和常见的递归下降解析器一样,我们使用若干中间解析函数来反映操作符的优先级和结合性。流上的模式匹配比正则的数据结构更为强大,因为它允许在模式里递归的调用解析函数,用以匹配输入流的子部件。更多的细节见Camlp4的文档。

#let rec parse_expr = parser
     [< e1 = parse_mult; e = parse_more_adds e1 >] -> e
 and parse_more_adds e1 = parser
     [< ’Kwd "+"; e2 = parse_mult; e = parse_more_adds (Sum(e1, e2)) >] -> e
   | [< ’Kwd "-"; e2 = parse_mult; e = parse_more_adds (Diff(e1, e2)) >] -> e
   | [< >] -> e1
 and parse_mult = parser
     [< e1 = parse_simple; e = parse_more_mults e1 >] -> e
 and parse_more_mults e1 = parser
     [< ’Kwd "*"; e2 = parse_simple; e = parse_more_mults (Prod(e1, e2)) >] -> e
   | [< ’Kwd "/"; e2 = parse_simple; e = parse_more_mults (Quot(e1, e2)) >] -> e
   | [< >] -> e1
 and parse_simple = parser
     [< ’Ident s >] -> Var s
   | [< ’Int i >] -> Const(float i)
   | [< ’Float f >] -> Const f
   | [< ’Kwd "("; e = parse_expr; ’Kwd ")" >] -> e;;
Error: Syntax error
 
#let parse_expression = parser [< e = parse_expr; _ = Stream.empty >] -> e;;
Error: Syntax error

通过组合来词法和语法解析器,我们最终获得了一个从字符串中读取表达式的函数:

#let read_expression s = parse_expression(lexer(Stream.of_string s));;
Error: Unbound value parse_expression
 
#read_expression "2*(x+y)";;
Error: Unbound value read_expression

小问题:为什么在下面两个例子中我们得到了不同的结果?

#read_expression "x - 1";;
Error: Unbound value read_expression
 
#read_expression "x-1";;
Error: Unbound value read_expression

解答:由Genlex提供的通用的词法解析器把负数识别为一个整数标志。因此“x-1”被读取为标志Ident "x" 跟着标志Int(-1);该序列不匹配任何解析规则。另一方面“x - 1”中的第二个空格导致词法解析器返回三个期望的标志:Ident "x"然后Kwd "-"然后Int(1)。

** 1.9 Standalone Caml programs

目前所有给出的例子是在交互系统下执行的。Caml代码也可以通过编译器“ocamlc”或“ocamlopt”单独地编译并非交互的执行。源代码需要放在以“.ml”为扩展名的文件中。源文件包含一序列的代码,并在运行时按照排列的顺序执行。不同于交互模式,类型和值不会自动打印;程序需要调用打印函数来显式地输出。这里是一个打印斐波纳契数列的独立的示例程序。

(* File fib.ml *)
let rec fib n =
  if n < 2 then 1 else fib(n-1) + fib(n-2);;
let main () =
  let arg = int_of_string Sys.argv.(1) in
  print_int(fib arg);
  print_newline();
  exit 0;;
main ();;

“Sys.argv”是包含命令行参数的字符串数组。“Sys.argv.(1)”因此是命令行的第一个参数。上面这个程序通过下列命令编译并执行:

$ ocamlc -o fib fib.ml
$ ./fib 10
89
$ ./fib 20
10946


* Chapter 2 The module system

这一章介绍Objective Caml的模块系统。

** 2.1 Structures

模块的主要动机是是将相关的定义(比如定义了一种数据类型和那个类型关联的操作符)打包在一起并为这些定义执行一致的命名策略。这样避免的用尽名称或者意外的命名冲突。这样的包称为一个结构通过“struct…end”结构引入,并包含任意定义语句的序列。结构通常给予一个模块绑定的名称。这里的例子是用结构把优先列队的类型和操作打包在一起:

#module PrioQueue =
   struct
     type priority = int
     type ’a queue = Empty | Node of priority * ’a * ’a queue * ’a queue
     let empty = Empty
     let rec insert queue prio elt =
       match queue with
         Empty -> Node(prio, elt, Empty, Empty)
       | Node(p, e, left, right) ->
           if prio <= p
           then Node(prio, elt, insert right p e, left)
           else Node(p, e, insert right prio elt, left)
     exception Queue_is_empty
     let rec remove_top = function
         Empty -> raise Queue_is_empty
       | Node(prio, elt, left, Empty) -> left
       | Node(prio, elt, Empty, right) -> right
       | Node(prio, elt, (Node(lprio, lelt, _, _) as left),
                         (Node(rprio, relt, _, _) as right)) ->
           if lprio <= rprio
           then Node(lprio, lelt, remove_top left, right)
           else Node(rprio, relt, left, remove_top right)
     let extract = function
         Empty -> raise Queue_is_empty
       | Node(prio, elt, _, _) as queue -> (prio, elt, remove_top queue)
   end;;
module PrioQueue :
  sig
    type priority = int
    type ’a queue = Empty | Node of priority * ’a * ’a queue * ’a queue
    val empty : ’a queue
    val insert : ’a queue -> priority -> ’a -> ’a queue
    exception Queue_is_empty
    val remove_top : ’a queue -> ’a queue
    val extract : ’a queue -> priority * ’a * ’a queue
  end
  
在结构的外面,它的组件可以用“.”点号标记来引用,也就是由结构名限制的标识符。例如“PrioQueue.insert”的在值的上下文中是结构“PrioQueue”中定义的一个函数。类似的,“PrioQueue.queue”在类型的上下文中是“PrioQueue”中定义的列队类型。

#PrioQueue.insert PrioQueue.empty 1 "hello";;
- : string PrioQueue.queue =
PrioQueue.Node (1, "hello", PrioQueue.Empty, PrioQueue.Empty)

** 2.2 Signatures

签名是结构的界面。签名指定了结构的哪些组件可以从外部访问,并通过何种类型。它可以用来隐藏结构中的一些组件(例如局部函数定义)或者由受限的类型导出相关组件。例如下面的签名指定了三个优先列队的操作符“empty”、“insert”和“extract”,但是没有辅助函数“remove_top”。类似的,它使得列队类型抽象化(通过不以具体的类型提供实际的表现形式)。

#module type PRIOQUEUE =
   sig
     type priority = int (* still concrete *)
     type ’a queue (* now abstract *)
     val empty : ’a queue
     val insert : ’a queue -> int -> ’a -> ’a queue
     val extract : ’a queue -> int * ’a * ’a queue
     exception Queue_is_empty
   end;;
module type PRIOQUEUE =
  sig
    type priority = int
    type ’a queue
    val empty : ’a queue
    val insert : ’a queue -> int -> ’a -> ’a queue
    val extract : ’a queue -> int * ’a * ’a queue
    exception Queue_is_empty
  end
  
通过该签名限制“PrioQueue”结构的结果是“PrioQueue”结构的另一种使用视角,其中“remove_top”函数不可访问同时有限列队的实际表现是隐藏的:

#module AbstractPrioQueue = (PrioQueue : PRIOQUEUE);;
module AbstractPrioQueue : PRIOQUEUE
 
#AbstractPrioQueue.remove_top;;
Error: Unbound value AbstractPrioQueue.remove_top
 
#AbstractPrioQueue.insert AbstractPrioQueue.empty 1 "hello";;
- : string AbstractPrioQueue.queue = <abstr>

限制也可以在定义结构的时候执行,就像

module PrioQueue = (struct ... end : PRIOQUEUE);;

上面的另一种可选语法是:

module PrioQueue : PRIOQUEUE = struct ... end;;

** 2.3 Functors

函子使用由结构到结构的”函数“。它们用来表达参数化的结构:以结构B作为参数的结构A,简单地说就是以B为形式参数(依照对B期望的签名)的函子F返回实际的结构A自身。函子F随后可以使用到B的若干实现B1...Bn上面,对应的产生结构A1...An。

例如这里是一个用有序列表作为集合的结构实现,以一个提供集合元素的类型的结构和该类型的排序函数(用来保持集合是有序的)为参数:

#type comparison = Less | Equal | Greater;;
type comparison = Less | Equal | Greater
 
#module type ORDERED_TYPE =
   sig
     type t
     val compare: t -> t -> comparison
   end;;
module type ORDERED_TYPE = sig type t val compare : t -> t -> comparison end
 
#module Set =
   functor (Elt: ORDERED_TYPE) ->
     struct
       type element = Elt.t
       type set = element list
       let empty = []
       let rec add x s =
         match s with
           [] -> [x]
         | hd::tl ->
            match Elt.compare x hd with
              Equal -> s (* x is already in s *)
            | Less -> x :: s (* x is smaller than all elements of s *)
            | Greater -> hd :: add x tl
       let rec member x s =
         match s with
           [] -> false
         | hd::tl ->
             match Elt.compare x hd with
               Equal -> true (* x belongs to s *)
             | Less -> false (* x is smaller than all elements of s *)
             | Greater -> member x tl
     end;;
module Set :
  functor (Elt : ORDERED_TYPE) ->
    sig
      type element = Elt.t
      type set = element list
      val empty : ’a list
      val add : Elt.t -> Elt.t list -> Elt.t list
      val member : Elt.t -> Elt.t list -> bool
    end

通过把函子“Set”应用到一个实现有序类型的结构上,我们获得了该类型的集合操作符:

#module OrderedString =
   struct
     type t = string
     let compare x y = if x = y then Equal else if x < y then Less else Greater
   end;;
module OrderedString :
  sig type t = string val compare : ’a -> ’a -> comparison end
 
#module StringSet = Set(OrderedString);;
module StringSet :
  sig
    type element = OrderedString.t
    type set = element list
    val empty : ’a list
    val add : OrderedString.t -> OrderedString.t list -> OrderedString.t list
    val member : OrderedString.t -> OrderedString.t list -> bool
  end
 
#StringSet.member "bar" (StringSet.add "foo" StringSet.empty);;
- : bool = false

** 2.4 Functors and type abstraction

在“PrioQueue”例子中,隐藏集合类型的实际实现会是一个良好的习惯,这样该结构的用户就不依赖于集合是一个列表,并我们能够随后切换到其他更高效的集合的表现形式而不破坏它们的代码。这可以通过合适的函子签名限制“Set”来实现:

#module type SETFUNCTOR =
   functor (Elt: ORDERED_TYPE) ->
     sig
       type element = Elt.t (* concrete *)
       type set (* abstract *)
       val empty : set
       val add : element -> set -> set
       val member : element -> set -> bool
     end;;
module type SETFUNCTOR =
  functor (Elt : ORDERED_TYPE) ->
    sig
      type element = Elt.t
      type set
      val empty : set
      val add : element -> set -> set
      val member : element -> set -> bool
    end
 
#module AbstractSet = (Set : SETFUNCTOR);;
module AbstractSet : SETFUNCTOR
 
#module AbstractStringSet = AbstractSet(OrderedString);;
module AbstractStringSet :
  sig
    type element = OrderedString.t
    type set = AbstractSet(OrderedString).set
    val empty : set
    val add : element -> set -> set
    val member : element -> set -> bool
  end
 
#AbstractStringSet.add "gee" AbstractStringSet.empty;;
- : AbstractStringSet.set = <abstr>

试图更优雅的书写类型约束,有人会希望命名函子返回的结构的签名,然后在约束中使用那个签名:

#module type SET =
   sig
     type element
     type set
     val empty : set
     val add : element -> set -> set
     val member : element -> set -> bool
   end;;
module type SET =
  sig
    type element
    type set
    val empty : set
    val add : element -> set -> set
    val member : element -> set -> bool
  end
 
#module WrongSet = (Set : functor(Elt: ORDERED_TYPE) -> SET);;
module WrongSet : functor (Elt : ORDERED_TYPE) -> SET
 
#module WrongStringSet = WrongSet(OrderedString);;
module WrongStringSet :
  sig
    type element = WrongSet(OrderedString).element
    type set = WrongSet(OrderedString).set
    val empty : set
    val add : element -> set -> set
    val member : element -> set -> bool
  end
 
#WrongStringSet.add "gee" WrongStringSet.empty;;
Error: This expression has type string but an expression was expected of type
         WrongStringSet.element = WrongSet(OrderedString).element

这里的问题是“Set”制定的类型元素是抽象的,使得在函子结果的元素和参数的“t”之间类型相等被遗忘了。所以“WrongStringSet.element”和字符串是不同的类型,“WrongStringSet”上的操作不能使用到字符串上。正如上述演示,签名“Set”中的类型元素声明为和“Elt.t”相等是很重要;不幸地,由于“SET”定义在“Elt”不存在的上下文中上面的想法是不可能的。为了克服这个困难,Objective Caml提供了签名上的类型约束来允许使用额外的类型相等来扩充一个签名:

#module AbstractSet =
   (Set : functor(Elt: ORDERED_TYPE) -> (SET with type element = Elt.t));;
module AbstractSet :
  functor (Elt : ORDERED_TYPE) ->
    sig
      type element = Elt.t
      type set
      val empty : set
      val add : element -> set -> set
      val member : element -> set -> bool
    end

和简化结构定义的情况一样,定义函子并约束其结果提供有另一种语法:

module AbstractSet(Elt: ORDERED_TYPE) : (SET with type element = Elt.t) =
  struct ... end;;
  
抽象函子结果的类型组件是一个强大的技术来提供我们所描述的这样提供了高度的类型安全。考虑一个字符串序不同于在“OrderedString”结构中实现的标准顺序。例如我们忽略大小写来比较字符串。

#module NoCaseString =
   struct
     type t = string
     let compare s1 s2 =
       OrderedString.compare (String.lowercase s1) (String.lowercase s2)
   end;;
module NoCaseString :
  sig type t = string val compare : string -> string -> comparison end
 
#module NoCaseStringSet = AbstractSet(NoCaseString);;
module NoCaseStringSet :
  sig
    type element = NoCaseString.t
    type set = AbstractSet(NoCaseString).set
    val empty : set
    val add : element -> set -> set
    val member : element -> set -> bool
  end
 
#NoCaseStringSet.add "FOO" AbstractStringSet.empty;;
Error: This expression has type
         AbstractStringSet.set = AbstractSet(OrderedString).set
       but an expression was expected of type
         NoCaseStringSet.set = AbstractSet(NoCaseString).set

注意“AbstractStringSet.set”和“NoCaseStringSet.set”这两个类型是不兼容的,这两个类型的值不相匹配。这是正确的行为:即使两个集合包含相同类型(字符串),两者构建于该类型的不同的顺序,操作符需要维护不同的不变量(标准顺序的严格递增和忽略大小写的顺序)。把“AbstractStringSet”的操作应用到类型“NoCaseStringSet.set”的值会给出错误的结果,或创建了违背“NoCaseStringSet”的不变量的列表。

** 2.5 Modules and separate compilation

目前所有的模块的例子都是在交互系统的上下文中给出。不过模块对大型的批量编译程序格外有用。对这样的程序,存在实践的必要性把源代码分割到若干文件中,称为编译单元,可以单独的编译,由此最小化修改后的重编译。

在Objective Caml中,编译单元是结构和签名的特例,单元之间的关系可以从模块系统的方面容易地解释。一个编译单元A包含两个文件:

实现文件A.ml,包含一序列定义,相当于在“struct…end”构造之内;
界面文件A.mli,包含一序列规格,相当于在“sig…end”构造之内。

两个文件定义了一个名为A的结构如同下面的定义插入在顶层环境中:

module A: sig (* contents of file A.mli *) end
        = struct (* contents of file A.ml *) end;;

文件定义的编译单元可以用“ocamlc -c”命令(-c选项表示“只编译,不要连接”)单独编译;这样产生了编译的界面文件(以.cmi为扩展名)和编译的目标代码文件(以.cmo为扩展名)。当所有的单元都被编译,它们的“.cmo”文件使用“ocaml"连接在一起。例如下列命令编译并连接一个由两个编译单元“Aux”和“Main”组成的程序:

$ ocamlc -c Aux.mli # produces aux.cmi
$ ocamlc -c Aux.ml # produces aux.cmo
$ ocamlc -c Main.mli # produces main.cmi
$ ocamlc -c Main.ml # produces main.cmo
$ ocamlc -o theprogram Aux.cmo Main.cmo

这个程序的行为正如同下列语句插入到顶层环境:

module Aux: sig (* contents of Aux.mli *) end
          = struct (* contents of Aux.ml *) end;;
module Main: sig (* contents of Main.mli *) end
           = struct (* contents of Main.ml *) end;;

特别地,“Main”可以引用“Aux”:“Main.ml”和“Main.mli”所包含的定义和声明可以引用“Aux.ml”的定义,使用“Aux.ident”标记,如果“Aux.mli”导出了这些定义的话。

在连接阶段给“ocaml”的“.cmo”文件的顺序决定了模块定义发生的顺序。因此在上面的例子中,“Aux”先出现并且“Main”可以引用它,但是“Aux”不能引用“Main”。

注意仅仅顶层的结构可以映射到单独编译的文件,并且不是函子或者模块类型。不过所有的模块类对象可以以结构的组件出现,所以解决方法是把函子和模块类型放在结构内,这样就能映射为文件了。


* 翻译说明

** 什么是OCaml/ML语言

OCaml是ML语言(当初作为可计算理论证明的工具产生的)的主要方言之一Caml语言当前的实现和扩展,是由INRIA开发的多范式语言。相比于ML另一方言SML,Caml语言是由它的实现(目前是OCaml)所描述的一种语言而没有基于某一报告或标准。但是OCaml在ML的基础上作出有用的扩展和尝试,使之在函数式编程语言中较适合做实际的应用。虽然ML系的语言并不广为使用(貌似仅在一些性能有关的金融数据分析的场合),但是这无法掩盖其设计上存在优异之处。并且OCaml目前在众Linux发行版中得到了较重点的支援,也影响到了F#和Scala语言的产生。关于编程语言类型的一书《Types And Programming Languages》中以OCaml作为描述语言。
个人觉得OCaml的代码十分清晰易读,至少从上面出现的例子中可以感知一二。它比Lisp更接近数学表达式,而比Haskell语法糖要少。在编译过程中编译为带类型的Lambda表达式的,这是它和它之前的函数式语言相通的地方。

** 和Standard ML的比较

SML当前是依据97年的修订报告,其功能和OCaml的核心加上模块这两部分是一致的,在语法上有些许差异。例如SML区分地除type外用datatype声明变体类型,用fun代替let绑定函数类型,用case...of而不是match...with进行模式匹配,用访问方法而不是下标的形式取记录的元素,有单独的eqtype表示可以判断相等的类型,在不同的内置类型重载了同样的算数运算符。
SML更关注于语言自身的规范和设计,在ML系语言中SML更加适合在教学场合中使用,并且不像OCaml受到法国文化的影响。

** 关于所翻译内容的说明

这里翻译的是OCaml手册中An introduction to Objective Caml部分的前两章节,这部分的原理是对所有ML系语言都使用,并且涵盖了编写程序时需要使用到的特性。其中核心部分用于编写一般的程序逻辑,而模块系统用于使用标准库和创建自己的库。其他特性如面向对象部分在很多实际应用中并没有用到。如果想通过实际的例子来获得一些感受的话:
简略的参考发卡片可以看
http://www.ocamlpro.com/code/2011-06-03-cheatsheets.html
这次有许多小的算法片段
http://rosettacode.org/wiki/Category:OCaml
一些开源项目的代码也可以拿来阅读,例如
形式语言系统Coq和P2P客户端Mldonkey。

** OCaml中提供的其他特性

其他特性的话,首先要说到面向对象特性,其围绕object,、class和type这三个关键词展开。注意OCaml在运行式已经擦除了类型信息,所以类型转换只能往父类单向进行,不过type仅代表接口上的关系而与class无关。在OCaml中继承表示句法关系而子类型表示语义关系,两者使用了不相干的语法。
至于常用的而上面没有说到的特性,一个是Labels,作为函数的关键词参数使用,另一个是Polymorphic variants,类似于Scheme中的Symbol。
此外还包含了一个标准库,和若干哦你工具如创建解析器的ocamllex和ocamlyacc以及从代码中生成文档的ocamldoc还有调试和性能测试工具。
另外有个语言扩充允许match语句中用when表示以条件来匹配还是一个较有用的特性。

** 有关的参考文档和阅读资料

首先是官网上的文档,包括OCaml和Caml Light的手册。它们侧重于对语言和实现本身的描述,这是书写程序时所必备的参考。
http://caml.inria.fr/resources/
还有oreilly的书名为《Developing Applications With Objective Caml》在官网是也免费的提供,涵盖了语言的教程和若干经验。
http://caml.inria.fr/pub/docs/oreilly-book/

** 可以使用的IDE工具

良好的缩进对代码的可读性相当重要,有编辑器帮助的话会很方便的。
这年头程序语言貌似都有强制缩进格式的倾向,让不同的人写出缩进完全一样的代码。
在Emacs中可以使用Tuareg Mode;在Ecliipse中可以使用OcaIDE,Scite也自带了OCaml的语法高亮。

** 和Haskell语言的区别

语法的外表上有继承关系倒是了,况其也是随着ML系的强类型函数式语言这一范式发展过来的。
区别在于Haskell是non-strict的,求值仅在需要是进行(注意一下此时的内存分配情况);是核心部分是纯函数语言,命令式借助于函数的continuation约束执行的次序并由强类型机制约束发生的范围;支持函数的重载,通过typeclass使得同样名称的操作符可以用到不同类型的实例上。此外,Haskell的模块机制和类型无关,仅表示标识符的可见性。
现在Haskell的关注度于已经有超越ML系的趋势,并且自身发展和用户群体更为活跃。

** 关于此次翻译的说明

本来是想根据官方文档的内容来简要的表述一下,后来发觉以自身的能力想说清楚是有难度的,所以就演变成了字面的直译了。
这样可能产生了莫名其妙的曲解,在此也只能暂且就这样了。虽然翻译的曲解不会影响到原文的意思,但是给不幸接触到此文的人误导就不好了。

2011年6月30日星期四

面向Scheme用户的Common Lisp语言的小贴士【程序语言介绍】

* Scheme
Scheme的主要参考资源是SICP和R5RS,优点是语言设计的相当精巧,便于学习和理解程序的原理。

* Common Lisp
Common Lisp是Lisp最主要的方言之一,是为了标准化众多分支而产生的,在AI领域特别是符号计算方面有所应用。和Lisp的另一方言Scheme相比,更适合写实际可用的程序,而不限于演示的目的。
本文假定读者已经了解了Scheme语言的基本使用,将侧重于CL语言自身中有差异的部分,以减少在使用CL因为困惑而不自在。
Lisp的共同点是在于List,这里尽量把Scm和CL当作不同的语言来看待,避开去具体比较之间的相似和相异之处。
这里假设已经了解了Lisp系语言的基本使用和编程范式,将仅从语言特性角度来看反而能都看到CL的一些特别之处。

* 参考文档
** Common Lisp the Language, 2nd Edition
语言描述文档,对语言特性和提供的库都有详细的说明
** Common Lisp HyperSpec
参考手册,用于查阅,形式类似于按照关键词组织的卡片表格样式
** ANSI Common Lisp
偏向于语言特性的教学,很适合本文的话题,所以这里将按照这本书的结构来写

* 正文
** 缩进对阅读代码来说,相当重要。如下内容如有歧义请以文档为准
** 列表list是Lisp中重要的数据结构,同时Lisp语言的表达式也以list形式书写,表达式可以求值
** 断言predicate命名以p结尾
** t表示true而nil表示false,t是所有类型的supertype,nil是所有类型的subtype
** 为方便表示不同的操作符,下面将Function称为函数,将Special Form称为语句,将Macro称为宏,有时候在用法上之间的差异会模糊
** 用defun定义全局函数,用defparameter定义全局变量并计算初始值(如果仅仅是定义的话,也可用defvar),用defconstant定义全局常量
** 用let/let*绑定局部变量,用flet/labels绑定局部函数
** 宏destructuring-bind可以接受模式pattern形式的绑定
** 语句setf用来改变全局或局部符号或表达式所表示的空间所绑定的值,当符号未绑定时自动绑定全局符号
** 语句setf可以同时接受多组符号和值的绑定,这里的符号可以是符号类型,也可是表达式来指定符号的空间或者表示对对象的修改
** 函数参数从左到右执行,函数定义时允许递归调用
** 格式化函数format的第一个参数表示输出的方式,格式字符串~A表示在该处输出值,~%表示换行
** 格式化函数中的格式字符串有一些复杂但有效的用法
** 语句quote可以在包内获取或创建符号,或者用来创建列表,可缩写为'
** 语句function可以将符号或lambda表达式对应的函数,可缩写为#'
** 以lambda开头的不是函数或者语句,而是一种单独形式表达式,类似于列表
** 函数apply和funcall用来将函数作用到参数上,第一个参数可以是函数也可以是符号,但不建议是lambda表达式
** 判断值的类型可以用类型相关的断言,或者用函数typep进行比较,typecase进行分支,deftype定义类型,coerce进行类型转换
** 判断值的内容是否相同用eql,判断列表及每个元素相同用equal,判断值所在的地址是否相同用eq
** 列表list通过函数list生成或者通过make-list来创建,内部由点对pair构成
** 用copy-list和copy-alist和copy-tree来复制列表和关联列表和嵌套列表
** 函数mapcar用来通过某函数将列表的每个元素映射并新创建一个列表
** 列表可以充当集合Set使用,或者是序列Sequence,或者是堆Stack,或者是关联列表Assoc-list,在CL中提供有相关的函数
** 多维数组由函数make-array创建或者用#na生成,由函数aref引用下标,并可由setf来改变数组内的值
** 向量是一种一维数组,用vector或者#()来生成,通过svref来引用。数组的函数如sort和aref同样可用
** 字符串也是一种一维数组,可以用equal判断相等(区分大小写),同时也有专门用于字符串的函数如函数char来获取下标对应的字符以及不区分大小写的比较(以“string-”为前缀)
** 列表可用nth获取下标,不过由于是递归调用cdr/rest所以性能不佳。和向量及字符串一起,都可以使用序列相关的函数,如elt获取下标对应的元素
** 序列相关的函数常见的关键词是:key :test :from-end :start :end
** 形如(defstruct point x y)定义了两个成员的结构Structure,由(make-point :x 0 :y 0))创建实例,并得到访问函数point-x和point-y,提供有setf形式用于修改,断言名为point-p。
** 字段可有初始值,结构也由:cone-name定义对应函数的前缀,有:print-function定义打印方式
** 哈希表Hash Table由make-hash-table创建(其:test默认为eql),gethash访问(其第二个返回值表示是否存在)
** 控制流程中语句progn依次执行语句并返回最后一个值,语句block的第一个参数表示标签并可用return-from返回语句块的值(标签为nil时可用return,也可在一些语句内使用,函数名可作为标签使用),tagbody可在内部任意位置位置使用并由通过go来跳转
** 分支cond和case的最后一个分支可以是t或者otherwise表示默认的情况
** 循环和迭代过程可以使用do或do*或dolist或dotimes或mapc(不返回值的mapcar)或loop
** 语句可以返回列表也可以由values返回多个值,通常只有第一个值其作用,可由multiple-value-bind或multiple-value-call或multiple-value-list使用多返回值
** 非局部跳转(跨越函数调用)可以用throw(参数为标签加返回值)和catch和unwind-protect ,而错误error会触发error handler
** 函数symbol-function用来获取符号对应的全局函数,也可以用setf的形式使用,它不可以用来访问局部函数
** 用documentation可以获得defun中参数后的描述用字符串,函数之外的类型也可以定义这样的文档
** 参数列表Parameter List指函数定义和调用时的&rest &optional &key,可以有默认值
** 函数定义中可以指定某变量使用动态作用域,形如(declare (special x)),可以在修改全局变量时以免造成副作用的扩散
** 函数compile用来编译符号所对应的函数,有些操作符会在编译期执行的,会影响到性能和一些值的绑定。
** 递归可以用数学归纳法来考虑
** 标准输入输出流Stream所存放的全局变量是*standard-input*和*standard-output*
** 由make-pathname创建路径,函数open(:direction表示读写方式)由路径打开流,函数close关闭流
** 宏with-open-file所定义的语句有一个隐含的unwind-protect的close,其第一个参数的首元素是该语句中绑定到流的变量名
** 函数read-*默认使用以*standard-input*作为字符输入,函数read-from-string从参数的字符串作为输入流,在读取时read-macro会被展开
** 函数prin1可以和read配对使用(会将转义字符显示出来),通常的输出使用princ,函数pprint对应*print-pretty*非nil
** 函数format中的格式化字符串在~后可跟,分割的参数,参数可空,右侧,可省略
** 符号Symbol不区分大小写(对于包含空格等字符的符号名,可以用双"|"包围),会intern到包package中,不同的包里的同名符号是不同的。
** 以冒号为前缀的关键词keyword的值是其本身,与包的作用域无关。有时需要用gensym得到一个唯一的符号。
** 函数intern用于从字符串在包内查找或创建符号,每个符号有它的属性列表
** 包由宏defpackage创建,可以指定:use :nicknames :export,使用in-package切换到某包内
** 通过“包名:符号名”的形式来使用别的包里导出export的符号
** 当符号有绑定全局变量时,可以用symbol-value获得该变量的值(不同的类型可以绑定到同一个符号)。局部变量只在编译或解释存在,不可以混用
** 类型number分为integer float ratio complex,存在自动和手动的类型转换
** 用=可以比较两个数是否相等(“/=表示参数各不相等”),而eql不仅要相等好需要类型一致
** 整数分为fixnum(最大正值为常量most-positive-fixnum)和bignum,会自动转换。浮点数有四种,之间储存和计算的精度不同
** eval以列表作为参数,执行使用全局作用域
** 定义宏defmacro返回一个列表,语法类似于defun,用macroexpand-1可以手动展开,常配合Backquote书写
** 宏将在在使用它的程序执行前替换原表达式,需要区分编译时和运行时执行的部分,以及和调用的上下文的影响(建议配合let使用)
** 用于setf的同名宏通过define-modify-macro定义,setf中的表达式参数作为该宏的第一个参数
** 定义类defclass,其参数为类名,超类列表,槽列表。函数make-instance通过符号创建类,函数slot-value访问实例的槽
** 槽slot可以定义:accessor :initarg :initform,定义“:allcation :class”则槽属于类而非实例,槽还可以定义:documentation :type
** 子类会继承超类superclass的槽,类可以有多个超类,按照从到右深度优先
** 同名的槽,:allocation :initform :documentation取做特殊化的类(子类),:initargs :accessors :readers :writers取并集,:type取交集,同名依据符号相同来判断
** standard-object是standard-class的实例,是t的subtype,是其他所有class的superclass
** 宏defmethod用于定义方法,可以给参数定义class或者type或者eql条件
** 方法必须有相同数量的参数,可选参数也需要个数一致,&rest或&key需要同时存在或不存在。其中只有必须的参数可以特例化,如果类型一致会覆盖先前定义的特例方法
** 由方法定义的函数称为generic function,可以对不同的类定义不同的方法,类型依照参数从左到右的顺序匹配定义了特例且最特例的类型,这有消息转递模型所差异
** 可以在方法的基础上定义辅助auxiliary方法:before(按照特殊往一般的顺序) :after(按照一般往特殊的顺序) :around(只执行最特殊的,可以(if (next-method-p) (call-next-method)))
** 宏defgeneric用于将所有的方法看作一个整体,例如可用:method-combination通过某操作符混合所有的方法
** CLOS可以配合PACKAGE机制来只导出需要暴露的函数
** 列表类型(也包括其他的容器)中会存在节点数据的共享,并可能构成环(打印需要*print-circle*指定为t,使用#n=和#n#来读入)。特别要注意副作用会影响到所有引用它的数据,例如member就会引用原数据,而list会创建一个新的列表(quote就不会)
** 操作列表的参数以形式(setf list1 (** list1))来使用,这里的操作符有的会创建新的列表,有的则是破坏性的destructive
** 破坏性的操作会改变对象的数据,但是不保证会做出如何的修改,而是确保返回值是正确的,这样可以比完全重新创建列表有性能上的好处
** 有无破坏性的函数可能会对应提供,如mapcar和mapcan,remove和delete,append和nconc,subst和nsubst,通常以命名以n为前缀(表示non-consing)
** 可以用declare定义函数的编译参数,以及用declaim定义全局的,包括optimize inline type,用the定义表达式的类型,数组时可定义:element-type,已知类型可以加快对方法的查找。性能的因素可以在不影响语句时再完善
** 可以定义类型,如(vector fixnum 20),(simple-array fixnum (4 4)),(integer 1 100),(simple-array fixnum (* *)),(or vector (and list (not (satisfies circular?))))
** 容易可以定义大于:fill-pointer的空间,以便添加元素用。创建pool可以重复使用以创建的对象,减少cons和gc的开销
** 当流是:element-type 'unsigned-byte时可以read-byte/write-byte
** 定义read-macro通过set-macro-character以及set-dispatch-macro-character来通过流返回列表
** 用户默认包是common-lisp-user,可以用make-package创建用in-package进入,用export导出use-package使用
** 宏loop用来书写迭代过程,可以仿照已有的例子来使用
** 函数error ecase check-type assert会抛出错误,可用ignore-errors转化为nil
** 语句or和and是语句,本身不是函数,也不像C++中那样可以overload为函数
** 可以使用trace以及交互模式中的指令对代码进行调试,交互回话可以保存为映像
** 通过函数load载入文件,通过eval-when在设置在装载或编译时执行语句
** 可以根据所使用的类型,有必要知道一下CL已经自带的一些函数或宏或方法

* Wiki
http://www.cliki.net

* 实现
我暂且用的是gcl和clisp,因为比较容易上手,话说自己还没什么CL的使用使用经验。
IDE可以用SLIME,LispIDE或者带tag和高亮和括号匹配的文本编辑器也行,Cusp不知还在维护否。
有一些开源的符号计算软件使用CL实现的,可以作为学习的资源和参考。

* 其他方言或相关语言
** Emacs Lisp
** Visual Lisp
** Clojure
** Dylan

* 接下来...
** 面向Scheme用户的ML语言的小贴士
** 面向Scheme用户的Haskell语言的小贴士

----
用org-mode列了一个提纲,展开缺乏,看着有点别扭。
有些细节可能会有理解误差,这里仅仅是导读的目的了。
此文纯介绍性质,不建议随意地在实际目的中使用。

----
关于另一个很重要的特性,就是程序边运行边修改,自己还没有这方面的经验和习惯,但是CL的一些语言设计确实有为这种用法考虑。
如果是有经验实现可以选择SBCL+SLIME,本文只是一个浅尝辄止的态度的产物,虽然出发点是想说说Scm和CL的差异的说。
恩...有些地方简略地有些不明不白了...

----
貌似说reduce要优于不定长参数。
loop宏和尾递归是两种风格不同的东西,前者算是更进一步的抽象吧。

2011年6月13日星期一

《现代操作系统》一书中的每章节的小结部分,放在这里的算是此书中比较浅显的概括

把每章节的SUMMARY翻译了一下,书是ISBN0-13-031358-0,有976页,这不是该书当前的最新版本。



MODERN OPERATING SYSTEMS
SECOND EDITION
by Andrew S. Tanenbaum

* 0 前言


* 1 介绍
操作系统可以从两个视角来看待:资源管理器和扩产的机器。从资源管理器的角度说,操作系统的工作是有效的管理系统的不同的部分。从扩充的机器的角度说,操作系统的工作是给用户提供一个比真实机器方便使用的虚拟机器。
操作系统有一个很长的历史,从它们代替一般的操作的时候开始,到现代的多程序的系统。重要的包括早期的批处理系统、多程序系统、以及个人计算机系统。
由于操作系统紧紧地和硬件交互,一些计算机硬件的知识对于理解操作系统的有用的。计算机由处理器、储存器以及I/O设备组成。这些部分由总线连接。
所有的操作系统都依赖的概念是进程、内存管理、I/O管理、文件系统和安全。它们都会在随后的章节里处理。
任何操作系统的核心是一系列可以处理的系统调用。它们表明了操作系统实际能做的事情。利于UNX系统,我们接触了一组系统调用。第一组系统调用和进程的创建和终止有关。第二组用来读取和写入文件。第三组用于目录管理。第四组包括其他杂项调用。
操作系统结构可以有多种方式。最常见的为单片机系统、层状层次、虚拟机系统、集成内核或者使用客户机服务器模型。

* 2 进程和线程
为了隐藏中断的作用,操作系统提供了由一系列进程并行运行组成的概念模型。进程可以被动态的创建和终止。每个进程有它自己的地址空间。
对于某些应用让一个进程里有多个线程控制是很有用的。这些线程相互独立地调度并个人有自己的堆栈,但是进程里的所有进程享用共同的地址空间。线程可以实现在用户空间或者内核当中。
进程和使用进程间的通讯机制相互通信,例如信号、监视、或者消息。这些机制用来确保不会有两个进程同时在它们会引起混乱的关键区域。进程可以正在运行、可运行或者阻塞状态,并且可以在自己或者另一个进程运行一个通讯机制的中断的时候改变状态。线程间的通讯也是类似的。
进程间的通讯机制可以解决一些问题、比如生产消费问题、餐饮的哲学家问题、读取器与写入器的问题、以及睡觉的理发师的问题。即使使用了这些机制,仍然需要避免错误和死锁问题。
许多调度算法为人所知。它们中一些原先是用于批处理系统的,例如最短任务优先。另一些则在批处理系统中和交互系统中通用。包括循环调度、优先级调度、多级列队、保障调度、彩票调度、以及公平共享调度。一些系统在调度机制和调度方针之间有明确的划分,这样就可以允许用户来控制调度算法。

* 3 死锁
死锁是任何操作系统中都潜在的问题。它在发生在一组进程中各被授权独立地访问一些资源,并每个进程也需要已经属于该组中其他进程的资源。这些进程被阻塞并都永远不能再运行。
死锁可以通过跟踪什么状态是安全的以及什么状态是不安全的来避免。安全的状态是才能在的一序列时间可以保证所有的进程可以结束。不安全的状态是没有这样的保证。Banker算法可以通过拒接将系统的置于不安全状态的请求来避免死锁。
死锁可以通过建立一种让它永远不会产生的设计来阻止。例如,通过仅允许进程只能同时持有一个资源,死锁的循环等待条件就被打破了。死锁也可以通过给所有的资源编号、并让进程请求资源严格按照递增的顺序。饥饿可以通过先来先服务的分配方针。

* 4 内存管理
在这章中我们探讨了内存的管理。我们看到最简单的系统不交换或分页。一旦程序被载入内存中,它将持续到结束。一些操作系统仅允许某时刻仅有一个进程在内存中,而另一些支持多程序。
下一步是交换。通过交换的应用,系统可以处理比内存空间更多的程序。没有空间的进程交换出到磁盘。内存和磁盘上的自由空间通过位图或者列表的形式跟踪。
现代的计算机通常有某种形式的虚拟内存。在最简单的形式中,每个进程的机制空间划分为称为页面大小一致的块,可以放置到内存中任意可获得的页面帧里面。有许多页面替换算法:两种较好的算法是Aging和WSClock。
页面系统的模型可以看作程序中抽象的页面引用字符串合计使用同样的字符串的不同算法。这些模型可以用来做出一些对分页行为的预测。
为了使分页系统工作良好,选择算法是不够的;还需要注意到一些问题如工作集的决定、内存分配的方针、以及页面的大小。
分段有助于在在执行中处理改变大小的数据结构并简化了连接和共享。它也促成了不同分段的不同保护方式。有时分段和分页是组合在一起提供了二维的虚拟内存模型。MULTICS和Intel Pentium系统支持分段和分页。

* 5 输入/输出
输入/输出是一个常被忽视,但是重要的话题。任何系统中相当大的部分是和I/O相连的。I/O可以通过三种方式来完成。第一种,是可编程了I/O,其中主CPU输入或输出每个字节或字并保持紧张的循环等待直到它能得到或发送下一个数据。第二种是中断驱动的I/O,其中CPU开始对字符或单词的传输后离开去做别的事情,直到中断到达表示I/O完成的信号。第三种是通过DMA,它是一个单独管理用户传输数据块的芯片,只有在整块数据传输完成的时候给出中断。
I/O可以以四个层次来结构:中断服务程序,设备驱动程序、设备无关的I/O软件、以及用户空间中的I/O库和后台程序。设备驱动处理运行设备的细节以及为余下的系统提供一致的接口。设备无关的I/O软件进行缓冲和错误报告之类的事情。
磁盘有多种类型,包括磁性的磁盘、阵列、和各种光盘。磁头的调度算法通常可以用来提升磁盘性能,不过这关系到所呈现的几何形态的复杂度。通过连接两个磁盘,可以构建特定作用属性的稳固储存。
时钟用于跟踪真实事件,限制进程可以运行时间长度、处理看门狗定时器、以及做报告。
面向字符的终端有一些特殊字符可用户输入和一些转义字符用于输出。输入可以在原始模式或者烹饪模式,这取决于程序想对输入有多少控制。输出中的转义序列控制光标的移动,并用户允许插入和删除屏幕上的文字。
许多个人计算机使用GUI来输出。它们基于WMP范式:窗口、图标、菜单、以及指点设别。基于GUI的设备一盘是事件驱动的,通过键盘鼠标以及其他送往程序的事件被尽快地处理。
网络终端有若干形式。其中一种最流行的是运行复杂地用于构建图形界面的X系统。X窗口的另一中方式是使用低层次的接口通过网络传输简单的原始像素。SLIM终端的实验显示这项技术也可以很好的工作。
最后,电源管理是便携计算机的一个主要的问题,因为电池的寿命是有限的。各种技术可被操作系统采用来降低电源的损耗。程序可以通过牺牲一些性能来帮助延长电池的使用时间。

* 6 文件系统
从外面来看,文件系统是文件和目录的集合,加上对它们的操作。文件可以被读取和写入,目录可以创建和销毁,并且文件可以在目录间移动。大部分现代的文件系统支持层次的目录系统,其中目录可以有子目录,并它们循环地继续有子目录。
当从内部来看,文件看起来有很大的不同。文件的设计者必须考虑储存是如何分配,以及系统是如何跟踪哪个块是属于哪个文件。可以的方式包括连续的文件、链接的列表、文件分配表、以及i-node。不同哦你高的系统有不同的目录结构。文件属性可以放在目录中或者其他地方(例如i-node中)。磁盘空间可以使用自由列表或者位图来管理。文件系统的可靠性通过制造增量的转储来增强以及通过让程序可以出错的文件系统。文件系统的性能是重要的并可以用若干方式来增强,包括转存、预读、以及仔细的方式文件块使之间临近。日志结构文件系统也通过大的单元进行写入来增强性能。
文件系统的例子包括ISO 9660、CP/M、MS-DOS、Windows 98、以及UNIX。它们在许多方面有区别,包括如何跟踪哪个块属于哪个文件、目录的结构、以及自由磁盘空间的管理方式。

* 7 多媒体操作系统
多媒体是新起的计算机的使用。由于多媒体文件的大尺寸和它们严格的实时回放需求,为文本设计的操作系统对多媒体不够理想。多媒体文件有多重的平行的轨道组成,通常是一轨视频和至少一轨音频以及有时也有字幕轨。它们必须在播放时同步。
音频的通过定期的采样来录制,通常是44,100次/秒(CD音质)。压制可用于音频信号定义统一的10x的压制速率。视频的压制同时使用帧内压缩(JPEG)和帧间压缩(MEPG),后者用P帧表示与前一帧不同的地方。B帧则居于前一帧或者下一帧。
多媒体需要实时调度已满足期限。两种算法常被采用。第一种是固定速率调度,它使用静态的优先级算法依照周期给进程赋予固定的优先级。第二种是期限最近优先,它是总选择最接近期限的进程的动态算法。EDF较复杂,但是能实现100%的利用率。RMS那样的则不能。
多媒体文件系统通常使用Push模型而不是Pull模型。一旦数据流开始,从磁盘上读取数据就不再要用户请求。这种途径和传统的操作系统有根本的不同,由于对满足实时请求的需要。
文件可以连续的储存或者不是。在后一种情况下,单元是可以可变程度的(一个块是一帧)或者固定长度的(一块有多帧)。这些途径有不同的取舍。
文件在磁盘上的放置影响到性能。当有多个文件的时候,有时organ-pipe算法可以使用。分割文件到多个磁盘上不论横向或纵向,是常见的。块和文件缓存策略也广泛地用来提升性能。

* 8 多处理器系统
计算机系统可以使用多个CPU来更加快速和可靠。三种多CPU系统的组成方式是多处理器、多计算机、以及分布式系统。其中每一种都有自己的特性和问题。
多处理器由两个或更多享用功能的RAM的CPU组成。CPU可以用总线、交叉开关、或者多级交换网络来互联。多种操作系统的配置是可行的,包括给每个CPU单独的操作系统、有一个主操作系统其他作为从属、或者使用对称的对处理器让一份操作系的拷贝可以让任何CPU运行。在后面一种情况,需要用锁来保持同步。当锁不能获得的时候,CPU可以旋转或者做上下文切换。多种调度是可以的,包括时间分时、空间共享、以及成群调度。
多计算机也有两个或者更多的CPU,但是这些CPU有它们自己的私有内存。它们不分享公用的内存,所以所有的通信使用消息的转递,在一些情况,网络接板有它自己的CPU,在这种情况下主CPU和接板的CPU必须自己组织以避免竞争条件。多计算机中用户层次的通讯通常使用远程过程调用,但是分布共享内存也可以使用。处理器局部的平衡是这里的一个问题,并有用于此的多种算法包括发送者启动的算法,接受方启动的算法、以及投标算法。
分布系统是松散耦合的系统,它的每个节点都是有着完整的外围设备和自己的操作系统的独立的计算机。通常这样的系统分布在较广的地理区域。中间件通常构建在操作系统之上来给应用程序提供一致的交互层。各种的中间件包括基于文档的、基于文件的、基于对象的、以及基于协调的中间件。一些例子如World Wide Web、AFS、CORBA、Globe、Linda、以及Jini。

* 9 安全
操作系统可以在许多方面都到威胁,从内部的攻击到从外界进入的病毒。许多攻击是黑客尝试闯入特定的系统,通常仅仅是猜测密码。这些攻击通常只是使用常用密码的字典并惊人的成功。密码安全可以通过使用Salt、一次性密码、以及挑战响应方案。智能卡和生物指示也可以使用。视网膜扫面已经实用了。
许多不同的对操作系统的攻击是一致的,包括特洛伊木马、登录欺骗、逻辑炸弹、陷阱门、以及缓冲溢出攻击。通用的攻击包括请求内存并对其窥探,使用非法的系统调用来看看发生什么,甚至尝试欺骗内部来透露他们不应该透露的信息。
病毒是许多用于增长的严重问题。病毒存在多种形式,包括内存常驻病毒、引导区感染、以及宏病毒。使用病毒扫面器在查找病毒特征是有用的,不过真正好的病毒能加密它们的大部分代码并在每次复制的时候修改余下的代码,使得检测非常困难。一些杀毒软件不仅仅通过查找病毒的特征码来工作,而是通过发现特定可疑的行为。通过安全的计算机使用习惯来避免病毒要优于尝试处理攻击后的后果。简单的说,不要载入执行来历不明的和可信度有疑问的程序。
移动代码是如今必须要处理的问题。把它放在沙箱内,解释运行、以及仅运行可信赖的供应商签名的代码是可行的途径。
系统可以用一个领域(如用户)垂直或者对象水平的矩阵来保护。矩阵可以切割为行,采用基于能力的系统,或者为列,采用基于ACL的系统。
安全的系统是可以被设计的,但是必须从开始就定位一个目标。可能最重要的设计规则是有一个最小的可信赖的计算机基础不能被任何资源的访问绕开。多层安全可以基于Bell-La Padula模型,为保密而设计,或者Biba模型,用于维护系统的完整性。橙皮书描述了可信系统需要满足的要求。最终,即使系统可证明是安全的,仍必须注意到隐蔽的渠道,它能够轻易的通过创建模型外的通信渠道来推翻系统。

* 10 案例1:UNIX和LINUX
UNIX由作为小型机的分时系统开始的,但是现在使用涵盖从笔记本计算机到超级计算机。存在有三个接口:Shell、C库、以及系统调用本身。Shell允许用于键入执行的命令。可以是简单的命令、管道、或者更复杂的结构。输入和输出可以重定向。C库涵盖了系统调用并也有增强的调用,例如printf用于格式化输出往文件。实际的系统调用接口是精简的,大约100个调用,每个调用仅仅做它需要的事情。
UNIX中的关键概念包括进程、内存模型、I/O、以及文件系统。进程可以分出子进程,产生树状的结构。UNIX中的进程管理使用两个关键的数据结构,进程表和用户结构。前者总在内存中,但是后者可以被交换或者分页出去。进程的创建通过复制进程表以及内存镜像来完成。调度使用基于优先级的算法并请相互进程。
内存模型每个进程由三个片段组成,text、data、stack。内存管理曾是用交换来完成,不过现在多数UNIX系统中通过分页来完成。核心地图跟踪每个页面的状态,页面守护进程使用使用时钟算法来保持大约有足有的自由页面。
I/O设备使用特殊的文件来访问,各自有一个主设备号和一个次设备号。块设备I/O使用缓冲缓存来减少访问磁盘的次数。LRU算法可用来管理缓存。字符I/O可以通过直接或者烹制模式。线路规程或流用于给字符I/O添加功能。
文件系统是由文件和目录组成的层次结构。所有的磁盘被载入有单独的根开始的单独的目录树。单独的文件可以链接如一个目录从文件系统的其他地方。要使用文件,必须先打开,产生一个用于读取或者写入的文件描述符。在内部,文件系统使用了三个主要的表:文件描述符表、打开的文件描述符表、以及i-node表。其中i-node表最为重要,包含了关于文件所有的管理信息以及它的块的位置。
保护是基于根据所用者用户组和其他来控制读写执行操作。对于目录,可执行标记解释为搜索的权限。

* 11 案例2:WINDOWS2000
Windows2000的结构是HAL、内核、执行文件、以及一层薄的用于捕获传入的系统调用的系统服务层。此外,有各种设备驱动,包括文件系统和GDI。HAL从上层中隐藏了一定的差异。内核试图给可执行文件隐藏余下的差异使得执行文件是机器独立的。
执行程序是基于内存对象。用户进程创建它们并取回句柄在随后操纵它们。执行组件也能创建对象。对象管理器维护了什么对象可以插入用于以后查找的命名空间。
Windows支持进程、作业、线程和Fiber(用户空间)。进程有虚拟地址空间和资源的容器。线程是执行的单位并由操作系统调度。作业是一组进程用于分配资源的额度。调度通过通过优先级算法让最高优先级的线程随后执行。
Windows2000支持按需分页的虚拟内存。分页算法是基于工作集的概念。系统维护若干自由页面的列表,这样每当页面错误发生,一般有自由页面可用。自由页面列表使用复杂的规则来调整,试图扔掉长时间里没有使用的页面。
I/O通过遵循Windows设备模型的设备驱动完成。每个驱动由初始设备对象开始,其中包含了系统用于添加设备和执行I/O的调用的过程的地址。驱动可以层叠作为过滤器。
NTFS文件系统是基于主文件表,它为每个文件或目录有一项记录。每个文件有多项属性,它可以在MFT记录中不常驻位于磁盘上。NTFS支持压缩和加密,以及其他的功能。
安全是基于访问控制列表。每个进程有访问控制标记来表明它是谁以及如果有的话,它有什么特别的特权。每个对象有一个和它相关的安全描述符。安全描述符指向一个自由访问控制解表,其中有允许或拒绝个人或组访问的访问控制项。
最后,Windows2000为文件系统维护单独系统范围的缓存。这是一个虚拟缓存而不是物理的。磁盘块的请求首先往缓存。如果它们不能满足,则适当的文件系统被调用以获取所需的块。

* 12 操作系统设计
设计一个操作系统有决定它要做什么开始。接口应该是简单、完整、并且高效的。它应该有清晰的用户接口范式、执行范式和数据范式。
系统应该合理地结构,使用一种已知的技术,例如分层或客户服务模式。内部的组件应该相互正交并清晰的从机制中划分出政策。一些问题应该有多思考,例如静态动态的数据结构、命名、绑定时间、以及实现模型的顺序。
性能是重要的,但是优化需要仔细选择而不会破坏系统的结构。空间时间的权衡、缓存、暗示、地区利用、以及优化常见情况是常常值得做的。
由几个人编写的系统不同于300人生产出的大系统。在后一种情况下,团队的结构和项目的管理在项目的成功与失败中扮演了关键的角色。
最终,操作系统不得不继续改变以遵循新的趋势迎接新的挑战。其中包括64位地址空间、大量的连接、桌面多处理器、多媒体、手持的无线计算机、以及种类繁多的嵌入系统。接下来的年份将会是操作系统设计的激动人心的时刻。

* 13 阅读清单和参考书目




*
下面是闲话时间,当前自己对操作系统的了解仅停留在浅浅的层面。关于操作系统方面还缺乏经验和心得,于是这里来说说Java和Scheme语言中多线程的原理和实现吧。这里的侧重是关于用户模式内线程,利用协程以及时间中断来实现多任务的切换。此外要注意到一些系统调用会阻塞整个进程,这也是需要处理的问题。当然,这部分闲话的内容是可以正好来运用一下操作系统方面的知识。

2011年6月10日星期五

Academy of Interactive Arts & Sciences【介绍文/翻译/施工】

Academy of Interactive Arts & Sciences From Wikipedia
嘛...暂时还没开工...
不过其实也没什么好翻译的,只是想找个条目来写写个人的想法。
里面好多东西不熟悉,也没办法有什么感想。
说自己熟悉的话,还是对NES和GBA要过一些。
另外那里还没有涉及到1996年之前的东西。
这样的话,就先坑在这里了。
要是说自己口味的话,喜欢参与感和空间感强的。
有时候对手柄和格子和树状结构有意外的好感。

2011年6月2日星期四

又一个坑了的视觉小说,\n顺便说说Java与Scheme的混合/嵌入使用

拿Slick2d和Kawa包了一组给Scheme用的API出来,做了一个简单而拙劣的VisualNovel演示。话说第三方库有源代码和JavaDoc外加严格的类型系统和Eclipse的辅助,使用起来还是挺方便的。
下面的东西是个试验用的半成品,不过后来发觉又依赖JRE又依赖平台二进制包感觉挺恐怖的。想分发或者跨平台的话暂且都有问题,也就没动力继续去完善了这个自命名Slickawa的包了。
于是代码什么的在很久很久以前就不继续了,现在拿出来发觉可以用来写篇日志,相当于随手写写遇到的想法吧。

话说Slick的提供的库的API让自己挺欣赏的,至少是打消了再去包装它一层的看法(比如SDL就一定要先包一个主循环出来类出来供派生才觉得舒服)。不过要注意的是Slick是在OpenGL上的一层包装,如果觉得它提供了某个抽象合适的话,就拿来用,或者直接看它的代码。如果不合适的话,大可不必考虑某些类的存在,按照自己的需要直接从更底层的方法往上层建立。达到目的即可,而且目的肯定不是重复一个和Slick一样的抽象层(比如移植其他平台用)吧。
不过SDL1.2和OpenGL用起来还是有个很明显的区别(就像PyGame和PyGlet),它们负责图像混合的设备不同。前者主要靠CPU,后者主要靠GPU,如果不这样顺着它们的原理用的话,性能会大有问题(所以C或者Shader的使用最好是无限制)。如果要在多媒体程序里做一些视觉效果的话,真的还是很容易出现性能瓶颈的。

给Scheme的API分为四组,sk中是基本的过程,skex中是可以用Scm本身来实现的,sklab是试验用方法,sklib是依赖底层的方法。这分别对应四个Java的Class,要暴露的方法实现为静态的,这样在Kawa中就可以直接使用了。
算是语言间类型的自动绑定吧,其实呢Kawa是把Scheme代码编译为Java的字节码,这样在性能上和互操作上都很方便。不过想在Kawa完全使用Java库还是有些不便,所以还是提供为简单的一个个过程较方便。对象仍旧是对象,方法变为以对象为参数的过程。
现在让Scheme代码和Java代码结合的地方可以有两种,一种是用Kawa提供的机制直接在Scm中使用Java的包和对象,一种是在Java中用Kawa中提供的类型映射类创建实例交给自己管理的Scheme运行环境。不过这两种方式都不要指望Kawa能够是Scheme和Java部分能够完全的分离,必然会有一个中间层在Scheme中操作了Java的数组,或者是在Java中操作了Scm的列表。
如果需要添加什么功能的话,要么单独的写为一个包,要么就在那个中间层里放心大胆的写。不必在意是写为纯Java的还是纯Scheme的为好,被中间层所选用的语言所限,不然在使用所依赖的库的时候会遇到麻烦。如果担心会导致所暴露的API会紊乱的话,就放到不同的命名空间里去。也不必在意是否暴露的足够的API,只要要中间层有足够的活性(有废止的方法标记一下就可以了,反正只涉及静态方法和单方法的界面,单一元素的修改仅会带来很有限的影响。),混合语言所带来的将不是负担而是效率了。中间层即使Java和Scheme语言同时用也可,目的都是让纯Scm部分的代码可以用某个函数,所以还是倾向于在Java中写这个中间层同时Scheme也用。至于Java6的那个对脚本语言的框架,造成通常得首先包装为对象传给那个框架,然后在用脚本语言提供适合自身类型的包装。用来两次包装之后,想实现一些功能的话,放在哪个部件里都觉得不是很方便。
相比另一个Scheme的Java实现SISC,本来自己是觉得它更小巧一些,所以一开始的更偏爱一些。后来觉得Kawa做得更成熟一些,于是就从比较省事的角度选择的Kawa。之前在用tinyscheme做过一次绑定,得自己添加垃圾收集用的类型,再添加Unicode编码的支持,再针对类型的转换把提供的API函数一个个写一遍。而且用到的函数得去tinyscheme的头文件里找,然后再去长长的单个源代码里看看是怎么回事后才用,再传递指针的时候很容易就把类型信息丢掉。结果就是TinyScheme的代码也混杂在宿主程序里面一起修改了。Java的好处是可以把单独要改的类拿出来改一下然后用(只要不涉及包的可见性以及开源的许可协议的限定的话),原本引入的jar文件可以丝毫不变的放在那里。不过话说似乎好多Scm实现都是为单独使用设计的,想手工包装到C/C++里面都有点手疼,而更倾向于用FFI在Scm代码中用C库(于是对第三方库就可能是先用C包一层,然后再Scm针对类型转换包一层了。这样总比在C中连类似什么也考虑要手疼的好一些,虽然这里来说说感想也看不出多少可再用的价值)。
有个chibi-scheme时间不如TinyScheme,但是设计得更加完善一些。

Java和Scheme都有Steele的参与,这或许是让两者看起来很协调的一方面吧(只是或许而已)。两者都有各自的变量命名习惯,都喜欢使用长的n的单词组合。虽然一个用大小写来分割单词,一个用横线来分割单词,但是这两者对应起来还是相当直观。都是很少用语法糖,都是写起来手疼,都是值是有类型的对象的语言。所以两者混合用起来还是蛮协调一致的感觉。
Scheme的运行环境有两个地方,一个是让Scm代码自己成为一个Java类,一个是人工的管理一个Runtime对象。如果仅仅是把Scheme作为数据来看待的话,似乎后者会比较方便。Scm的一个优势是自身可以当作一种数据格式来使用,Kawa中提供了解析供的方法。而让Scm代码去实现某个interface然后传回Java也是可以的。此外还可以main中直接eval,提供一些API后控制权给脚本,让Scheme当胶水使用。
如果仅仅是想REPL地试验一下某个Java代码片段,有个BeanShell还是蛮方便用的。

关于下面的实现,还有些额外的说明。这里就列举一下,语句会不大通顺。首先呢,当类型不重要的时候,用Scm中的List来传递值了,这样比从对象里查询要方便一些(如果List是Lazy的话就更方便了,语言的执行就是 Graph Reduction)。其次来说,这里Java的主循环三种事件要调用Scheme提供的函数。Java部分只要只管要时去调用,而场景的切换放在Scm里面做了。至于场景切换要怎么修改提供给Java的过程,以及场景切换中还是否要做一些额外的事情,Java部分是不用管的。所以这里为了方便的在Scm中实现多个场景,做了一个简单的OO。注意逻辑和渲染和必须分割开来的,中间可以用全局(相对两者而言)来传递信息。还有呢,涉及RGBA混合的过程无论写在Scheme中还是写在Java中都是会性能不够的,正确做法是写在OpenGL里面,可惜自己还不会。动画效果这里参考了Qt的状态和变换框架,这里仅仅提供了一个用来进行y=kx线性变化的类。其实利用y=f(kx1)+g(kx2)的组合还是能做出很多效果的,比如以线性变化为时间轴映射到多个变量上,或者串联多个线性变换,这些都是可以发挥想象里的地方。然后作用坐标、透明度、颜色以及其他可以数值表示的地方,看起来还是挺生动的(这方面Flash是榜样,不过Flash性能限制)。

写的时候参照了KRKR2/KAG3和ONScripter和RenPy的部分代码,以及rpgchina.net和gamediy.net上的教程,以及Slick和PyGame和ClanLib的API:
;;;开始
(sk:make "VisualNovelDemo")
(sk:path ".;visualnovel")
(sk:display-mode 800 600 #f)
(sk:fps 60)
(sk:debug #t)
;;;OO
(define (send obj msg . arg)
  (cond ((obj msg)
         =>(lambda (x) (apply x arg)))))
(define (dispatch prototype method-alist)
  (lambda (mth)
    (cond
      ((assoc mth method-alist) => (lambda (x) (cadr x)))
      ((procedure? prototype) (prototype mth) )
      (else #f))))
;;;全局变量
(define *env* (interaction-environment))
(define *background* #f)
;(define *script* (sk:load-data "script.scm"))
(define *script* (skex:load-line-data "script.scm"))
(define *scripts-now* #f)
;;;全局过程
;(define *music* #f)
(define (state-clear)
  (set! *scene*
        (dispatch '()
                  (list
                   (list 'frame (lambda (delta) '()))
                   (list 'button (lambda (b) '()))
                   (list 'render (lambda (g) '()))
                   )))
  )
(define (dialog-jump! label)
  ;(sk:display "try")(sk:display label)
  (let ((s (member (list 'label label) *script*)))
    (sk:display s)
    (when s
      (state-clear)
      (set! *scripts-now* s)
      (script-next!)
      ;(sk:display (state))
      )))
;;;场景
(define *scene*
  (dispatch '()
            (list
             (list 'frame (lambda (delta) '()))
             (list 'button (lambda (b) '()))
             (list 'render (lambda (g) '()))
             )))
;;;对话场景
(define (scene-dialog text)
  (define dialog-font (sk:load-font "Simhei" 32))
  (define *dialog-char-count* (skex:make-linear 0 (sk:string-length text) 1))
  (define (dialog-end?)
    (skex:linear-end? *dialog-char-count*))
  (define (dialog-end!)
    (skex:linear-end! *dialog-char-count*))
  (define (on-frame delta)
    (skex:linear-next! *dialog-char-count* (* 0.03 delta)))
  (define (on-render g)
    (sk:draw-color 30 428 (sk:color 0 0 0 128) (- 800 60) 128 )
    (skex:draw-text
     34 432
     (sk:substring text 0 (skex:linear-now *dialog-char-count*))
     (- 800 64) dialog-font (sk:color 0 0 0 128))
    (skex:draw-text
     32 430
     (sk:substring text 0 (skex:linear-now *dialog-char-count*))
     (- 800 64) dialog-font (sk:color 255 255 255 255))
    (when (dialog-end?)
      (sk:draw-color 740 530 (sk:color 128 255 128 255) 8 8)
      )
    )
  
  (define (on-button b)
    (if (or (equal? b '(pressed A)) (and (pair? b)(eq? (car b) 'touch)))
        (if (dialog-end?)
            (script-next!)
            (dialog-end!))))
  (dispatch
   '()
   (list
    (list 'frame on-frame )
    (list 'button on-button )
    (list 'render on-render )
    ))
  )
;;;scene-effect 背景切换效果
;;;背景切换场景
;;;(bg "1.png" 0)
(define (scene-bg-change arg)
  (define *bg-future* (sk:load-image (cadr arg)))
  (define *bg-changing* (skex:make-linear 0 1 (/ 1 (caddr arg))))
  (define on-frame
    (lambda (delta)
      (skex:linear-next! *bg-changing* delta)
      (when (skex:linear-end? *bg-changing*)
        (set! *background* *bg-future*)
        (set! *bg-changing* #f)
        (script-next!))))
  (define on-button
    (lambda (b) '()))
  (define (on-render g)
    (sk:draw-image 0 0 *bg-future* (* 255 (skex:linear-now *bg-changing*))))
  (dispatch '()
            (list
             (list 'frame on-frame )
             (list 'button on-button )
             (list 'render on-render ))))
;;;scene-effect 背景遮片效果
;;;effect-mask
;;;(effect mask "1.png" "rule.png" 100)
;;;name = 'mask
;;;arg = '(mask "1.png" "rule.png" 100)
(define (scene-bg-effect arg)
  ;;to extend this lambda class
  (define (make-effect bg-future effect-render-with-p% time-last)
    (dispatch '()
              (list
               (list 'frame (lambda (delta) '()))
               (list 'button (lambda (b) '()))
               (list 'render (lambda (g) '()))
               )))
  (case (cadr arg)
    ((mask) (scene-bg-mask-change (cdr arg)))
    ((bg) (scene-bg-change (cdr arg)))
    (else (error "effect"))))
;;;'(mask "1.png" "rule.png" 100)
(define (scene-bg-mask-change arg)
  (define *bg-future* (sk:load-image (cadr arg)))
  (define *bg-mask* (sk:load-image (caddr arg)))
  (define *time-line* (skex:make-linear 0 1 (/ 1 (cadddr arg))))
  (define on-frame
    (lambda (delta)
      (skex:linear-next! *time-line* delta)
      (when (skex:linear-end? *time-line*)
        (set! *background* *bg-future*)
        (set! *time-line* #f)
        (script-next!))))
  (define on-button
    (lambda (b) '()))
  (define (on-render g)
    (sklib:draw-image-with-mask 0 0 *bg-future* *bg-mask* (* 255 (skex:linear-now *time-line*))))
  (dispatch '()
            (list
             (list 'frame on-frame )
             (list 'button on-button )
             (list 'render on-render ))))
;;;用户界面场景
(define (scene-ui arg)
  ;(ui ((text 116 500 "开始" fnt clr) start) ((text 516 500 "退出" fnt clr) end))
  (define *ui* '())
  (define (ui-draw x)
    (map (lambda (i)
           (apply
            (case (caar i)
              ((text) sk:draw-string)
              ((image) sk:draw-image)
              (else (error i)))
            (map (lambda (j) (eval j *env*)) (cdar i))))
         x))
  (define (ui-area x)
    (map
     (lambda (i)
       (list
        (let ((arg (map (lambda (j) (eval j *env*)) (cdar i))))
          (let ((x (car arg))
                (y (cadr arg))
                (s (case (caar i)
                     ((text) (sk:text-size (caddr arg) (cadddr arg)))
                     ((image) sk:draw-image)
                     (else (error i)))))
            (list x y (car s) (cadr s))))
        (cadr i)))
     x))
  (define *button-area* #f)
  (set!
   *scene*
   (dispatch
    '()
    (list
     (list
      'frame
      (lambda (delta) '()))
     (list
      'button
      (lambda (b)
        ;(sk:display (ui-area *ui*))
        (when (and (pair? b)(eq? (car b) 'touch))
          ;(touched (1 2))
          (let ((x (caadr b))(y (cadadr b)))
            (map (lambda (i)
                   (when (skex:contained? x y (car i))
                     ;(sk:display (cadr i))
                     (when (symbol? (cadr i))
                       (dialog-jump! (cadr i)))))
                 (ui-area *ui*))))
        (when (and (pair? b)(eq? (car b) 'cursor))
          ;(touched (1 2))
          (let ((x (caadr b))(y (cadadr b)))
            (set! *button-area* #f)
            (map (lambda (i)
                   (when (skex:contained? x y (car i))
                     (set! *button-area* (or *button-area* (car i))))
                   (when *button-area*
                     (set!
                      *button-area*
                      (apply
                       (lambda (a b c d) (list a b (+ 2 c) (+ 2 d)))
                       *button-area*))))
                 (ui-area *ui*))))))
     (list
      'render
      (lambda (g)
        (when *button-area*
          (apply sk:fill (append *button-area* (list (sk:color 0 0 0 128)))))
        (ui-draw *ui*)))
     )))
  (sk:display (cdr arg))
  (set! *ui* (cdr arg))
  *scene*)
;;;解析并执行脚本
(define (script-next!)
  (if (not (null? (cdr *scripts-now*)))
      (begin
        (set! *scripts-now* (cdr *scripts-now*))
        (state-clear)
        (cond ((string? (car *scripts-now*))
               ;;显示对话
               ;;"Hello World"
               (set! *scene* (scene-dialog (car *scripts-now*))))
              ((pair? (car *scripts-now*))
               (case (caar *scripts-now*)
                 ((bg)
                  ;;切换背景
                  ;;(bg "05_1_2.jpg" 100)
                  (set! *scene* (scene-bg-change (car *scripts-now*))))
                 ((effect)
                  ;;切换效果
                  ;;(effect mask "sdf.jpg" "rule/12.png" 2000)
                  ;;(effect bg "rule/12.png" 2000)
                  ;;(effect bg:mask "rule/12.png" 2000)
                  (set! *scene* (scene-bg-effect (car *scripts-now*))))
                 ((ui)
                  ;;显示界面
                  ;;(ui ((text 116 500 "开始" fnt clr) start) ((text 516 500 "退出" fnt clr) end))
                  (set! *scene*(scene-ui (car *scripts-now*))))
                 ((music)
                  ;;播放音乐
                  ;;(music "11.ogg" 100)
                  ;(sk:play-music (sk:load-music (cadr (car *scripts-now*))) #t)
(sk:play-music (cadr (car *scripts-now*)) #t)
                  (script-next!))
                 ((eval)
                  ;;(eval (set! fnt (sk:load-font "Simhei" 48)))
                  (eval (cadr (car *scripts-now*)) *env*)
                  (script-next!))
                 ((label)
                  (script-next!))
                 ((jump)
                  (dialog-jump! (cadr (car *scripts-now*))))
                 (else (error "未知指令"))))
              ((null? (car *scripts-now*)) (script-next!))
              (else (error "未知指令"))))
      (sk:exit)
      ))

(sk:on-init
 (lambda (e)
   ;;;载入剧本
   (set! *scripts-now* (cons '() *script*))
   ;(set! bgm (sk:load-music "music/bgm03.ogg"))
   (script-next!)))
(sk:on-frame
 (lambda (delta)
   (send *scene* 'frame delta)))
(sk:on-button
 (lambda (b)
   (send *scene* 'button b)))
(sk:on-render
 (lambda (g)
   (when *background*
     (sk:draw-image 0 0 *background* 255))
   (send *scene* 'render g)))
(sk:start)

所用的脚本格式中@开始的行是命令,读取是首尾加括号,不然则加引号。读取后是一个sexp的列表,这样可以在Scheme中直接操作。
话说IEEE标准里没有收eval语句,因为有点细节上的欠缺。虽然R5RS里有,个人还是觉得这里也不必要去用完整的eval过程,不过自己改写出来一个eval还是个重复劳动。
脚本就是纯文本,话说一开始的写法是每个字符串要加引号。虽然有正则这种东西,但是想重新分段什么的还是不方便。与其每次保存是要处理,不如直接扩充Reader部分。
上面的代码在重构的时候消灭了很多全局变量,顺便也抽象出来一些较直观的概念。这些修改不影响跑测试代码,但是这体现Scm代码的进化方式。
以上的OO是基于原型的消息传递,还缺少一个set-this消息,继承时会用到。不过添加这样一个消息的话,对已有代码影响很小,而且暂时没用到,所以还没有添加。

Java部分的代码或许以后传吧,没多少内容
不过还是暂且来简单的写一些说明吧——
首先呢,是最常用到的若干包和类(以及类的方法):
kawa.standard.Scheme 对应 Scheme的一个运行环境;
gnu.lists.LList 对应 Scheme中的类型,列表;
gnu.mapping.Symbol 对应 Scheme中的类型,符号;
至于整型就是Integer,字符串就是String
想把sexp字符转为Scheme的嵌套Pair的h话:
LispReader reader = new LispReader(new InPort(new StringReader(sexp)));
return ReaderParens.readList(reader, 0, 1, -1);
至于Number的话可能是gnu.math.Numeric也可能是java.lang.Number,
如要用instanceof判断之后再获取值,比如调用.floatValue();。
此外,现在绘制是一堆draw-*的过程,另一种实现方式是:
提供 <? extends Drawable & Posable ...>然后统一的用draw来调用。
这样就转变为考虑怎样在场景里放置物品,而让绘制操作可以自动进行。
这部分暂时还没用到,只是在Java中申明了Interface,还是放到Scm中需要的时候写这部分好了。
话说一般用对象的使用,以及界面的实现好了,类的派生什么的还是少用为好。
比如这里Java给Scheme的API就不包括类的派生,不过Silck2D的习惯本身也没有精灵类。
有时候嘛,精灵类还是需要的,用来管理场景里哪些东西要绘制,若仅仅是OO的话,还是放在Scm中为好。
在Scheme中可以用lambda来做参数传递时转化为实现了所需要的只有一个方法的界面,
此外Kawa提供的一些机制还是可以用虽然目前不够完善所以用着不舒服。
kawa中导入Java的类是使用(define-namespace sk ),
然后可以直接使用静态成员方法,创建和使用对象也有提供了方法的。
想开一个交互的调试窗口的话,可以执行如下的代码(可以绑定到按键上):
ReplDocument doc = new ReplDocument(scm, scm.getEnvironment(), true);
GuiConsole con = new GuiConsole(doc);
con.setVisible(true);
其中scm是Kawa提供的Scheme类的实例,也就是我们的scm代码编译后运行的环境。
像Gambit-C一类编译类的Scm实现,直接和C混合着用虽然看起来不够美观。
但总比让FFI的部分复杂要好,毕竟C在内存管理和类型转换上比Java的鸿沟大。
另一个编译器Chicken是可以即当编译器也可嵌入当解释器用,不过Chicken的内存管理方式比较异类。
值得庆幸的是,两者都可以定义变量在GC时执行的过程,这样可以省写一些Free(不要和Close混淆哦,open/close是成对等价于with使用的)。
是嵌入使用,还是有FFI调用外部类,不同的实现有不同的方式的。此外,用C库的话,还有字符串编码问题要自行解决一下。
关于语言标准,IEEE出于简化考虑比R5RS少了eval和卫生宏,不过R5RS还没有module和record-type这两个很有用的组织代码的手段。
再如果仅仅是拿sexp当数据格式来使用的话,那就和使用什么实现没有关系了,手工解决即可。



剧本部分是拿以前的日志重写的,现在有点反胃了。
所有@开始的行已删除,现在算是一个纯文本了。
说实话,废话比以前多了,而且人物感觉更加薄弱。
在遥远的被阻隔的异世界
记忆之海
埋藏着记忆力淡去的痕迹
虽然显得遥远而迷茫
可是……

《遥远的记忆之海》

【Chapter 0】
这里是死后的世界,而年轻的我是记忆之海上的渡船人。
每天都会有亡灵抵达这里,来在这片汹涌的波涛下探寻往日的回忆。
虽然只是一些被遗忘的影像,这恐怕是对被阻隔在异世界的亡灵们有效的抚慰。
我将用这片小舟载着他们,驶向掩埋于他们意识的幻境之中,去探寻这份被遗忘的记忆。
不知道自己是如何开始这项职业的,也不知道是否在遥远的未来会有某个终结点。
大概我便会这么一直以这样平淡而幸福的方式生活下去吧——每天都可以期待不同的故事。
而自己就做好一个船夫好了,这点好奇心尚不会为自己的记忆增加多余的烦恼。

【Chapter 1】
【我】 坐稳呦~要出发了~
我在船尾向着船头走上来的一位老奶奶说道。
然后熟练而悠闲地划动起身旁的桨,让船缓缓却高速地飞向某个预定的水域。
海水在炫目却冰凉的天空下闪着光芒,一眼望去只能看见浅浅的海面。
目标抵达后,我让船平稳地停下而随意地顺着波浪起伏,然后向着船上老人站立的那一头说到——
【我】 你的记忆便保存在这里,在这片浑浊的水面之下。不过还有若干事项要知道——
【我】 在波浪起来的时候,要努力地往海底望,凭自己的坚定的意志去努力地望。
【我】 让自己的身躯仿佛为回忆包围、洗涤、沉浸,直到某一刻海水骤然变得清晰。
【我】 这样你便能看见深深的海底,看见那片保存着你的记忆的地方。
【我】 那是只属于你的地方,只有凭自己的力量才能看见,而别人的帮助对此无能为力。
而老人听见了我的话,点了点头,然后将视线远远的望着海平面的尽头。
她用手触摸着船的边沿,却一直没有敢低下头去将视线触及身旁水面的光芒。
虽然犹豫了一会,老人随后还是放弃了努力,也没有去尝试,转身向内在船头坐下。
【我】 就真的这样放弃了吗,这可是一个难得的机会,不需要那个世界的记忆了吗。
每个人只有一次机会来这里探寻活着时候的记忆,老人的行为多少让我不解。
【老人】 确实呢……
老人轻轻地应了声,然后坦然地点了点头,颤动着的嘴唇似乎有话要说。
我也暂且安下心来,在这水天包裹的空间里躺在船的一角,听着老人传来的言语:
【老人】 随着人生漫长的时光,我已经是一个年迈的人了。记忆力在一天天流逝,身体也一天天薄弱。
【老人】 变得不再有力气去触摸身边的世界中的幸福,而对周围事物的意识也越渐模糊。
【老人】 活着,自己却越来越难以感受到自己是存在着的。于是生命的最终一刻,便在完全不知觉中抵达了。
【老人】 过完了一生,纵然有坎坷或遗憾,可终究还是幸福的一生,可以让我安心于死后了。
【老人】 可是衰老的记忆力依旧是留下的残缺,对于自己最后的时光,竟然不能在心里珍藏着这份幸福。
【老人】 所以我便来到了这片记忆之海,想弥补这份残缺,想为自己寻找一份安慰。
【老人】 至少不论生后或生后,我想让自己明白,自己确实是幸福的生活着的。
【老人】 不过啊,果然我还是有这份幸福感便足够了呢。
【老人】 这种感受纵然已经被遗忘,也肯定在那个世界里曾经存在过吧。
我打量着对面的老者,觉得她是在害怕由记忆去触及内心的真实,不禁叹气感到遗憾。
老人在船头沉默地坐着,渐渐平静了略带激动的言语,我随后起身撑起船驶上回程之路。
伴着海平面上柔和而巨大的夕阳,船的划痕消失在身后的那片先前抵达过的水域,
这也同时告别了那里那些对于老人将永远被掩埋于海底的对往日的记忆与情感。
这过去的,便是一个普通的工作日,随着一天天的过去,我不久也就会把这天淡忘的。
因为这毕竟只是我不断往复着的类似的日子中的一天,一个没有源头也没有终点的记忆所背负的时光。
接下来一天的客户是一位中年男子,身体健壮没有疾病的样子,看上去是个生活中积极的人。
他是意外而死去的吧,真是遗憾呢,我简单地这样判断着。然后撑起船,又一起踏上一个新的旅途。

【Chapter 2】
船平稳地向预定的某地行去,今天的海面的波浪依旧缓和,我在船头悠闲地把着方向。
而他在船的另一头显出好奇,往四周那片行船偶然路过的水天之痕,不断地张望。
【我】 这途中附近不知是埋藏着谁的记忆,在无尽的记忆之海上,恐怕连我也可能不再会抵达这里。
我静静地坐在船的末端,以船夫的身份这样解释道,然后视线依旧向着遥远的目光不能触及的何处。
【中年】 好了,我是有点兴奋,毕竟是第一次来到记忆之海。如果这样做对航船有影响的话,我会注意的。
我能够感受到他一旁的视线,那似乎是一种寻求着言语上的联系的期待,这恐怕是出于他待人的热情吧。
【我】 我想知道,你为什么要用这唯一的机会,到这里探寻自己的记忆呢?你还没有到一个健忘的年纪。
【中年】 我来寻找记忆,并不是因为它们被我遗忘,而是因为它们所承载的时光已经离我而远去。
【中年】 我是想寻找一丝安慰——即使将来记忆变得淡去,记忆也曾经凭借着自我的存在而存在过。
【中年】 这也是那个生者的世界所留给我的痕迹,告诉自己往日的努力的意义所在,没有遗憾也是一种遗憾吧。
【中年】 那些记忆纵然不能在物质上于现在现在的我建立起沟通,但是分明就是我在这里可以依旧延续下的一种财富。
【中年】 虽然记忆显得飘渺但却是中真实,这也就是我来到记忆之海缘由,想在这里挖掘到的一份心灵中的宝藏。
船速已经变缓,这是即将到达预定的海域了,我向他做着关于探寻记忆的说明,引着他往船外沿的地方走去。
然后留下他一人等待海风的气息掀起记忆之海翻滚的浪花,祝福他的思绪将能够触及到脚下海水的彼端世界。
风与浪下船头的挺拔地站立着,在海天间映出一个厚实的身影,轮廓仿佛是一扇凭空为世界展开的门。
他的声音在海风之间,在倾诉着言语,在一层层的展开着他的过去——
【中年】 这是我的出生,这是我的父母,这是我的学校,
【中年】 我的成年,我的工作,我的老婆,我的女儿,我的事业,我的生活……
男人在回忆着他活着的经历,眼前海水的蔚蓝色里翻滚着幸福的味道,一丝腥味,又一丝甘甜。
在随后回程的航线上,他一直在向我分享着他在这里获得的满足——
【中年】 美好的期待一直在延续着,直到有一天,那天的一场意外的事故,让我只能告别那一切。
【中年】 回忆是以痛苦终结的,我想把这最后的时刻忘掉,可是又害怕失去了想守护的东西。
【中年】 我便这样犹豫着在这个死后的世界,后来想法开始有些坦然——
【中年】 记忆的存在并不是因为它们被记住,而是它们被经历过。
【中年】 记忆的痕迹即使随着时光淡去而似乎不曾有过,它们也不会消失依然存在。
【中年】 不经意间看到自己身体上留下的微小残缺,知道这便是一种以不可弥补的痕迹来保存着记忆。
【中年】 我想我脑海中的记忆也是一样的,是因为我曾今为着他们的存在而做出过什么。
【中年】 这便足够了,它们就是我在记忆之海下埋藏的一份财富,将永远为海天守候。
【中年】 所以,记忆里的东西无法改变,也不需要改变了,在现在这个世界里依然可以有新的记忆。
他只是说着他想说出来的事情,似乎不在意我是怎样漫不经心地听着,这样能否记住他说出的话。
在傍晚的时候,打量着我们周围海面似乎永恒不变的夕阳景色,我想——
他说出了现在的感受,这样便是让这种感受以与人共同的记忆的形式确认着存在,让自己能够保留下去。
不过即使这样,着对于我,仍只是不知过去与未来的时光里的一天,一个在永恒的时间轴上的一个渺小痕迹。
而接下来一天的客人是位年轻的学生,年龄似乎与我接近而略小,我依然只是职业地将他引上船。
今天的天空似乎有些异样的阴沉,不过不会影响到航行,于是这又将开始一个新的旅程。

【Chapter 3】
我控着方向,让船往预定的地点驶去,在有些阴沉的天空下划过淡淡的线条。
他和来到记忆之海的大多数人一样,在船的前头打量周围,以未知抚慰着未知,显得有些无措。
回忆的味道就是这样的吧,我也顺着他的视线向远方望去,心中划过这样的想法。
其实的船行不需要过多的体力操作,在今天格外低的天空之下,航行显得有些沉闷。
不过如果天空晴朗,这就是个同往日一样的航行了,充满生活的平淡的温馨,平淡便足够了。
我沉浸在自己的思绪中,随后忽然感到船身的一个摇晃,我看见船对面的那个身影站起身子。
他向我走来,我赶忙先稳定下船的航行,然后放松下身子。此时听见他说话的声音——
【青年】 您比我大吧,我可以叫你哥哥吗?
【我】 我已经是不在意自己的年龄了。
【青年】 那我就叫你哥哥吧!
【我】 这随便你。
【青年】 嗯,哥哥好!
【我】 ……
他在我一旁坐下,没有把刚才打招呼的热情继续下去,而是将视线转向远方,有些顾虑的样子。
【我】 来说你为什么要来到这里,是想寻找到怎样的记忆吧。
虽然他的举动让我感到有些奇怪,我还是试图以平静的语气挑起对话。
【青年】 不知道。
他把头转向我,带着年轻人的稚气。
【青年】其实我确实不知道,我没有想寻找的东西。
即使这样也不必要有多余的犹豫吧。
【我】 这里有记忆的宝藏哦,会有让人感到幸福的东西,不要为让自己可以努力的机会而犹豫。
【青年】可是那些记忆是我主动抛开的,它们让我感到难受,我却矛盾地又为一种缺失感来到这里。
【我】 好了,既然来到这里了,即使意外,也会找到些东西吧。
【我】 它们都曾今属于你,今后也依然是。想着抛弃,就可能会让自己失去更多的东西。
他看着我的眼睛,像在寻找一种希望。而航行也在这不知觉中驶近了目的地。
【我】 去吧,相信自己心中小小的愿望,在海浪之间寻找能够寻找到的东西。
【青年】 恩,谢谢哥哥。
他答应了,然后走向船的那头。站立在船的边沿上,在阴沉的海天之间,显得波澜壮阔。
而我一人在船的这头放松下身子,视线漫无目的地望向天空,意识到居然对着客人说出自己的想法。
我这是说给谁听的呢。一个陌生人?一个在这死后世界里再也不会相遇的人?还是说……我自己?
我在怀疑着自己举动的意义,是否就代表着自己已经做出或者将会做出一些多余的事情呢。
可是此刻我异样的感觉到,我的思绪与情感在被他联系着,从未有过的被一个人所联系着。
想着在此刻能为别人的困难添上自己的帮助,这同时也是在敞开心扉地能够去接受别人的帮助。
看到船头转过头来望着我,在脸上露出一个微笑,而我看着也在自己脸上回应着一个微笑。
两个人的微笑,未曾在这里奢望过的微笑,我意识到这是一个第一次在这死后世界里自己希望永远记住的东西。
忽然平静的一切被打破了,一个浪打在了船身上,他刚刚侧转的身子没有站稳,摇晃着向记忆之海里跌落下去。
在这一瞬间里,海风也变得巨大了,天空更加阴沉下去,而且似乎要发展往一个糟糕的方向。
此刻顾不上太多,我想我得救他。赶忙跑向他所在的船头,往波浪翻滚的海水里跳了下去。
我在下沉,身边被黑暗包围着。那是一片无尽的黑暗,我感到瞬间失去了重力,努力划着水却寻找不到方向。
周围也异样的安静,这是一个海面下无声的世界,时间的流淌似乎漫长,甚至凝结。
渐渐地我的心也在水中平静下来,我能感受到自己的呼吸,呼吸在这个海底并无异样。
恐惧之后这我才意识到,这是在一个死后的世界,一个已经不会再死去而离开的世界,
一个欣慰却又孤独的世界,一个没有失去也没有保留的世界,一个让记忆永恒封存的世界。
在这个黑暗无声的世界里,我顺着水流漂浮着,让意识随着身体漂浮着。
在记忆的海洋中以心灵去触摸着曾今,以及那些孕育着现在和未来的往昔时刻。
我能体会到在深海之下闪烁的幽幽光芒,像一个指引者在前方对我轻轻的召唤着。
我凭借着意志向光芒游去,让光点在眼前接近在身边扩散,觉得这样才能够拯救到什么。
这样才能够实现自己对他人的一个守候,一个哪怕在这死后世界已经显得多余的举动。
一种是哪怕只是出于内心原始的善良的淳朴的冲动,也要去带着落海的少年顺利的回来。
光芒弥散于海底,如同思绪飘荡在无尽的水中接受着温柔而永恒的抚慰,包裹在我的周围。
渐渐地,这些光点构成的屏障上清晰出一个影像,在向我讲述着什么。
在向我呈现着一个“生”所在的世界,一个在海底无尽的黑暗里心所体会的“光”所组成的世界。

【Chapter 4】
【青年】 真是一个空旷的操场啊。
耳边响起了青年的言语,轻轻地感叹着,然后声音又远去了。我想这是少年的记忆传递给我的信息吧。
在他的视角上,我以第一人称在看到了他的双手,和他眼前的整片操场。
接下来将在这个记忆构建的世界里,以一天天的经历,去体会着他的过去。
可是这只是视觉,他的意识以及他的存在感,却无法通过薄弱的纽带感觉到。
身体开始活动起来,由机械变得自然地走动着,向着教学楼那里去寻找人的踪影。
我的意识仅仅是随着身体漂浮着,在这个世界里不能左右什么,也不会有想去左右什么的愿望。
在阳光下曝露的身体,接触着这里的空气与水分,仿佛在由陌生不断变得亲近着。
与空旷的操场相比,教学楼因为人的踪迹,而显出格外不同的氛围。
身体继续往教室里走去,人的气息的存在让它移动着的脚步学会了自信。
同时身体也是在渴望着阳光之外的什么,让自己来到这人群中去寻找着。
身体在经历着成长,可是这样似乎仍缺少着什么,它所见到的人群都在它面前散开了。
当身体带着疑惑去走进下一个教室,带着或许会有改观的期望,依旧得到的是一个失望的结果。
【青年】 果然人们是讨厌我的,这个世界里已经不需要我的存在了。
此刻身体举动正是表达着他的意志,这让我清晰的感受到意识的存在,但是明白这种体验的阻隔。
之后,身体便失去了他本身的驱动,松软下来。重量压在了我的身上,而我只是依然麻木地站在教室中央。
刚才跑去教室外的人群开始渐渐返回,他们仿佛无视了我的存在,又回到了他们的日常。
我就这样站在教室里,近距离的带着身体逝去的愿望。去接触人群的气息,去沉浸于海洋的梦境之中。
可是,梦境最终将迎来黎明。
【同学】 刚才真是一个讨厌的人啊,就这么像无视我们的跑近教室来。”
是“讨厌”吗?一句声音之后,周围的声音也纷纷附和起来,成为这个狭小的教室里共通的话题。
我能感受到其中的恐惧,这正是我能从身体中所感受到的。
让我出于内心的害怕,从这个空间里,从这个人群中向外跑去,跑向一个与此隔绝的世界中。
我在遥远的地方大口的喘着气。驻足后望,那个教室,那片学校已经变成渺小的身影。
这已经足够远了,这已经是喊声不能再被传递到的距离了。我的心开始变得空荡荡的。
这是一种安心吗?我看着自己缓慢起落的脚步,在坚硬的水泥地面没有留下任何的痕迹。
我再去望那片远去的世界,一个希望着阻隔开的,一个永远只保留着不起眼的存在的世界。
我漂浮在这个梦境的世界,和一个已经属于我的身体,因为躲避着什么而肆意游荡着。
只到有一天,也是偶然而特别的一天,我似乎是感到孤单,感到厌倦了。
也似乎是出于好奇,决定再去一次那所学校,再次重拾起曾今想寻找的什么。
校门在眼前清晰了,操场在眼前清晰了,教学楼在眼前清晰了,曾今去过的那所教室在眼前清晰了。
自己觉得心中的愿望,去寻找一个未知到重要的东西的心愿,也这路途上变得清晰了。
这或许就是在凭借着海的梦境的经历,来记忆里所未填的空缺吧。
在那间教室的前,我敲了敲门走了进去,心里已经做好了接受各种意外的准备。
这不是躲闪着旁人视线,而是在寻找他人的帮助,寻找着一种重拾遗失的启示。
他站在教室门前,鼓起勇气地努力睁开眼,去接受着人群的目光。
身体在人群中肆意的走动着,人们并没有做出异样的反应。
身体想在人群中挑起话题,人们的意志中已经淡忘了他的痕迹了。
这我才发现,他所做出决定已经无法改变,关于那个让自己消失于此的决定。
他已经不再属于这个世界了,这一个他曾想抛开却一直未割舍的世界。
那我又将飘向何方呢,向着一个新的永恒的世界吗?
在意识在这个身体已经在远离我而去的时候,我又似乎不愿回到那片记忆之海上。
因为在我海的梦境中,在这死后的世界里,我是第一次意识到了我所希望寻找的东西。
我的意识回到的我的身体上,我闭着眼漂浮在黑暗的无尽的记忆之海的深处。
随着水流飘向我一个不知为何方的地方,一个永远将背负着记忆的地方。
在漫长的飘荡中,终于,我决定,睁开我的眼睛,去看看周围的世界。
去看看身边的世界,哪怕看到的依旧只是黑暗,去依旧能在世界里发现着什么。

【Chapter 5】
这是一片天空柔和的色彩,西斜的阳光透过玻璃照射在我面前的床铺上。
双手是棉被的触觉,鼻尖是医药水的味道,身边有机器在运转的声响。
这是一个空荡荡的病房,我孤单的一个人躺在中央。身体不能动,只能望着粉白的屋顶。
在这狭小的容器里,我感到内心的一阵寂寞与痛苦,因为孤单而在对外界恐惧而害怕着。
害怕着我的记忆里所寄托的想象,会成为自己的一种负担,会让自己面对着未知却只会守护着丝丝迷茫。
我闭上眼,想象自己正被水包围着,想象就在海底,在那片无尽的黑暗中。
希望再次抵达那个世界每天航行在记忆之海上,一直地去陪同着别人寻找着别人在寻找的东西。
于是在这样的孤单中,我的意识又变得模糊开始轻浮,再向一个遥远的地方飘去了。
直到忽然间响起清脆的敲门声,这让我回过神来,可是我仍害怕着不敢睁开我的眼睛。
我听出来是同班的同学来了,他们的话语声在翻滚着我的记忆,清晰着我的心跳。
这让我想到,我忽视了一些自己没有察觉的细节——
那片无尽的大海中也有一份属于自己的记忆吗,是否他们一直埋藏在那里而我却没有在意呢。
我是否也有过一丝小小的心愿要实现——在那个异世界中,也去寻找属于自己的那一份记忆呢。
那些记忆是一份仍然需要自己继续延续下去的记忆,它们还尚未到一个应该被海水所掩埋的时刻。
处在这个生者的世界里的我,是否只有那个异世界里才能找到唯一的归宿,而该早早的就去呢。
可是活着不该是一个被轻易淡忘着的概念,而让记忆独自在无尽深海之下,去忍受着永恒的没有终结的孤单。
是啊,刚才心头居然有抛弃“生”的世界的想法,自己觉得可笑。
去寻找活着的的自己的意义所在,才是对那个死后世界无尽时光最好的终结。
况且一直有人在为着我的“生”而努力呢,让我能够再次的活过来,而我竟想拒绝他人的心愿。
它们的努力让我能够有机会去真正地体会到自己内心的希望,这同时也是他人给予我的希望。
不论是给予的关心或者是给予的治疗,都是由这一切的努力才让我又回到了这个世界中。
【同学】 真希望你能够早点醒过来哦,和我们一起去看班级篮球赛。
熟悉的声音在面前在病房中弥散开来。
而我的内心出于一种固执,依然让自己的双眼紧紧闭着,用拒绝去回避心头残余的害怕。
【同学】 今天我们先走了,明天放学的时候还会来看你的。
然后是一个轻轻的关门声。
病房里恢复了先前的安静,又只剩下我孤单的一个人在这狭小的房间里。
此刻安静得如同深海的气息,我心头的另一种害怕又让自己猛地设法睁开自己的眼睛。
可是我发现自己的眼睛没能睁开,只是忽然有泪水的热度在脸颊上流淌开来。
我努力地张开口,努力地说着——
【我】 只是一个旅途,这几天里我去了一个遥远的地方,现在我已经回来了……
破碎的言语没有出声,只化作苦涩与甘甜,混杂着口角泪水的味道。
而所告别的旅途呢,
将依然安静地在一个遥远的地方延续下去,延续往彼世界中所不存在的尽头。

话说这种质量不高的应急式产物果然连自己都讨厌,当然GalGame是不应该用这样东西做剧本的。
还是去看 阿加莎 克里斯蒂 的小说去吧。。。
顺便觉得小野不由美的也不错。。。
我这里质量拙劣,仅此而已。。。

----
后来试了试html5+Biwascheme或Processing+Kawa或Processing+自己解析脚本,just work。