吱
任何 C 或 Fortran 程序复杂到一定程度之后,都会包含一个临时开发的、不合规范的、充满程序错误的、运行速度很慢的、只有一半功能的 Common Lisp 实现。—— 格林斯潘第十定律
Paul Graham 后来给这个格言加了一个推论。
包括 Common Lisp。
包括 Erlang、Ruby、JavaScript 在内的高度灵活的动态语言,不免和 Lisp 的设计有很多相似之处。在这些语言的虚拟机上支持 Lisp 本身的语法其实相对来说并不麻烦。
其实用特殊字符写代码有个比较常见的用途是在 Android 开发中使用一本非 ASCII 字符的字典,比如中文甚至 emoji 来做混淆。。。而反编译工具遇到这些字符变量名会触发异常导致无法反编译成功
几个月前买了原版书还没怎么看。。。下了一单中文版。。。
惊了,我才知道搭建 gem 原来也是有脚手架工具了,每次都是手动一个个文件建出来的 0.0
感觉对显式定义 Type,然后对函数进行重载这种方法确实挺冗余的。虽然说静态类型是能提高代码分析质量的好方法,对提升性能能有很大的帮助。但在这上面还是很难和优雅之间找到一个平衡。比如
class TestClass
getter :value
def initialize(str : String)
initialize(str.to_i)
end
def initialize(@value : Int32)
end
def initialize(mixedA : Int32 | String, mixedB : Int32 | String)
initialize(initialize(mixedA) + initialize(mixedB))
end
end
用 Ruby 来实现的话可以写成
class TestClass
attr_reader :value
def initialize(*args)
@value = args.map { |v| v.to_i }.reduce(:+)
end
end
更新: 我错了,没想到 Crystal 完全支持这种写法。。。
class TestClass
getter :value
def initialize(*args)
@value = args.map { |v| v.to_i }.reduce(:+)
end
end
只是说性能没有完全定义全那么好。。。我觉得 Crystal 符合 matz 想在 Ruby 3 中实现的 Soft Type。也就是能类型推断的就推,不能推断的就不推。Crystal 里还是保留了 *args
这种写法的兼容,我要收回之前的批评。
#4 楼 @mizuhashi 其实还有些类似的框架,甚至有支持 SSR 啊什么的
#4 楼 @mizuhashi youchan/menilite
Opal 作者今年已经写了个类似 React 的东西了,今年 RubyKaigi 的 Keynote 之一。
其实比如说
class Demo
def initialize(n)
@secret = n
end
def get_binding
binding
end
end
k1 = Demo.new(99)
b1 = k1.get_binding
eval("@secret", b1) #=> 99
可以写成
class Demo
def initialize(n)
@secret = n
end
end
k1 = Demo.new(99)
k1.instance_variable_get('@secret') #=> 99
还可以写成
class Demo
def initialize(n)
@secret = n
end
end
k1 = Demo.new(99)
k1.instance_exec(&lambda { @secret })
其实除了 eval
以外的所有的元编程方法,都可以被认为是对 eval
大杀器的约束,限制其的一些行为。
因为 LeetCode 往你函数里输入的并不是 ['X..X','...X','...X']
而是 [["X", ".", ".", "X"], [".", ".", ".", "X"], [".", ".", ".", "X"]]
。
那个 Run Code Result 里会自动把 Input 的多维数组的第二维开始全部展开,非常迷。
count_battleships(%w(X..X ...X ...X)) # => 2
count_battleships([%w(X . . X), %w(. . . X), %w(. . . X)]) # => 4
在一开始 LeetCode 打给你的样例函数里
# @param {Character[][]} board
# @return {Integer}
def count_battleships(board)
end
就在注释里给你描述了参数是单字符组成的二维数组了。
另外被题主高超的数组下标加减法能力给搞晕了,一开始还没看懂代码到底在干什么。。。其实只要把 s.to_s
改成 s.join
就行了。
这个算法复杂度是 O(n) 的,理论上应该非常快,但是实测 109ms,比平均速度还要慢一些。因为为了能在一个字符串里操作,你把整个 board 重新生成了一遍。
花了五分钟,写了个 O(n) 的 DFS 解决方案,好久不写算法了,跑出来 75ms, beats 100.00% of ruby submissions。
# @param {Character[][]} board
# @return {Integer}
def count_battleships(board)
@board = board # Make it class visible for dfs to modify
@size_y = board.length
return 0 if @size_y == 0
@size_x = board[0].length
return 0 if @size_x == 0
count = 0
@size_y.times do |y|
@size_x.times do |x|
if @board[y][x] == 'X'
count += 1
dfs(x, y)
end
end
end
count
end
# Depth-first Search
def dfs(x, y)
return unless @board[y][x] == 'X'
@board[y][x] = '.' # Delete the pixel if searched
# Corner detection
dfs(x+1, y) unless x == @size_x - 1
dfs(x, y+1) unless y == @size_y - 1
end
不过其实可以不 DFS,按楼主扫一遍的思路的话,不操作数组也可以写,代码如下,
# @param {Character[][]} board
# @return {Integer}
def count_battleships(board)
board = board
size_y = board.length
return 0 if size_y == 0
size_x = board[0].length
return 0 if size_x == 0
count = 0
size_y.times do |y|
size_x.times do |x|
count += 1 if board[y][x] == 'X' && board[y][x+1] != 'X' && (board[y+1].nil? || board[y+1][x] != 'X')
end
end
count
end
跑出来也是 75ms, beats 100.00% of ruby submissions。复杂度一样的两个算法,DFS 那个会多写入和反复扫描几下,但会少判断几下,所以时间上总的来说是一样。
早上装 JRuby 的时候报了一屏幕的证书错误,我还以为是临时性抽风。。。结果下午试了一下还是这样,暂时先改 http 用了。。。但翻了苹果的公告,只查到对 StartCom 的一个 Free SSL 失去信任的公告,StartCom Class 1 DV Server CA 应该是不受影响的,暂时没有搞懂原因。
勾起来我对用过的一些日本企业的网站的回忆。。。这个前端的界面非常有。。。日本公司的感觉。
#22 楼 @xiaoronglv 是啊,上海有一段时间没搞 Ruby Tuesday 了,正好看到杭州在搞,就坐火车过来了。
#19 楼 @gwotzehsing Sinatra 用 thin 的话就已经相当于包了一层异步了。sinatra-synchrony 又不维护了。。。其实裸跑 hello world EM 本身倒是有性能限制。。。不过加上一些别的东西就不算限制了。之后会把数据库驱动都做一遍。。。至少会把我平时用到的东西尽可能都搞一下。
感谢诸位如此慷慨的 Star,人生第一次上 GitHub Trending 了。。。
以及感谢各位的意见 Benchmark 跟踪和路由匹配的重构都将会尽快
突然发现成为了过去 24 小时加 Star 最多的 Ruby 项目。。。受宠若惊。。。
👍
#\ -s puma
必须要加在 config.ru
文件的第一行才有效,其目的是让 rackup
命令变成 rackup -s puma
。。。加在第 15 行是没有用的。。。
#44 楼 @derekyxie 一般用非线性视频剪辑工具分分钟想黑苹果。。。
@jasl http://rubyconfchina.org 因为备案问题被挂了。。。但 http://2016.rubyconfchina.org 还可以用。。。
讲道理的话,Ruby 作为 Lisp 的方言,闭包是非常重要和基础的东西,否则就变成写了一手 Java 了。。。