&
常見使用&
的狀況如下
:007 > [1, 2, 3].map(&:to_s)
=> ["1", "2", "3"]
如果你的畫面中字體有分顏色,可以發現&
與:to_s
顏色不同。
Ruby中沒有&:
這個東西,其實是&
與symbol
的組合。
間單的回答通常就是&
生成{|nun|num }
。
:015 > [1, 2, 3].map {|int| int.to_s}
=> ["1", "2", "3"]
:016 > [1, 2, 3].map(&:to_s)
=> ["1", "2", "3"]
方法變參數的寫法。
:032 > [1, 2, 3].each(&method(:puts))
1
2
3
=> [1, 2, 3]
而比較準確一點的說&object
,&
與object
的關係是。
1.如果object
是proc
,&
會把proc
轉換成block
。
proc用多了會忘記block != proc
以下有兩種用法
def i_need_a_block(&block)
puts "所以需要call"
block.call
end
:005 > i_need_a_block {puts "Block here!"}
所以需要call
Block here!
還有介紹過的yield
def i_need_another_block
puts "我先不想看到&"
yield
end
:010 > new_proc = proc {puts "但是不能沒有&" }
=> #<Proc:0x00007fb0981cde78 (irb):10>
:011 > i_need_another_block(&new_proc)
我先不想看到&
但是不能沒有&
2.如果&
對象不是proc
,那就是&
會試圖調動對象內的to_proc
方法。
這是symbol
的to_proc
描述。
Returns a Proc object which responds to the given method by sym.
(1..3).collect(&:to_s) #=> ["1", "2", "3"]
如果不想深究,可以記住的確就是協助產生{|num| num }
這樣的block
。
如果有興趣。符號中的to_proc
的定義方式大概長得像這樣。
class Symbol
def to_proc
->(obj, args = nil) { obj.send(self, *args) }
end
end
下面的code出自於https://maximomussini.com/posts/ruby-to_proc/ 。
說明了converts it to a block.
names.map &:to_s
# We can expand it to &呼叫了symbol的to_proc
names.map &:to_s.to_proc
# Replacing "to_proc" with the result of calling the method
# 將上面的定義帶入
names.map &->(name, args = nil) { name.send(:to_s, *args) }
# "map" passes a single argument to the block, so we can simplify
# map本身就具將參數迭代可看一段
names.map &->(name) { name.send(:to_s) }
# Calling the method directly we get
names.map &->(name) { name.to_s }
# Since "&" transforms Procs and Lambdas to blocks, it's equivalent to
names.map { |name| name.to_s }
另外提到了一個重點。
There’s nothing special about the shorthand &:method syntax. Ruby arbitrarily defines Symbol#to_proc in a way that allows programmers to avoid some boilerplate.
是的。願意的話可以改寫to_proc
功能。
還可以看看&
的炫酷用法。
:043 > %w(abs msd sddf).map(&:size).reduce(&:+) #其實reduce裡的&還可以省略
=> 10
:033 > hash = {a: 123, b: 456, c: 789}
=> {:a=>123, :b=>456, :c=>789}
:034 > [:a, :b, :c].map(&hash)
=> [123, 456, 789]
Monkey patch
與meta programming
meta programming
是一個概念。meta programming
常被翻譯元程式設計
,程式設計大概懂,元
就....meta
曾經看過一篇文章,忘記出處了,解釋原文是希臘文,有之後
與超越
的意思在,後面衍生為很像是about
,例如metadata
== data about data
。
直接看兩句詞典的meta
例句:
It's a meta joke. It's sort of a joke about jokes.
這本身就是一個笑話。是一個關於笑話的笑話。
I am standing at my desk typing this about the media right now. It feels very meta.
我現在正站在辦公桌前打這篇關於媒體的文章。我感覺就是在寫自己。
很抽象,但看了這兩句就懂維基百科說的了。
維基百科
元程式設計(英語:Metaprogramming),又譯超程式設計,是指某類電腦程式的編寫,這類電腦程式編寫或者操縱其它程式(或者自身)作為它們的資料,或者在執行時完成部分本應在編譯時完成的工作。多數情況下,與手工編寫全部代碼相比,程式設計師可以獲得更高的工作效率,或者給與程式更大的靈活度去處理新的情形而無需重新編譯。
在Ruby這類動態語言且將資料都包裝成一個個類別,我們處理任何object
都是用Class
本身自己的程式方法去處理,各Class
已經將原本就抽象的object
特性封裝好了,就是一種meta programming
方式,且因為這種方式,Ruby也能將本身語言非常口語化。
:012 > "reverse".reverse
=> "esrever"
Monkey patch
是種描述。open class
也是前幾天code中,一直有在做的事情。
Ruby自由到已經內建好的Class也可以讓你修改。
:001 > [1, 2, 3].to_s
=> "[1, 2, 3]"
class Array
def to_s
self.map{|num|num.to_s} #這裡的to_s是Integer的to_s
end
end
:007 > [1, 2, 3].to_s
=> ["1", "2", "3"]
當然也會衍生到這類open
過的class_methods
應該集中某處避免debug
找不到,或是如何保留原本array.to_s
功能等。
不過針對Monkey pathch
於Ruby
就是非常簡單的,我們為了增加子類別功能或更改其中一個方法的作用,使用open class
這項這性,對子類別的某個與上層同名的功能做修改的行為。
當然有人說,Monkey pathch
屬於不好的操作,易造成程式碼雜亂,為了在執行層面得到正確資料,而對方法實施修改等。但學會將程式碼整理好,不為了交差隨便了事,才是成年人。況且,針對功能擴充應在於module
,open class
的用意是在讓親子層之間有所差異而操作。
判斷句縮寫,三元運算子
if aaa
bbb
end
=> return bbb if aaa #return可省略
if aaa
bbb
else
ccc
end
=> aaa ? (bbb) : (ddd) #()可省略,但是要注意有些方法不()起來會導致語法錯誤。
if aaa
bbb
elsif ccc
ddd
else
eee
end
=> aaa ? bbb :(ccc ? ddd : eee) #()我沒有勇氣省略...
關於Ruby
還有很多可以說。
但還是該進到Rails
部分了,雖然一些問題是從Ruby
衍生而來,但說明Rails
的部分,自然Ruby
也會說明到了。
今天的:Leetcode
392.Is Subsequence (指針題)
414.Third Maximum Number (單純語法熟練度題)
392.Is Subsequence
題目連結:https://leetcode.com/problems/is-subsequence/
題目重點:會達成true
,代表t
一定是a
的各元素中間穿插新的元素。
def is_subsequence(s, t)
end
puts ("abc", "ahbgdc") #=>true
puts ("axc", "ahbgdc") #=>false
畫圖時間,及我將例子更改為數字陣列。
[1, 6, 3, 7, 5] #=t
&
$ #慢指針 一開始設計為0
[1, 3, 5] #=s
#我們由t的指針當快指針
#index = 0
[1, 6, 3, 7, 5] #t第一個是1,請問s[0]是1嗎?
&
$
[1, 3, 5] #=s是的,那我+1,請你幫我檢查第2個。 index += 1
[1, 6, 3, 7, 5] #t第二個是6,請問s[1]是6嗎?
&
$
[1, 3, 5] #=s 不是,我不動,請繼續檢查。
[1, 6, 3, 7, 5] #t第三個是3,請問s[1]是6嗎?
&
$
[1, 3, 5] #=s 是,那我+1,請你幫我檢查第3個。 index += 1
[1, 6, 3, 7, 5] #t第四個是7,請問s[2]是7嗎?
&
$
[1, 3, 5] #no, next plz!
[1, 6, 3, 7, 5] #t第五個是5,請問s[2]是5嗎?
&
$
[1, 3, 5] #yes, index += 1。
t
如果超過五個,要繼續跑也沒關係,不可能再判斷出相等,index
也不會再+=
def is_subsequence(s, t)
index = 0
t.each_char do |str|
index += 1 if str == s[index]
end
index == s.size
end
414.Third Maximum Number
題目連結:https://leetcode.com/problems/third-maximum-number/
題目重點:是不是還記得Ruby
的max
可以抓指定前幾個大的。少於三個元素的回報最大的就好。max(?)太少用忘掉時,差點撞牆
def third_max(nums)
end
puts third_max([3,2,1]) #=> 1
puts third_max([1,2]) #=> 2
puts third_max([2,2,3,1]) #=> 2
題目第三個例子有提醒要uniq
,還有元素少於3個回最大
nums.max if nums.size < 3
nums.uniq.max
第三大的 == 抓前三取最小
nums.uniq.max(3).min
錯誤
def third_max(nums)
nums.size > 2 ? nums.uniq.max(3).min : nums.max
end
因為例子有[1,1,2]
。需要uniq。
可行的
def third_max(nums)
nums.uniq.size > 2 ? nums.uniq.max(3).min : nums.max
end
今天提到的
1.& 是什麼
2.meta programming
3.Monkey pathch
4.Is Subsequence && Third Maximum Number