第一次尝试 Ruby 开发,写了 400+ lines 代码,硬是坑了自己一天
诚然,是自己学艺不精
说一说,今天到底遇到了什么坑
1) 数组#
Ruby 中的数组切片是 [begin..end]
, 在代码中有一处写成了 [index, count]
将近半小时才 debug 出来
还有更坑爹的一点 切片操作是包含尾部边界的
#####2) strip
Ruby 的字符串方法 strip
并不能去除指定的字符
查找 stackoverflow 的解决方案后,用往 String 类加了扩展
module StringExtensions
refine String do
def strip(chars=nil)
if chars
chars = Regexp.escape(chars)
self.gsub(/\A[#{chars}]+|[#{chars}]+\z/, "")
else
super()
end
end
end
end
用了 refinement
,避免 monkeypatch
3) 字符串定义#
定义字符串有三种
''
不会转义,写 Python 写惯了,不适应
""
转义
<<~HEREDOC HEREDOC
4) puts 和 print#
debug 做断点时遇到的, puts
会将 \n
这样的字符直接当换行输出
irb(main):006:0> arr = ["\n"]
=> ["\n"]
irb(main):007:0> puts arr
=> nil
irb(main):008:0> print arr
["\n"]=> nil
5) 内部类#
脑子真是抽风了,还写出了这种代码
class Template
def self.render
new.render
end
def common
puts 'common methods'
end
def render
CondTemplate.render
# Looptemplate.render
# ...
end
class CondTemplate
def self.render
common
end
end
end
Template.render
Output
test.rb:19:in `render': undefined local variable or method `common' for Template::CondTemplate:Class (NameError)
CondTemplate
是定义在 Template
内部,所以应该可以访问其方法。想想好像没有什么问题,平常又不是没写过闭包
def closure
def inner_func
puts 'this is inner'
end
def pass
inner_func()
end
method(:pass)
end
func = closure()
func.call
但是仔细想想,好像有点问题。于是用 Python 写了一遍,发现也会报错。但是 Java 是可以的
import java.io.*;
class OuterClass {
class InnerClass{
public String innerFunc(){
return outerFunc();
}
}
public String outerFunc(){
return "this is outer";
}
}
class Test{
public static void main(String args[]) {
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
System.out.println(inner.innerFunc());
}
}
根据一番 Google,这样写其实是为了完善多继承。而 Java 可以这样写,好像是因为原来没有 lambda
closure
这些,又不能多继承。所以为了增强 Java 的使用,引入了内部类来弥补。而 Python 是支持多继承的, Ruby 也有 Mixin 的对策。
详细的戳这里 Java 中引入内部类的意义?
回头要深究一下这个问题
#####6) 函数参数
Ruby 不支持这种写法
def func1(a, b=1, c=2, d=3)
puts "a=#{a}"
puts "b=#{b}"
puts "c=#{c}"
puts "d=#{d}"
end
def func2(*args, **kwargs)
func1(*args, **kwargs)
end
func2(10, 20, c=100, d=1000)
**
不会 unpack
到相应的参数中去
如何以正确的姿势传一个 hash 参数
不仅仅是这样
func1(1, c=100)
Output
a=1
b=100
c=2
d=3
替代方法
def func1(a, b:1, c:2, d:3)
puts "a=#{a}"
puts "b=#{b}"
puts "c=#{c}"
puts "d=#{d}"
end
func1(1, c:100)
但是这样不能这样传参 func1(1, 2, c:3, d:4)
Ruby 有没有可能跳过一个带默认值的参数,为下一个带默认值的参数提供值?