|| = (หรือเท่ากับ) หมายถึงอะไรในรูบี


340

รหัสต่อไปนี้หมายความว่าอะไรในทับทิม?

||=

มันมีความหมายหรือเหตุผลสำหรับไวยากรณ์หรือไม่

คำตอบ:


175

คำถามนี้ถูกกล่าวถึงบ่อยครั้งในรายการส่งเมลของ Ruby และบล็อก Ruby ที่ตอนนี้มีแม้แต่เธรดในรายการส่งเมลของ Ruby ซึ่งมีจุดประสงค์เพียงอย่างเดียวคือรวบรวมลิงก์ไปยังกระทู้อื่น ๆ ทั้งหมดในรายการส่งเมลของ Ruby ที่กล่าวถึงปัญหานี้ .

นี่คือหนึ่ง: รายการที่ชัดเจนของเธรดและหน้า | | = (หรือเท่ากัน)

หากคุณจริงๆต้องการที่จะรู้ว่าสิ่งที่เกิดขึ้นจะดูที่มาตรา 11.4.2.3 "ที่ได้รับมอบหมายโดยย่อว่า" ของที่ร่างจำเพาะทับทิมภาษา

เป็นการประมาณครั้งแรก

a ||= b

เทียบเท่ากับ

a || a = b

และไม่เทียบเท่า

a = a || b

อย่างไรก็ตามนั่นเป็นเพียงการประมาณครั้งแรกโดยเฉพาะอย่างยิ่งถ้าaไม่ได้กำหนด ความหมายยังแตกต่างกันไปขึ้นอยู่กับว่าเป็นการกำหนดตัวแปรอย่างง่ายการกำหนดวิธีการหรือการกำหนดดัชนี:

a    ||= b
a.c  ||= b
a[c] ||= b

ทุกคนต่างปฏิบัติกัน


2
ลิงก์ที่สองได้รับความเดือดร้อนจากบิตเน่า (ความคิดเห็นจากเมตาโดยstackoverflow.com/users/540162/nightfirecat )
Andrew Grimm

331
นั่นเป็นคำตอบที่ไม่ลึกลับมาก คำตอบสั้น ๆ น่าจะเป็น: || = b หมายถึงถ้า a ไม่ได้กำหนดไว้ให้กำหนดค่าของ b มิฉะนั้นปล่อยให้อยู่คนเดียว (ตกลงมีความแตกต่างและกรณีพิเศษ แต่เป็นกรณีพื้นฐาน)
Steve Bennett

20
@SteveBennett: ฉันจะไม่เรียกความจริงที่a = false; a ||= trueไม่ได้ทำในสิ่งที่คำตอบของคุณบอกว่ามันจะ "แตกต่างกันนิดหน่อย"
Jörg W Mittag

23
อาจมีการถามคำถามนี้บ่อยครั้งเพราะมีคนตอบว่าคำถามนี้ถูกถามบ่อยครั้ง
einnocent

8
ด้วยคำตอบนี้ง่ายต่อการดูว่าทำไมมีหลายกระทู้ หากคุณพยายามค้นหาคำตอบสำหรับคำถามนี้โดยใช้หมวกสามเณรคุณจะสังเกตเห็นว่าคำตอบทั้งหมดไม่ชัดเจน ตัวอย่างเช่นเมื่อคุณกำลังพูดสิ่งที่ไม่ใช่ ฉันแนะนำให้ปรับปรุงคำตอบของคุณและให้คำตอบง่ายๆสำหรับมือใหม่: a = b เว้นแต่
อาร์โนลด์โรอา

594

a ||= bเป็นผู้ประกอบการที่ได้รับมอบหมายตามเงื่อนไข มันหมายความว่าถ้าaจะไม่ได้กำหนดหรือfalseyแล้วประเมินbและการตั้งค่าaเพื่อผล หากaมีการกำหนดและประเมินความจริงอย่างเท่าเทียมกันbจะไม่มีการประเมินและจะไม่มีการมอบหมายใด ๆ เกิดขึ้น ตัวอย่างเช่น:

a ||= nil # => nil
a ||= 0 # => 0
a ||= 2 # => 0

