??xml version="1.0" encoding="utf-8" standalone="yes"?>
单测试通过?/p>
]]>
有了freetype实现底层字体渲染Q我只需要处理一些布局Ҏ卛_Q其中要实现的有以下几点Q?br />
1、英、中字体
很多中文字体中的英文字体都比较难看,所以在X的字体配|中讄了一个字体顺序。我也可以学学,传递一个字体列表,拿到一个字W时Q按序从字体列表中查询Q查询不到时查下一个字体,q样可以实现英、中使用不同字体了?br />
2、分?br />D落分行要考虑C、英文不同的分割方式Q还有标点符P某引h点符号不能在行尾Q比如?lt;{)Q某些标点不能在行首Q比如?gt;Q,某些标点不能分割Q比如破折号Q,所以实际上要有一个分割算法,把段落分成一个个的标讎ͼ汉字直接分割Q英文按I格分割Q不能在行首的标点就分到前面单词里,不能在行分在后面的单词里?br />
3、对?br />寚w方式有左、中、右、两?Full Justification)q几U方式,目前大部分开源渲染库都不支持两端寚wQ这也是我要自己实现的主要原因。左、中、右只要计算Z行的所有字W宽度,再计出左边距即可。两端对齐则需要计每个单词的间距?br />
4、段首羃q?br />
原来设想在分D后直接加上全角I格Q不惌个空格在转成UNICODE~码Ӟ它的~码是\u0000Q不能获取到全角I格的宽度。于是把它设成字体高度,看了一下效果还好?br />
]]>
int[] c = [1,2,3];
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
c.length = 2;
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
c.length = 3;
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
c.length = 4;
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
}
它输出结果如下:
B7D19FB0, B7D19FB4, B7D19FB8,
B7D19FB0, B7D19FB4,
B7D19FB0, B7D19FB4, B7D19FB8,
B7D1CFA0, B7D1CFA4, B7D1CFA8, B7D1CFAC,
可以看到?行地址相同Q后面一行地址不同。ؓ什么?
D语言的数l分配是内存紧凑的,当减数l长度减时Q只需要修改切片大而不需要重新分配。当长度变大Ӟ也会查原来的~冲区是否够大,以确定是否需要重新分配空间。注意第2ơ操作时把长度恢复ؓ原来大小Ӟq真的恢复了原来的状态,后面长出来的元素会被初始化ؓ默认倹{?br />
再来看一个:
int[] c = [1,2,3];
int[] d = c;
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
foreach(inout int i; d){
writef(&i);
writef(", ");
}
writefln("");
d.length = 2;
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
foreach(inout int i; d){
writef(&i);
writef(", ");
}
writefln("");
d.length = 4;
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
foreach(inout int i; d){
writef(&i);
writef(", ");
}
writefln("");
}
在执行int[] d = c;以后Qd的确是和c׃n了存储区。不q在改变d的长度以后,它就和c分道扬镳了。所以int[] d = c不能理解为d是一个指向c的引用,它实际上创徏了一个新的数l对象,但ƈ不拷贝数l元素,它和int[] d = c[0 .. length]是等LQ都是数l切片操作?br />
q个问题让我困惑不已。比如你用char[]表示一个单词,用char[][]表示一行,char[][][]表示多行。如何引用这个单词?你当然可以每ơ用lines[i][j]Q但如果处理步骤很多Q这会不会看h很头大?
看上d该这样用:
char[][] line = lines[0];
line.length = line.length + 1;
line[length - 1] = ",";
可惜Ҏ前面的结论,q将无法影响到lines。如果找不到一个引用类型指向数l,有时候用v来还真是很麻烦。看h把Line/Word包装成类是个勉强凑合的主意。。?img src ="http://www.shnenglu.com/cpunion/aggbug/13418.html" width = "1" height = "1" />
]]>
指针的slicing操作和数lslicing语意是相同的?br />
通过slicing生成D数组Q比原来直接使用指针的好处是可以有边界检查?br />
最q刚好犯了这个错误,在用freetypeӞrender出来的位图数据直接用slicing生成数组保存h。由于slicingq不复制数据Q这样后面的render操作会覆盖前面的数据Q所以我保存的数l其实都指向同一个缓冲区。当释放face对象Ӟ~冲Z没了Q再讉K恐怕要D错误了?br />
q个是D文档中明描qC的,我却׃Ҏ间才排除q个错误Q写下来记录之~
]]>
int foo;
public:
this(int foo){
this.foo = foo;
}
void bar(){
writefln(foo);
}
}
void main(){
alias void delegate() DG;
DG dg = &(new Foo(1)).bar;
Foo[10] foos;
foreach(int i, inout Foo foo; foos){
foo = new Foo(i);
}
void** ptr = cast(void**)&dg;
foreach(Foo foo; foos){
*ptr = cast(void*)foo;
dg();
}
}
q种方式也不是我们所希望的,一般来说委托绑定到多个对象Ӟ因ؓ是取到某成员函数指针Q再q行l定。比如模拟一个ActiveSupport所扩展的一个ruby.Array#map用法Q?br />
class Foo{
int foo;
public:
this(int foo){
this.foo = foo;
}
void bar(){
writefln(foo);
}
}
class Array(T){
private:
T[] data;
public:
this(T[] data){
this.data = data[0 .. length];
}
void map(void function() func){
void delegate() dg;
void** funcPtr = cast(void**)&dg + 1;
*funcPtr = func;
void ** ptr = cast(void**)&dg;
foreach(T v; data){
*ptr = cast(void*)v;
dg();
}
}
}
void main(){
auto arr = new Array!(Foo)([new Foo(1), new Foo(2), new Foo(3)]);
arr.map(&Foo.bar);
}
是的Qdelegate内部保存?个指针,所以我们可以容易地hack它?br />
[注:上面的main函数中数l直接量赋给栈对象也是这个版本中新增的内容,昄只能用于static对象是很鸡肋的。这里简单带q不提。]
[注:上面q个map的模拟ƈ不是ActiveSupport的map扩展的全部用途,那个mapq是攉q回|q里只演C用语法。ActiveSupport中扩展的map调用语法是map(&:to_s)Q就可以攉到数l中所有元素调用to_s后的q回倹{]
2、给内嵌内的实例增加outer属性,指向外层对象?br />
class Outer{
class Inner{}
this(){
Inner inner = new Inner;
inner.outer.foo();
}
void foo(){
writefln("foo");
}
}
void main(){
Outer outer = new Outer;
}
q个Ҏ可能应用ƈ不是很广吧?br />
3、mixin多个析构函数?br />
this(){
}
~this(){
writefln("A::~A()");
}
}
template B(){
~this(){
writefln("B::~B()");
}
}
class C{
mixin A;
mixin B;
}
void main(){
C c = new C;
delete c;
}
q些析构函数会和mixin相反的顺序执行。我不明白的是,Z么不让mixin多个构造函敎ͼZ不让q些构造函数晚于被mixin的类Q上面的Cc)的构造函敎ͼq按mixinq来的顺序执行?
]]>
一、imagemagick:
http://www.cit.gu.edu.au/~anthony/graphics/imagick6/
可以l制文字Q不q中文好像不能自动断行?br />
二、vips
http://vips.sourceforge.net
使用pangol制文字Q中文可以断行,~少2端对齐功能。自׃改代码增加了调整行距功能Q做成ruby扩展库,amd64上用失败,原因待查?br />
三、freetype
http://vips.sourceforge.net
不依赖其它图?H口库,其它不熟悉,待查?br />
四、Graphite
跨^台的字体渲染库。待查?br />
搜寻已有数月Q目前看到的几个库都不太理想Qmac osx上可能比较专业,不过集成较困难?br />
Ҏ|站上的比较完整的字体绘制和布局斚w的资料:
http://developer.apple.com/documentation/Carbon/Conceptual/ATSUI_Concepts/index.html
其中布局斚w的专业知识:
http://developer.apple.com/documentation/Carbon/Conceptual/ATSUI_Concepts/atsui_chap3/chapter_3_section_3.html#//apple_ref/doc/uid/TP30000029-TPXREF157
其它资料Q?br />
]]>
2q前被迫使用linux作开发^収ͼ使用的是fedora core 2Q感觉一般。后来去掉图形界面运行服务器E序Q开发主要还是在windows上,有需要时puttyq上L作?br />
其后1q多Q安装过suse, ubuntuQ还有许多记不得名字的发行版Q感觉ƈ不好Qubuntu的界面主题给我印象比较深?br />
半年前正式开始在同事的鼓吹下试用gentooQ才发现q个安装最ȝ的发行版使用h却是最舒服的,特别是对于开发者来说。你能想到的语言、库Q基本上都可以直接在里面emerge刎ͼ而且总能保持最新版本,特别适合开发h员?br />
不过对于gentoopȝ不熟悉,也走了不弯路。网上的linux资料相当多,当然有很大一部分也是相当老,往往你照着某资料配|半天,才发现它已经q时了。最头疼的是界面化Q我惌的是一个至看得过ȝ界面Q不影响|页览。看着|上大堆的教E,不胜其烦Q一直没搞懂。其间在ubuntu、suse和gentoo之间摇摆了几ơ,后来因ؓsuse占用资源太多Q被我抛弃?br />
q时候已l对windows有点烦,又在rails的带动下安装了mac osxQ同时还安装了ubuntu和gentoo。mac osx下除了textmateq个~辑器还有点吸引力以外,其它部分没多少吸引我的了,命o行让我烦g巌Ӏ在linux下可以rm aa -rf或rm -rf aa来删除一个文Ӟ在mac osx下必M用后一UŞ式,自由惯了H然受到U束Q感觉真是不爽?br />
保留ubuntu主要是因为它可以完美支持我的W记本上所有硬Ӟ声音控制面板也支持,不过对于开发h员来_安装点开发包q真是麻烦,升也比较慢。其实后来才发现gentoo对硬件支持一点也不差Q只是不会用而已?br />
最qgentoo 2006.1发布Q安装以后就一直在使用它,除了界面_体字和无线|络没解决以外,倒也没什么问题。前几天H然开H,搞懂了所有Y件安装前都看看USE标志需求,把整个系l升U了一下,重新~译内核再安装无UK动,一切都很顺利,界面_体字竟然自己出来了Q只是浏览器里面没有_体。网上找了一下,原来因ؓ我安装的是bin版本Q中文支持都没有Q于是设|LINGUASQemerge安装源码版本Q终于搞定。就q个问题让我折腾了半年Q真是惭愧。接下来同样讄USE搞定vlc囑Ş界面、SCIMQrealplayer也没有以前那个段错误Qpgadmin也好了,q发现ubuntu里面的realplayer放不出来的一些电影可以在q里面放出来Qvlc+realplayer基本上可以搞定所有视频格式了。感觉一切都好hQ终于明白gentoo里面USE是最重要的,以前把它当成个可选项了,安装软g以前最好emerge -av一下看看有哪些USE需求。要早明白这个,也不用安装得q么辛苦了?br />
接着在邮件列表中一些朋友的帮助下,安装了gnome-volumn-managerQ放入光盘就能自动mountQ按退出键也能自动umountq弹出,和windows下一h便了Q连Ud盘和ipod也能很好支持。唯一遗憾是图形化的无U网l配|工兯没有安装上,虽然通过脚本也可以配|,但毕竟不是那么方ѝ开源社区最q几q在易用性上下了工夫,gentoo也有庞大的开发社区,惛_解决q个也不用多久了?br />
用过很多发行版,gentoo是我用得最辛苦的一个,却也是用得最心的一个?br />
贴点桌面抓图Q?br />
]]>
void main(){
{
static int[] arr = [1,2,3,4,5];
writefln(typeid(typeof(arr[0])));
writefln(arr);
}
{
static float[] arr = [1f,1,3,4,5];
writefln(typeid(typeof(arr[0])));
writefln(arr);
}
{
static char[][] arr = ["1","2","3","4","5"];
writefln(typeid(typeof(arr[0])));
writefln(arr);
}
}
数组cdq1个元素类型决定,cd不匹配将会生编译错误?br />
接着是多l数l:
void main(){
static int[][] arr = [[1,2,3,4], [4,5,6], [7,8]];
foreach(int[] sub; arr){
foreach(int i; sub){
writefln(i);
}
}
}
另一个特性是更强的typedef。原有的typedef强类型在某些情况下会产生混ؕ?br />
下面的代码摘?http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D.bugs&artnum=3843
typedef int Int1;
typedef int Int2;
void show(Int1 v) {
writefln("Int1: %d", v);
}
void show(Int2 v) {
writefln("Int2: %d", v);
}
void show(int i) {
writefln("int: %d", i);
}
void show(long l) {
writefln("long: %d", l);
}
void main() {
Int1 value1 = 42;
Int2 value2 = 69;
show(value1 + value2);
show(value2 + value1);
show(2 * value1);
show(value1 * 2);
show(value1 + value1);
show(value2 - value2);
show(value1 + 2);
show(3 + value2);
long l = 23;
show(value1 + l);
show(l + value2);
short s = 105;
show(s + value1);
show(value2 + s);
}
如上面代码所C。typedef定义出来的类型和原有cd的相同Ş式重载函数可以共存,q可以完成更强类型的重蝲QCQ+的重载还不能实现q个?br />
q个强类型的typedef好像原本支持,大概是运结果类型比较模p?br />
好处是显|见的。比如有一个Time和TimeIntervalcdQ它用来表示l对旉或相Ҏ间间隔;另有一个输出函数用来显C结果?br />
import std.string;
typedef long Time;
typedef long TimeInterval;
void output(Time t){
writefln("Time: " ~ toString(cast(long)t));
}
void output(TimeInterval t){
writefln("Interval: " ~ toString(cast(long)t));
}
void main(){
Time time = cast(Time)100;
TimeInterval interval = cast(TimeInterval)100;
output(time);
output(interval);
}
是的Q用上ȝ了很多,因ؓ我们试图用一个数值类型去表示多个矢量cd?br />
q里Time time = cast(Time)100不再只是100q个单的数|它还携带了Timeq个cd。TimeInterval interval = cast(TimeInterval)100也不只是100q个数|我们l它赋予了时间间隔的含义?br />
q可以想像得更开阔一些,用它定义旉、长度、面U、加速度、速度、温度等Q重载一些计函敎ͼ可惜Dq不支持全局操作W重载)Q这样就方便完成一些物理量的运了Q而且cd得到查,速度加一个整数值结果还是速度Q速度乘时间得到的是长度,旉减时间得到的是时间间隔,速度加时间将产生~译错误。。。。。。神奇的是这些类型可能都是一些简单类型,我相信它臛_可以保证q行效率不会太低。当然你用CQ+cM可以完成q些Qƈ且利用编译器优化让它的效率保持最高,甚至内联的结果就是简单类型的q算Q我q是更愿意用这单的cd来typedef。当然这可能需要写大量重复的函数重载Ş式,没有关系Q我想用模板和mixin应该可以化这一q程Q而且会有相当多的家伙们愿意用这U麻烦的形式来获得更“正”的~译查?br />
所以说QD语言的typedef的意义其实就是实C矢量cd?br />
又多想了一炏V?br />
强类型要Q语法糖也应该要。是不是可以借鉴一下ruby的语法,实现q种调用呢?
l = 1.m;
Time t = Time.now;
TimeInterval i = 3.hours;
免去了一些初始化的麻烦?br />
]]>
Z数据安全性考虑Q某些破坏性链接应该用posthQ比如一个删除记录的h?br />
除了脚本认以外Q服务端q需要post验证Q因本是可以l过的。想像你的页面上有一个删除链接,只作了客L脚本认Q老的scaffold生成代码有这问题Q,被google扑ֈ了,它一个请求就会让你的数据丢失?br />
rails对于q类h的处理,是通过verifyҎQ默认的scaffold生成代码有如下内容:
verify :method => :post, :only => [ :destroy, :create, :update ],
:redirect_to => { :action => :list }
只有posthӞdestroy才会被允许,如果是getQ就会被重定向到list?br />
二、实?/b>
我自己实C一个method_dispatchQ当h一?test/aӞ如果是getQ则会直接执行TestController#aQ如果是postQ则会执行TestController#a_postQa_post应该是protectedQ这样不会直接暴露给客户Qget/post׃格区分开来了?br />
method_dispatch现在是直接实现在ApplicationController中的Q代码如下:
protected
def self.method_dispatch(*methods)
before_filter :do_method_dispatch, :only => methods.flatten.map(&:to_sym)
end
private
def do_method_dispatch
if request.post? && respond_to?("#{action_name}_post")
eval("#{action_name}_post")
return false
end
end
end
׃ApplicationController里面的方法会被子cȝ承到Q所以必M格处理访问别?br />
使用如下Q?br />
method_dispatch :a
def index
end
def a
render :text => 'get a'
end
def b
render :text => 'get b'
end
protected
def a_post
render :text => 'post a'
end
def b_post
render :text => 'post b'
end
end
注意a_postQb_post要被保护h防止直接调用?br />
index.rhtml里面演示了用get和post的情况:
<%= link_to "Post a", {:action => 'a'}, {:post => true} %><br />
<%= link_to "Get b", :action => 'b' %>
<%= link_to "Post b", {:action => 'b'}, {:post => true} %><br />
rails在处理有:post => true参数的link_toӞ生成的代码如下:
this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; f.submit();return false;">Post a</a>
l测试上面代码工作情况良好,使用get讉K/test/aӞ昄get aQ用post讉KӞ昄post a。用get讉K/test/bӞ昄get bQ用postӞ昄get bQ因为bq没有用method_dispatch?br />
三、应?/b>
下面的posts_controller.rb是scaffold生成的:
def index
list
render :action => 'list'
end
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
verify :method => :post, :only => [ :destroy, :create, :update ],
:redirect_to => { :action => :list }
def list
@post_pages, @posts = paginate :posts, :per_page => 10
end
def show
@post = Post.find(params[:id])
end
def new
@post = Post.new
end
def create
@post = Post.new(params[:post])
if @post.save
flash[:notice] = 'Post was successfully created.'
redirect_to :action => 'list'
else
render :action => 'new'
end
end
def edit
@post = Post.find(params[:id])
end
def update
@post = Post.find(params[:id])
if @post.update_attributes(params[:post])
flash[:notice] = 'Post was successfully updated.'
redirect_to :action => 'show', :id => @post
else
render :action => 'edit'
end
end
def destroy
Post.find(params[:id]).destroy
redirect_to :action => 'list'
end
end
可以看到Q它d了verifyQ但actionq多Q需要在verify中维护一份对应方法名Q稍不留就Ҏ出现漏洞?br />
我把它修改如下:
method_dispatch :new, :edit, :destroy
def index
list
render :action => 'list'
end
def list
@post_pages, @posts = paginate :posts, :per_page => 10
end
def show
@post = Post.find(params[:id])
end
def new
@post = Post.new
end
def edit
@post = Post.find(params[:id])
end
def destroy
render :inline => <<-EOS
Are you sure?
<%= link_to "Yes", {}, :post => true %>
<%= link_to "No", :action => 'edit', :id => params[:id]%>
EOS
end
protected
def destroy_post
Post.find(params[:id]).destroy
redirect_to :action => 'list'
end
def edit_post
@post = Post.find(params[:id])
if @post.update_attributes(params[:post])
flash[:notice] = 'Post was successfully updated.'
redirect_to :action => 'show', :id => @post
else
render :action => 'edit'
end
end
def new_post
@post = Post.new(params[:post])
if @post.save
flash[:notice] = 'Post was successfully created.'
redirect_to :action => 'list'
else
render :action => 'new'
end
end
end
相应圎ͼq需要把new.rhtml中的action从create修改到newQ把edit.rhtml中的action从update修改到edit?br />
q样的修Ҏ必须使用posth的action隐藏hQ而相应的get操作是不修改或删除记录的Q如果以posthQ才会自动调用这些保护的Ҏ?br />
]]>
在其它语a里实现AOP的确比较ȝQjava要用到动态proxyQ如果是CQ+Q除了从源码上修改还真没好办法,aspectc是q么做的。那么ruby里面如何实现呢?
׃ruby是动态脚本语aQ运行期可以把一个方法改名,也可以构造一个字W串动态生成方法,那么实现q个׃是难事了?br />
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def execute_before(before_method, *methods)
methods.flatten.map(&:to_sym).each do |method|
alias_method "#{method}_old".to_sym, method
class_eval <<-eval_end
def #{method}(*args)
#{before_method}(*args)
#{method}_old(*args)
end
eval_end
end
end
end
end
使用时只需要在c里面includeq个模块p了,相当于mixin的功能?br />
def index
a(1)
b(1,2)
c(1,2,3)
render :text => 'hello'
end
protected
def log(*args)
puts "log: #{args.map(&:to_s).join(', ')}"
end
def a(a)
end
def b(a,b)
end
def c(a,b,c)
end
include ExecuteBefore
execute_before :log, :a, :b, :c
end
注意Q由于用execute_before时后面几个方法必要有定义,所以必L在后面,否则׃出错?br />
]]>
adapter: postgresql
database: myproject_development
username: postgres
password:
development_mysql:
adapter: mysql
database: myproject_development
username: root
password:
development:
development_mysql
test:
adapter: postgresql
database: myproject_test
username: postgres
password:
production:
development
正常q行没什么问题。后来发现在q行rake test作单元测试时会报错,把拷贝过来就没有问题。不qrubyonrails.com上不允许匿名提交bugQ还真麻烦?br />
另外发现config.active_record.schema_format = :ruby配置下,postgresql的timestamp字段默认值current_timestamp不能正确复制到数据库。经查它是用db:schema:dump复制下数据库模式Q再使用db:schema:load生成试数据库模式的Q这个模块ؓ了各数据库统一Q会L那些不一致的默认倹{解军_法是讄config.active_record.schema_format = :sql?img src ="http://www.shnenglu.com/cpunion/aggbug/12536.html" width = "1" height = "1" />
]]>
语言Q?br />haskell, lisp 函数式编E语aQ受cookoo鼓舞开始学习haskellQ加上haskell是实现pugs的语aQ看来学一下也是应该的。lisp有时间也要看看,当是折自qŞ。?br />erlang 分布式编E语aQ已有应用OpenPoker,作?strong>宗冥浩Q简?http://blog.mylkcn.net/senzung.php
prolog
感觉面向对象以后的语a没什么想象力了。?br />
目Q?br />osian on dsource.org
ddl on dsource.org
FP相关论坛Q?br />http://agiletao.com/thread.php?fid=31
http://ocaml.cn/
]]>
]]>
取消的理由是q个转换太隐晦了Q最好是昑ּ地标C出q种转换Q所以引入一个lazy关键字。D语言q在发展中,很多Ҏ都在尝试,q种修改也不是第一ơ了?br />
首先看看q个lazy?br />
上一版实Cq样一个特性:
writefln(msg());
}
log("Hello, " ~ "Li Jie! \n" ~ "Welcome!");
log的参数被隐式转化Z个委托,q样只有用到q个值的时候才真正求倹{?br />
׃q种隐式转化很容易Ş成陷阱,所以这一版改Z个lazy关键字,看v来要z一些了Q?br />
writefln(msg);
}
log("Hello, " ~ "Li Jie! \n" ~ "Welcome!");
log函数中用msgq个变量׃调用那个隐式的委托,要注意的是每ơ取msg的值都会执行这个委托,所以我觉得q个陷阱更大了,当然它把陷阱丢给~写代码的hQ而不是用代码的人,所以好坏还无从分L?br />
下面q点代码可以演示q个陷阱:
int b = a+1;
int c = a*3;
int d = a/2;
}
int bar(){
writefln("Call bar()");
return 12;
}
foo(bar());
看v来bar好像会执行一ơ,实际上这D代码会打印??Call bar()"Q原来用委托还可以看到一个显式的函数调用呢?br />
另一个member templatesҎ未见到文档Q猜惛_概是支持成员函数模板吧?br />
]]>
]]>
另一:
http://www.howtoforge.com/xen_3.0_ubuntu_dapper_drake
]]>
代码:
order = Order.find(1)
order.update_attribute(:status, 'finished')
假定orders表有10个字D,你只x新其中一个,但active record会生成一个更新全部字D늚SQL语句Q假定其中一个字D值长度是20KQ这个负担可能会有些重?
我尝试解册个问题,写了个简单的插gQ?
代码:
module ActiveRecord
class Base
def update_attribute(name, value)
update_attributes(name => value)
end
def update_attributes(new_attributes)
return if new_attributes.nil?
attributes = new_attributes.dup
attributes.stringify_keys!
self.attributes = attributes
update(attributes)
end
private
def update(attrs = nil)
connection.update(
"UPDATE #{self.class.table_name} " +
"SET #{quoted_comma_pair_list(connection, attributes_with_quotes(false, attrs))} " +
"WHERE #{self.class.primary_key} = #{quote(id)}",
"#{self.class.name} Update"
)
return true
end
def attributes_with_quotes(include_primary_key = true, attrs = nil)
(attrs || attributes).inject({}) do |quoted, (name, value)|
if column = column_for_attribute(name)
quoted[name] = quote(value, column) unless !include_primary_key && column.primary
end
quoted
end
end
end
end
attributes_with_quotes函数的参数搞q么复杂Q原因是我想即便是用q段代码替换库里面的部分Q也不媄响原有代码的正常功能?
可以单测试一下上面的例子Q它生成的SQL语句会简z很多,大概是这样子Q?
UPDATE orders SET "status" = 'finished' WHERE id = 1
已发现的BUG和修复:
1、没有调用validation (by cookoo)?/strong>׃原有代码调用saveQ而save被覆盖成有验证的代码Q所以具有验证功能。解军_法是增加一D代码:
module ValidationsFix
def
self.append_features(base)
#
:nodoc:
super
base.class_eval do
alias_method :update_attributes_without_validation, :update_attributes
alias_method :update_attributes, :update_attributes_with_validation
end
end
def
update_attributes_with_validation(new_attributes)
return
if
new_attributes.nil?
attributes = new_attributes.dup
attributes.stringify_keys!
self.attributes
=
attributes
if
valid?
update_attributes_without_validation(attributes)
else
return
false
end
end
end
end
ActiveRecord::Base.class_eval do
include ActiveRecord::ValidationsFix
end
]]>
详细信息可见Q?a >http://www.digitalmars.com/d/lazy-evaluation.html
它首先解决了一个存在于java中的日志问题Qjava里面一个写日志标准格式如下Q?br />
log.info("aaaa");
}
因ؓlog.info的参数求值可能媄响性能Q所以用这U繁琐的方式来降低关闭日志时的性能开销?br />
C/C++使用宏来解决q个问题Q唯一的问题是修改日志U别会导致项目必重~译?br />
[注:指的是用宏来定义日志U别的方式,使用其它动态修Ҏ志别的方式Ҏ能要求很高的项目来说可能不可接受]
D语言使用另一U方式来解决Q首先要用到“表辑ּ到委托的隐式转换”,下面是委托作为参数时的用方法:
writefln(dg());
}
foo( delegate char[] (){
return "Hello, World";
}
);
因ؓq个委托q不需要参敎ͼ而返回值可以推|所以在早先的一个版本里QD允许我们化这个过E:
writefln(dg());
}
foo({return "Hello, World";});
DMD 0.165允许我们更进一步:
writefln(dg());
}
foo("Hello, World");
q个字符串参C被隐式{换成一个委托?br />
现在可以用一LҎ处理日志Q在没有宏的pȝ中,日志函数一般格式如下:
{
if (logging)
fwritefln(logfile, message);
}
Z让它使用懒惰求D个特性,q里把这个函数的参数改ؓ委托Q?br />
{
if (logging)
fwritefln(logfile, dg());
}
从上面提到的内容我们知道使用它也很简单:log("My name is " ~ "Li Jie");
q个参数的求值就是在log函数里面完成的?br />
当然委托会增加一些开销Q在上面q个例子中,q个开销是在日志打开时执行委托所带来的,它增加了一ơ委托调用的开销Q不q好在打开日志功能Ӟ其它斚w的开销q大q委托调用。关闭日志时Q它不会带来开销Q它只是把字W串指针压栈改ؓ委托指针压栈?img src ="http://www.shnenglu.com/cpunion/aggbug/11517.html" width = "1" height = "1" />
]]>
一、移植C库到D的一般过E?/strong>
C使用头文件来处理W号依赖Q在D里面链接外部库文件时Q要使用extern (C)声明来引入符Pq是一个{换过E?/p>
如何转换一个C头文件到D文gQD文档的htomodule.html有详说明。一般的转换q程如下Q?
1、运行预处理E序处理掉头文g里面的宏?/p>
2、删除经q预处理以后的多余信息。由于C的头文g包含Q每个头文gl过预处理以后都会包含一些重复内容,我们需要剔除这部分内容Q通过查找行号卛_完成?/p>
3、{换相应声明到D声明Q这一步可以用一个c2hE序来完成?/p>
注意预处理程序处理完毕以后,宏函C及宏定义的常量会被去除,q可能不是你惌的,所以最好的办法可能是手工{换?/p>
另一U调用是在D里面调用动态链接库Q这需要你使用implib工具从动态链接库产生一?lib导入库文Ӟ然后生成D声明Q再~译链接卛_。如果是在linux下用共享库Q则只需要编写D声明文gQ然后直接链接即可?br />
二、调用C?/strong>
转换完毕以后Q就可以调用了。如果你只是要测试一下,可以只声明使用q的外部函数、变量即可?/p>
例如我们要编写Programming Ruby里面的一个Ruby Extension例子Q相应的D代码如下Q?/p>
和C代码很相伹{由于我们只使用了几个外部函数、变量,所以只需要声明这几个W号卛_Q?/p>
三、生成动态链接库(Windows DLL)或共享库(Linux so文g)
D语言在Windows上编写DLLQ除了要有D源文件以外,q要有DLL定义文gQ?/p>
q是一个通用的格式,只是一些描qC息,因ؓD中可以用export关键字导出符P所以不需要在q里声明导出函数Q只有在~写COM DLL时才会增加其它一些信息?/p>
另外׃D语言要初始化GC以及其它一些信息,所以还需要在DllMain里面调用初始化及l止代码。由于不同^台的初始化过E不完全相同Q这里我单封闭了一下不同^台的初始化代码:
现在可以为Windows~写初始化及l止代码Q?/p>
׃Linux׃n库ƈ没有标准的入口函?或是我不知道?Q这里用gcc扩展的初始、终止代码,不过是以C语言实现的:
现在可以试~译链接Q在Linux上编译命令如下:
你可以在irb下测试:
可以看到addLq回一个arrayQ与期望l果一致?/p>
使用gdc是因为dmd在linux上无法生成共享库?/p>
在Windows上的~译命o如下Q?/p>
ruby18.lib是用implib从msvcrt-ruby18.dll导出的,q个~译q程很顺利,不过不幸的是它运行有一些问题,大概是一些初始值错误,我暂时还没有扑ֈ原因。或怹应该试一下gdcQ不q我不知道如何从.DLL文g导出一个gdc支持的ELF格式的导入库文g?br />
四、项目打?/strong>
打算建立一个rubyd目Q除了{换ruby头文件以外,q要作一些扩展,比如转换Dcdrubyc,q方面已有借鉴Q比如dsource.org上的pyd目?/p>
׃以前在徏立项目方面有q失败经?asgard目׃兴趣转移和其它原因比如语法丑陋等而未能进?Q这ơ还是保守一些,先完成D声明的{换,我已l用工兯{换了所有头文gQ不q正如前面所_宏函数和宏常量都丢失了,所以需要重新手工{换?br />
五、其它问?/strong>
1、如何从.DLL文g导出一个gdc支持的ELF格式的导入库文gQ?strong>如果你知道可以告诉我Q先谢过了?/p>
2、dmd生成可执行文仉题不大,生成动态链接库或共享库有很大缺P特别是不能生成共享库Q我可不惛_找一个只能再Windows上正常运行的~译器。如何让它改q这些方面?
3、gdc使用dmd前端和gcc后端Q应该会成熟一些,不过一般会比dmd前端版本E低Q而且gdc发布版本不是很频J,大概4-5个dmd版本才会有一个gdc版本(初略计算)Q所以一些新Ҏ不能够及时加入q来?/p>