看到有位同学发帖秀 Rails 面试题。个人表示... 到目前为止,那些题目对我仍旧有压力... 正好让我也想起了之前遇到的一个 Ruby 问题。
class Class
def to_proc
proc {|x,y| new x, y }
end
end
[[1, "a"], [2, "b"], [3, "c"]].map(&Array) # => 请使用 Ruby 1.9 以上版本, 说出你的答案.
我不妨斗胆再对您的 Ruby 水平做个论断:(随便瞎扯,仅供参考)
如果你可以不执行代码输出结果 (而且不看我下面总结的内容), 在三分钟之内写出正确的结果,并且可以理清所有细节,那么你一定很牛!能涉及到这些 (偏门的) 的 Ruby 知识,而且到达如此深度,这已经可以说明一切了。
如果你直接看代码不明所以,执行输出结果后,五分钟之内想通,也不错啦!这需要非常熟悉 Ruby 才行的。偶不记得花了几分钟了,但肯定超过 5 分钟了。不过记得那会儿老婆在旁边看电视古装剧,麻烦得很。
如果你完全看得懂代码原义, 但是完全想不通为啥是这个结果... 不要灰心,大家都是这个阶段过来的,而且你的 Ruby 水平也是靠谱的。有时间可以试着深度研究下,或者参考下底下的知识点,再或者花点时间 Google 一下,也许就懂了呢?就算不懂也其实也没关系,可以先放下,过几个月再来看。每个人都在进步嘛。
如果你看不懂全部 代码原义, 这其时也不代表什么。你对 Ruby 不太熟悉罢了。不过,做项目之余,也许你该恶补 (或系统学习一下) Ruby 的基础知识了。
好吧,也许你猜出了结果了... 即使你完全不懂 Ruby....
不谈这道题的实用性的前提下,我认为这道题很有代表性,可以很好的考验一个 Rubyist 的以下诸方面关键的能力:
很少人会关注 new x,y 会返回什么吧? 这个测试让人蛋疼。 我觉得关键还是 &Array 相当于
if Array.is_a?(Proc)
Array
else
Array.to_proc
end
map { |x| Array.to_proc.call x }
貌似大家的关注点.... 怎么都跑到 Array.new 的参数上去了... 看来个人差异很大呀。
事实上这个例子,因为加了一个参数的缘故,貌似更加直白了,我之前看到这个例子的时候,是下面这样的。
class Class
def to_proc
->(args) { new args }
end
end
[[1], [2], [3]].map(&Array) # => 请使用 Ruby 1.9 以上版本, 说出你的答案.
我看了老半天, 才明白... new 的真正含义...
#13 楼 @zw963 你这个更简单了。这道题我就查了下 Array.new(3, "a")
的 API,本来以为是 [3, "a"]
没想到是 ["a", "a", "a"]
然后仔细看了一下 Array.new
,看来盲点很多啊。
原来这个帖子 http://ruby-china.org/topics/5645 有这个讨论。
其实楼主这个问题很不错的,在应用中有不少人经常用这个方法来处理map
中对象的转换和封装的。它可以更一般化
class Class
def to_proc
proc(&method(:new))
end
end
这样就可以根据需要随意的创建对象了,只有有对应的构造方法
[{:name => 'Tom'}, {:name => 'Jerry'}].map(&User)
或者做类型转换,
User.all.map(&UserWrapper)
哈 . 可当时第一次看到这代码,唯一的盲点是:self... 有点蒙,老以为怎么那么像 Csharp 中的 new 关键字... 可能是最近 CSharp 代码看多了吧。
事实上,这个问题也的确是在我查 Csharp 中的 lambda 的用法时,在 so 看到的。
看不懂,也不知道这个面试意义多大,看的懂的可能在语言底层的细节非常扎实,说明是一个非常注重细节理解的人。可能需要的工作岗位是要求编写非常细致的代码,对性能、安全性、稳定性要求很高的岗位。
早上就看到这个回复,因为在做事儿,扫了眼,根本没看明白。刚才有重新读了下。足足花了 20 分钟,把代码流程过了一遍,终于看明白了,而且有了不少心得体会,自觉又长进了一些。哈哈。
看来我的代码真的起到了 抛砖引玉
的作用,很明显比我的代码又复杂了不止一层呀,额外涉及到了许多知识点,对学习很有帮助,不过... 我那个够晦涩了,这个远比那个还要晦涩....
如果实际代码中,我可能会写下面的代码更直接一点
[{:name => 'Tom'}, {:name => 'Jerry'}].map {|e| User.new(e) }
另外有一个问题想请教你:
class Class
def to_proc
proc &method(:new)
end
end
User.to_proc # => #<Proc:0x00000001ab3848 (lambda)>
你明明用的是 proc &method(:new),为什么返回的却是 lambda ?
proc_object = proc {p}
p proc_object.lambda? # => false
proc_object = proc &method(:p)
p proc_object.lambda? # => true
可是方法定义是:
def to_proc
proc &method(:new)
end
proc 应该返回 Proc 才是呀!lambda &method(:new) 返回 lambda 才对呀。
你可以试试下面的代码:
class Class
def to_proc
proc {}
end
end
User.to_proc # => 不再是 lambda 了.
这正是我疑问的地方...
proc_object = proc &method(:p)
p proc_object.lambda? # => true
为什么这个会返回 lambda ?? 难道有什么猫腻?
上面那个返回 lambda, 还要下面代码有什么用?
lambda_object = lambda &method(:p)
puts proc {}
puts proc &lambda{}
puts proc &method(:puts)
puts proc &proc{}
puts proc &:puts
puts "=" * 50
puts lambda {}
puts lambda &lambda{}
puts lambda &method(:puts)
puts lambda &proc{}
puts lambda &:puts
puts "=" * 50
puts Proc.new {}
puts Proc.new &lambda{}
puts Proc.new &method(:puts)
puts Proc.new &proc{}
puts Proc.new &:puts
=>
#<Proc:[email protected]:1>
#<Proc:[email protected]:2 (lambda)>
#<Proc:0x874b078 (lambda)>
#<Proc:[email protected]:4>
#<Proc:0x874afec>
==================================================
#<Proc:[email protected]:7 (lambda)>
#<Proc:[email protected]:8 (lambda)>
#<Proc:0x874af10 (lambda)>
#<Proc:[email protected]:10>
#<Proc:0x874afec>
==================================================
#<Proc:[email protected]:13>
#<Proc:[email protected]:14 (lambda)>
#<Proc:0x874adf8 (lambda)>
#<Proc:[email protected]:16>
#<Proc:0x874afec
不同的用法只和默认的对象有关,从 behavior 来说,lambda 可以理解为匿名的 method,他们都有严格的参数个数的限制,但 proc 没有,这是 proc 的魔法。
想了一下想出来了,然后忍不住跑了跑,居然是对得……其实这题不大懂 Ruby 蒙也蒙的对吧。虽然挺有意思,不过个人比较反感面试考核这种题目。考点公司实际碰到的问题更好。
BTW,这种方法生成的 array,每个元素都是引用同一个对象,感觉没有什么实际意义,而且算是个坑……
re = Array.new 3, 'a'
re[0].object_id == re[1].object_id # true
步骤化解过程
[[1, "a"], [2, "b"], [3, "c"]].map(&Array)
[[1, "a"], [2, "b"], [3, "c"]].map {|size, obj| Array.to_proc size, obj }
[[1, "a"], [2, "b"], [3, "c"]].map {|size, obj| Array.new size, obj }
# => [["a"], ["b", "b"], ["c", "c", "c"]]
浇盆冷水,窃以为,这种题目在面试中,如果面试者是个刚从学校出来的学生,也许有点用,否则没多少用处,针对 lz 提到的六个要点,我宁愿一个个直接拿出来问待面试者的理解,然后再展开深入的了解待面试者做过的事情,对技术的理解,对碰到问题的处理方式,和队友的相处方式,我觉得,招聘需要关注很多方面,会做题,远不表示对知识的掌握
哈哈。其实,这道题的意义就在于:对六个要点一一分解,并吃透,并理解这些要点在这里例子中实际起到的作用。这绝不是一道给出答案就完了的题。能挖掘很多东西出来 (以上六点,又可以引申出不少东西来), 这正好可以作为你对面试者挖掘的起点,否则,你直接提出问题,而没有一个实际例子,这样很难描述以上 知识点
吧?
p.s.
好吧,其实从头到脚,我只是提了一句,看到有人贴 Rails面试题, 然后我想到之前遇到的一个问题
, 而且我标题也说了么... 是自测题~ 是楼上的各位 XD 硬要把这道题作为面试题。