foo = false # => false
foo ||= true # => true
foo ||= false # => true

ดูเหมือนว่าผู้ประกอบการที่ได้รับมอบหมายคนอื่น ๆ (เช่น+=) จะสับสนแต่ก็มีพฤติกรรมแตกต่างกัน

  • a += b แปลเป็น a = a + b
  • a ||= b แปลโดยประมาณเป็น a || a = b

a || a = bมันเป็นความใกล้ชวเลข ความแตกต่างคือว่าเมื่อaไม่ได้กำหนด, a || a = bจะยกNameErrorในขณะที่a ||= bชุดที่จะa bความแตกต่างนี้ไม่สำคัญถ้าaและbทั้งสองเป็นตัวแปรท้องถิ่น แต่มีความสำคัญถ้าอย่างใดอย่างหนึ่งเป็นวิธีการ getter / setter ของชั้นเรียน

อ่านเพิ่มเติม:


52
ขอบคุณสำหรับคำตอบนี้มันสมเหตุสมผลมากขึ้น
Tom Hert

havent ทำการค้นหามากพอ แต่ก็ยังไม่เข้าใจว่าทำไมคุณถึงใช้สิ่งนี้แทน a = a || ข อาจเป็นเพียงความคิดเห็นส่วนตัวของฉัน แต่ไร้สาระเล็กน้อยที่มีความแตกต่างนิดหน่อยที่มีอยู่ ...
dtc

2
@dtc h = Hash.new(0); h[1] ||= 2พิจารณา ตอนนี้พิจารณาทั้งสองเป็นไปได้ขยายVSh[1] = h[1] || 2 h[1] || h[1] = 2ทั้งสองนิพจน์จะประเมิน0แต่ครั้งแรกจะเพิ่มขนาดของแฮช บางทีนั่นอาจเป็นสาเหตุที่ Matz เลือกที่จะ||=ทำตัวเหมือนการขยายตัวครั้งที่สอง (ฉันใช้สิ่งนี้จากตัวอย่างจากหนึ่งในกระทู้ที่เชื่อมโยงกับคำตอบอื่น)
antinome

1
ฉันชอบคำตอบอื่น ๆ ว่ามันเจาะลึกแค่ไหน แต่ฉันชอบคำตอบนี้เพราะความเรียบง่ายสำหรับคนที่เรียนรูบี้นี่คือคำตอบที่เราต้องการ หากเรารู้ว่า | | = หมายถึงอะไรคำถามก็อาจจะถูกพูดต่างออกไป
OBCENEIKON

1
Fyi a || a = bยกNameErrorถ้าaยังไม่ได้กำหนด a ||= bไม่ แต่แทนที่จะเริ่มต้นและชุดมันa bนั่นคือความแตกต่างระหว่างสองเท่าที่ฉันรู้ ในทำนองเดียวกันความแตกต่างเพียงอย่างเดียวระหว่างa = a || bและa ||= bฉันรู้ว่าถ้าa=เป็นวิธีการก็จะถูกเรียกโดยไม่คำนึงถึงสิ่งที่aส่งกลับ นอกจากนี้ยังมีความแตกต่างเพียงอย่างเดียวระหว่างa = b unless aและa ||= bที่ฉันรู้ก็คือว่าคำสั่งประเมินnilแทนaถ้าaเป็น truthy มีการประมาณจำนวนมาก แต่ไม่มีอะไรที่เทียบเท่า ...
Ajedi32

32

คำตอบที่รัดกุมและสมบูรณ์

a ||= b

ประเมินวิธีเดียวกันกับแต่ละบรรทัดต่อไปนี้

a || a = b
a ? a : a = b
if a then a else a = b end

-

ในทางกลับกัน,

a = a || b

ประเมินวิธีเดียวกันกับแต่ละบรรทัดต่อไปนี้

a = a ? a : b
if a then a = a else a = b end

-

แก้ไข: ตามที่ AJedi32 ชี้ให้เห็นในความคิดเห็นสิ่งนี้จะเป็นจริงถ้า: 1. a เป็นตัวแปรที่กำหนดไว้ 2. การประเมินหนึ่งครั้งและสองครั้งไม่ส่งผลให้เกิดความแตกต่างในสถานะของโปรแกรมหรือระบบ


