设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
楼主: DeathKing
打印 上一主题 下一主题

[讨论] Ruby/RGSS Tips 每日一更 [技术区的版聊帖?]

  [复制链接]

Lv3.寻梦者

梦石
0
星屑
1050
在线时间
1564 小时
注册时间
2008-7-30
帖子
4418

贵宾

跳转到指定楼层
发表于 2010-8-26 10:30:17 | 显示全部楼层 回帖奖励 |正序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x


这个是一个偶然的想法,需要一定的试点。是这样的,这个帖子每天将会更新一些Ruby 或者 RGSS 的小技巧,这些技巧一般很简短,易于掌握。

细则如下:
  • 每天只能有一个新回复,其他请使用“点评”功能,补充请使用“编辑”功能。否则版主有权删贴。
  • 和水区版聊帖一样,先抢先得。
  • 每个tips不宜超过200字
  • 每月根据情况施予不同的表彰
  • 精华内容将被搜集、整理。
  • 不要重复。或者过于简略而含糊不清。
  • 转载或引用请注明原文或引用链接(有些会员可能无法发送链接)。



注意!
  • 本帖采用的是[倒序看帖],新的帖子在最上方。
  • 其他的问题将在以后补充。




点评

开个6R Ruby研究社好了 (笑  发表于 2010-8-27 23:03

See FScript Here:https://github.com/DeathKing/fscript
潜心编写URG3中。
所有对URG3的疑问和勘误或者建议,请移步至发布页面。
欢迎萌妹纸催更

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
549
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

9
发表于 2011-6-14 16:56:02 | 显示全部楼层

Ruyb 之 Block, Proc, Lambda

Block 不是对象,是Ruby的语言特性,近似于闭包(Closure)。
范例:
def meth
  res=  yield
  "Block called returns #{res}"
end
puts  meth do next “next_value” end    #Block called returns next_value
puts  meth do break “break_value” end   # break_vcowcuo错误哦alue
def my
  meth do return “reutnr_value” end
end
puts my ()      # return_value

红色部分就是 Block.

block 之 next
block中的 next [value] 导致 block结束,并返回[value]给调用函数。


block 之 break
block中的 break [value] 导致 block结束,并导致调用block的函数也返回,返回值是[value]。


block 之 return
block中的 return [value] 导致 block结束,并导致定义block的函数返回,返回值是[value]。



ProcProc 是Ruby 对 block的面向对象的封装。
范例:
def meth (&proc)
  res=  proc.call
  "Proc called returns #{res}"
end
puts  meth
do next “next_value” end    #Proc called returns next_value
puts eth do break “break_value” end   # 出错
def my
  meth do return “reutnr_value” end
end
puts my ()      # return_value

红色部分就是 Proc.

Proc 之 next
Proc中的 next [value] 导致 Proc结束,并返回[value]给调用函数。

block 之 break
Proc中不能使用break,这回导致异常。


block 之 return
Proc中的 return [value] 导致 Proc结束,并导致定义Proc的函数返回,返回值是[value]。


LambdaLambda 是Ruby 对 Proc进一步的封装。
范例:
def meth (&proc)
  res=  proc.call
  "Lambda called returns #{res}"
end
def my
  meth (&lambda do return “reutnr_value” end)
end
puts my ()      # Lambda called returns return_value

红色部分就是 Lambda.
Lambda 和 Proc的区别就在 Lambda中的 return 导致 lambda 函数结束,并返回调用lamdad的函数(Proc和Block都是从定义的它们的函数放回)


Block,Proc,Lambda的区别总结
  • Block 中 用next从自身返回,用break从调用它的函数中返回, 用 returnc从定义它的函数中返回;
  • Proc 是对Block的面向对象封装,不支持breaky用法 ;
  • lambda是对Proc的封装, Lambda中return等同于next;
转载自http://www.cnblogs.com/napoleon_liu/archive/2009/11/25/1610638.html

点评

lambda更像方法,return从自身跳出。  发表于 2011-6-24 16:20
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
549
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

8
发表于 2011-4-8 07:57:58 | 显示全部楼层
Ruby命名参数

在设计一个大型库的时候,由于一个方法传递的参数可能很多,而参数默认值会有顺序的限制,如果我们要传递比较靠后的一个参数的值,那么就要把前面的一起传递进去,不太方便,这时我们希望能直接指明要传递哪个参数

Ruby没有原生的命名参数,但是可以使用Hash传递时的语法糖来达到类似命名参数的效果

例如我们想创建一个Window类(与RM的不完全相同,只是举例),在初始化时可以提交很多值,其中x,y,w,h是必填,然后还有些z, windowskin等属性
  1. class Window
  2.   def initialize(x, y, width, height, params)
  3.     self.x = x
  4.     self.y = y
  5.     self.width = width
  6.     self.height = height
  7.     self.z = params[:z] if params[:z]
  8.     self.windowskin = params[:windowskin] if params[:windowskin]
  9.   end
  10. end
  11. @window = Window.new(0, 0, 100, 100, :windowskin => "window")
复制代码

点评

->DK,函数里num.is_a?(Fixnum)可以么? 参数*arg,就能用*arg[x]。(不过还是Hash好用些...)  发表于 2011-4-15 14:45
@DK 有一定的意义,相当于有了多重分派(见本主题之前某贴)的好处。但实际上 Ruby 的反射以及灵活的参数列表足矣,无须进一步复杂化使解释器实现  发表于 2011-4-15 04:27
->DK 我记得在看The Ruby Way的时候提到过一个库,实现契约式设计的,在方法开头加入对参数的验证,不只是能验证类型 还能限制范围assert a, Positive之类   发表于 2011-4-9 07:06
->D7 不用*,最后一个是个Hash对象  发表于 2011-4-9 07:04
def initialize(x, y, width, height, *params) ?  发表于 2011-4-8 23:31
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
549
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

7
发表于 2011-1-19 08:22:33 | 显示全部楼层

单例类

以下引用紫苏在73楼的发言
我个人认为使用最广泛的“单例类”这个名称并不好,因为这很容易和著名的单例类设计模式混淆。单例类设计模式是在设计类的时候保证其实例只有一个


所谓著名的单例类设计模式是指实例只有一个,例如内建的TrueClass FalseClass NilClass是单例类
在Ruby中单例类可以这么实现
  1. class Singleton
  2.   class << self
  3.     alias old_new new
  4.     def new(*args)
  5.       if @instance #可以用?:运算符或者逻辑或运算符||写成一句
  6.         @instance
  7.       else
  8.         @instance = old_new(*args)
  9.       end
  10.     end
  11.   end
  12. end
复制代码
而有另一些时候,我们希望的不是这个类只能有唯一实例,而是希望这个类的实例不会重复
例如有一个Game_Actor类(可能跟RM的不完全相同),有名字和其他属性,我们希望不会出现重名的两个角色
  1. class << Game_Actor #在RM默认脚本基础上,已经有了这个类
  2.   @all = {}
  3.   alias old_new new
  4.   def new(name, *args)
  5.     @all[name] || old_new(name, *args) #用逻辑或运算符的示例
  6.   end
  7. end
复制代码
这样第一次Game_Actor.new("拉尔夫")会生成一个新角色,第二次时直接返回第一次的
如果要用id标识唯一性,那么@all用数组即可
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
549
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

6
发表于 2010-11-17 16:19:31 | 显示全部楼层
逻辑表达式

Ruby把nil和false认为逻辑假,其余任何对象认为逻辑真

if 0
  print "0 is true"
else
  print "0 is false"
end

这在其他语言里一般会得到 0 is false,但是在Ruby里是 0 is true

可以利用这个特性来做一些有趣的简写

while line = gets
  print line
end

会把标准输入一行行打印出来,直到文件尾


由于if不一定必须为true和false,而是可以使用任何对象,所以逻辑运算符也不会强制返回逻辑值,而是返回第一个决定逻辑值的对象


true and nil #=>nil
1 and "a" #=>"a"
false and true #=> false
false or nil #=> nil
&& 和 || 也有这一特性

比较常用的有个||=运算符,可以用来代替 a = x if a这样的语句

hash = {a: "b"}
hash[:a] ||= "c"
在想修改hash或数组的值,但是不确定那个键是否存在,并不想因此额外增加长度时使用
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
549
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

5
发表于 2010-11-3 16:22:25 | 显示全部楼层
与c等语言不同,ruby的整数大小没有限制,超过特定值后会自动变成Bignum

点评

换个说法:弱类型是在对某个对象进行操作的时候不检查类型,而强类型是必须检查类型才能成功执行。Ruby 的 duck typing 则是需要通过动态判断类型的  发表于 2010-11-4 21:01
超过50%以上的人认为 C 是弱类型,因为 C 的大部分数据类型可以进行隐式类型转换。  发表于 2010-11-4 20:58
弱类型是指可以隐式转换数据类型,Ruby 的 duck typing 并非隐式转换,你还是没弄清楚弱类型和动态类型的区别。动态类型语言,变量是没有类型的。  发表于 2010-11-4 20:56
a = 1 p a #=> 1 a = "1" p a #=> "1" 这个在强类型语言里是做不到的  发表于 2010-11-4 20:49
那么变量就只能指C底层的变量了...C是弱类型吗=.=  发表于 2010-11-4 20:46
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
549
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

4
发表于 2010-10-29 15:37:51 | 显示全部楼层

条件编译

原文:http://rpg.blue/thread-159531-1-2.html

对于一些不是很“动态”的条件分歧,例如对系统的判断等程序开始运行之后一般不会变的
if system_is_windows?
  def do
    #do_in_windows
  end
elsif system_is_linux?
  def do
    #do_in_linux
  end
end

由于ruby的一切都是运行时处理,而没有原生的预编译指令,所以这看起来不像预编译
但是想象一下RM的脚本架构(其他比较大的ruby工程也是像这样),在main之前,定义所有类和方法,这个过程可以近似的认为是编译
如果是做通用库,或者是需要大量执行的方法,效率会有一定提升(吗)

点评

本来我是想和 define? 一起用来解决一些纠结的事的。。。。  发表于 2010-10-29 17:05
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
549
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

3
发表于 2010-10-25 16:04:27 | 显示全部楼层
又自己抓出来一个ruby1.9小细节
p [1,2,3].to_s #=> "[1,2,3]"  in 1.9
p [1,2,3].to_s #=> "123"  in 1.8

数组的.to_s变成了以人类可读形式输出
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
549
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

2
发表于 2010-10-13 16:58:41 | 显示全部楼层
看紫苏大人讲了好多1.9特性,于是我也来弄一下。。。不过级别完全不够所以只说个自己用过的小细节

在1.8中,取string里的一个字符会得到一个整数,其值是那个字符的ASCII码,除非你是C语言控,否则你不会认为这是一项功能而是一个bug
指的庆幸的是在1.9这个缺陷得到了改变,取出的将是一个只包含那个字符的string对象

a = "ABC"
p a[0]
#=> 65 in 1.8
#=> "A" in 1.9

ruby1.9乃太萌了,紫苏大人给点资料吧- -最好有中文

点评

不知道 Programming Ruby 1.9 有没有被翻译成中文 = =  发表于 2010-10-13 19:56
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
549
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

1
发表于 2010-8-30 08:18:07 | 显示全部楼层

2010-8-30

重名陷阱

由于Ruby在语法上很人性化很自由,这也就带来了一些问题

例如
1.在方法调用中省略括号所引起的误会  注:标引用的部分引自Ruby手册
因为表示Range对象(或范围表达式)的.., ...的结合度较低(请参考操作符表达式),所以会引发下列错误
1..3.to_a
=> -:1: bad value for range (ArgumentError)
上面的代码会被解释成下面这个样子。
1..(3.to_a)
下面的代码不会得到预期的结果
p (1..3).to_a
因为它被解释成下面的代码。
(p (1..3)).to_a
p (true && true)    #=> true
p (true and true)   #=> parse error
p ((true and true)) #=> true
因为true and false被看作是语句,所以必须使用括号将其变为表达式的等价形式。同时,将它传给p的参数时还需要再加上一层括号才行。
p {1=>2}    #=> parse error (大括号被当作块)
p ({1=>2})  #=> {1=>2}
p (1=>2)    #=> {1=>2} (参数被当作哈希表)
p (1=>2, 3) #=> parse error    (只能把省略大括号的哈希表放在参数列表的最后)
p (0,1=>2)  #=> 0
                1=>2

2.运算符和方法的重名
a=1;
b = a+2;   # a 和 2 的和
b = a +2;  # 被解释成 a(+2)
b = a + 2; # a 和 2 的和

a = b = c = true
a?b:c       # 被解释成 a?(b(:c))
a ? b : c   # 条件操作符

3.变量和方法的重名
以小写字母开头的方法,可能与变量重名
  1. def a
  2.   1
  3. end
  4. p a #=>1
  5. a = 2
  6. p a #=> 2
  7. p a() #=> 1
复制代码
如果没有a这个变量,那么只p a就可以输出1
但是大写字母则不同,无论有没有同名常量,都必须加()
  1. def A
  2.   1
  3. end
  4. p A #=>出错
  5. A = 2
  6. p A #=>2
  7. p A() #=>1
复制代码
带等号方法
  1. def a=(val)
  2.   @a = val
  3. end
  4. a = 1
  5. p @a #=> nil
  6. self.a = 1
  7. p @a #=> 1
复制代码

点评

个人觉得空格不是一种好的习惯..因为可以代替空格的字符实在是太多了..  发表于 2010-12-28 09:35
这不是手册上的吗~~~话说第2点“运算符和方法的重名”在RM里试过了~~~欲知后事如何,自己试~~~  发表于 2010-9-30 11:36
受教了~原来还有这种事啊……看来好的编程习惯很重要啊~  发表于 2010-9-2 14:02
moy
空格果然是好东西.....  发表于 2010-8-31 00:30
看来要工整的写才行。。  发表于 2010-8-30 14:35
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
549
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

发表于 2010-8-27 08:39:48 | 显示全部楼层

2010-08-27 简略写法

p不是关键字,但是可以执行p 1正常输出1而不出错,为什么?
Ruby里调用方法时,如果不会产生歧义,则可以省略括号,使代码变得整洁美观
比如要输出一个跟RM里的用语【等级】同名的文件,可以简写成这样
  1. print IO.read Vocab.level
复制代码
这比完整写法
  1. print(IO.read(Vocab.level()))
复制代码
好看的多
但是一定要注意使用时的原则是不引起歧义,例如
  1. open File.expand_path "test.txt" , "w"
复制代码
就会出错,原因是参数"w"可能是expand_path的参数也可以是open的参数
所以必须加一层括号
  1. open File.expand_path("test.txt") , "w"
复制代码
Ruby中类似的简写除了括号之外,还有其他的,例如Hash
  1. p 1 => 2
复制代码
乍一看似乎是会Syntax,但是这一句是能执行的,输出{1 => 2}
这一特性在ruby的应用(窗口编程/网页)中使用得十分广泛

点评

只推荐用于单参数  发表于 2010-8-27 10:55
这样可能会一定程度降低可读性,使用时确保自己熟悉每个方法的参数  发表于 2010-8-27 09:08
点了回复的时候没看到嘛 >_< 结果就撞上了,不过今天入账2枚,收获颇丰啊。  发表于 2010-8-27 08:57
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-5-3 20:20

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表