1
คุณแน่ใจเหรอ นี่ก็หมายความว่าถ้าaเป็นเท็จ / ศูนย์ / ไม่ได้กำหนดก็จะถูกประเมินสองครั้ง (แต่ฉันไม่รู้ Ruby ดังนั้นฉันไม่รู้เลยว่า lvalues ​​สามารถ 'ประเมิน' ได้หรือไม่ ... )
Steve Bennett

ฉันเห็นสิ่งที่คุณพูด สิ่งที่ฉันหมายถึงโดยสองบรรทัดที่เทียบเท่าคือสถานะปลายจะเทียบเท่าหลังจากประเมินทั้งบรรทัดแล้วหมายถึงค่าของ a, b และสิ่งที่ส่งคืน ล่ามทับทิมหรือไม่ใช้สถานะที่แตกต่าง - เช่นการประเมินหลายของ - เพื่อให้มีความเป็นไปได้ทั้งหมด มีผู้เชี่ยวชาญด้านล่ามทับทิมคนไหนบ้าง?
the_minted

3
มันไม่ถูกต้องนัก a || a = b, a ? a : a = b, if a then a else a = b endและif a then a = a else a = b endจะโยนข้อผิดพลาดถ้าaจะไม่ได้กำหนดในขณะที่a ||= bและa = a || bจะไม่ นอกจากนี้a || a = b, a ? a : a = b, if a then a else a = b end, a = a ? a : bและif a then a = a else a = b endประเมินaสองครั้งเมื่อaเป็น truthy ขณะa ||= bและa = a || bทำไม่ได้
Ajedi32

1
* การแก้ไข: a || a = bจะไม่ประเมินaสองครั้งเมื่อaเป็นจริง
Ajedi32

1
@the_minted the end state will be equivalent after the whole line has been evaluatedนั้นไม่จำเป็นต้องเป็นความจริง เกิดอะไรขึ้นถ้าaเป็นวิธีการ? วิธีการสามารถมีผลข้างเคียง เช่นกับpublic; def a=n; @a=n; end; def a; @a+=1; end; self.a = 5, self.a ||= bจะกลับ 6 แต่self.a ? self.a : self.a = bจะกลับมา 7
Ajedi32

27

ในระยะสั้นa||=bหมายถึง: ถ้าaเป็นundefined, nil or falseกำหนดที่จะb aมิฉะนั้นให้aเหมือนเดิม


16
โดยทั่วไป


x ||= y วิธี

หากxมีค่าใด ๆ ปล่อยไว้ตามลำพังและไม่เปลี่ยนค่ามิฉะนั้นจะตั้งค่าไว้xให้เป็นy


13

มันหมายถึงหรือเท่ากับ มันจะตรวจสอบว่ามีการกำหนดค่าทางด้านซ้ายจากนั้นใช้ค่านั้น หากไม่ใช่ให้ใช้ค่าทางด้านขวา คุณสามารถใช้มันใน Rails เพื่อแคชตัวแปรอินสแตนซ์ในแบบจำลอง

ตัวอย่างการใช้ Rails อย่างรวดเร็วซึ่งเราสร้างฟังก์ชั่นเพื่อดึงข้อมูลผู้ใช้ที่เข้าสู่ระบบในปัจจุบัน:

class User > ActiveRecord::Base

  def current_user
    @current_user ||= User.find_by_id(session[:user_id])
  end

end

มันตรวจสอบเพื่อดูว่ามีการตั้งค่าตัวแปรอินสแตนซ์ @current_user ถ้าเป็นมันจะส่งคืนซึ่งจะเป็นการบันทึกการโทรฐานข้อมูล หากยังไม่ได้ตั้งค่าเราจะทำการโทรแล้วตั้งค่าตัวแปร @current_user เป็นค่านั้น มันเป็นเทคนิคการแคชอย่างง่าย ๆ แต่ดีเยี่ยมเมื่อคุณดึงตัวแปรอินสแตนซ์เดียวกันในแอปพลิเคชันหลาย ๆ ครั้ง


8
นี่เป็นสิ่งที่ผิด โปรดอ่านRuby-Forum.Com/topic/151660และลิงก์ที่ให้ไว้
Jörg W Mittag

1
@Jo (umlaut) rg ฉันไม่เห็นว่ามีอะไรผิดปกติ ลิงค์ของคุณคือรายการลิงค์อื่น ๆ ไม่มีคำอธิบายที่แท้จริงว่าทำไมมันถึงผิดมันก็เหมือนกับการตัดสินคุณค่าในตอนท้ายของคุณ
eggmatters

คำตอบนี้ไม่ถูกต้องเพราะมันไม่เพียง แต่ก่อให้เกิดundefinedแต่ยังบนfalseและnilซึ่งอาจจะไม่เกี่ยวข้องcurrent_userแต่โดยเฉพาะอย่างยิ่งfalseสามารถ unexpectecd ในกรณีอื่น ๆ
dfherr

แม้คำตอบนี้อาจไม่สมบูรณ์ก็ตาม (ไม่ได้ผลสำหรับ nil / false) เป็นครั้งแรกที่อธิบายว่าทำไมคุณถึงต้องการใช้ || = ขอบคุณมาก!
Jonathan Tuzman


8

จะแม่นยำa ||= bหมายความว่า "ถ้าaจะไม่ได้กำหนดหรือ falsy ( falseหรือnil) ชุดaการbและประเมินผลการ (เช่นกลับ) bมิฉะนั้นประเมินa"

อื่น ๆ มักจะพยายามที่จะแสดงให้เห็นถึงนี้โดยบอกว่าa ||= bจะเทียบเท่ากับหรือa || a = b a = a || bสิ่งที่เทียบเท่าเหล่านี้อาจเป็นประโยชน์สำหรับการทำความเข้าใจแนวคิด แต่โปรดทราบว่าสิ่งเหล่านี้ไม่ถูกต้องภายใต้เงื่อนไขทั้งหมด ให้ฉันอธิบาย:

  • a ||= ba || a = b ?

    พฤติกรรมของคำสั่งเหล่านี้แตกต่างกันเมื่อaเป็นตัวแปรท้องถิ่นที่ไม่ได้กำหนด ในกรณีที่a ||= bจะตั้งaไปb(และประเมินb) ในขณะที่จะเพิ่มa || a = bNameError: undefined local variable or method 'a' for main:Object

  • a ||= ba = a || b ?

    เทียบเท่าของงบเหล่านี้มักจะสันนิษฐานว่าตั้งแต่เท่าเทียมคล้ายเป็นความจริงอื่น ๆย่อมอบหมายผู้ประกอบการ (เช่น+=, -=, *=, /=, %=, **=, &=, |=, ^=, <<=และ>>=) อย่างไรก็ตามสำหรับ||=พฤติกรรมของข้อความเหล่านี้อาจแตกต่างกันเมื่อa=เป็นวิธีการในวัตถุและaเป็นความจริง ในกรณีที่a ||= bจะทำอะไร (นอกเหนือจากการประเมินa) ในขณะที่a = a || bจะเรียกa=(a)ในa's รับ ตามที่คนอื่น ๆได้ชี้ให้เห็นสิ่งนี้สามารถสร้างความแตกต่างเมื่อการโทรa=aมีผลข้างเคียงเช่นการเพิ่มปุ่มลงในแฮช

  • a ||= ba = b unless a ??

    พฤติกรรมของข้อความเหล่านี้แตกต่างกันในสิ่งที่พวกเขาประเมินว่าเมื่อใดaเป็นความจริง ในกรณีที่a = b unless aจะมีการประเมินการnil(แม้ว่าaจะยังคงไม่ได้รับการตั้งค่าตามที่คาดไว้) ในขณะที่จะมีการประเมินเพื่อa ||= ba

  • a ||= bdefined?(a) ? (a || a = b) : (a = b) ????

    ยังคงไม่. งบเหล่านี้อาจแตกต่างกันเมื่อมีmethod_missingวิธีการที่มีอยู่ซึ่งจะส่งกลับค่า truthy aสำหรับ ในกรณีนี้a ||= bจะมีการประเมินเพื่อสิ่งที่method_missingผลตอบแทนและไม่พยายามที่จะตั้งค่าaในขณะที่defined?(a) ? (a || a = b) : (a = b)จะตั้งค่าaการและประเมินผลการbb

เอาล่ะเอาล่ะเพื่อให้สิ่งที่เป็น a ||= bเทียบเท่ากับ? มีวิธีที่จะแสดงสิ่งนี้ในรูบีหรือไม่?

อืมสมมติว่าฉันไม่ได้มองอะไรเลยฉันเชื่อว่าa ||= bเป็นหน้าที่เทียบเท่ากับ ... ( drumroll )

begin
  a = nil if false
  a || a = b
end

ยึดมั่นใน! นั่นเป็นเพียงตัวอย่างแรกที่มี noop มาก่อนหรือไม่ ก็ไม่มาก โปรดจำไว้ว่าฉันพูดก่อนหน้าa ||= bนี้ว่าไม่เท่ากับa || a = bเมื่อaเป็นตัวแปรท้องถิ่นไม่ได้กำหนด? ดีa = nil if falseเพื่อให้แน่ใจว่าaจะไม่ได้กำหนดแม้ว่าสายที่ไม่เคยดำเนินการ ตัวแปรโลคัลใน Ruby ถูกกำหนดขอบเขตไว้เล็กน้อย


ตัวอย่างที่สามเพิ่มเติมของคุณ:(a=b unless a) or a
vol7ron

1
@ vol7ron นั่นมีปัญหาที่คล้ายกันเป็น # 2 ถ้าaเป็นวิธีการมันจะถูกเรียกสองครั้งแทนที่จะเป็นครั้งเดียว (ถ้ามันคืนค่าความจริงในครั้งแรก) ซึ่งอาจทำให้พฤติกรรมแตกต่างกันหากยกตัวอย่างเช่นaใช้เวลานานในการกลับหรือมีผลข้างเคียง
Ajedi32

นอกจากนี้ประโยคแรกไม่ควรบอกว่ามอบหมายbให้aหรือไม่ rhs ยังคงกำหนดให้กับ lhs หรือกล่าวอีกนัยหนึ่ง lhs ยังไม่ได้กำหนดค่าของมันเพื่อ rhs?
vol7ron

a ||= bคำตอบที่ดีที่สุดที่ฉันพบบนอินเทอร์เน็ต ขอบคุณ
Eric Duminil

3

unless x x = y end

ยกเว้นว่า x มีค่า (ไม่ใช่ศูนย์หรือเท็จ) ให้ตั้งค่าเท่ากับ y

เทียบเท่ากับ

x ||= y


3

สมมติ a = 2และb = 3

จากนั้นa ||= b จะส่งผลให้aมูลค่าของเช่น2เช่นค่า

เช่นเมื่อประเมินค่าบางอย่างไม่ได้ผลfalseหรือnil.. นั่นเป็นเหตุผลที่มันllไม่ได้ประเมินbค่าของ

ตอนนี้สมมติว่า a = nilและb = 3และ

จากนั้นa ||= bจะส่งผลให้ 3เช่นbค่าของ

ในขั้นแรกให้ลองประเมินค่าของซึ่งส่งผลให้nil.. เพื่อประเมินbค่าของ

ตัวอย่างที่ดีที่สุดที่ใช้ในแอพ Ror คือ:

#To get currently logged in iser
def current_user
  @current_user ||= User.find_by_id(session[:user_id])
end

# Make current_user available in templates as a helper
helper_method :current_user

โดยที่User.find_by_id(session[:user_id])จะถูกไล่ออกถ้าหาก@current_userไม่ได้เริ่มต้นก่อน


3

a || = b

บ่งบอกว่าค่าใด ๆ ที่มีอยู่ใน 'a' และคุณไม่ต้องการที่จะเปลี่ยนแปลงมันให้ใช้ค่านั้นมิฉะนั้นถ้า 'a' ไม่มีค่าใด ๆ ให้ใช้ค่าของ 'b'

คำศัพท์ง่าย ๆ ถ้าด้านซ้ายถ้าไม่ใช่ null ให้ชี้ไปที่ค่าที่มีอยู่แล้วชี้ไปที่ค่าที่ด้านขวา


2
a ||= b

เทียบเท่ากับ

a || a = b

และไม่

a = a || b

เนื่องจากสถานการณ์ที่คุณกำหนดแฮชด้วยค่าเริ่มต้น (แฮชจะส่งคืนค่าเริ่มต้นสำหรับคีย์ที่ไม่ได้กำหนด)

a = Hash.new(true) #Which is: {}

ถ้าคุณใช้:

a[10] ||= 10 #same as a[10] || a[10] = 10

ยังคงเป็น:

{}

แต่เมื่อคุณเขียนมันอย่างนั้น:

a[10] = a[10] || 10

กลายเป็น:

{10 => true}

เพราะคุณได้กำหนดค่าของตัวเองที่สำคัญ10ซึ่งเป็นค่าเริ่มต้นที่เป็นจริงดังนั้นตอนนี้แฮชถูกกำหนดสำหรับคีย์10แทนที่จะไม่ทำการกำหนดในตอนแรก


2

มันเหมือนกับการเริ่มต้นที่ขี้เกียจ หากตัวแปรมีการกำหนดไว้แล้วมันจะใช้ค่านั้นแทนการสร้างค่าอีกครั้ง


2

โปรดจำไว้ด้วยว่านั่น||=ไม่ใช่การดำเนินการของอะตอมดังนั้นจึงไม่ปลอดภัยสำหรับเธรด ตามกฎของหัวแม่มืออย่าใช้มันสำหรับวิธีการเรียน


2

นี่คือสัญลักษณ์การกำหนดค่าเริ่มต้น

ตัวอย่างเช่น: x || = 1
สิ่งนี้จะตรวจสอบเพื่อดูว่า x เป็นศูนย์หรือไม่ ถ้า x ไม่มีจริงแล้วมันจะกำหนดค่าใหม่นั้น (1 ในตัวอย่างของเรา)

ชัดเจนมากขึ้น:
ถ้า x == nil
x = 1
จุดสิ้นสุด


อย่างใดอย่างหนึ่งnilหรือfalseไม่เท่านั้นnil
อเล็กซ์

2

|| =เป็นผู้ดำเนินการกำหนดเงื่อนไข

  x ||= y

เทียบเท่ากับ

  x = x || y

หรืออีกวิธีหนึ่ง

if defined?(x) and x
    x = x
else 
    x = y
end

2

ถ้าไม่ได้มีค่าก็จะได้รับการกำหนดค่าของX Yมิฉะนั้นจะเก็บค่าเดิมไว้ 5 ในตัวอย่างนี้:

irb(main):020:0> x = 5
=> 5
irb(main):021:0> y = 10
=> 10
irb(main):022:0> x ||= y
=> 5

# Now set x to nil. 

irb(main):025:0> x = nil
=> nil
irb(main):026:0> x ||= y
=> 10

1

ในฐานะที่เป็นความเข้าใจผิดกัน, a ||= bจะไม่เทียบเท่ากับแต่ก็จะทำงานเช่นa = a || ba || a = b

แต่นี่เป็นกรณีที่ยุ่งยาก ถ้าaไม่ได้ถูกกำหนดa || a = 42ยกNameErrorในขณะที่ผลตอบแทนa ||= 42 42ดังนั้นพวกเขาดูเหมือนจะไม่แสดงออกอย่างเท่าเทียมกัน


1

||= กำหนดค่าให้ถูกต้องเฉพาะเมื่อเหลือ == nil (หรือไม่ได้กำหนดหรือเป็นเท็จ)


คุณอาจหมายถึง 'กำหนดค่าให้กับซ้าย' แทนขวา
Maysam Torabi


0
irb(main):001:0> a = 1
=> 1
irb(main):002:0> a ||= 2
=> 1

เพราะaได้ตั้งไว้แล้ว1

irb(main):003:0> a = nil
=> nil
irb(main):004:0> a ||= 2
=> 2

เนื่องจากว่าaเป็นnil


วันที่ตอบคืออะไรที่นี่ ทำไมมันไม่แสดงปี?
ชีฟ

0
b = 5
a ||= b

สิ่งนี้แปลเป็น:

a = a || b

ซึ่งจะเป็น

a = nil || 5

ดังนั้นในที่สุด

a = 5

ตอนนี้ถ้าคุณเรียกสิ่งนี้อีกครั้ง:

a ||= b
a = a || b
a = 5 || 5
a = 5

b = 6

ตอนนี้ถ้าคุณเรียกสิ่งนี้อีกครั้ง:

a ||= b
a = a || b
a = 5 || 6
a = 5 

หากคุณสังเกตเห็นbค่าจะไม่ถูกมอบหมายให้aค่าจะไม่ได้รับมอบหมายให้จะยังคงมีa5

เป็นรูปแบบการบันทึกที่ใช้ใน Ruby เพื่อเพิ่มความเร็วของ accessors

def users
  @users ||= User.all
end

สิ่งนี้แปลเป็น:

@users = @users || User.all

ดังนั้นคุณจะโทรไปยังฐานข้อมูลเป็นครั้งแรกที่คุณเรียกวิธีนี้

การเรียกใช้เมธอดนี้ในอนาคตจะส่งคืนค่าของ@usersตัวแปรอินสแตนซ์


0

||= เรียกว่าผู้ประกอบการที่ได้รับมอบหมายตามเงื่อนไข

มันใช้งานได้=แต่ยกเว้นว่าถ้าตัวแปรได้รับการกำหนดแล้วแล้วมันจะไม่ทำอะไรเลย

ตัวอย่างแรก:

x ||= 10

ตัวอย่างที่สอง:

x = 20
x ||= 10

ในตัวอย่างแรกxตอนนี้เท่ากับ 10 อย่างไรก็ตามในตัวอย่างที่สองxถูกกำหนดเป็น 20 แล้วดังนั้นตัวดำเนินการตามเงื่อนไขจะไม่มีผลกระทบ xยังคงเป็น 20 x ||= 10หลังจากทำงาน


-2

a ||= bเหมือนกับคำพูดa = b if a.nil?หรือa = b unless a

แต่ตัวเลือกทั้ง 3 ตัวนี้แสดงประสิทธิภาพเดียวกันหรือไม่ ด้วย Ruby 2.5.1 สิ่งนี้

1000000.times do
  a ||= 1
  a ||= 1
  a ||= 1
  a ||= 1
  a ||= 1
  a ||= 1
  a ||= 1
  a ||= 1
  a ||= 1
  a ||= 1
end

ใช้เวลา 0.099 วินาทีบนพีซีของฉันในขณะที่

1000000.times do
  a = 1 unless a
  a = 1 unless a
  a = 1 unless a
  a = 1 unless a
  a = 1 unless a
  a = 1 unless a
  a = 1 unless a
  a = 1 unless a
  a = 1 unless a
  a = 1 unless a
end

ใช้เวลา 0.062 วินาที เร็วกว่าเกือบ 40%

แล้วเราก็มี:

1000000.times do
  a = 1 if a.nil?
  a = 1 if a.nil?
  a = 1 if a.nil?
  a = 1 if a.nil?
  a = 1 if a.nil?
  a = 1 if a.nil?
  a = 1 if a.nil?
  a = 1 if a.nil?
  a = 1 if a.nil?
  a = 1 if a.nil?
end

ซึ่งใช้เวลา 0.166 วินาที

ไม่ใช่ว่าสิ่งนี้จะส่งผลกระทบต่อประสิทธิภาพการทำงานที่สำคัญโดยทั่วไป แต่ถ้าคุณต้องการการปรับให้เหมาะสมสุดท้ายนั้นให้พิจารณาผลลัพธ์นี้ ยังไงซะ:a = 1 unless aง่ายต่อการอ่านสำหรับสามเณรมันเป็นตัวอธิบาย

หมายเหตุ 1: เหตุผลในการทำซ้ำบรรทัดการมอบหมายซ้ำหลาย ๆ ครั้งคือการลดค่าใช้จ่ายของลูปในเวลาที่วัด

หมายเหตุ 2: ผลลัพธ์จะคล้ายกันถ้าฉันa=nilไม่มีศูนย์ก่อนการมอบหมายแต่ละครั้ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.