æè¡é¨ã®ç¬¹ç°ï¼ko1ï¼ã¨é è¤ï¼mameï¼ã§ããã¯ãã¯ããã㧠Ruby (MRI: Matz Ruby Implementationããããã ruby ã³ãã³ã) ã®éçºããã¦ãã¾ãããéãããã£ã¦ Ruby ãéçºãã¦ããã®ã§ããã® Ruby ã³ããã¿ã§ãã
æ¬æ¥ 12/25 ã«ãã¤ãã« Ruby 3.0.0 ããªãªã¼ã¹ããã¾ãããä¸æ¨å¹´ãæ¨å¹´ã«ç¶ããä»å¹´ã Ruby 3.0 ã® NEWS.md ãã¡ã¤ã«ã®è§£èª¬ããã¾ããNEWS ãã¡ã¤ã«ã¨ã¯ä½ããã¯ä¸æ¨å¹´ã®è¨äºãè¦ã¦ãã ããï¼ãªã Ruby 3.0.0 ãããNEWS.md ã«ãã¡ã¤ã«åãå¤ãã¾ããï¼ã
- ããã¨èªã¿è§£ã Ruby 2.6 NEWS ãã¡ã¤ã« - ã¯ãã¯ãããéçºè ããã°
- ããã¨èªã¿è§£ãRuby 2.7 NEWS - ã¯ãã¯ãããéçºè ããã°
Ruby 3.0 ã¯ãRuby ã«ã¨ã£ã¦ã»ã¼ 8 å¹´ã¶ãã®ã¡ã¸ã£ã¼ãã¼ã¸ã§ã³ã¢ããã¨ãªãã¾ãï¼Ruby 2.0 㯠2013/02/24ï¼ãé«éåï¼Ruby 3x3ï¼ãéçå解æã並å並è¡ã®3大ç®æ¨ããããã¦éçºããã¦ããè¨å¿µãã¹ããã¼ã¸ã§ã³ã§ãããNEWS.mdã¯ããã¨æ·¡ã ã¨æ¸ããã¦ããã®ã§ããã®è¨äºãæ·¡ã ã¨æ¸ãã¦ããã¾ãã
ä»ã«ã Ruby 3.0 ã解説ãã¦ããè¨äºã¯ããã¤ãããã¾ããè¦ã¤ãããã®ã ããªã³ã¯ãç½®ãã¦ããã¾ãã
- Rubyã§åãã§ãã¯ï¼åããã¦ç解ããRBSå ¥é ?ãµã³ãã«ã³ã¼ãã§ãããï¼Ruby 3.0ã®ä¸»ãªæ°æ©è½ã¨å¤æ´ç¹ Part 1?
- ãµã³ãã«ã³ã¼ãã§ãããï¼Ruby 3.0ã®ä¸»ãªæ°æ©è½ã¨å¤æ´ç¹ Part 2 - æ°æ©è½ã¨å¤æ´ç¹ã®ç·ã¾ã¨ã
- Ruby 3.0 Advent Calendar 2020
ãªããæ¬è¨äºã¯æ°æ©è½ã解説ãããã¨ããããã¨ãªãããå¤æ´ãå ¥ã£ãèæ¯ãè¦å´ãªã©ã®è£è©±ãè¨æ¶ã®ç¯å²ã§æ¸ãã¦ããã¨ãããç¹å¾´ã§ãã
â è¨èªã®å¤æ´
ãã¼ã¯ã¼ãå¼æ°ã®åé¢
- Keyword arguments are now separated from positional arguments. Code that resulted in deprecation warnings in Ruby 2.7 will now result in ArgumentError or different behavior. [Feature #14183]
Ruby 3ã§ã¯ããã¼ã¯ã¼ãå¼æ°ãé常ã®å¼æ°ã¨ã¯ç¬ç«ããå¼æ°ã«ãªãã¾ãããããã¯éäºæãªå¤æ´ã«ãªã£ã¦ãã¾ãã
# ãã¼ã¯ã¼ãå¼æ°ãåãåãã¡ã½ãã def foo(key: 42) end foo(key: 42) # OK: ãã¼ã¯ã¼ãå¼æ°ã渡ãã¦ãã opt = { key: 42 } foo(opt) # NG: æ®éã®å¼æ°ã渡ãã¦ããã®ã§ã¨ã©ã¼ï¼2.7ã§ã¯è¦åä»ãã§åãã¦ããï¼ foo(**opt) # OK: ããã·ã¥ãæ示çã«ãã¼ã¯ã¼ãã«å¤æãã¦ãã
2.7ã§ã¯æ®éã®å¼æ°ããã¼ã¯ã¼ãå¼æ°ã«æé»çã«å¤æãã¦ãã¾ãããã3.0ããã¯ãã®æé»çå¤æãè¡ããªãããã«ãªãã¾ãããå¤ãã®ã±ã¼ã¹ã¯ä¸è¨ã®ä¾ã®ããã«ãfoo(opt)
ãfoo(**opt)
ã®ããã«æ¸ãæãããã§å¯¾å¿ã§ããã¨æãã¾ãã
ãªãããã¼ã¯ã¼ãå¼æ°ããæ®éã®å¼æ°ã¸ã®æé»çå¤æã¯ç¶æããã¦ãã¾ãï¼åé¤ããã«ã¯äºææ§ã®å½±é¿ã大ããããããï¼ã次ã®ã³ã¼ãã¯Ruby 3.0ã§ãåä½ãã¾ãã
# æ®éã®ãªãã·ã§ãã«å¼æ°ãåãåãã¡ã½ãã def foo(opt = {}) end foo(key: 42) # OK: ãã¼ã¯ã¼ãå¼æ°ãæé»çã«æ®éã®å¼æ°ã«å¤æããã # # âã¯åãã¾ãããä»å¾ã¯æ¬¡ã®ããã«æ¸ãã®ãããããã§ã # def foo(**opt) # end
ãã®å¤æ´ã«ã¤ãã¦ã®è©³ç´°ã¯ãæ¨å¹´ã®ãããã¨èªã¿è§£ãRuby 2.7 NEWSãããRubyå ¬å¼ãµã¤ãã®ç§»è¡ã¬ã¤ããåç §ãã¦ãã ããã
è£è©±
ããã®è£è©±ãèªãã ãã¨ã¨ã¦ãé·ãã®ã§ãããã¤ã¾ãã§ã
æ¨å¹´ã®è¨äºã§ãæ¸ãããã¨ã§ãããRuby 2.0ã§ãã¼ã¯ã¼ãå¼æ°ãæåã«å®è£ ããã®ã¯ç§ï¼é è¤ï¼ã§ããå½æã¯Ruby 1.8ã¨ã®é£ç¶æ§ã»äºææ§ãæèãããããããããç¡çã®ããè¨èªè¨è¨ã¨ãªã£ã¦ãã¾ããããã®ãããéç´æçæåãé »ç¹ã«å ±åãããï¼ãããæ¬è³ªçã«å£ãã¦ããã®ã§å ´å½ããçãªå¯¾å¿ããã§ããªãï¼ã¨ããè¨è¨ä¸è¯ã«ãªã£ã¦ãã¾ããããããã©ãã«ããããã¨ã¯ãRubyè¨è¨è ã®matzã ãã§ãªããèªåã«ã¨ã£ã¦ãç©å¹´ã®æ²é¡ã§ãã *1 ã
ã¨ã¯ãããå¤ãã®ã±ã¼ã¹ã§ã¯ãããªãã«æå¾ éãã«åãã¦ããæ©è½ãªã®ã§ã2.7ã§å¤æ´ãäºåããè¦åãå°å ¥ããã¨ãããæ°å¤ãã®æ²é³´ãä¸æºã®å£°ããããã¾ãããå¤æ´ã®å»¶æãä¸æ¢ãè¦éã«å ¥ãã¤ã¤ãRuby on Railsã®äº¤æµãµã¤ãã«matzãã¹ã¬ãããç«ã¦ã¦ãã¦ã¼ã¶ã®å£°ãç´æ¥èããã¨ã«ãã¾ããã延ã¹40件ã»ã©ã®ãã¾ãã¾ãªã³ã¡ã³ããããã ããã®ã§ãé è¤ããã¹ã¦ã®ãæè¦ãä½åº¦ãèªã¿è¿ããåé¡éè¨ãã¾ããããã®çµæããå¤æ´äºåã®è¦åãåºããã¨èªä½ãä¸æº *2ããå®åçãªå¯¾å¿ãã¦ãã¦ãå ±æããã¦ããªã *3ãã¨ãããã¨ãä¸æºã®æºæ³ã§ãåé¡ã®å¤æ´èªä½ã«ã¯æå¤ã¨ååããªäººãå¤ããã¨ããããã¾ãããããã§ãåè ã®åé¡ã«å¯¾ãã¦ã¯æåã®å¯¾å¿ã¨ãããã¨ã§ 2.7.2 ã§ããã©ã«ãã§è¦åãç¡å¹ã«ãã¾ãããå¾è ã®åé¡ã«å¯¾ãã¦ã¯ãã³ã¡ã³ãå ã§ä¸ããããåå¥ã®åé¡ã«å¯¾ãã¦å¯¾å¦æ¹æ³ãä¸ç·ã«èãã¦ããã¾ãããã¾ããè¦åãæè»ã«é表示ã«ã§ããdeprecation_toolkit gemãã¹ã¬ããå ã§å ±æããããã¨ã大ããã£ãã§ããä¸æ¹ã§Ruby on Railsæ¬ä½ã¯ï¼kamipoããã¨ããããã人ãamatsudaãããªã©ã®ãå°½åã§ï¼ãã¼ã¯ã¼ãå¼æ°ã®åé¢ã«æåãã¾ãããåé¢ã延æãããã¨Ruby on Railsã®ãªãªã¼ã¹ã¹ã±ã¸ã¥ã¼ã«ã«æªå½±é¿ã«ãªãå¯è½æ§ããã *4 ã¨ãããã¨ããã¢ãªã³ã°ã§ããã£ãã®ã§ãçèã«çèãéããä¸ã§ã3.0ã§å¤æ´ã決è¡ãããã¨ã«ãªãã¾ããã
ï¼æ責ï¼mameï¼
deprecatedè¦åãããã©ã«ãã§åºãªããã¨ã«ãªã£ã
- Deprecation warnings are no longer shown by default (since Ruby 2.7.2).
Turn them on with
-W:deprecated
(or with-w
to show other warnings too). Feature #16345
ãå»æ¢äºå®ã§ãããã¨ããè¦åã¯ååã¨ãã¦$VERBOSEã¢ã¼ãã§ãã表示ãããªããã¨ã«ãªãã¾ããããã¼ã¯ã¼ãå¼æ°åé¢ã®è¦åã ãã§ã¯ãªãããã¹ã¦ã®deprecatedè¦åã対象ã§ãã3.0.0 ããã§ã¯ãªãã2.7.2 ãå¤æ´ããã¦ãã¾ãã
åç¯ã§å»¶ã¹ãããã«ããã¼ã¯ã¼ãå¼æ°åé¢ã®çµé¨ããã£ããã§ãdeprecatedè¦åã®ãããããè¦ç´ãããããã§ããæã¯ååã¨ãã¦ããã¾ã$VERBOSEã¢ã¼ãã§ã ãè¦åãåºããã次ã«ç¡æ¡ä»¶ã§è¦åãåºãããæå¾ã«å¤æ´ãããã¨ãã3ãã¼ã¸ã§ã³ãçµã¦å»æ¢ãè¡ã£ã¦ãã¾ããããããããã¯å¤æ´ã¾ã§ã«æéããããããã«ãç¡æ¡ä»¶è¦åã®ãã§ã¼ãºã¯ã¨ã³ãã¦ã¼ã¶ï¼Rubyã§æ¸ãããããã°ã©ã ã使ãã ãã®ã¦ã¼ã¶ï¼ã«è¦ãã¦ãè©®ç¡ãè¦åãè¦ããã ãã«ãªãã®ã§ããã£ã¦ä¸ä¾¿ãã¨ãããã£ã¼ãããã¯ãå¤æ°å¾ãã®ã§ãç¡æ¡ä»¶è¦åãã§ã¼ãºããªããã¨ãããã¨ã«ãªãã¾ããã
ï¼mameï¼
å¼æ°å§è²ã®è¨æ³ã®æ¡å¼µ
- Arguments forwarding (
...
) now supports leading arguments. [Feature #16378]
ãã¼ã¯ã¼ãå¼æ°ã®åé¢ã®æªå½±é¿ã®1ã¤ã«ãå¼æ°ãå§è²ããã®ãããã©ãã«ãªããã¨ãããã¾ãããã®ãããRuby 2.7ã§ã¯å¼æ°ãå§è²ããããã®æ§æãå°å ¥ãããã®ã§ãããå¼æ°ãä¸åå¤æ´ã§ããªãã®ã§ä½¿ããã±ã¼ã¹ãéå®ããã¦ãã¾ããã
Ruby 3.0ã§ã¯ã次ã®ããã«ãå é ã®å¼æ°ãåãé¤ããããæ°ããå¤ã追å ããããããã¨ã許ãããããã«ãªãã¾ããã
def method_missing(meth, ...) send(:"do_#{meth}", ...) end
å é ã®å¼æ°ä»¥å¤ã¯ãã¯ãå¤æ´ã§ããªãã®ã§ãããããã ãã§ãå¤ãã®ã±ã¼ã¹ãæãããã¨ãã声ãåè¿°ã®ãã¢ãªã³ã°ã¹ã¬ãããªã©ã§ãèããããããå°å ¥ããã¾ããã
ï¼mameï¼
ãããã¯ããã¼ã¯ã¼ãå¼æ°ãåãåãå ´åã®æå³ã®æ´ç
- Procs accepting a single rest argument and keywords are no longer subject to autosplatting. This now matches the behavior of Procs accepting a single rest argument and no keywords. [Feature #16166]
ãã¾ãç¥ããã¦ããªãããããã¾ããããRubyã®ãããã¯ã®å¼æ°ã¯ä¼é殿ã§ãã
proc {|a, b| a }.call([1]) #=> 1 proc {|a, k:42| a }.call([1]) #=> 1
ä¸è¨ã®ããã«ã2å¼æ°ä»¥ä¸ãåãåããããã¯ã«é
åãã²ã¨ã¤ã ã渡ãã¦å¼ã³åºãã¨ãé
åã®ä¸èº«ãå¼æ°ã¨ãã¦è§£éããã¾ãããªã®ã§ãä¸è¨ã®ä¾ã§ã¯a
ã«[1]
ã§ã¯ãªã1
ãå
¥ãã¾ãããã®æåã¯autosplatãªã©ã¨å¼ã°ãããã¨ãããã¾ãï¼æ£å¼ãªæ©è½åãªã®ãã¯ç¥ããªãï¼ã
1å¼æ°ã®ãããã¯ã§ã¯autosplatã¯ããã¾ããã
proc {|a| a }.call([1]) #=> [1]
ã¾ããå¯å¤é·å¼æ°ãåãåããããã¯ã§ãautosplatã¯ããã¾ããã
proc {|*a| a }.call([1]) #=> [[1]]
ãã ããæ®éã®å¼æ°ã«å ãã¦å¯å¤é·å¼æ°ãåãåããããã¯ã§ã¯autosplatãããã¾ãã
proc {|x, *a| a }.call([1]) #=> [] # xã«1ãå ¥ããå¯å¤é·å¼æ°ã®aã¯ç©ºé åã«ãªã
æ£ç´ãautosplatã®æ¡ä»¶ã¯é è¤ãæ£ç¢ºã«ç解ãã¦ãã¾ããï¼ã³ã¼ããèªãã§ãç解ã§ãã¾ããï¼ãé常ã«ãããããæåã§ãããå¤ãã®å ´åã§ãã¾ãåãã®ã§ãçèã«çèãéããä¸ã§ãªãã¨ãªããããªã£ã¦ãã¾ãã
ãã¦ä»åã®å¤æ´ã¯ãå¯å¤é·å¼æ°ã¨ãã¼ã¯ã¼ãå¼æ°ãçµã¿åãããå ´åã®è©±ã§ãã2.7ã¾ã§ã¯autosplatãããã¦ãã¾ãããã3.0ããã¯autosplatããããªããã¨ã«ãªãã¾ããã
proc {|*a, k:42| p a }.call([1]) #=> [1] # 2.7 proc {|*a, k:42| p a }.call([1]) #=> [[1]] # 3.0
é£ããã§ããâ¦â¦ã
ï¼mameï¼
$SAFEåé¤
- $SAFE is now a normal global variable with no special behavior. C-API methods related to $SAFE have been removed. [Feature #16131]
å¤ã®ã»ãã¥ãªãã£æ©æ§ã§ãã $SAFE
æ©è½ã¯ãRuby 2.7 ã§å»æ¢ããã¾ãããï¼ããã¨èªã¿è§£ãRuby 2.7 NEWS - ã¯ãã¯ãããéçºè
ããã° ã$SAFE
ã®å»æ¢ãï¼ãã¾ã 対å¿ãã¦ããªãã³ã¼ãã«è¦åãªã©ãåºãããã$SAFE
èªä½ãç¹å¥æ±ããã¦ãä½ã代å
¥ããããè¦åãåºãããããã¯ä¾å¤ãåºããã¨ããæåã«ãªã£ã¦ãã¾ããããã®ãããªç¹å¥ä½¿ãã Ruby 3.0 ããããã¦ãæ¬å½ã«ãã ã®ã°ãã¼ãã«å¤æ°ã«ãªã£ããã¨ãããã¨ã§ãã
$SAFE = 42 # Ruby 2.7 ã¾ã§ã¯ãã¨ã©ã¼ï¼0 or 1 ãã許ããªãã£ãï¼ãRuby 3.0 ããã¯ç´ éã p $SAFE #=> 42
(ko1)
$KCODEåé¤
- $KCODE is now a normal global variable with no special behavior. No warnings are emitted by access/assignment to it, and the assigned value will be returned. [Feature #17136]
$SAFE
ã¨åããããªè©±ã§ãããRuby 1.9.0ï¼ããã¶ãã¨å¤ãã§ããï¼ããå¤ãè¨å®ãã¦ãä½ãæå³ããªãã£ã$KCODE
ã«ã¤ãã¦ãå¤ã代å
¥ãããåç
§ãããããã¨è¦åãã ãã¦ããã®ããRuby 3.0 ããã¯ç¹å¥æ±ãããªãããã«ãã¾ããã
$KCODE = 42 p $KCODE #=> Ruby 2.7 以å # warning: variable $KCODE is no longer effective; ignored # warning: variable $KCODE is no longer effective # nil # #=> Ruby 3.0 # 42
(ko1)
ã·ã³ã°ã«ãã³ã¯ã©ã¹å®ç¾©ã®ä¸ã§ã® yield
ãç¦æ¢ã«
- yield in singleton class definitions in methods is now a SyntaxError instead of a warning. yield in a class definition outside of a method is now a SyntaxError instead of a LocalJumpError. [Feature #15575]
次ã®ãããªã³ã¼ããã¨ã©ã¼ï¼LocalJumpError
ï¼ã«ãªãããã«ãªãã¾ããã
def foo class << Object.new yield end end foo{ p :ok } #=> :ok
Ruby 2.7ã§å»æ¢äºå®ã¨ãªãï¼ããã¨èªã¿è§£ãRuby 2.7 NEWS - ã¯ãã¯ãããéçºè ããã° ãã·ã³ã°ã«ãã³ã¯ã©ã¹ã®ä¸ã§ yield ã¯å»æ¢äºå®ã ï¼ãé å½ã«å»æ¢ããããã¨ããæãã§ãã
(ko1)
ãã¿ã¼ã³ããããæ£å¼æ©è½ã«
- Pattern matching is no longer experimental. [Feature #17260]
Ruby 2.7ã§è©¦é¨çã«å°å ¥ããããã¿ã¼ã³ãããã§ãããæ£å¼ãªæ©è½ã¨ãªãã¾ããã
å ·ä½çãªå¤æ´ã¨ãã¦ã¯ããã¿ã¼ã³ãããã使ãã¨åºã¦ããè¦åã 3.0 ã§ã¯åºãªããªãã¾ããã
case [1, 2, 3] in [x, y, z] end # Ruby 2.7 ã§ã¯è¦åãåºã¦ããï¼3.0 ã§ã¯åºãªãï¼ #=> warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!
ï¼mameï¼
å³ä»£å ¥ãå°å ¥ããã
- One-line pattern matching is redesigned. [EXPERIMENTAL]
=>
is added. It can be used as like rightward assignment. [Feature #17260]
ä¸é¨ã§å¾ æã®æ©è½ã¨ããã¦ãããå³ä»£å ¥ãå°å ¥ããã¾ããã
{ a: 1, b: 2, c: 3 } => hash p hash #=> [1, 2, 3]
ãã¦ãããã¯ãã¿ã¼ã³ãããã®ä¸é¨ã¨è¨ããã¨ã«ãªã£ã¦ãã¾ãããã£ã¦ãå³å´ã«ã¯ä»»æã®ãã¿ã¼ã³ãæ¸ãã¾ãããã ãä¸è¨ã®éããexperimentalã§ããã¨ããè¦åãåºã¾ãï¼ãã¿ã¼ã³ãåä¸ã®å¤æ°ã®ã¨ãã ãã¯å°å ¥ã確å®çãªã®ã§ãexperimentalè¦åã¯åºã¾ããï¼ã
{ a: 1, b: 2, c: 3 } => { a:, b:, c: } # warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby! p a #=> 1 p b #=> 2 p c #=> 3 { a: 1, b: 2, c: 3 } => { a:, b:, c:, d: } # NoMatchingPatternErrorï¼ãã¼ã¯ã¼ã `d` ããªãããï¼
è£è©±
èªåã¯å³ä»£å ¥ã®ä½¿ãã©ãããããããã£ã¦ããªãã®ã§ãããè¤æ°è¡ã«æ¸¡ãã¡ã½ãããã§ã¼ã³ã®æå¾ã«ä»£å ¥ããã¨ããªã©ã«ä¾¿å©ã¨ãã人ãä½äººãããï¼matzãå«ãï¼ã®ã§å°å ¥ãããããã§ããæ£ç´ãç¡çã«ä½¿ãå¿ è¦ã¯ãªãã¨æãã¾ãã
ããã¤ã注æç¹ã ãæ¸ãã¦ããã¾ãã
ãã¿ã¼ã³ãããã®ä¸é¨ã¨ãã¦å®ç¾ããã¦ãããããã¤ã³ã¹ã¿ã³ã¹å¤æ°ãªã©ã«å³ä»£å ¥ãããã¨ã¯ã§ãã¾ããï¼ã¤ã³ã¹ã¿ã³ã¹å¤æ°ã¯ãã¿ã¼ã³ã¨ãã¦æ¸ããªãã®ã§ï¼ã
{ a: 1, b: 2, c: 3 } => @a # SyntaxError
ã¾ããæ®éã®ä»£å ¥ã¨éã£ã¦ãè¿ãå¤ã¯å©ç¨ã§ãã¾ããã
ret = ({ a: 1, b: 2, c: 3 } => hash) #=> SyntaxError (void value expression)
ããã«ããã£ããå¼æ°ã«å³ä»£å ¥ãæ¸ããã¨ããã¨ããã¼ã¯ã¼ãå¼æ°ã«ãªã£ã¦ãã¾ãã®ã§æ³¨æã§ãã
foo(val = expr) # OK foo(expr => val) # NG: expr ããã¼ãval ãå¤ã¨ãããã¼ã¯ã¼ãå¼æ°
(mame)
ä¸è¡ãã¿ã¼ã³ããããåè¨è¨ããã
- One-line pattern matching is redesigned. [EXPERIMENTAL]
in
is changed to returntrue
orfalse
. [Feature #17371] [Feature #17260]
åé
ã®å³ä»£å
¥ã¯ãRuby 2.7ã§ã¯=>
ã§ã¯ãªãin
ã¨ããæ¼ç®åã§å°å
¥ããã¦ãããã®ã§ããããããæã£ãã»ã©ä½¿ãããªãããã¨ãããã¨ã§ãããå³ä»£å
¥ãããè¨æ³ã§å試é¨å°å
¥ãããã¨ã«ãªãã¾ããã
ããã¦in
æ¼ç®åèªä½ã¯ããããã®æå¦ãtrue/falseãè¿ããã®ã«å¤ããã¾ããã
{ a: 1, b: 2, c: 3 } in { a:, b:, c: } #=> true { a: 1, b: 2, c: 3 } in { a:, b:, c:, d: } #=> false # warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby!
Ruby 2.7ã«å¼ãç¶ããexperimentalè¦åãåºã¾ãã
ãªããin
ã¨=>
ã¯è¿ãå¤ä»¥å¤ã¯åãã§ãã
(mame)
findãã¿ã¼ã³ã追å ããã
- Find pattern is added. [EXPERIMENTAL] [Feature #16828]
é åã®ä¸ã§ãããããç®æãæ¢ç´¢ãããã¿ã¼ã³ã試é¨å°å ¥ããã¾ããã
case ["a", 1, "b", "c", 2, "d", "e", "f", 3] in [*pre, String => x, String => y, *post] p pre #=> ["a", 1] p x #=> "b" p y #=> "c" p post #=> [2, "d", "e", "f", 3] end
ã¡ãã£ã¨ãããããã§ããã[*pre, String => x, String => y, *post]
ã¨ãããã¿ã¼ã³ã¯ãStringã2é£ç¶ã§ç»å ´ããç®æãæ¢ããã¿ã¼ã³ã§ããä¸è¨ã®ä¾ã§ã¯ã"b", "c"
ã®ç®æã«ããããã¦ãã¾ãï¼æåã«ãããããã¨ããã§æ¢ç´¢ã¯æ¢ã¾ãã¾ãï¼ã
è£è©±
matzã®èããã®æ°æ©è½ã§ããã¦ã¼ã¹ã±ã¼ã¹ããã¾ãæ確ã§ã¯ãªãã®ã§ãããmatzã®ä¸å£°ã§å ¥ãã¾ããã
æ¢ç´¢ãè¡ããã¿ã¼ã³ã¯ããã¾ãä¸è¬çãªãã¿ã¼ã³ãããã«ã¯ãªãæ©è½ã§ãããç·å½¢æ¢ç´¢ããè¡ããªãããã«ãªã£ã¦ããã®ã§ãããã¾ã§è¤éãªæåã«ã¯ãªããªãã¨æãã¾ãã
ï¼mameï¼
ã¹ã¼ãã¼ã¯ã©ã¹ã§ã¯ã©ã¹å¤æ°ãåå®ç¾©ãã¦ãã¾ã£ãã¨ãããµãã¯ã©ã¹ã§åç §ããã¨ãã«ä¾å¤ãåºãããã«ãªã£ã
- When a class variable is overtaken by the same definition in an ancestor class/module, a RuntimeError is now raised (previously, it only issued a warning in verbose mode). Additionally, accessing a class variable from the toplevel scope is now a RuntimeError. [Bug #14541]
å®ã¯ç¶æ¿ã絡ãã¨é£ããã¯ã©ã¹å¤æ°ã§ããããããã¥ããä¾ã§ä¾å¤ãåºãããã«ãªãã¾ããã
ã¾ããä¾å¤ãåºãªãã±ã¼ã¹ããç´¹ä»ãã¾ãã
class C @@foo = :C end class D < C @@foo = :D # C ã® @@foo ãå¤æ´ãã¦ãã end class C p @@foo #=> :D end
ãã®ã¨ãã@@foo
ã¨ããã®ã¯ãD
ã§ãå®ç¾©ãã¦ããããã«è¦ãã¦ãå®ã¯C
ã®ã¯ã©ã¹å¤æ°ãå¤æ´ãã¦ãã¾ããç¶æ¿å
ãè¦ãããã§ãããã±ã£ã¨è¦ãæããããã¥ããã
ãã¦ãC
ã®@@foo
ããã£ãã¨ãã¯ãD
ã®æèã§ã¯ã©ã¹å¤æ°ãè¨å®ãããã¨ãããã¨ã¯ãããã¾ãããã§ã¯ãå
ã«D
ã«è¨å®ãããã¨ããã®åºåºã¯ã©ã¹ã§ããC
ã®ã¯ã©ã¹å¤æ°ãè¨å®ãããã©ããªãã§ããããã
class C end class D < C @@foo = :D # D ã® @@foo ã«ä»£å ¥ end class C @@foo = :C # C ã® @@foo ã«ä»£å ¥ end class D p @@foo # Ruby 2.7 以å #=> warning: class variable @@foo of D is overtaken by C #=> :C # # Ruby 3.0 #=> class variable @@foo of D is overtaken by C (RuntimeError) end
Ruby 2.7ã¾ã§ã¯ãC
ã«ä¸æ¸ãããã¦ãã¾ã£ãããã¨ãããããªè¦åãåºãã¦ãC
ã®@@foo
ãåç
§ãããããã«ãªãã¾ããï¼ãã®ãããè¦åã®å¾ã:C
ãè¿ãï¼ãããããã¡ãã£ã¨ãããã¥ãéããã ãããã¨ãããã¨ã§ãè¦åã®ä»£ããã«ã¨ã©ã¼ãåºãããã«ãªãã¾ããï¼RuntimeError
ï¼ã
ããããã¤ãã§ã«ï¼ï¼ï¼ããããã¬ãã«ã§ã¯ã©ã¹å¤æ°ãè¨å®ãããåç
§ããããããã¨ãç¦æ¢ï¼RuntimeError
ï¼ããã¾ããã
# è¨å®ãç¦æ¢ @@foo = 1 #=> class variable access from toplevel (RuntimeError) class Object @@bar = 2 end # åç §ãç¦æ¢ p @@bar #=> class variable access from toplevel (RuntimeError)
æ£ç´ããããããªããã§ãã¯ã©ã¹å¤æ°ã¯ãªãã¹ã使ããªãæ¹ãããã¨æãã¾ãããï¼ã¨ãã«ãç¶æ¿ã絡ãã¦ï¼ãRactorã§ä½¿ããªããã
(ko1)
Numbered parameter ã¸ã®ä»£å ¥ãè¦åããç¦æ¢ã«
- Assigning to a numbered parameter is now a SyntaxError instead of a warning.
1.times{|i| p i}
ã®ä»£ããã« 1.times{p _1}
ã®ããã«ããããã¯ä»®å¼æ°ã®ååãæé»ã®å¼æ°åã§æ¸ããã¨ããNumbered parameterã¨ããæ©è½ã Ruby 2.7 ããå°å
¥ããã¾ããï¼ããã¨èªã¿è§£ãRuby 2.7 NEWS - ã¯ãã¯ãããéçºè
ããã° ãNumbered parametersãï¼ã
_1
ãªã©ãç¹å¥æ±ãããã«ããã£ã¦ãæ¢åã®ã³ã¼ãã§_1
ãªã©ã®ååãå©ç¨ãã¦ããä¾ã«ã¤ãã¦è°è«ããã£ãã®ã§ãããRuby 2.7ã®æ®µéã§ã¯ãã¾ãããããªã«ä½¿ã£ã¦ãªãã ãããããè¦åã ãåºãã¨ãããã¨ãªãã¾ãããRuby 3.0 ã§ã¯ãå©ç¨ãã¦ããç®æãå
¨é¨ã¨ã©ã¼ã«ããããã«ãã¾ããã
_1 = 10 # ãã¼ã«ã«å¤æ°åã¨ãã¦å©ç¨ def a _1 # ä»®å¼æ°åã¨ãã¦å©ç¨ end def _1 # ã¡ã½ããåã¨ãã¦å©ç¨ end 1.times{|_1| p _1} # ãããã¯ã®ä»®å¼æ°åã¨ãã¦å©ç¨
ãã®ä¾ã§ã¯ã
- Ruby 2.6 ã¾ã§ã¯ãåé¡ãªãå©ç¨å¯è½
- Ruby 2.7 ã§ã¯ããã¼ã¹æã«ãããã "warning: `_1' is reserved for numbered parameter; consider another name" ã¨ããè¦å
- Ruby 3.0 ã§ã¯ããã¼ã¹æã«ãããã "_1 is reserved for numbered parameter" ã¨ããã¨ã©ã¼ã¡ãã»ã¼ã¸ã§æ§æ解æ失æ
ã¨ãªãã¾ããæå¾ã®ä¾ã¯ãæå³ãå¤ãããªãã®ã§éã£ã¦ãããããã§ãããã¾ãèªåã§å¤æ°åã¨ãã¦ä½¿ãåã«ã¯ä¸å¾ç¦æ¢ã«ãªãã¾ããã
(ko1)
ä¸è¡ã¡ã½ããå®ç¾©ã追å ããã
- Endless method definition is added. [EXPERIMENTAL] [Feature #16746]
endã®ãªãã¡ã½ããå®ç¾©ã®æ°ææ³ãå°å ¥ããã¾ããã
def square(x) = x * x p square(5) #=> 25
次ã®ããã«æ¸ãã®ã¨ã¾ã£ããåãæå³ã§ãã
def square(x) x * x end
ãããªåç´ãªã¡ã½ããã®ããã«3è¡ãæ¸ããªãã¦è¯ããªãã¾ãããå¬ããã§ãããï¼ï¼
ç¡å¼æ°ã®ã¡ã½ãããç´ ç´ã«æ¸ãã¾ããã=
ã®åã«ã¹ãã¼ã¹ãå¿
é ã§ãã
def answer = 42 # OK def answer=42 # NG: SyntaxError
ãªããªããsetterã¡ã½ããã¨ã®åºå¥ãã§ããªãããã§ããã¾ããsetterã¡ã½ããã¯è¦ãç®ãããããããªããã¨ããããä¸è¡ã¡ã½ããå®ç¾©ã§ã¯æ¸ããªããªã£ã¦ãã¾ãã
def set=(x) = @x = x #=> setter method cannot be defined in an endless method definition
è£è©±
ãã¨ãã¨ç§ï¼é è¤ï¼ãææ¡ããæ©è½ã§ãããRubyã®ææ³ã¯end
ãå¤ç¨ããã®ã§ãRuby ãçµããããã§ç¸èµ·ãæªããã¨ããã¨ã¤ããªã«ãã¼ã«ãã¿ã§ããã
ãããmatzã¯ã¨ã¤ããªã«ãã¼ã«ãã¿ã¨ãããã¨ãç解ããä¸ã§ãç´°ããç¹ãé¤ãã°çé¢ç®ã«ãã¸ãã£ããã¨ãããnobuãç´°ããåé¡ã解決ãã *5 ã®ã§ãå ¥ã£ã¦ãã¾ãã¾ããã
çé¢ç®ãªè©±ãä¸è¨ã® square
ã¡ã½ããã®ããã«ç°¡åãªã¡ã½ããå®ç¾©ã§ 3 è¡ãæ¸ãã®ã¯ç¡é§ãªãããªæ°ã¯ãã¦ãã¾ãããRubyã®ããã±ã¼ã¸ã«å«ã¾ãã¦ããã³ã¼ãã§èª¿ã¹ãã¨ããªã㨠24% ã®ã¡ã½ããå®ç¾©ã 3 è¡ã§ãããã¨ããããã¾ãããã¾ããããã§ãæ°ææ³ãå°å
¥ããã®ã¯èºèºããããªãã®ã§ããããä¸é¨ã®ããã°ã©ã ã§ä¾¿å©ãªå¯è½æ§ããããããã¨ããmatzã®ç´æã«ããå°å
¥ããã¾ããã
Rubyã®æ°æ©è½ææ¡ã§ã¯ã¦ã¼ã¹ã±ã¼ã¹ãå¼·ãæ±ãããã¾ãããmatzã ãã¯ä¾å¤ã§ããç´æã«åºã¥ã決æã¯ãè¨èªä»æ§ãå§å¡ä¼å¶ã§æ±ºããè¨èªã§ã¯ã§ããªãã¨æãã®ã§ãé¢ç½ããªãã¨æã£ã¦ãã¾ãã
ãªããä¸è¡ã¡ã½ããå®ç¾©ã¯ååã·ã³ãã«ãªå ´åã«ä½¿ããããã¨ãæ³å®ãã¦ããã®ã§ãå¯ä½ç¨ãä¼´ãå¼ãªã©ã¯æ¸ããªãã»ããããã§ããsetterã¡ã½ãããå®ç¾©ã§ããªããªã£ã¦ããã®ã«ã¯ãããããçç±ãããã¾ãã
ï¼mameï¼
å¼å±éãå«ãæååãªãã©ã«ã¯ãfrozen-string-literal: true
㧠freeze ããªããªã£ã
- Interpolated String literals are no longer frozen when
# frozen-string-literal: true
is used. [Feature #17104]
# frozen-string-literal: true
ãæå®ãã¦ããã¨ããã®å¾ã«ããæååãªãã©ã«ããã¹ã¦ frozen ãªç¶æ
ã¨ãªãã¾ãã
# frozen-string-literal: true p "foo".frozen? #=> true
ããã¯ãå¼å±éãå«ãæååãªãã©ã«ï¼åãè¾¼ã¿æååï¼ã frozen ã«ãã¦ãã¾ããã
# frozen-string-literal: true p "foo#{42}bar".frozen? #=> true
Ruby 3.0ããã¯ãåãè¾¼ã¿æååã«ã¤ãã¦ã¯ freeze ããã§ãããã ããã£ã¦ãã¨ã§ freeze ãããªããªãã¾ããï¼ãã®ä¾ã§ã¯ false
ãåºåãããï¼ã
frozen-string-literal: true
èªä½ã¯ãæåãã freeze ãã¦ãããã¨ã§ä½åº¦ãåãæååãçæããªãã¦ãæ¸ããã¨ãããã¨ãæå³ãã¦ããããã©ãåãè¾¼ã¿æååã¯ããããããã«ããããªãã®ã§ãæ¯åçæãã¦ãã¾ããã¤ã¾ãããã®å©ç¹ã¯ãªãã®ã«ãããã freeze ããªãã¦ãããã ãããã¨ããææ¡ã§ãã
ç§ã®è¨æ¶ã確ããªãããã®åãè¾¼ã¿æååã®æåã¯ãåãè¾¼ã¿æååã§ãæååãªãã©ã«ã®ä¸ç¨®ãªã®ã§ãæååãªãã©ã«ã frozen ã§ãããã¨ããæå®ãªããåãè¾¼ã¿æååã freeze ãã¡ãã£ãã»ããç解ã¯ãããããããã¨ããæå³ã§ freeze ãã¦ããã¨æãã®ã§ãããMatz ããã¾ã freeze ããã§ããããããã£ã¦è¨ã£ãã®ã§ freeze ããªãããã«ãªãã¾ããã
å人çã«ã¯ãfreeze ããã¾ã¾ã®ã»ããè¯ãã£ããªãã
(ko1)
éç解æåºç¤ãå°å ¥ããã
- A static analysis foundation is introduced. See "Static analysis" section in detail.
- RBS is introduced. It is a type definition language for Ruby programs.
- TypeProf is experimentally bundled. It is a type analysis tool for Ruby programs.
RBSã¨TypeProfãå°å ¥ããã¾ããããã®è¾ºã¯ãã§ã«å¥è¨äºãæ¸ãã¦ããã®ã§ãåç §ãã ããã
ï¼mameï¼
ã³ãã³ãã©ã¤ã³ãªãã·ã§ã³
--help
ã¨ãã¼ã¸ã£
- When the environment variable
RUBY_PAGER
orPAGER
is present and has non-empty value, and the standard input and output are tty,--help
option shows the help message via the pager designated by the value. [Feature #16754]
ç´°ãã話ã§ããç°å¢å¤æ° RUBY_PAGER
ã PAGER
ã空ã§ãªãæååã§è¨å®ããã¦ããã°ãruby --help
ã¨ãã詳細ãã«ããåºåããã¨ããããããã¼ã¸ã£ã¼ã¨ãã¦å©ç¨ãã¦åºåããããã«ãªãã¾ãããæè¿ãgit ã¨ãã§ãè¦ãæåã§ããï¼git ã§ã¯ç°å¢å¤æ°ãè¨å®ããã¦ãªãã¦ã less
ãèµ·åãã¡ãããã©ï¼ã
é¢ä¿ãªããã©ãruby -h
ã§ç°¡æçãã«ããruby --help
ã§è©³ç´°çãã«ããåºã¾ãã
(ko1)
--backtrace-limit
ãªãã·ã§ã³
--backtrace-limit
option limits the maximum length of backtrace. [Feature #8661]
ä¾å¤çºçæã®ããã¯ãã¬ã¼ã¹ã®æ大è¡æ°ãæå®ãããªãã·ã§ã³ãå°å ¥ããã¾ããã
def f6 = raise def f5 = f6 def f4 = f5 def f3 = f4 def f2 = f3 def f1 = f2 f1
ã¿ãããªã³ã¼ãã次ã®ããã«å®è¡ãã㨠... 3 levels...
ã®ããã«çç¥ããã¾ãã
$ ruby --backtrace-limit=3 test.rb -e:6:in `f6': unhandled exception from -e:5:in `f5' from -e:4:in `f4' from -e:3:in `f3' ... 3 levels...
ããã¯ãå¾è¿°ããããã¯ãã¬ã¼ã¹ã®åé転ã«éãã¦å°å ¥ããã¾ããã
ï¼mameï¼
â çµã¿è¾¼ã¿ã¯ã©ã¹ã®ã¢ãããã¼ã
Array
ã®ãµãã¯ã©ã¹ã®ã¡ã½ãããããµãã¯ã©ã¹ã§ã¯ãªããArray
ã¯ã©ã¹ã®ãªãã¸ã§ã¯ããè¿ãããã«ãªã£ã
- The following methods now return Array instances instead of subclass instances when called on subclass instances: [Bug #6087]
- Array#drop
- Array#drop_while
- Array#flatten
- Array#slice!
- Array#slice / Array#[]
- Array#take
- Array#take_while
- Array#uniq
- Array#*
ä½ãè¨ã£ã¦ããã¨è¨ãã¨ãArrayãç¶æ¿ããã¯ã©ã¹ãå®ç¾©ããå ´åã®è©±ã§ãã
class MyArray < Array end ary = MyArray.new([1, 2, 3]).drop(1) p ary #=> [2, 3] p ary.class #=> MyArray # 2.7 p ary.class #=> Array # 3.0
ä¸è¨ã®éããMyArray#drop
ãªã©ã¯MyArray
ã®ã¤ã³ã¹ã¿ã³ã¹ãè¿ãã¦ãã¾ããã
ä¸æ¹ã§ãMyArray#rotate
ã¯2.7ã§ãArray
ã®ã¤ã³ã¹ã¿ã³ã¹ãè¿ãã¦ããã®ã§ãä¸è²«æ§ããªãç¶æ
ã«ãªã£ã¦ãã¾ããã
3.0ããã¯ããã®ãããªã¡ã½ããã¯ä¸è²«ãã¦Array
ãè¿ãããã«ãªãã¾ããã
ãã®åé¡ã¯Ruby 2.0ã®ããã«ææããã¾ãããããç´ãããæ°ããããã©éäºæãæ°ã«ãªãã®ã§æ¬¡ã®ã¡ã¸ã£ã¼ãã¼ã¸ã§ã³ã®ã¨ãã«èãããï¼ï¼å¿ãã¦ãã¾ããï¼ãã¨ããå¤æã«ãªã£ã¦ãã¾ããããããã¾ãã¾ä»å¹´æãåºãã¦ãã¾ã£ãã®ã§ãç´ããã¨ã«ãªãã¾ããã9å¹´è¶ãã®ä¿®æ£ã
ããã¨ç´åï¼ãªãªã¼ã¹2ã¶æåï¼ã«å¤ãã£ã¦ããã®ã§ãéäºæåé¡ããããªãã¨ãããªããå人çã«ã¯ãArray
ãString
ã®ãããªã³ã¢ã¯ã©ã¹ã¯ãã¾ãç¶æ¿ããªãã»ããããã¨æãã¾ãã
ï¼mameï¼
String
ã®ãµãã¯ã©ã¹ã®ã¡ã½ãããããµãã¯ã©ã¹ã§ã¯ãªããString
ã¯ã©ã¹ã®ãªãã¸ã§ã¯ããè¿ãããã«ãªã£ã
- The following methods now return or yield String instances instead of subclass instances when called on subclass instances: [Bug #10845]
- String#*
- String#capitalize
- String#center
- String#chomp
- String#chop
- String#delete
- String#delete_prefix
- String#delete_suffix
- String#downcase
- String#dump
- String#each_char
- String#each_grapheme_cluster
- String#each_line
- String#gsub
- String#ljust
- String#lstrip
- String#partition
- String#reverse
- String#rjust
- String#rpartition
- String#rstrip
- String#scrub
- String#slice!
- String#slice / String#
- String#split
- String#squeeze
- String#strip
- String#sub
- String#succ / String#next
- String#swapcase
- String#tr
- String#tr_s
- String#upcase
åé ã¨åãå¤æ´ã¯æååã®æ¹ã§ãè¡ããã¦ãã¾ãã
ãªãããã®å¤æ´ã§ Rails ã® SafeBuffer ã¯ã©ã¹ãåããªããªã£ã¦ãã¾ãããRails ã®ææ°çã§ã¯ä¿®æ£ããã¦ãã¾ãã
ï¼mameï¼
Dir.globã®çµæãã½ã¼ããããããã«ãªã£ã
- Dir.glob and Dir. now sort the results by default, and accept
sort:
keyword option. [Feature #8709]
ãã®ã¾ã¾ã§ãã
# Rubyã®ããã±ã¼ã¸ãã£ã¬ã¯ããªã§å®è¡ãã Dir.glob("*.c") #=> ["marshal.c", "symbol.c", "regparse.c", "st.c", ...] # 2.7 Dir.glob("*.c") #=> ["addr2line.c", "array.c", "ast.c", "bignum.c", ...] # 3.0
Ruby 2.7ã¾ã§ã¯Dir.glob
ã¯ãã¡ã¤ã«ã·ã¹ãã ã«ä¾åããé åºã§ãã¡ã¤ã«ãåæãã¦ãã¾ããããRuby 3.0ããã¯ããã©ã«ãã§ã½ã¼ããããããã«ãªãã¾ãããããã½ã¼ããã¦ã»ãããªãå ´åã¯ãDir.glob("*.c", sort: false)
ã¨ãã¦ãã ãã
ãã¡ã¤ã«åæã¯O(n)ã§ã§ããã®ã«ãã½ã¼ããããã¨O(n log n)ã«ãªã£ã¦ãã¾ããã¨ãããã¨ã§è¥å¹²ã®èºèºãããã¾ããããç¾å®çã«ã¯ãã¡ã¤ã«ã¢ã¯ã»ã¹ã«æ¯ã¹ã¦æååã½ã¼ãã¯ç¡è¦ã§ããã»ã©éããã¨ãã¾ããLinuxã®glob(3)ãããã©ã«ãã§ã½ã¼ãããããããã¨ã決ãæã¨ãªããå¤æ´ããã¾ããã
ãglobã®çµæã¯sortãã¦ä½¿ããã¨ããRubocopã®ã«ã¼ã«ããããããã§ãããRuby 3.0ããã¯ç¡æå³ã«ãªãã®ã§ãããã»ããè¯ãããã§ãã
ï¼mameï¼
Windows ã®ããã©ã«ãå¤é¨ã¨ã³ã³ã¼ãã£ã³ã°ã UTF-8 ã«ãªã£ã
- Windows: Read ENV names and values as UTF-8 encoded Strings [Feature #12650]
- Changed default for Encoding.default_external to UTF-8 on Windows [Feature #16604]
Windowsã§ã¯ããã±ã¼ã«ã«ãããã«ãããã©ã«ãã®å¤é¨ã¨ã³ã³ã¼ãã£ã³ã°ï¼-E
ãªãã·ã§ã³ãæå®ãããªãã¨ãã® Encoding.default_external
ï¼ã UTF-8 ã«ãªãã¾ããã
> ruby -e 'p Encoding.default_external' #<Encoding:UTF-8> > ruby -Ecp932 -e 'p Encoding.default_external' #<Encoding:Windows-31J>
ã¾ããç°å¢å¤æ°ã®å¤ã¯ããã±ã¼ã«ã«ããã UTF-8 ã«ãªãã¾ããã
> ruby -e 'p ENV["PATH"].encoding' #<Encoding:UTF-8> > ruby -Ecp932 -e 'p ENV["PATH"].encoding' #<Encoding:UTF-8>
(ko1)
IBM720 ã¨ããã¨ã³ã³ã¼ãã£ã³ã°ã®è¿½å
- Added new encoding IBM720. [Feature #16233]
IBM720 ã¨ããã®ã¨ã¤ãªã¢ã¹ CP720 ã¨ããã¨ã³ã³ã¼ãã£ã³ã°ã追å ãããããã§ãã
(ko1)
Fiber scheduler ãå°å ¥ããã
- Fiber
- Fiber.new(blocking: true/false) allows you to create non-blocking execution contexts. [Feature #16786]
- Fiber#blocking? tells whether the fiber is non-blocking. [Feature #16786]
- Introduce Fiber.set_scheduler for intercepting blocking operations and Fiber.scheduler for accessing the current scheduler. See doc/scheduler.md for more details. [Feature #16786]
- ConditionVariable
- ConditionVariable#wait may now invoke the
block
/unblock
scheduler hooks in a non-blocking context. [Feature #16786]
- ConditionVariable#wait may now invoke the
- IO
IO#nonblock? now defaults to
true
. [Feature #16786]IO#wait_readable, IO#wait_writable, IO#read, IO#write and other related methods (e.g. IO#puts, IO#gets) may invoke the scheduler hook
#io_wait(io, events, timeout)
in a non-blocking execution context. [Feature #16786]
- Kernel
- Kernel.sleep invokes the scheduler hook
#kernel_sleep(...)
in a non-blocking execution context. [Feature #16786]
- Kernel.sleep invokes the scheduler hook
- Mutex
Mutex
is now acquired per-Fiber
instead of per-Thread
. This change should be compatible for essentially all usages and avoids blocking when using a scheduler. [Feature #16792]
- Queue / SizedQueue
- Queue#pop, SizedQueue#push and related methods may now invoke the
block
/unblock
scheduler hooks in a non-blocking context. [Feature #16786]
- Queue#pop, SizedQueue#push and related methods may now invoke the
- Thread
- Thread#join invokes the scheduler hooks
block
/unblock
in a non-blocking execution context. [Feature #16786]
- Thread#join invokes the scheduler hooks
I/O å¦çãªã©ãå®è¡ããã¨ãããã¯ããå¦çã§ã¯ããããå¾ ã£ã¦ããéã«ä»ã®ç¬ç«ããå¦çãè¡ãã¨å¹çãè¯ããªããã¨ãç¥ããã¦ãã¾ããããã¾ã§ã¯ãã¹ã¬ããã使ãããEventMachine ãªã©ã使ã£ã¦èªåã§çµã¿ç«ã¦ã¦ããå¿ è¦ãããã¾ããï¼ããããããã³ããããã³ã°ãªããã°ã©ãã³ã°ï¼ãããããI/O ãªã©ã§ãããã¯ããããä»ã®ç¬ç«ãã Fiber ãå®è¡ãããããªã¹ã±ã¸ã¥ã¼ã©ããRuby ã§è¨è¿°ããããã®ä»çµã¿ã Fiber scheduler ã§ãã
æ©è½ã®ç´¹ä»
Fiber scheduler ã«ãã£ã¦ãI/O ãªã©ã®ãå¾ ã¡ãå¤ãå«ãã 大éã®å¦çã並è¡ã«è¡ããªããã°ãªããªãç¨éã§ãFiber ã使ã£ã¦ãã¹ã¬ããããã軽éã«æ±ããã¨ãã§ãã¾ãããã®ããã«ãã¤ããã¤å¤æ´ã並ãã§ãã¾ããã
ç¾å¨ã® MRI ã®ã¹ã¬ããã¯ã1ã¤ã®Rubyã¹ã¬ããã«å¯¾ãã¦1ã¤ã®OSã¹ã¬ãããä½ãã¾ãããã®ãããçæãéããä¸éããã£ãããããããã¨ããåé¡ãããã¾ãã
$ time ruby27 -ve '(1..).each{|i|begin; Thread.new{sleep}; rescue; p [$!, i]; exit; end}' ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux] [#<ThreadError: can't create Thread: Resource temporarily unavailable>, 32627] real 0m7.305s user 0m6.726s sys 0m20.182s $ time ruby30 -ve '(1..).each{|i|begin; Thread.new{sleep}; rescue; p [$!, i]; exit; end}' ruby 3.0.0dev (2020-12-21T04:25:03Z master 74a7877836) [x86_64-linux] [#<ThreadError: can't create Thread: Resource temporarily unavailable>, 32627] real 0m14.677s user 0m5.722s sys 0m10.415s
ãã®ã·ã¹ãã ã ã¨ã3ä¸åç¨åº¦ã§ä¸éããã¾ãï¼OSã®ããã»ã¹æ°ã®ä¸éï¼ããããRuby 3ã§æéãåãããã«ãªã£ã¦ã¾ãã...ãªãã§ã ãã
Fiber ã§ãã¨ããããªæãã
$ time ruby27 -ve 'fs=[]; (1..).each{|i| begin; fs << (f = Fiber.new{Fiber.yield}); f.resume; rescue; p [$!, i]; exit; end }' ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux] [#<FiberError: can't set a guard page: Cannot allocate memory>, 31745] real 0m0.452s user 0m0.244s sys 0m0.208s $ time ruby30 -ve 'fs=[]; (1..).each{|i| begin; fs << (f = Fiber.new{Fiber.yield}); f.resume; rescue; p [$!, i]; exit; end }' ruby 3.0.0dev (2020-12-21T04:25:03Z master 74a7877836) [x86_64-linux] [#<FiberError: can't set a guard page: Cannot allocate memory>, 31745] real 0m0.497s user 0m0.277s sys 0m0.220s
ãããæ°ã¯3ä¸åç¨åº¦ã§ãããããã¯ãã¡ã¢ãªãããã¯ã·ã§ã³ã®ããã«mmap
ã使ã£ã¦ããã®ã§ããããã®çæä¸éã«ããã£ã¦ããã®ã§ã¯ãªããã¨æãã¾ãï¼Cannot allocate memory ã¨ããã®ãããï¼ãæ°ã¯ããã¨ãã¦ãçæé度ãæ¯ã¹ãã¨ã1æ¡éãã¾ãããã¨ãã¡ããã¨æ¸ãã¦ããªãã§ãããã¡ã¢ãªæ¶è²»ã Fiber ã®ã»ããå°ãªãã§ãã
ãã®ã¸ãããFiber ã¯è»½éã¨ãã£ã¦ããçç±ã«ãªãã¾ãã
Fiber ãã¹ã¬ããããã©ã¡ãã並è¡å¦çï¼ãã¨ãã°ãç¬ç«ããIOå¦çãå
¸åçã«ã¯ã¦ã§ããªã¯ã¨ã¹ããããã¦ã¬ã¹ãã³ã¹ããå¦çï¼ãè¡ãã®ã¯åãã§ãããã¹ã¬ããã¯ãããã¼ãªã¿ã¤ãã³ã°ï¼å¦çç³»ä¾åã®ã¿ã¤ãã³ã°ã¨ãããï¼åæã«åãæ¿ããã®ã«å¯¾ããFiber ã¯èªå㧠"resume/yield" ãªã©ãå©ç¨ãã¦åãæ¿ããè¡ãå¿
è¦ãããã¾ããããã¯ãåæã«åãæ¿ãããªããã¨ãã Fiber ã®ã¡ãªããã§ãããã®ã§ãããFiber ãç¨ã㦠IO å¦çããã£ã¦ããã¨ãread
ãªã©ã§ãããã¯ãã¦ãã¾ãã¨åãæ¿ããã¿ã¤ãã³ã°ãé¸ãã¦ãã¾ãã®ã§ï¼ä»ã®å®è¡å¯è½ãª Fiber ã«å¦çããã¤ããã¨ãã§ããªãã®ã§ï¼ãread
ãªã©ãããã¯ãããããªå¦çãé¿ãã¦ããã°ã©ãã³ã°ããå¿
è¦ãããã¾ããã
Fiber scheduler ã¯ãå
¸åçãªããããã³ã°ããããããªå¦çï¼read
ã¨ãï¼ãèµ·ãã£ãããã¦ã¼ã¶ã¼ã¬ãã«ï¼ã¤ã¾ããRubyï¼ã§è¨è¿°ããããã³ãã©ã«é£ã°ãã¦ãèªå㧠non-blocking IO å¦çãæ¸ãã¦ä»ã® Fiber ã«å¦çããã¤ããã¨ãã£ããã¨ãèªåã§æ¸ããã¨ãã§ããããã«ããä»çµã¿ã§ãããã®ãã³ãã©ãå®ç¾©ãããªãã¸ã§ã¯ãããããã§ã¯ã¹ã±ã¸ã¥ã¼ã©ã¼ã¨å¼ãã§ãã¾ãã
ç¾å¨å®è¡ä¸ã®ã¹ã¬ããã®ã¹ã±ã¸ã¥ã¼ã©ãè¨å®ããã«ã¯ãFbier.set_scheduler(scheduler_object)
ã®ããã«æå®ãã¾ãï¼ã¹ã¬ãããã¼ã«ã«ãªå±æ§ã§ãï¼ã
ããããã³ã°ãããããªå¦çãèµ·ããã¨ã¹ã±ã¸ã¥ã¼ã©ã¼ã®ãã³ãã©ãèµ·åããã¾ããç¾å¨æ¬¡ã®ãããªå¦çã§ãã¹ã±ã¸ã¥ã¼ã©ãå¼ã³åºãã¾ãã
ConditionVariable#wait
IO#wait_readable
,IO#wait_writable
,IO#read
,IO#write
and other related methods (e.g.IO#puts
,IO#gets
)Kernel.sleep
Mutex#lock
and related methodsQueue#pop
,SizedQueue#push
and related methodsThread#join
ã©ã®ã¡ã½ããããã©ã®ãããªã¹ã±ã¸ã¥ã¼ã©ã¼ã®ããã¯ãå¼ã¶ãã©ããã¯ã詳細ãªã®ã§ç«ã¡å ¥ãã¾ããï¼è©³ç´°ã¯ ruby/fiber.md at master ã» ruby/ruby ãã覧ãã ããï¼ã
å°ã試ãã¦ã¿ã¾ããããsleep
ããã¨ãã¹ã±ã¸ã¥ã¼ã©ã¼ã®ãã³ãã©ãå¼ã°ããã®ã§ç¢ºèªãã¦ã¿ã¾ããmethod_missing
ã ããå®ç¾©ããã¹ã±ã¸ã¥ã¼ã©ãç¨æãã¦ãã©ã®ãããªããã¯ãå¼ã°ããã確èªãã¦ã¿ã¾ãããã
class MyScheduler def method_missing *args p args end end Fiber.set_scheduler(MyScheduler.new) Fiber.new{ sleep(10) }.resume #=> [:kernel_sleep, 10]
MyScheduler#kernel_sleep(10)
ã¨ããã¡ã½ãããå¼ã°ãã¦ãããã¨ããããã¾ããã¹ã±ã¸ã¥ã¼ã©ã¼ã¯ãå¥ã®å®è¡å¯è½ãª Fiber ã«å¦çã移ãã¦ãããã§ãããå®éã« Kernel#sleep(10)
ãå¼ã³ã ãã¦ã¹ãªã¼ããã¦ãè¯ãããã§ãã
ãã®æ©è½ã®å°å ¥ã«éãã次ã®ãããªå¤æ´ãå ¥ã£ã¦ãã¾ãã
- Mutex ã Fiber local ã«ãªãã¨ãã£ãå¤æ´ãããã¾ãããã¤ã¾ããFiber scheduler ãå©ç¨ããããã°ã©ã ã¯ãã¹ã¬ããããã°ã©ãã³ã°ã¨åæ§ã«ã注ææ·±ãããã¯ãè¡ããªã©ããå¿ è¦ãããã¾ãã
- IO ã¯åºæ¬çã« non-blocking ã¢ã¼ãã«ãªãã¾ããï¼ããæ®éã«ä½¿ãåã«ã¯ä½ãå¤ããã¾ãããIO#read ãã¦ããããã¯ããããã«è¦ãã¾ããã·ã¹ãã å´ã®è¨å®ã®è©±ã«ãªãã¾ãï¼
Fiber.new(blocking: false)
ã¨ãããã©ã¡ã¼ã¿ãå¢ãã¾ãããtrue ã ã¨ãã¹ã±ã¸ã¥ã¼ã©ãå¼ã°ããªããªãã¾ããroot fiber ï¼ã¹ã¬ããã¨ã»ããã§çæããã Fiberï¼ã¯ãtrue ã«ãªã£ã¦ãã¾ãã- ã¹ã¬ããçµäºæãã¹ã±ã¸ã¥ã¼ã©ãããããã®ã¹ã±ã¸ã¥ã¼ã©ã«
#close
ãå®ç¾©ããã¦ããã°ããããå¼ã°ãããã¨ã«ãªãã¾ããã
é£ããããªæ©è½ã§ãããå®éãããç´æ¥ä½¿ãã®ã¯ãå¤åã¨ã¦ãé£ããã®ã§ããã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ãç´æ¥ä½¿ãã®ã¯ãã¾ããããããã¾ããããããå©ç¨ãã¦éåæ IO ãå®ç¾ãã async gemï¼ä»æ§ææ¡è ã® Samuel ãããä½ã£ã¦ããã©ã¤ãã©ãªï¼ãªã©ãå©ç¨ããã¨ããã¨æãã¾ãã
ãã®æ©è½ï¼ã使ã£ã¦ã¹ã±ã¸ã¥ã¼ã©ãæä¾ãã gemï¼ã使ãã¹ããã©ããã§ãããæ¢åã®ããã°ã©ã ãç´æ¥åããããã¨ãç®çã¨ãã¦ããããããããããªããã¯ãå ¥ã£ã¦ãããåãããã¨ãã§ããå¯è½æ§ã¯é«ãã§ããããã¦ãã¹ã¬ããã®ä»£ããã« Fiber ãç¨ãããã¨ã§ãé«ã並è¡æ§ãéæãããã¨ãã§ããããããã¾ããããã ãããã¾ã§ã®ããã°ã©ãã³ã°ã¢ãã«ã¨å¾®å¦ã«ç°ãªãé¨åãã½ã³ã½ã³ããã®ã§ãã¯ã¾ãã¨å¤§å¤ã ã¨æãã¾ãããªã®ã§ãå°ããªããã°ã©ã ãã試ãã¦ããã¨ããã®ã§ã¯ãªããã¨æãã¾ããç®çã«åè´ããã¨ãè¯ããã®ã ã¨æãã¾ãã
ãã®æ°æ©è½ãã¾ã¨ããã¨ãRuby ã¬ãã«ã§ Fiber ãåãæ¿ãã¦åããã¹ã±ã¸ã¥ã¼ã©ã¼ãè¨è¿°ããããã®æ©è½ã¨ãããã¨ãã§ãã¾ãããã®æ©è½ã«ããããã¨ãã°å¤§éã®ã¦ã§ããªã¯ã¨ã¹ããåæã«ãã°ããªãã¦ã¯ãªããªãã¨ãããC10K åé¡ããRuby ã§åé¡ãªãå¦çãããã¨ãã§ããããã«ãªãã¨æå¾ ããã¾ãã
æ©è½ã«ã¤ãã¦ã®å人çãªæè¦
ãã®æ©è½ãå°å ¥ãããããé常ã«å¤ãã®è°è«ããªããã¾ããããã£ã¨ãæ¬è³ªçã«ã¯ããã®ã¹ã±ã¸ã¥ã¼ã©ã¼ã Ruby ã¦ã¼ã¶ã¼ã«è¨è¿°ããããã¨ãã§ãããã¨ããç¹ã§ãã
å©ç¹ã¨ãã¦ã¯ãåãã¹ã±ã¸ã¥ã¼ã©å®è£ ãããã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ãåãã MRI 以å¤ã®å®è£ ã§ãå ±æã§ããã¨ãããã®ã§ããã¾ããããã°ã©ã ã«é©ããã¹ã±ã¸ã¥ã¼ã©ãèªåã§æ¸ããã¨ãã§ããã¨ããã®ãå©ç¹ã®ä¸ã¤ã ã¨æãã¾ãï¼90年代ã®ãã¤ã¯ãã«ã¼ãã«ç 究ãæãåºãã¾ãï¼ã
ããå人çã«ã¯Rubyã§ãããªãããã«ããã»ããè¯ãã£ãããããªãããªã¨æã£ã¦ãã¾ããã¹ã±ã¸ã¥ã¼ã©ãåããã¹ãã¤ã³ã¿ã¼ãã§ã¼ã¹ãä½ã§ããããé常ã«é£ããåé¡ã§ãç¾å¨ã¯çµæ§ã¢ãããã¯ãªå°è±¡ãåãã¾ããã¾ããããããã³ã°ãããããããªãå¦çã«ã¯æ§ã ãªãã®ããããRuby ã ãã§ãªãã¨ãã§ãããã®ã°ããã§ã¯ããã¾ãããã¨ããããã§ããã®æ¹éã§é²ãã®ã¯é£ããããããªãããªãã¨æã£ã¦ãã¾ããæåã¯ãI/O éå®ã§åãæ¿ããéå®çãªã¹ã±ã¸ã¥ã¼ã©ã¨ãã話ã ã£ãã®ã§ãéå®çãªã·ãã¥ã¨ã¼ã·ã§ã³ã«ããã¦ã¯è¯ãããã¨æã£ããã§ãããæ±ç¨çãªã¹ã±ã¸ã¥ã¼ã©ã«ããã£ã¦ããã®ã§ã大ä¸å¤«ããªãã¨å°ãä¸å®ã«æã£ã¦ãã¾ãã
å°æ¥çã«ã¯ãã¹ã¬ããã®ããã¯ã¨ã³ãã Fiber ãç¨ãã¦ãã context ãç¨ãã¦è¯ãæãã«ã¹ã±ã¸ã¥ã¼ãªã³ã°ããï¼ããããM:Nã¢ãã«ï¼ãã®ãä½ã£ã¦ãã¹ã¬ããèªä½ã Fiber scheduler ã¨åçã®æ§è½ã«ãªãããã«ãã¦ããã¨è¯ãã®ã§ã¯ãªãããªãã¨æã£ã¦ãã¾ãï¼åºæ¬çãªè¨è¨ã¯ã§ãã¦ããã®ã§ããã¨ã¯ä½ãã ãï¼ããã¤ã§ããã ããï¼ã
(ko1)
Fiberãã¨ã®ããã¯ãã¬ã¼ã¹æ
å ±ãåãã Fiber#backtrace
㨠Fiber#backtrace_locations
ãå°å
¥ããã
- Fiber#backtrace & Fiber#backtrace_locations provide per-fiber backtrace. [Feature #16815]
Thread#backtrace
ã¯ããã®ã¹ã¬ãããç¾å¨å®è¡ä¸ã®ããã¯ãã¬ã¼ã¹ãåºãæ©è½ã§ããããããã Fiber ãã¨ã«å¾ã Fiber#backtrace
㨠Fiber#backtrace_locations
ãå°å
¥ããã¾ããã
def foo = Fiber.yield def bar = Fiber.yield f1 = Fiber.new{ foo }; f1.resume f2 = Fiber.new{ bar }; f2.resume pp f1.backtrace #=> ["t.rb:1:in `yield'", "t.rb:1:in `foo'", "t.rb:4:in `block in <main>'"] pp f2.backtrace #=> ["t.rb:2:in `yield'", "t.rb:2:in `bar'", "t.rb:5:in `block in <main>'"]
ããããFiber scheduler ã§ï¼ã¨ããããã¹ã±ã¸ã¥ã¼ã©ã®ãããã°ã§ï¼ä¾¿å©ã«ä½¿ãããã®æ©è½ã§ããã
(ko1)
Fiber#transfer
ã®å¶éãç·©åããã
- The limitation of Fiber#transfer is relaxed. [Bug #17221]
ããã¾ã§ãFiber#resume/yield
ã¨Fiber#transfer
ãæ··ãããã¨ã¯ç¦æ¢ãã¦ããã®ã§ããï¼ãã® Fiber 㯠resume/yieldããã® Fiber 㯠transfer å°ç¨ãã®ããã«ä½¿ã£ã¦ã»ããã£ãï¼ããã®å¶éãç·©åãã¦ãè¯ãæãã«ä½¿ããããã«ãã¾ããã詳細ã¯ãã±ãããè¦ã¦ãã ãããç°¡åã«ããã¨ãresume/yield
ä¸ã® Fiber ã«ã¯ transfer ã§ããªããtransfer ãã¦ãã Fiber ã«ã¯ resume ã§ããªããªã©ã¨ããå¶ç´ã ãã§ããããã ãã¨ãããã®ã§ãï¼æ¬å½ã¯ããå°ã詳細ï¼ã
ãã¨ãã¨ãããªãããããããããã© resume/yield ã®é¢ä¿ãå£ãããã transfer æ··ããããªããã¨ããã®ããæ··ããã®ç¦æ¢ã«ãã¦ããçç±ãªãã§ããããã¡ãã¨èããã¨ãæ··ãã¦ã¯ãããªãçç±ãã¯ã£ãããã¦ããã®ã§ãããæ´çã§ããã¨ãããã¨ã§ãã
Fiber scheduler ã¾ããã§ãã®å¶éãç·©åãã¦ã»ãããã¨ãããªã¯ã¨ã¹ãããããé è¤ããã¨å»¶ã ã¨è°è«ãã¦ããã¨ãããããã§æ´çã§ããããããªãï¼ãã¨ããã®ããµã£ã¦ãã¦ãäºäººã§åæ¥ãããè°è«ãã¦æ¡ä»¶ãæ´ãåºããã¨ãã§ãã¾ããã10å¹´ãããæ°ã«ãªã£ã¦ããåé¡ããããã«è§£æ±ºãã¦ãã¨ã¦ãå¬ããæ¹åã§ãï¼ã§ããå½±é¿ã¯ã»ã¨ãã©ãªãï¼ã
(ko1)
compaction GC ãèªåã§ãã£ã¦ããã GC.auto_compact = true
ã追å ããã
- GC.auto_compact= and GC.auto_compact have been added to control
when compaction runs. Setting
auto_compact=
to true will cause compaction to occur during major collections. At the moment, compaction adds significant overhead to major collections, so please test first! [Feature #17176]
Ruby 2.7 ããããã¼ãã®ä¸èº«ãã³ã³ãã¯ã·ã§ã³ãã GC.compact
ãå°å
¥ããã¾ãããããã¯ãæåã§å¥½ããªã¿ã¤ãã³ã°ã§è¡ãããã¨ãããã®ã§ãããããã major GCï¼ä¸ä»£å¥GC ã§ãæã
è¡ããã¼ãå
¨ä½ã対象ã«ãã GCãé
ãï¼ã®ã¨ãã«è¡ããã¨ãããã®ã§ãã
GC.compact
ã«ã¤ãã¦ã¯ãéçºè
ã® Aaron ããã解説ãã Rubyconf 2020 ã®åç»ãã¢ãããã¼ãããã¦ãã¾ããï¼
Automatic GC Compaction in MRI - Aaron Patterson - YouTube
GC.auto_compact = true
ã¨ãããã¨ã§ãmajor GC ãèµ·ããã¨ã³ã³ãã¯ã·ã§ã³ãå®è¡ãã¦ããã¾ãããã®ãããå®æçã«ã¡ã¢ãªã®æé¤ããã¦ããããã¨ã«ãªããã¡ã¢ãªå¹çã®åä¸ãããã³å±ææ§åä¸ã«ããæ§è½æ¹åãæå¾
ã§ãã¾ããããããã«ãæ¸ãã¦ããéããã³ã³ãã¯ã·ã§ã³èªä½ãçµæ§ãªãªã¼ããããã«ãªãã®ã§ãèªåã®ã¢ããªã§å¹ããã©ãã確èªãã¦ã¿ãã¨ããã¨æãã¾ããããã©ã«ãã¯ããããããã¨ã§ false ã§ãã
ãã¯ãã«ã«ã«ã¯ read-barrier ã¨ãå°å ¥ãã¦ãã¦ãã¸ãã£ã¦æãã§ããè²ã 大å¤ããã§é¿ãã¦ãããã§ãããã¡ããã¨åããã ãªãã
æ£ç´ãã¾ã å®è£ ãããªãã¦ããªããããªæ°ãããã®ã§ï¼æ¡å¼µã©ã¤ãã©ãªããããæªããã§ãï¼ãã¿ããªãããã«ããã使ãã£ã¦ã®ã«ã¯ããªããªãæ°ããã¾ãï¼ã¯ã¾ããªããã°ã使ã£ã¦ãããã¨æãã¾ãï¼ã
(ko1)
Hash#except
ãå°å
¥ããã
- Hash#except has been added, which returns a hash excluding the given keys and their values. [Feature #15822]
- ENV.except has been added, which returns a hash excluding the given keys and their values. [Feature #15822]
ActiveSupportã«ããHash#exceptãçµã¿è¾¼ã¿ã«ãªãã¾ããã
{ a: 1, b: 2, c: 3 }.except(:b) #=> {:a=>1, :c=>3}
ENV#except
ãåæ§ã«è¿½å ããã¦ãã¾ãã
è¦æã¯ä»¥åããããã¾ãããããååããã£ããæ¥ãªããçµã¿è¾¼ã¿ã«ããã»ã©ã®ã¦ã¼ã¹ã±ã¼ã¹ãããã®ãããããããªããã¨ãããã¨ã§å
éãã«ãªã£ã¦ãã¾ãããexclude
ã®ãããªååãæ¤è¨ãããããã§ãããçµå±ActiveSupportã«å¾ããã¨ã«ãªãã¾ããããªããexceptã¯ãï½ãé¤ãã¦ãã¨ããåç½®è©ããç¥ãã¾ããã§ãããããé¤å¤ãããã¨ããåè©ã®ç¨æ³ãããããã§ãã
ï¼mameï¼
Hash#transform_keysã
ããã·ã¥ãåãåãããã«
- Hash#transform_keys now accepts a hash that maps keys to new keys. [Feature #16274]
ããã·ã¥ã®ãã¼ãå¤æããHash#transform_keys
ããå¤æã®å¯¾å¿ãHashã§ç¤ºããããã«ãªãã¾ããã
# âæ°æ©è½ { a: 1, b: 2, c: 3 }.transform_keys({ a: :A }) #=> { A: 1, b: 2, c: 3 } # âå¾æ¥ã®æ©è½ã§åããã¨ãããã¨ããã { a: 1, b: 2, c: 3 }.transform_keys {|k| k == :a ? :A : k } #=> { A: 1, b: 2, c: 3 }
JSONã®å¤æã®ãããªã¨ãã«ä¾¿å©ã®ãããªæ°ã¯ãã¾ãã
ï¼mameï¼
Kernel#clone
㧠freeze: true
ã¨ããã freeze ãããããã«ãªã£ã
Kernel#clone
when called withfreeze: false
keyword will call#initialize_clone
with thefreeze: false
keyword. [Bug #14266]Kernel#clone
when called withfreeze: true
keyword will call#initialize_clone
with thefreeze: true
keyword, and will return a frozen copy even if the receiver is unfrozen. [Feature #16175]
2ã¤ã®å¤æ´ãèªããã¦ãã¾ããããããç´°ããå 容ã§ãã
ã¾ã1ã¤ãã®å¤æ´ã«ã¤ãã¦ãKernel#clone
ã¯ãªãã¸ã§ã¯ããè¤è£½ããã¡ã½ããã§ãããfreezeããããªãã¸ã§ã¯ããcloneãããfreezeãããè¤è£½ãè¿ãã¾ãã
ary = [1, 2, 3].freeze p ary.clone.frozen? #=> true
ããããcloneã§freezeç¶æ
ã¯ä¿åãã¦ã»ãããªãã±ã¼ã¹ããããRuby 2.4ã§freeze: false
ã¨ãããã¼ã¯ã¼ãå¼æ°ãå°å
¥ããã¾ããã
ary = [1, 2, 3].freeze p ary.clone(freeze: false).frozen? #=> false
ãã®ã¨ããfreeze: true
ã¨ããã®ã¯ãå¾æ¥ã©ãããfreezeç¶æ
ãä¿åãããã¨ããæå³ã«ãªãã¾ããããã£ã¦ãå
ã®ãªãã¸ã§ã¯ããfreezeããã¦ããªãå ´åãfreezeããã¦ããªãè¤è£½ãè¿ããã¦ãã¾ããã
ary = [1, 2, 3].freeze p ary.clone(freeze: true).frozen? #=> true s = "str" # freeze ããã¦ããªã p s.clone(freeze: true).frozen? #=> false
ãããfreeze: true
ã¨æ¸ãã¦ããã®ã«freezeããã¦ããªãè¤è£½ãè¿ãã®ã¯ãã°ã§ã¯ï¼ãã¨ããææãæ¥ãã®ã§ãããããããã«ãªãã¾ããã
s = "str" # freeze ããã¦ããªã p s.clone(freeze: true).frozen? #=> Ruby 3.0 ã§ã¯ true
ãªãã ãã¬ãããã ã¿ãããªè©±ã§ããã
ããã²ã¨ã¤ã®è©±ã®å¤æ´ãããã¤ã¾ãã§ãããã¯Setã¯ã©ã¹ã clone(freeze: false)
ããã¨ãã«èµ·ããåé¡ã«é¢ãã話ã§ããSetã¯ã©ã¹ã¯å
é¨çã«Hashã§éåã表ç¾ãã¦ããã®ã§ãããSet#freezeããã¨å
é¨ã®Hashãfreezeãã¾ãããã£ã¦ãfreezeããSetã¤ã³ã¹ã¿ã³ã¹ãclone(freeze: false)
ã§è¤è£½ãã¦ããå
é¨çãªHashã¯freezeãããã¾ã¾ã«ãªãã¨ããåé¡ãããã¾ãããããã§ãcloneæã«å¼ã°ããinitialize_clone
ã¡ã½ããã«freeze:
ãã¼ã¯ã¼ãã渡ãããã«ãã¦ãå
é¨çãªHashã®cloneã«freeze:
ãã¼ã¯ã¼ãã渡ããããã«å¤æ´ããã¾ããã
(mame)
eval
å
ã®ãã¡ã¤ã«åãè¡çªå·ãbinding
ããç¶æ¿ããªãããã«ãªã£ã
- Kernel#eval when called with two arguments will use "(eval)" for
__FILE__
and 1 for__LINE__
in the evaluated code. [Bug #4352] - Binding#eval when called with one arguments will use "(eval)" for
__FILE__
and 1 for__LINE__
in the evaluated code. [Bug #4352] [Bug #17419]
eval
ã®ä¸ã§ã®__FILE__
ã__LINE__
ãå¾®å¦ã«å¤ããã¾ãã次ã®ä¾ãè¦ã¦ãã ããã
1: # eval-test.rb 2: b = binding 3: 4: eval("p __LINE__", b) #=> Ruby 2.7ã§ã¯è¦åã¨ã¨ãã«2ãRuby 3.0ã§ã¯1
ãã®ã³ã¼ãã¯ãRuby 2.7ã§å®è¡ããã¨ã次ã®ããã«ï¼è¦åã¨ã¨ãã«ï¼2ãåºã¦ãã¾ããã
$ ruby eval-test.rb eval-test.rb:2: warning: __LINE__ in eval may not return location in binding; use Binding#source_location instead eval-test.rb:4: warning: in `eval' 2
Ruby 2.7ã¾ã§ã®eval
ã¯ããã©ã«ãã§ã渡ãããbindingã®ãã¡ã¤ã«åãè¡çªå·ãç¶æ¿ãã¦ãã¾ãããããã§è¡¨ç¤ºããã2ã¯ãbindingãä½ãããè¡çªå·ã§ãã
ãããããã¯æã¨ãã¦æ··ä¹±ã®å ã§ããã次ã®ä¾ãè¦ã¦ãã ããã
1: b = binding 2: 3: eval(<<END, b) 4: 5: raise 6: END
ãããRuby 2.7ã§å®è¡ããã¨ã次ã®ãããªããã¯ãã¬ã¼ã¹ãåºã¾ãã
$ ruby2.7 eval-test.rb Traceback (most recent call last): 2: from eval-test.rb:3:in `<main>' 1: from eval-test.rb:3:in `eval' eval-test.rb:2:in `<main>': unhandled exception
eval-test.rbã®2è¡ç®ã§ä¾å¤ãåºããã¨ã«ãªã£ã¦ãã¾ããããã®è¡ã¯ç©ºè¡ã§ããè¬ã§ãããªããããã¯ãbindingã®ãã¡ã¤ã«åã¨è¡çªå·ãæé»çã«å¼ãç¶ãã çµæã§ãã
Ruby 3.0ããã¯ããã®å¼ãç¶ããè¡ããªãããã«ãªãã¾ããã
$ ruby3.0 eval-test.rb (eval):2:in `<main>': unhandled exception from eval-test.rb:3:in `eval' from eval-test.rb:3:in `<main>'
ç´ããããçµæããªããªãã¾ããã
ãªããããå¾æ¥ã©ããã®æåã«ãããå ´åã¯ãeval("p __LINE__", b, *b.source_location)
ã®ããã«Binding#source_location
ã使ã£ã¦ãã ãããã¾ããBinding#eval
ãåæ§ã«å¤ãã£ã¦ãã¾ããb.eval(src)
ã¯b.eval(src, *b.source_location)
ã¨ãã¦ãã ããã
ï¼mameï¼
Kernel#lambda
ã«ãããã¯å¼æ°ã渡ãããè¦åãåºãããã«ãªã£ã
- Kernel#lambda now warns if called without a literal block. [Feature #15973]
ã©ããããlambda(&pr)
ã®ããã«æ¸¡ãã¨ãProcãªãã¸ã§ã¯ãã lambda ã«å¤æãã¦ããããã¨ãã誤解ããã£ãããã§ãããã¤ãã®å ´æã§å®éã«ä½¿ããã¦ãã¾ãããããå®ã¯ãããªæ©è½ã¯ç¡ãã®ã§ãlambda{ ... }
ã®ããã«ãããã¯ãæå®ããã®ã§ã¯ãªããlambda(&pr)
ã®ããã« Proc ã渡ããå ´åã«ã¯è¦åãåºãããã«ãªãã¾ããã
lambda(&proc{}) #=> warning: lambda without a literal block is deprecated; use the proc without lambda instead
å°æ¥çã«ã¯ã¨ã©ã¼ã«ãªãã®ããªãã
(ko1)
å¾ããè¡ã£ã Module#include
ãç¡è¦ãããªããªã£ã
- Module#include and Module#prepend now affect classes and modules that have already included or prepended the receiver, mirroring the behavior if the arguments were included in the receiver before the other modules and classes included or prepended the receiver. [Feature #9573]
ã¢ã¸ã¥ã¼ã«ã®includeã®é åºã«ãã£ã¦ã¯ãincludeãç¡è¦ãããããã«è¦ããã±ã¼ã¹ãããã¾ããããããä¿®æ£ãããã¨ããå 容ã§ãã
# ã¢ã¸ã¥ã¼ã«ã 2 ã¤ä½ã module M1; end module M2; end # ã¯ã©ã¹ C 㯠M1 ã include ãã class C include M1 end # M1 ãå¾ãã M2 ã include ãã module M1 include M2 end # C ã®ã¹ã¼ãã¼ã¯ã©ã¹ã« M2 ãå ¥ã£ã¦ããªãã£ããã3.0 ããå ¥ãããã«ãªã£ã p C.ancestors #=> [C, M1, Object, Kernel, BasicObject] # 2.7 p C.ancestors #=> [C, M1, M2, Object, Kernel, BasicObject] # 3.0
ãã®ããã«ããã¨ãã M2 ã include ãã¦ããã®ãç¡è¦ããã¦ãã¾ãããç¡è¦ããã¦ããã®ã¯å®è£ ã®é½åã§ããããæ°åã§ä¿®æ£ããã¾ããã
å人çãªãªã¹ã¹ã¡ã¯ããã®ããã«ããã¨ããã¢ã¸ã¥ã¼ã«ã include ãããããªãã¨ã¯ããªããã¨ã§ãããã¨ãã include/prepend ã¯ä»ã«ãåé¡ããããã¨ãç¥ããã¦ãã¾ãï¼include ã®é åºã«ãã£ã¦ã¯ãancestors ã«åãã¢ã¸ã¥ã¼ã«ãè¤æ°åç¾ãã¦ãã¾ãã¨ããprepend ã絡ããã¨æå³ãããããªããªãã¨ãï¼ã
ï¼mameï¼
private attr_reader :foo
ã¨æ¸ããããã«ãªã£ã
Module#public, Module#protected, Module#private, Module#public_class_method, Module#private_class_method, toplevel "private" and "public" methods now accept single array argument with a list of method names. [Feature #17314]
Module#attr_accessor, Module#attr_reader, Module#attr_writer and Module#attr methods now return an array of defined method names as symbols. [Feature #17314]
Module#alias_method now returns the defined alias as a symbol. [Feature #17314]
表é¡ã®ã¨ãããprivate 㪠attr_reader ãªã©ãã·ã³ãã«ã«æ¸ããæ§ã«ãªãã¾ããã
å ·ä½çãªå¤æ´ã¨ãã¦ã¯ã(1) attr_reader ã attr_accessor ãå®ç¾©ããã¡ã½ããã®ã·ã³ãã«ã®é åãè¿ãããã«ãªã£ãã(2) public ã private ãé åãå¼æ°ã«åãåããããã«ãªã£ããã§ãã
class Foo # (1) attr_reader ã attr_accessor ãå®ç¾©ããã¡ã½ããã®ã·ã³ãã«ã®é åãè¿ãããã«ãªã£ã attr_accessor :foo, :bar #=> [:foo, :foo=, :bar, :bar=] # (2) public ã private ãé åãå¼æ°ã«åãåããããã«ãªã£ã private [:foo, :foo=, :bar, :bar=] # 2 ã¤ãçµã¿åãããã¨ã次ã®ããã«æ¸ãã¦ãåãæå³ã«ãªã private attr_accessor :foo, :bar end
ã¾ããalias_method
ã¡ã½ãããå®ç¾©ãããã¡ã½ããã®ã·ã³ãã«ãè¿ãããã«ãªãã¾ãããããã private alias_method :foo, :bar
ã¨æ¸ãããã¨ãçã£ããã®ã§ãã
(mame)
Proc ã®ç価å¤å®ï¼Proc#==
, Proc#eql?
ï¼ãå°ãç·©åããã
- Proc#== and Proc#eql? are now defined and will return true for separate Proc instances if the procs were created from the same block. [Feature #14267]
ããã¾ã§ãProc#==
ã¯ãåããªãã¸ã§ã¯ããã©ããã§å¤æãã¦ãã¾ããï¼ã¨ããããProc#==
ã¯ãªãã¦ãObject#==
ã使ããã¦ããï¼ããããã®å¶éãç·©åããåãã¡ã½ããå¼ã³åºãã®ãããã¯ãã©ã¡ã¼ã¿ã§ä½ãããProcã¯ãProc#==
ã§trueãè¿ãããã«ãªãã¾ãããæ£ç´ããããèªãã§ãæå³ããããªãã¨æãã®ã§ããããããé¢ä¿ããã¨ããã¯ãã¬ã ã¨æãã®ã§ããã¾ãæ°ã«ããªãã¦ããã¨æãã¾ããåºæ¬çã«ã¯ãProc#==
ãªãã¦ä½¿ããªãã§ãã ãããã¾ããHash ã®ãã¼ã«ããã¹ãã§ããªãã§ãããã
ä¸å¿ãã¡ããã¨æ¸ãã¦ããã¾ãã¨ããã㯠Ruby 2.5 ã§å°å ¥ããã lazy proc allocationï¼Ruby 2.5 ã®æ¹åãèªæ ¢ããã - ã¯ãã¯ãããéçºè ããã° ãLazy Proc allocation ã«ãããããã¯ãã©ã¡ã¼ã¿ãç¨ãããããã¯æ¸¡ãã®é«éåã ï¼ã®éäºæã解æ¶ããããã®ãã®ã§ãã
def bar &b b end def foo(&b1) b2 = bar(&b1) p b1 == b2 p b1.equal? b2 end foo{} #=> b1 == b2 b1.equal? b2 # Ruby 2.4 以å true true # Ruby 2.5-2.7 false false # Ruby 3.0 true false
Ruby 2.4 ã§ã¯ãb1
ã¯Proc
ãçæãããããbar(&b1)
ã¨ãã¦æ¸¡ãã¦ãããã§ã«Proc
ãçæããã¦ããã®ã§ãåã«ãã® Proc ã渡ãã ãã§ããããã®ãããb1.equal? b2
㯠true ã§ããã
ããããLazy Proc Allocation ã«ãã£ã¦ãProc ã®çæãé
延ããã¦ãã¾ãã®ã§ãbar ã§åã㦠Proc ãä½ããããã¦ãã®æ
å ±ã¯ foo å´ã«ã¯æ¸¡ããªãã®ã§ foo ã§ãæ°ãã« Proc ãä½ããb1 == b2
㨠b1.equal? b2
ã¨ãã« false ã«ãªã£ã¦ãã¾ã£ã¦ããã®ã§ããããã®æåèªä½ã¯éäºæã¨ãã¦å½æããèªèãã¦ããã®ã§ããããã¾ã¼èª°ãå°ãããããã¨æã£ã¦ãããããªãã RSpec ã§è¸ãã ããããã§ãããã
ã¨ãããã¨ã§ãã©ããããã¨æã£ã¦ããããProc#==
ãå¤ããã°ããã®ã§ã¯ï¼éããªãã¸ã§ã¯ãã§ããããããã±ã¼ã¹ãªã true ã«ãªããã㪠Proc#==
ã«ããã°è¯ãã®ã§ã¯ï¼ã¨ããç´ æ´ããã解決çãå¾ã¦ã解決ããã®ã§ããã
(ko1)
Ractor ã«ãã並å並è¡ããã°ã©ãã³ã°ã®ãµãã¼ã
- New class added to enable parallel execution. See doc/ractor.md for more details.
Rubyã§ç°¡åã«ä¸¦å並è¡ããã°ã©ãã³ã°ãè¡ãããã® Ractor ãå°å ¥ããã¾ããã
ã¾ã ãå®é¨çæ©è½ï¼ä»æ§ãä¸å®å®ãå®è£
ãä¸å®å®ï¼ãªã®ã§ãæåã« Ractor.new
㧠Ractor ãçæããã¨ããè¦åãåºãããã«ãªã£ã¦ãã¾ãã
ç´°ããä»æ§ã«ã¤ãã¦ã¯ãå¥ã®è³æããåèã«ãã¦ãã ãããä¸è¨ã«ãç§ã®çºè¡¨ããè³æã¸ã®ãªã³ã¯ãæ²è¼ãã¦ããã¾ãã
- ruby/ractor.md at master · ruby/ruby
- Ractor report - RubyKaigi Takeout 2020
- Ruby ã« Software Transactional Memory (STM) ãå ¥ãããã¨æã£ã話 - ã¯ãã¯ãããéçºè ããã°
ï¼è¿½è¨ï¼è§£èª¬ããè¨äºãããã¾ããï¼
(ko1)
Random::DEFAULT ãéæ¨å¥¨ã«
Random::DEFAULT
now refers to theRandom
class instead of being aRandom
instance, so it can work withRactor
. [Feature #17322]Random::DEFAULT
is deprecated since its value is now confusing and it is no longer global, useKernel.rand
/Random.rand
directly, or create aRandom
instance withRandom.new
instead. [Feature #17351]
ããã©ã«ãã®ä¹±æ°çæå¨ Random::DEFAULT
ãéæ¨å¥¨ã«ãªãã¾ããã代ããã« Random
ã¯ã©ã¹ãªãã¸ã§ã¯ããå©ç¨ã§ãã¾ããã¾ããRandom::DEFAULT
ã¯ãRandom
ã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ã ã£ãã®ããRandom
ã¯ã©ã¹èªä½ãè¿ãããã«ãªãã¾ããã
p Random::DEFAULT == Random #=> true Random::DEFAULT.srand(0) # seed ãæå®ã㦠p Random::DEFAULT.rand(10) # => 5 p Random::DEFAULT.bytes(3) #=> "\xC0\xCC!" # Random ã¯ã©ã¹ã§åããã¨ãã§ãã Random.srand(0) p Random.rand(10) #=> 5 p Random.bytes(3) #=> "\xC0\xCC!"
éæ¨å¥¨ã«ãªã£ãã®ã§ã-w ä»ãã§å®è¡ãã¦ããã¨ãã« Random::DEFAULT
ãåç
§ããã¨è¦åãåºãããã«ãªãã¾ããã
$ ruby -w -e 'p Random::DEFAULT' -e:1: warning: constant Random::DEFAULT is deprecated Random
ãã¨ãã¨ãRandom
ã¯ã©ã¹ã«ã¯ rand
ãªã©ã®ã¡ã½ããããã£ã¤ãã¦ãã¾ããããããã®ã¡ã½ããã¯ãRandom::DEFAULT
ã¨åãä¹±æ°çæå¨ãåç
§ãã¦å®è¡ãã¾ãããã®ãããRandom::DEFAULT
ã®ä»£ããã« Random
ãç¨ããã°ãã ããããã¾ãããããã«ãªã£ã¦ãã¾ãããã ãã¯ã©ã¹ã«ãªã£ãã®ã§ãMarshal
ãªã©ã«å¯¾å¿ããªããªã£ãã®ãè¥å¹²ã®éäºæã«ãªã£ã¦ãã¾ãï¼ä¸å¿ãå
¬éããã¦ãã gem ã調ã¹ãéãããã®ãããªãã¨ããã¦ãããã®ã¯ããã¾ããã§ããï¼ã
ãªã㧠Random
ã¯ã©ã¹ãç¹ç°ã¡ã½ããã¨ã㦠rand
ãªã©ãæã£ã¦ããã®ãããããªãã£ãã®ã§ããï¼ç§ã¯åãã¦ç¥ã£ãï¼ãèãã¦ã¿ãã¨ãããã©ã«ãã®ä¹±æ°çæå¨ãç¨ããã¡ã½ãããç½®ãå ´æã欲ããã£ããã¨ãããã¨ã§ããï¼Random.rand()
ãªã©ãã¤ããã®ã¯ 1.9.2ãRandom::DEFAULT
ãã§ããã®ã¯ 1.9.3ã§ãã¡ãã£ã¨å¾ãªãã§ããï¼ããã§ã« Kernel#rand
ãªã©ã¯ããã¾ããããRandom#bytes
ãªã©ã¯ã確ãã«ç½®ãå ´æãå°ãããã§ããã
ãã®å¤æ´ã®èæ¯ããç´¹ä»ãã¾ãã
Random::DEFAULT
ã¯ãããã¾ã§ Kernel#rand
ãªã©ãå©ç¨ããç似乱æ°çæå¨ãããã¦ãã¾ãããã¤ã¾ããrand(10)
ãªã©ãå®è¡ããã¨ããã® Random::DEFAULT
ã®çæå¨ã®ä¹±æ°ãæ¶è²»ãã¦ããããã§ãã
ããããRactor ãå ¥ãã¨ãåæã«è¤æ°ã® Ractor ãçæå¨ãå©ç¨ãã¦ãã¾ããããçæå¨ã®å®è£ ãã¹ã¬ããã»ã¼ãã«ããå¿ è¦ãããã¾ããããã ããã®å¯¾å¿ã¯çµæ§å¤§å¤ã ãªããã¨ããã®ã§ãçæå¨ã¯ Ractor ãã¼ã«ã«ã¨ããã®ãè¯ããããã¨ãªãã¾ããï¼ã¤ã¾ããä¹±æ°çæå¨ã¯ Ractor ãã¾ããã§å ±æãããªãï¼ã
ç¾å¨ã®å®ç¾©ã ã¨ãKernel#rand
ãªã©ã¯ãå¯ä¸åå¨ãã Random::DEFAULT
ãä¹±æ°çæå¨ã¨ãã¦å©ç¨ãããã¨ããå®ç¾©ãªã®ã§ããããããã¯ã«ãªãã¾ãããRactor ãã¨ã«æã¤ããã«ã¯ãRandom::DEFAULT
ã使ããã¨ããããã«ã¯ãããªããã®ã§ããããããã§ãRandom::DEFUALT
ã®æå³ãå¤æ´ããå¿
è¦ãåºã¦ãã¾ãããåè£ã¨ãã¦ã¯ã次ã®äºã¤ã§ãã
- (1)
Random::DEFAULT
ã«ç¹æ®ãªRandom
ã¤ã³ã¹ã¿ã³ã¹ãè¨å®ãã¦ããã㯠Ractor local ãªããã©ã«ãã®ä¹±æ°çæå¨ãåç §ãã - (2)
Rnadom
ã¯ã©ã¹ãªãã¸ã§ã¯ãã¯ããªããRandom
ã¤ã³ã¹ã¿ã³ã¹ããã¤ã¡ã½ãããå®è£ ãã¦ããã®ã§ãRandom::DEFAULT = Random
ã¨ããå®ç¾©ã«ãã¦ãã¾ããRandom.rand
ãªã©ã¯ Ractor local ãªä¹±æ°çæå¨ãåç §ãããã¨ããæå³ã«å¤æ´ãã
ã¨ããããã§ãå®è£ ã®é¢åãå°ãªã (2) ãé¸ã¶ãã¨ã«ãã¾ãããç¹ç°ã¡ã½ãããªããRactor local ãªãã®ãåç §ãããã¨ããç¹å¥ãªæå³ãããã¾ããã¨è¨ãå¼µã£ã¦ãåãå ¥ããããã ãã
ãã¾ããä¹±æ°çæå¨ãæèãããã¨ã¯ãªãã®ã§ã¯ãªããã¨æãã®ã§ãããã¡ãã£ã¨å¤ãã£ã¦ããã¨ãããã¨ã¯ãæ¿ç¥ãããã ããã
(ko1)
Symbol#to_proc
ã lambda ãè¿ãããã«ãªã£ã
- Symbol#to_proc now returns a lambda Proc. [Feature #16260]
Symbol#to_proc
ã§çæãã Proc ã lambda ã¨ãªãããã«ãªãã¾ããã
Proc 㯠proc{}/Proc.new{}
ããã³ã¡ã½ããã®ãããã¯ä»®å¼æ°ã§ããã¦çæããå ´åã¨ãlambda{}
ã->{}
ã§çæããå ´åã§æåãç°ãªãã¾ããããã§ã¯ãåè
ãprocãå¾è
ã lambda ã¨å¼ã¶ãã¨ã«ãã¾ããProc#inspect
ã§ãlambda ã®å ´å lambda
ã¨åºã¾ãã
p ->{} #=> #<Proc:0x00000280db845220 t.rb:1 (lambda)>
proc 㨠lambda ã®ãã£ã¨ãããããããéãã¯ãå¼æ°ã®æ°ã®ãã§ãã¯æ©è½ã§ããããproc ã¯ææ§ã«è§£éããã®ã§ã渡ãããå®å¼æ°ã®æ°ã¨ä»®å¼æ°ã®æ°ãéã£ã¦ããä½ããªããªãã¨ãè¯ãæãã«ï¼ãã®è¯ãæãããã°ã¨ãããæ··ä¹±ãå¼ãã§ãããã§ãã...ï¼è§£éãã¾ããlambda ã¯éãã¨ã¨ã©ã¼ã«ãªãã¾ãã
proc{|a| p a}.call(1, 2) #=> 1 ->a{p a}.call(1, 2) #=> `block in <main>': wrong number of arguments (given 2, expected 1) (ArgumentError)
ã§ãSymbol#to_proc
ã§ä½ã£ãProcãªãã¸ã§ã¯ãã¯ãlambda ã£ã½ãæåã«ãªãã®ã«ãinspect ãã¦ã lambda ã£ã¦åºã¦ããªãã®ã¯å¤ã ãããã¨ãããã¨ã§ãlambda ã«ãªãã¾ããã
pr = :object_id.to_proc p pr #=> #<Proc:0x00000236441f1270(&:object_id) (lambda)> # ruby 3.0 ãã (lambda) ãã¤ãã p pr.call(1) # 1.object_id ã¨åã #=> 1.object_id ã®çµæ 3 ãè¿ã p pr.call(1, 2) # 1.object_id(2) ã¨åã #=> in `object_id': wrong number of arguments (given 1, expected 0) (ArgumentError)
(ko1)
ã·ã³ãã«ã®ååã«å¯¾å¿ããæååãè¿ã Symbol#name
ã®è¿½å
- Symbol#name has been added, which returns the name of the symbol if it is named. The returned string is frozen. [Feature #16150]
:sym.name #=> "sym"
ã¨ãªããã㪠Symbol#name
ãå°å
¥ããã¾ãããã§ããString#to_s
ã§ãåããããªæåã ã£ããã§ããããä½ãéããã¨ããã¨ãè¿ã£ã¦ããæååã frozen ã«ãªã£ãã®ã§ãããfrozen ã«ãªã£ã¦ãããããéè¤æé¤ãã¤ã¾ãä½åèªãã§ãåãæååãªãã¸ã§ã¯ããè¿ããã¨ãå¯è½ã«ãªãã¾ãããã¿ããªãæååçæãæé¤ãããã¦ãããããªããã§ããã
ãã¨ãã¨ãSymbol#to_s
ã freeze ã«ãã¦ãã¾ãããã£ã¦ææ¡ããã£ã¦ããã£ã¬ã³ã¸ããã¦ããã§ãããéäºæãã¤ããã¨ãããã¨ã§ reject ã«ãªãã¾ããããªããå¥ã®æ¹æ³ããªãããã¨ãããã¨ã§ãSymbol#name
ã¨ããå¥æ¡ãç¨æããã¾ããããããRubyKaigi takeout 2020 ã®ãã¨ã® zoom ã§ããªããçãä¸ãã£ã¦å
¥ãããã§ããã£ãããï¼
(ko1)
ãããããã¯æ¤ç¥ãç¡å¹ã«ãããªãã·ã§ã³ãå°å ¥ããã
- Thread.ignore_deadlock accessor has been added for disabling the default deadlock detection, allowing the use of signal handlers to break deadlock. [Bug #13768]
ã¹ã¬ããã§ããã¯ããäºãå¾ ã£ã¦ãã¾ã£ã¦ã«ã£ã¡ããã£ã¡ããããªããªããããªå ´åããããããã¯ã¨å¼ã°ãã¾ããRuby ã«ã¯ç°¡åãªãããããã¯æ¤åºæ©è½ãããããã¹ã¦ã§ã¯ãªãã§ããããããããã¯ã«ãªã£ãã¨ãã«ä¾å¤ãçºçãããï¼å¤åãã°ã§ãããããï¼ãããã°ã«æç¨ãªæ å ±ãåºåãã¾ãã
q = Queue.new Thread.new{ q.pop } q.pop __END__ t.rb:6:in `pop': No live threads left. Deadlock? (fatal) 2 threads, 2 sleeps current:0x000001b07776b280 main thread:0x000001b0721a80b0 * #<Thread:0x000001b07221ca68 sleep_forever> rb_thread_t:0x000001b0721a80b0 native:0x0000000000000128 int:0 * #<Thread:0x000001b0777790d8 t.rb:3 sleep_forever> rb_thread_t:0x000001b07776b280 native:0x0000000000000184 int:0 from t.rb:6:in `<main>'
ãã®ä¾ã§ã¯ã1ã¤ã® Queue ããã¹ã¦ã®ã¹ã¬ãããå¾ ã£ã¦ããã®ã§ã誰ãèµ·ãããã¨ã¯ç¡ãã ããã¨ãããã¨ã§ããããããã¯ã¨èªå®ããã¨ã©ã¼ãåºåãã¦ãã¾ãã
ãã¦ãä¸ã®ä¸ã«ã¯ã·ã°ãã«ã®å°çã«ãããã¹ã¬ããå®è¡ã復帰ãããããã¨ããããã°ã©ã ãããã¾ãã
q = Queue.new trap(:INT){ q << 1 } q.pop __END__ t.rb:4:in `pop': No live threads left. Deadlock? (fatal) 1 threads, 1 sleeps current:0x0000019cecf68630 main thread:0x0000019cecf68630 * #<Thread:0x0000019cecfdca98 sleep_forever> rb_thread_t:0x0000019cecf68630 native:0x0000000000000128 int:0 from t.rb:4:in `<main>'
ãã®ãããªå ´åã§ããtrap ã®åå¨ã«æ°ã¥ããããããããã¯ã¨å¤å®ãã¦ãã¾ãã¾ããã§ããããã°ã©ãã¼çã«ã¯ãããããã¯ãããªãã®ã§ä½ã¨ããã¦ã»ãããã¨ãããªã¯ã¨ã¹ããæ¥ã¦ãã¾ããã
ããããè°è«ããã®ã§ããï¼trap ã1ã¤ã§ãè¨å®ããã¦ããã° deadlock æ¤ç¥ãã¹ãããããã¨ããããã§ããããããã°ã©ã ã®å®è¡ãåéããã¨ã¯éããªãããªãã¨ãï¼ãçµå±ããããããã¯æ¤ç¥èªä½ããªãã«ãããæ©è½ã§ããã®ã§ã¯ãªãããã¨ãªãã¾ãããããã Thread.ignore_deadlock = true
ã§ãã
Thread.ignore_deadlock = true q = Queue.new trap(:INT){ q << 1 } q.pop # Ctrl-C ã§çµäºãã
ã¾ããããã¾ãé£ãããã¨ããªãã»ããããã§ãããã·ã°ãã«ã¨ãé£ããã
(ko1)
è¦åå¨ãã®ã¡ã½ããã category
ãã¼ã¯ã¼ããåãåãããã«ãªã£ã
- Warning#warn now supports a category keyword argument. [Feature #17122]
Ruby 2.7ãããè¦åã«ã«ãã´ãªã¨ããæ¦å¿µãå°å
¥ããã¾ããããã¾ã®ã¨ãã:deprecated
ã¨:experimental
ã¨ããªããã¨ãã3種é¡ã®ã«ãã´ãªã ãã§ãã
:deprecated
ã:experimental
ã®ã«ãã´ãªã«å±ãè¦åã¯Rubyã®ã¤ã³ã¿ããªã¿å
é¨ã§ããä½ããªãã£ãã®ã§ãããã¦ã¼ã¶ãã«ãã´ãªã«å±ãè¦åãåºããããã«ãªãã¾ããã
warn("foo is deprecated", category: :deprecated)
ä¸ã®è¦åã¯ãWarning[:deprecated] = true
ãæå¹ã«ãã¦ããªãã¨è¡¨ç¤ºããã¾ããã
ã¾ããè¦åçºçãããã¯ããã¡ã½ããWarning.warn
ãããã®ã§ãããããã«ãcategoryã®æ
å ±ã渡ãããããã«ãªãã¾ããã
def Warning.warn(msg, category: nil) p [msg, category] end warn("foo is deprecated", category: :deprecated) #=> ["foo is deprecated", :deprecated]
ï¼mameï¼
â æ¨æºã©ã¤ãã©ãªã®ã¢ãããã¼ã
ã©ã¤ãã©ãªããããããã¢ãããã¼ããã¾ãããNEWS ã«ããã¤ãè¼ã£ã¦ãã¾ãããä»åã¯èª¿ã¹ãã®ãé¢åãªã®ã§ãã¹ããããã¾ãã
BigDecimal
Update to BigDecimal 3.0.0
This version is Ractor compatible.
Bundler
- Update to Bundler 2.2.3
CGI
Update to 0.2.0
This version is Ractor compatible.
CSV
- Update to CSV 3.1.9
Date
Update to Date 3.1.1
This version is Ractor compatible.
Digest
Update to Digest 3.0.0
This version is Ractor compatible.
Etc
Update to Etc 1.2.0
This version is Ractor compatible.
Fiddle
- Update to Fiddle 1.0.5
IRB
- Update to IRB 1.2.6
JSON
Update to JSON 2.5.0
This version is Ractor compatible.
Set
Update to set 1.0.0
SortedSet has been removed for dependency and performance reasons.
Set#join is added as a shorthand for
.to_a.join
.Set#<=> is added.
Socket
- Add :connect_timeout to TCPSocket.new [Feature #17187]
Net::HTTP
Net::HTTP#verify_hostname= and Net::HTTP#verify_hostname have been added to skip hostname verification. [Feature #16555]
Net::HTTP.get, Net::HTTP.get_response, and Net::HTTP.get_print can take the request headers as a Hash in the second argument when the first argument is a URI. [Feature #16686]
Net::SMTP
Add SNI support.
Net::SMTP.start arguments are keyword arguments.
TLS should not check the host name by default.
OpenStruct
Initialization is no longer lazy. [Bug #12136]
Builtin methods can now be overridden safely. [Bug #15409]
Implementation uses only methods ending with
!
.Ractor compatible.
Improved support for YAML. [Bug #8382]
Use officially discouraged. Read OpenStruct@Caveats section.
Pathname
- Ractor compatible.
Psych
Update to Psych 3.3.0
This version is Ractor compatible.
Reline
- Update to Reline 0.1.5
RubyGems
- Update to RubyGems 3.2.3
StringIO
Update to StringIO 3.0.0
This version is Ractor compatible.
StringScanner
Update to StringScanner 3.0.0
This version is Ractor compatible.
â éäºæ
æ£è¦è¡¨ç¾ãªãã©ã«ãããã³ Range ãªãã¸ã§ã¯ãã freeze ããã
- Regexp literals and all Range objects are frozen [Feature #8948] [Feature #16377] [Feature #15504]
ã ããã Ractorã®é½åãªãã§ãããæ£è¦è¡¨ç¾ãªãã©ã«ã¨Rangeãªãã¸ã§ã¯ãã®ãã¹ã¦ã freeze ããããã¨ã«ãªãã¾ããã
p /abc/.frozen? #=> Ruby 3.0 ãã true p /a#{42}c/.frozen? #=> Ruby 3.0 ãã true p Regexp.new('abc').frozen? #=> å¤ããã false p (1..2).frozen? #=> Ruby 3.0 ãã true p Range.new(1, 2).frozen? #=> Ruby 3.0 ãã true
ã¾ãã誰ããããã®ãªãã¸ã§ã¯ããå¤æ´ããªããããã¨æãã®ã§ãæ®éã®äººã«ã¯æ°ã«ããªãã¦ãããå¤æ´ãããªããã¨æãã¾ãã
Regexp.new('abc')
ã freeze ããã¦ããªãã®ã¯ãå®éã«ãããå¤æ´ãã人ãããããã§ãï¼ç¹ç°ã¡ã½ããã追å ãã¦ããï¼ããããªéäºææ°ã«ããªãã¦ããããã©ãã©ãå¤æ´ããããã¼ãã¨ããæè¦ããã£ããã§ããï¼Matzã¨ãï¼ãããã¯ä¿å®çã«ããã¾ãããããæ°ã®ãã人ãããã°ãããã freeze ãããããããã¾ããã
ãããªæãã§ãImmutable ã£ã½ããªãã¸ã§ã¯ãã¯ã©ãã©ã freeze ããã¦ãã¾ãã
é¢ä¿ãªããã©ããã® freeze åã®æåã®ã»ããSymbol
㯠2013 å¹´ã« freeze ããã¾ããã
* include/ruby/ruby.h: make Symbol objects frozen. ã» ruby/ruby@1e27eda
ã³ãããã¡ãã»ã¼ã¸ã§ "I want to freeze this good day, too." ã£ã¦å¯¿ãã§ã¾ããã©ããããç§ãçµå©ããæ¥ã ã£ããã§ããããè¨å¿µã³ãããã
(ko1)
Hash#each
ã常ã«2è¦ç´ é
åãyieldããããã«
- EXPERIMENTAL: Hash#each consistently yields a 2-element array [Bug #12706]
- Now
{ a: 1 }.each(&->(k, v) { })
raises an ArgumentError due to lambda's arity check.
- Now
ä¸è¨ã§è¨ãã°ãæé©åã®ãã°ä¿®æ£ã§ããé ã«èª¬æãã¾ãã
Hash ã¯åºæ¬çã«ããã¼ã¨å¤ãã¿ãã«ã«ããé åã yield ãã¾ãã
{ a: 1 }.each {|ary| p ary } #=> [:a, 1]
ããããå¼æ°ã2ã¤ããã¨ãã¯autosplatããã¾ãã
{ a: 1 }.each {|k, v| p k } #=> :a
ãã®ã¨ãããã¡ãã¡é åãä½ã£ã¦å解ããã®ã¯ç¡é§ãªã®ã§ãå¼æ°ã2ã¤ããã¨ãã¯å é¨çã«é åãä½ããªãããã«ããæé©åãè¡ããã¦ãã¾ããã
ããããã®æé©åã¯ããããã¯ãlambdaã§ããã¨ãã§ãé©ç¨ããã¦ãã¾ã£ã¦ãã¾ãããlambdaã¯autosplatãããªãã®ã§ãå¼æ°ã®æ°ãééã£ã¦ããã¨ããä¾å¤ãåºãã®ãæ£ããã£ãã§ãã3.0ã§ã¯ååã«å¾ãããããã¯ãlambdaã®ã¨ãã¯ä¾å¤ãæããããã«ãªãã¾ããã
# Ruby 2.7 { a: 1 }.each(&-> (k, v) { p k }) #=> :a # Ruby 3.0 { a: 1 }.each(&-> (k, v) { p k }) #=> ArgumentError (wrong number of arguments (given 1, expected 2))
ï¼mameï¼
æ¨æºåºåãã¯ãã¼ãºãããå¾ã«åºåãããã¨ãã¦ãEPIPEä¾å¤ãæããªãããã«ãªã£ã
- When writing to STDOUT redirected to a closed pipe, no broken pipe error message will be shown now. [Feature #14413]
ç´°ããæ¹åã§ããRuby 2.7ã¾ã§ã¯ãrubyã®åºåãheadãªã©ã§éä¸ã§æ¢ããã¨ãrubyã®ä¾å¤ããã¯ãã¬ã¼ã¹ãè¦ããããã¨ããã£ãã¨æãã¾ãã
$ ruby -e 'loop { puts "foo" }' | head foo foo foo foo foo foo foo foo foo foo Traceback (most recent call last): 5: from -e:1:in `<main>' 4: from -e:1:in `loop' 3: from -e:1:in `block in <main>' 2: from -e:1:in `puts' 1: from -e:1:in `puts' -e:1:in `write': Broken pipe @ io_writev - <STDOUT> (Errno::EPIPE)
ããã¯ãã¯ãã¼ãºããããã¤ãã«æ¸ãè¾¼ã¿ãè¡ã£ã¦ããããã§ããããããããã®ããã¯ãã¬ã¼ã¹ã¯ç¹ã«ä¾¿å©ã§ã¯ãªããã¨ãä» ã®ã¤ã³ã¿ããªã¿ã§ã¯ä½ãè¨ããã«çµäºãããã¨ãããRuby 3.0ããã¯åæ§ã«ä½ãè¨ããã«çµäºããããã«ãªãã¾ããã
(mame)
å®æ°ã®TRUE
ã¨FALSE
ã¨NIL
ãå®ç¾©ãããªãããã«ãªã£ã
TRUE
/FALSE
/NIL
constants are no longer defined.
ããç¥ããªããã§ãããé常ã«å¤ä»£ã®rubyã§ã¯ãtrueãfalseãnilã¯ãTRUEãFALSEãNILã§ãã *6 ããããç¾ä»£ã§ãäºææ§ã®ããã«ãªãã¨ãªãæ®ããç¶ãã¦ããã®ã§ãããã¤ãã«åé¤ããã¾ããããç²ããã¾ã§ããã
(mame)
Integer#zero?
ãæ¹ãã¦å®ç¾©ããã
- Integer#zero? overrides Numeric#zero? for optimization. [Misc #16961]
ããã¾ã§ãInteger#zero?
ã¯ãªãã¦ãã¹ã¼ãã¼ã¯ã©ã¹ã® Numeric#zero?
ã使ããã¦ãã¦ãããã§ãããé«éåã®ããã« Integer#zero?
ãæ¹ãã¦å®ç¾©ãã¾ãããã¨ãã話ã§ããã»ã¼å½±é¿ã¯ãªããã§ãããä¸ãä¸ Numeric#zero?
ãåå®ç¾©ãã¦ããInteger#zero?
ã«ã¯å½±é¿ãä¸ããªããã¨ã«ãªãã¾ãã
(ko1)
Enumerable#grep
ã¨grep_v
ã«æ£è¦è¡¨ç¾ã渡ãã¦ãããã¯ã渡ããªãã£ãå ´åã$~
ãæ´æ°ããªããªã£ã
- Enumerable#grep and grep_v when passed a Regexp and no block no longer modify Regexp.last_match [Bug #17030]
è¦åºãã®éãã§ãã
["foo", "bar", "baz", "qux"].grep(/ba./) p $~ #=> #<MatchData "baz"> in 2.7 p $~ #=> nil in 3.0
ary.grep(REGEXP)
ã ary.select {|e| e.match?(REGEXP) }
ããé
ãï¼MatchData ãªãã¸ã§ã¯ããçæããããï¼ï¼ãã¨ããåé¡ã«å¯¾ãã対å¿ã®ããã§ããéäºæãå
¥ããã«æé©åã§ããã¨ãããæ¢ãã¦ããããã¨ããé°å²æ°ã ã£ãæ°ãããã®ã§ãããæ°ã¥ãããéäºæãå
¥ã£ã¦ã¾ããã大ä¸å¤«ããªã
ï¼mameï¼
open-uri ã Kernel#open
ãä¸æ¸ãå®ç¾©ããªããªã£ã
- Requiring 'open-uri' no longer redefines
Kernel#open
. CallURI.open
directly oruse URI#open
instead. [Misc #15893]
ã¿ããªãæãã open-uri ã® Kernel#open
ãæ¶ãã¾ãããä»å¾ã¯ URI.open
ã使ã£ã¦ãã ããã
require "open-uri" # 2.7 ã§ã¯è¦åä»ãã§åãã¦ããã3.0 ã§ã¯ã¨ã©ã¼ open("https://example.com") {|f| f.read } #=> No such file or directory @ rb_sysopen - https://example.com (Errno::ENOENT) # 2.7 ã§ã 3.0 ã§ãåã URI.open("https://example.com") {|f| f.read } #=> "<!doctype html>\n<html>\n..."
ã»ãã¥ãªãã£åä¸ã®ããã ããã§ããKernel#open
ã¯ãã¡ã¤ã«ãéãã ãã§ãªãããã¤ãçµç±ã§ã³ãã³ããå®è¡ã§ããããopen-uriã®æ¡å¼µã§HTTPãã§ãããã§ããããã大å¤ä¾¿å©ãªã¡ã½ããã§ãããããããã¯æ»æè
ã«ã¨ã£ã¦ã便å©ãããããããããã¨ãããã¨ã§ããã¡ã¤ã«ãéãæ©è½å°ç¨ã®File.open("...")
ããURIããã§ããããæ©è½å°ç¨ã®URI.open("...")
ãªã©ã«åå²æ´çãé²ãã§ãã¾ãããã®ä¸ç°ã¨ãã¦ãopen-uriãKernel#open
ãä¸æ¸ãããã®ããããããã§ãã
ï¼mameï¼
SortedSet
ãåé¤ããã
- SortedSet has been removed for dependency and performance reasons.
set.rb ã«æ±ãåããã§å®è£
ããã¦ãã SortedSet
ãå¥ã® gem ã«åé¢ããã¾ããã
SortedSet ã«ã¢ã¯ã»ã¹ããã¨ä¾å¤ãåºã¾ãã
require "set" SortedSet #=> The `SortedSet` class has been extracted from the `set` library.You must use the `sorted_set` gem or other alternatives. (RuntimeError)
åé¤ãããçç±ã¯ãSortedSet
ãæ¨æºæ·»ä»ã§ãªã rbtree gem ã«ä¾åãã¦ãããã¨ï¼rbtree ããªãã¨ã㯠pure Ruby ã®å®è£
ãåãããã©ãããã¯é
ããã¨ï¼ã ããã§ãã
gem install sorted_set
ããã°ããã®ã¾ã¾åãããã«ãªãã¾ããå®ã¯ãrbtree gem ã 3.0.0 対å¿ãã¦ããªãããã«ç´åã¾ã§åããªãã£ãï¼æ¬è¨äºãæ¸ãã¦è©¦ãããã¨ã§æ°ã¥ããï¼ã®ã§ãããã¡ã³ããã® knu ããããªãªã¼ã¹ã¾ã§ã«å¯¾å¦ãã¦ããã¾ããã
ï¼mameï¼
â æ¨æºã©ã¤ãã©ãªã®éäºæ
Default gem å
- Default gems
- The following libraries are promoted the default gems from stdlib.
- English
- abbrev
- base64
- drb
- debug
- erb
- find
- net-ftp
- net-http
- net-imap
- net-protocol
- open-uri
- optparse
- pp
- prettyprint
- resolv-replace
- resolv
- rinda
- set
- securerandom
- shellwords
- tempfile
- tmpdir
- time
- tsort
- un
- weakref
- The following extensions are promoted the default gems from stdlib.
- digest
- io-nonblock
- io-wait
- nkf
- pathname
- syslog
- win32ole
- The following libraries are promoted the default gems from stdlib.
ãããã®ã©ã¤ãã©ãªã default gem åããã¾ãããGemfile ã«ãã¼ã¸ã§ã³æå®ãããã¨ããã¡ããå©ç¨ããã¾ãã
(ko1)
Ruby ã¤ã³ã¹ãã¼ã«æã«ãã¤ã³ã¹ãã¼ã«ãããªããªã£ãã©ã¤ãã©ãª
Bundled gems
- net-telnet and xmlrpc have been removed from the bundled gems. If you are interested in maintaining them, please comment on your plan to https://github.com/ruby/xmlrpc or https://github.com/ruby/net-telnet.
SDBM have been removed from ruby standard library. [Bug #8446]
- The issues of sdbm will be handled at https://github.com/ruby/sdbm
WEBrick have been removed from ruby standard library. [Feature #17303]
- The issues of webrick will be handled at https://github.com/ruby/webrick
ä¸è¨ã©ã¤ãã©ãªããRuby ã¤ã³ã¹ãã¼ã«æã«ã¤ã³ã¹ãã¼ã«ãããªããªãã¾ãããgem ã¨ãã¦å¥éã¤ã³ã¹ãã¼ã«ããå¿ è¦ãããã¾ãã
WEBrick ãä¸ç·ã«ã¤ã³ã¹ãã¼ã«ãããªããªãã®ã¯ãçµæ§å¤§ããå¤æ´ã§ãããæ代ãæãã¾ãã
(ko1)
C API updates
ããã¤ããC æ¡å¼µã©ã¤ãã©ãªãæ¸ãããã® C API ãæ´æ°ããã¦ãã¾ãã
- C API functions related to $SAFE have been removed. [Feature #16131]
$SAFE
ã«é¢ãã C API ãåé¤ããã¦ãã¾ãã
- C API header file
ruby/ruby.h
was split. [GH-2991] Should have no impact on extension libraries, but users might experience slow compilations.
ä»ã¾ã§ãruby.h
ã¨ãã大ããªããããã¡ã¤ã«ã«ããããæ¸ãã¦ãã£ãã®ããè¤æ°ã®ãã¡ã¤ã«ã«åå²ãã¦ãã¾ãã
ãã ãruby.h
ãããã¾ã§éãããã¹ã¦ã include ãã¦ããã®ã§ãæ¡å¼µã©ã¤ãã©ãªã®ãã«ãã«å©ç¨ããåã«ã¯å¤æ´ããã¾ããã
Memory view interface [EXPERIMENTAL]
- The memory view interface is a C-API set to exchange a raw memory area, such as a numeric array and a bitmap image, between extension libraries. The extension libraries can share also the metadata of the memory area that consists of the shape, the element format, and so on. Using these kinds of metadata, the extension libraries can share even a multidimensional array appropriately. This feature is designed by referring to Python's buffer protocol. [Feature #13767] [Feature #14722]
ã¡ã¢ãªä¸ã®ï¼å¤æ¬¡å ï¼é åãã¼ã¿ããããã»ã¹å ã®ä»ã®ã©ã¤ãã©ãªãªã©ã¨ã¡ã¿ãã¼ã¿ä»ãã§äº¤æããããã® Memory view interface ã追å ããã¾ããã主ã«ã大ããªè¡åãã¼ã¿ãç»åãã¼ã¿ãªã©ããããã©ã¤ãã©ãªã§å¦çãã¦ããã¨ãã«ãå¥ã®ã©ã¤ãã©ãªã«æ¸¡ãã¦å¦çããã¦ããããã¨ãã£ãç¨éã§å©ç¨ããã¾ããPython ã 㨠buffer protocol ã¨å¼ã°ãã¦ããæ©è½ãåç §ãã¦è¿½å ãããããã§ãã
対象ã¨ãªãã©ã¤ãã©ãªã X 㨠Y ã®2ã¤ã§ããã°ãX->YãY->X ã®ãã¼ã¿ã®å¤æå¨ãä½ãã ãã§ããããã§ããããããæ°ãå¢ããã¨å¤æå¨ã®æ°ãã©ãã©ãå¢ãã¦ããã¾ããMemory view interface ãç¨ããã°ãçµ±ä¸ãããã¡ã¿ãã¼ã¿ã®ãã¨ã§äº¤æãããã¨ãã§ããã®ã§ãå¤æå¨ãä½ããªãã¦ãè¯ããªãã¾ããã¾ããçã®ã¡ã¢ãªããã®ã¾ã¾æ¸¡ããã¨ãã§ããã®ã§ãä½ãåé·ãªãã©ã¼ãããï¼ä¾ãã° CSVï¼ã«å¤æãã¦æ¸¡ããã¨ãã£ããã¨ãä¸è¦ã«ãªãã®ã§ãæ§è½çãªå©ç¹ãããããã§ãã
éçºããã mrkn ããã«ããè¨äºãå ¬éããã¦ãã¾ãï¼MemoryView: Ruby 3.0 ããå°å ¥ãããæ°å¤é åã®ã©ã¤ãã©ãªéå ±æã®ããã®ä»çµã¿ - Speee DEVELOPER BLOG
- Ractor related C APIs are introduced (experimental) in "include/ruby/ractor.h".
Ractor ã«é¢ãã C API ãå°ã追å ããã¾ãããæ£ç´ãããã§è¶³ãã¦ããã®ãããããªãã®ã§ãããã¨ããããå¿ è¦ããªãã¨æãã¨ããã足ãã¦ãã¾ãã
(ko1)
â å®è£ ã®æ¹å
ã¡ã½ãããã£ãã·ã¥ãå·æ°ããã
New method cache mechanism for Ractor [Feature #16614]
- Inline method caches pointed from ISeq can be accessed by multiple Ractors in parallel and synchronization is needed even for method caches. However, such synchronization can be overhead so introducing new inline method cache mechanisms, (1) Disposable inline method cache (2) per-Class method cache and (3) new invalidation mechanism. (1) can avoid per-method call synchronization because it only uses atomic operations. See the ticket for more details.
ã¡ã½ããæ¢ç´¢ã®ãã³ã«ãã¯ã©ã¹ç¶æ¿æ¨ã辿ã£ã¦ã¡ã½ãããæ¢ãå½ã¦ãã®ã¯æéããããã®ã§ãã¡ã½ããæ¢ç´¢ã®çµæãããç¨åº¦ãã£ãã·ã¥ããã¨ããã®ãã¡ã½ãããã£ãã·ã¥ã§ãã
Ruby 2.7 ã¾ã§ã¯ãäºã¤ã®ã¡ã½ãããã£ãã·ã¥ã使ã£ã¦ãã¾ããã
- ã¤ã³ã©ã¤ã³ã¡ã½ãããã£ãã·ã¥ï¼ãã¤ãã³ã¼ãã«ãã£ãã·ã¥ãçªã£è¾¼ãã§ãããRuby 1.9 (YARV) ããå°å ¥
- ã°ãã¼ãã«ã¡ã½ãããã£ãã·ã¥ï¼åºå®é·ã®1åã®ãã¼ãã«ãç¨æãã¦ãããã«ã¡ã½ããæ¢ç´¢çµæãä¿åãã¦ããããããå¤ã Ruby ããã»ã¼åããã®ãå©ç¨
ããããã¡ãã£ã¨ãã¤æ¹åãã¦ãã£ã¦ããã®ã§ãããä»åããã£ã¨å¤æ´ãã¾ãããã¨ããã®ããè¤æ°ã® Ractor ããåæã«ã¢ã¯ã»ã¹ããã¨ãæãããããããã¨ãæå¾ ãããï¼å®éã90%以ä¸ã¯ã ããããããããï¼ã¤ã³ã©ã¤ã³ã¡ã½ãããã£ãã·ã¥ã«ããã¦ãæ¯åããã¯ãå¿ è¦ã«ãªããã¨ããæ§é ã ã£ãããã§ããããã¯ãæ±ãã¨ããªã¼ããããããããã®ã§ãããã§ã¯ããã¯ã®ä¸è¦ãªãã¼ã¿æ§é ãå¿ è¦ã«ãªãã¾ãã
ããã§ã次ã®ããã«å¤æ´ãã¾ããã
- (1) ã¤ã³ã©ã¤ã³ã¡ã½ãããã£ãã·ã¥ããæ¯åããã¯ãåããªãã¦ãããä»çµã¿ã«ãã
- (2) ã°ãã¼ãã«ã¡ã½ãããã£ãã·ã¥ããããã¯ã©ã¹ãã¨ã®ãã£ãã·ã¥ã«ãã
ä»çµã¿ãã¡ããã¨èª¬æããã®ã¯ã¨ã¦ãé¢åãªãã§ããã(1) ã¤ã³ã©ã¤ã³ãã£ãã·ã¥ã«ã¤ãã¦ã®ã¢ã¤ãã£ã¢ã¨ãã¦ã¯ãããã¾ã§1ã¤ã®ã¤ã³ã©ã¤ã³ãã£ãã·ã¥ãé½åº¦æ´æ°ãã¦ããã®ãããã£ãã·ã¥ã«å¿ è¦ãªæ å ±ã1ãªãã¸ã§ã¯ãã¨ãã¦ã¾ã¨ãã¦ããã¦ããã£ãã·ã¥ããã¨ãã«ã¯ããã¤ãã³ã¼ããããã®ãªãã¸ã§ã¯ãã¸ã®åç §ãä¿åããã¨ããã¢ãããã¯ãªå¦çã§æ¸ãããã«ãããã¨ãããã®ã§ãã
(1) ã®å¤æ´ã®ããã«ãæ¢åã®ã°ãã¼ãã«ã¡ã½ãããã£ãã·ã¥ã§ã¯ä¸è¶³ãããï¼ããããè²ã ä¸æºããã£ãï¼ããã®åº¦ (2) ã¯ã©ã¹ãã¨ã®ã¡ã½ãããã£ãã·ã¥ãç¨æãã¾ããã
æ§è½æ¹åã»ã¯ã·ã§ã³ã«ãããã§ãããå®ã¯ Ruby 3.0 ã§ãã¤ã¯ããã³ããã¼ã¯ã®æ§è½ã (JIT ãªãã®å ´å) å°ãè½ã¡ã¦ãã¦ãããããã®åå ã®ä¸ã¤ã§ãããããããã§ã並ååãã¦ããã許ãã¦ã
(ko1)
super
ã§å¿
è¦ãªã¡ã½ããæ¢ç´¢ããçµæããã£ãã·ã¥ãããã¨ã§é«éåãã
super
is optimized when the same type of method is called in the previous call if it's not refinements or an attr reader or writer.
super
ã§å¼ã³åºãã¡ã½ããã¯ãRuby 2.7 以åã§ã¯æ¯åã¡ã½ããæ¢ç´¢ãã¾ããã«ãã¦ããã®ã§ãããä»åæ¢ç´¢çµæãã»ãã®ã¡ã½ããå¼ã³åºãã¨åããããã£ãã·ã¥ãããã¨ã«ãã¦æ§è½æ¹åãè¡ãã¾ããã
(ko1)
ãã¼ã¯ã¼ãå¼æ°ã渡ãã¨ãã«ç¡é§ãªããã·ã¥ã®è¤è£½ãããã
- The number of hashes allocated when using a keyword splat in a method call has been reduced to a maximum of 1, and passing a keyword splat to a method that accepts specific keywords does not allocate a hash.
ãã¨ãã°ããããã³ã¼ããRuby 2.7 ã§ã¯ foo(**opt)
ã®å¼ã³åºãã§ããã·ã¥ã 2 åè¤è£½ãã¦ããã®ã§ããã3.0 ã§ã¯ 1 åã«ãªãã¾ããã
def foo(**opt) end opt = { a: 1 } foo(**opt) # Ruby 2.7 ã§ã¯ããã§ããã·ã¥ã 2 åè¤è£½ãã¦ããã3.0 ã§ã¯ 1 åã«ãªã£ã
ã¾ãã次ã®ã³ã¼ãã§ã¯ãè¤è£½åæ°ã 1 åãã 0 åã«æ¹åãã¾ããã
def foo(a: 1) end opt = { a: 1 } foo(**opt) # Ruby 2.7 ã§ã¯ããã§ããã·ã¥ã 1 åè¤è£½ãã¦ããã3.0 ã§ã¯ 0 åã«ãªã£ã
ãã¼ã¯ã¼ãå¼æ°ã¾ããã§è²¢ç®ãã¾ãã£ã¦ããã Jeremy ãããç´°ãããªæé©åã§ãã
ï¼mameï¼
JIT
- Performance improvements of JIT-ed code
- Microarchitectural optimizations
- Native functions shared by multiple methods are deduplicated on JIT compaction.
- Decrease code size of hot paths by some optimizations and partitioning cold paths.
- Instance variables
- Eliminate some redundant checks.
- Skip checking a class and a object multiple times in a method when possible.
- Optimize accesses in some core classes like Hash and their subclasses.
- Method inlining support for some C methods
Kernel
:#class
,#frozen?
Integer
:#-@
,#~
,#abs
,#bit_length
,#even?
,#integer?
,#magnitude
,#odd?
,#ord
,#to_i
,#to_int
,#zero?
Struct
: reader methods for 10th or later members
- Constant references are inlined.
- Always generate appropriate code for
==
,nil?
, and!
calls depending on a receiver class. - Reduce the number of PC accesses on branches and method returns.
- Optimize C method calls a little.
- Microarchitectural optimizations
- Compilation process improvements
- It does not keep temporary files in /tmp anymore.
- Throttle GC and compaction of JIT-ed code.
- Avoid GC-ing JIT-ed code when not necessary.
- GC-ing JIT-ed code is executed in a background thread.
- Reduce the number of locks between Ruby and JIT threads.
ããããªä»çµã¿ã§ JIT ã«ã¤ãã¦ã®æ§è½æ¹åãè¡ãã¾ããã詳細ã¯ä»åº¦éçºè ã®å½åãããè¨äºããããããã®ã§ããã¡ãããå¾ ã¡ãã ããã
追è¨ï¼å½åãããæ¸ãã¦ããã¾ããã
(ko1)
â ãã®ä»
ãã®ã»ãã®å¤æ´ã§ãã
ruby2_keywordã空ã®ãã¼ã¯ã¼ãå¼æ°ããã·ã¥ãç¶æããªããªã£ã
- Methods using
ruby2_keywords
will no longer keep empty keyword splats, those are now removed just as they are for methods not usingruby2_keywords
.
次ã®ãããªæåã®éããå ¥ãã¾ããã
ruby2_keywords def proxy_foo(*a) p a end proxy_foo(**{}) #=> [{}] # 2.7 proxy_foo(**{}) #=> [] # 3.0
ãªããã®ãããªéããå¿ è¦ã«ãªã£ãã¯ãããããããããã®ã§ãèªã¿é£ã°ãã¦ããã£ã¦å¤§ä¸å¤«ã§ããRuby 2ã®ãã¼ã¯ã¼ãå¼æ°ãããã«å£ãã¦ããããæãåããã¨ãã½ã¼ãã§ãã
ç´ ç´ãªæå¾
ã¨ãã¦ã¯ã**{}
ã¯ä½ãæå®ãã¦ããªãã®ã¨åãæ±ãã§ãã£ã¦æ¬²ããã§ãããããRuby 2ã§ã¯ã**{}
ããæå¾ã®ããã·ã¥ã®å¼æ°ããã¼ã¯ã¼ãã§ãªããã¨ã示ãããã®ããªãã¯ãã¨ãã¦ç¨ã«å¿
è¦ã«ãªã£ã¦ãã¾ããã
# Ruby 2.7 ã§ã®æå³ def foo(opt = nil, k: "default") p [opt, k] end # ãã®ã¡ã½ããã®ãªãã·ã§ã³å¼æ° opt ã«ããã·ã¥ {k: "val"} ã渡ããããã©ãããï¼ # ããã¯ãã¡ foo({k: "val"}) #=> [nil, "val"] # ãã¼ã¯ã¼ãã¨ãã¦è§£éããã¦ãã¾ã£ã¦ãã # ãããæ£è§£ foo({k: "val"}, **{}) #=> [{:k=>"val"}, "default"] # opt ã«ããã·ã¥ã渡ãã
ããã¦ããã®ãããªfoo
ãã¿ã¼ã²ããã¨ãã¦å§è²ãè¡ãproxy_foo
ã¨ããã¡ã½ãããruby2_keywords
ä»ãã§å®£è¨ããã±ã¼ã¹ãèãã¾ãã
ruby2_keywords def proxy_foo(*a) foo(*a) end # 次ã®ããã«åããªãã¨ãããªã proxy_foo({k: "val"}) #=> [nil, "val"] proxy_foo({k: "val"}, **{}) #=> [{:k=>"val"}, "default"]
ã¤ã¾ããproxy_foo
ã¯**{}
ã渡ããããã©ãããåæã«å¿ããããã«ã¯ãããªãã£ãã¨ãããã¨ã§ãããã®ããã«Ruby 2.7ã§ã¯ãå¼ã³åºãå
ã§**{}
ãã¤ãã¦ããã¨ãã«å¯å¤é·å¼æ°ã®æå¾ã«ç©ºã®ããã·ã¥ãæ®ãããã«ãªã£ã¦ãã¾ããã
ãã¦Ruby 3.0ã§ã¯ããã¼ã¯ã¼ãå¼æ°ã渡ãããã¨ãã¯foo(k: "val")
ãããã·ã¥ãæ®éã®å¼æ°ã¨ãã¦æ¸¡ãããã¨ãã¯foo({ k: "val" })
ã¨æ¸ãåãããã¨ãã§ããããã«ãªãã¾ããããã£ã¦ãå
ã®foo
ã¡ã½ããã«ãªãã·ã§ã³å¼æ°ã¨ãã¦ããã·ã¥ã渡ãããã¨ãã¯ãç´ ç´ã«foo({ k: "val" })
ã¨æ¸ãã ãã§å¤§ä¸å¤«ã§ãã
# Ruby 3.0 ã§ã®æå³ def foo(opt = nil, k: "default") p [opt, k] end # ãã®ã¡ã½ããã®ãªãã·ã§ã³å¼æ° opt ã«ããã·ã¥ {k: "val"} ã渡ããããã©ãããï¼ # ç´ ç´ã«ããã ãã§OK foo({k: "val"}) #=> [{:k=>"val"}, "default"] # opt ã«ããã·ã¥ã渡ãã
ããã«ããã**{}
ã使ãããªãã¯ãä¸è¦ã«ãªãã¾ããããã£ã¦ãproxy_foo
ã**{}
ã渡ããããã©ãããè¦ãã¦ããå¿
è¦ã¯ãªããªã£ãã®ã§ãç°¡æ½ã«ããããã«åé ã®å¤æ´ããªããã¾ããã
ï¼mameï¼
ããã¯ãã¬ã¼ã¹ã®é åºãåé転
- When an exception is caught in the default handler, the error message and backtrace are printed in order from the innermost. [Feature #8661]
ããã¯ãã¬ã¼ã¹ã®é åºã¯Ruby 2.5ã§é転ããã®ã§ãããRuby 3.0ã§åé転ãã¾ããï¼å¤ãé ã«æ»ã£ãï¼ã
次ã®ã³ã¼ãã§ã®ããã¯ãã¬ã¼ã¹ãè¦ãã°ãããã¨æãã¾ãã
def foo; raise; end def bar; foo; end bar
Ruby 2.7ã®åºåã<main>
ãä¸çªä¸ã
$ ruby test.rb Traceback (most recent call last): 2: from test.rb:3:in `<main>' 1: from test.rb:2:in `bar' test.rb:1:in `foo': unhandled exception
Ruby 3.0ã®åºåã<main>
ãä¸çªä¸ã
$ ruby test.rb test.rb:1:in `foo': unhandled exception from test.rb:2:in `bar' from test.rb:3:in `<main>'
Ruby 2.5ã§é転ããåæ©ã¯ãããã¯ãã¬ã¼ã¹ãé·ãããã¨ãã«ä¾å¤ã¡ãã»ã¼ã¸ãè¦ã¤ããããã«ç«¯æ«åºåãã¹ã¯ãã¼ã«ããªããã°ãªããªãã®ãããã ã£ããã¨ã§ããããã®åé¡ã軽æ¸ããããã«ãåè¿°ã® --backtrace-limit
ãå°å
¥ããã¾ããã
åé転ããã®ã«ã¯ããã¤ãçç±ãããã¾ãã
- ããã¯ãã¬ã¼ã¹ã®é åºããã¼ã«ãè¨å®ã«ãã£ã¦ãã©ãã©ã«ãªã£ã¦ãã¾ããçµ±ä¸ãé²ãæ§åããªãã£ã ((ä»®ã«ãã¼ã«ã対å¿ãã¦ããã¦ãã
p *caller
ã¨ããã³ã¼ãã§æ¬ä¼¼çã«ããã¯ãã¬ã¼ã¹ãåºåãããæãªã©ãããããããé転ãããã®ã¯é£ããã£ãã)) - ä¸é¨ã®Railsã¦ã¼ã¶ããé転ããã¦æ¬²ããã¨ããè¦æããã£ã¦å¤ãã£ãããæ¬å½ã«å¤ãã®Railsã¦ã¼ã¶ãé転ãæãã§ããã®ãæªãããªã£ã
- ãå¤ãæ¹ã®é ã«æ»ãã¦ã»ãããã¨ããæå¥ã3å¹´éè¨ãç¶ãã人ãããï¼ç§ã§ãï¼
ãããRuby 2.7ã®é åºãæ¬å½ã«æ¬å½ã«ããã£ãã®ã«ï¼ãã¨ãã人ããããã声ãä¸ãç¶ããã¨ããã¨æãã¾ãï¼æµç³ã«åã é転ã¯ãããããã¨æãã¾ããâ¦â¦ï¼ã
ï¼mameï¼
æªåæåã¤ã³ã¹ã¿ã³ã¹å¤æ°ã«ã¢ã¯ã»ã¹ãã¦ãè¦åãåºãªãããã«ãªã£ã
- Accessing an uninitialized instance variable no longer emits a warning in verbose mode. [Feature #17055]
æªåæåã®ã¤ã³ã¹ã¿ã³ã¹å¤æ°ãåç §ããã¨ã-w ä»ãã§å®è¡ãã¦ããã¨è¦åãåºã¦ãã¦ã¾ãããããã®è¦åãåºãªããªãã¾ãããæåã¨ãã¦ã¯ãåã« nil ãè¿ãã¾ãã
$ ruby_2_7_ruby -we 'p @foo' -e:1: warning: instance variable @foo not initialized nil $ ruby -we 'p @foo' nil
ãã®è¦åã¯ãã¤ã³ã¹ã¿ã³ã¹å¤æ°åã typo ã«æ°ã¥ãããããã¨ãããã¨ã§å°å ¥ããã¦ãã¾ãããã
- ãã®è¦åãæé¤ããããã«ãäºåã«åæåãå¿
è¦ã§é¢å
- æ¸ãã®ãé¢å
- å®è¡æã«åæåã³ã¼ããé ããªãã®ãé¢å
- ããããã-w ã¤ãã§ããã¾ãå®è¡ããªããããæ®æ®µããæ°ã¥ããªããã
ã¨ãããã¨ã§ãè¦åãåºããªããªãã¾ããããã®ãããinitialize
ã¡ã½ããã§ã® nil åæåã¯ããã®ããã«ã¯ä¸è¦ã«ãªãã¾ããã
(ko1)
â ãããã«
8 å¹´ã¶ãã«ã¡ã¸ã£ã¼ãã¼ã¸ã§ã³ã¢ãããã Ruby 3.0 ãå¹´æ«å¹´å§ã®ãä¼ã¿ã«ã§ãããã²æ¥½ããã§ã¿ã¦ãã ããã
Ruby 3 ã§ã¯ãéçæ¤è¨¼ã並è¡ä¸¦åå¦çã®ãµãã¼ããªã©ã大ããªæ©è½ã®å°å ¥ãããã¾ããã ã¾ããç®æ¨ã¨ãã¦ãã Ruby 2.0 ããã3åéããRuby 3x3 ã JIT ã³ã³ãã¤ã©ã®å°å ¥ã«ããéæãã¾ããã
Ruby ã¯ãããããé²åãç¶ãã¦ããã¾ãããæå¾ ãã ããï¼
ã§ã¯ããããã¼ããªãã¼ï¼
PS: ææ¥ 12/26 (å) 13 æãããRuby 3.0 ã®ãªãªã¼ã¹ã«ã¤ãã¦ãã¾ã¤ãã¨ããã交ãã¦èªãã¤ãã³ããéå¬ãã¾ãï¼Ruby 3.0 release event - connpassï¼ãããããã£ãããåå ãã ããã
*1:ã¾ããå¾è¿°ããéçå解æã®ããã«ãã¼ã¯ã¼ãå¼æ°ãæ±ãããããããã¨ããçããããã¾ããã
*2:productionã«æå ¥ã§ããªããRubyã§æ¸ããããã¼ã«ã使ã£ã¦ããã ãã®äººã«è¦åãè¦ãã¦ãä¸å®ãç ½ãã ãããªã©ã
*3:è¦åãæ¢ããæ¹æ³ã¯æä¾ãã¦ããã®ã§ãããã³ãã¥ã±ã¼ã·ã§ã³ãä¸è¶³ãã¦ããããããæè»ãªè¦åé¤å¤æå®ãå¿ è¦ã ã£ãããããç°¡åãªæ¹æ³ãæã¾ããã£ããã
*4:å°æ¥ã®Rails 7ã¯Ruby 3.0以éãè¦æ±ããå ¬ç®ãé«ãã®ã§ãRuby 3.0ã§æªåé¢ãRuby 3.1ã§åé¢ãã¨ãªãã¨é½åãæªãã
*5:é è¤ã®å®åã§ã¯ def: foo(a) = expression ã¨ããããã« def ã®å¾ã«ã³ãã³ãå¿ è¦ã¨ããææ³ããå®è£ ã§ããªãã£ãã®ã§ãããbison ãæ¯èªã®ããã«è©±ãã nobu ãä¸ç¬ã§ã³ãã³ãªãã§åå®è£ ãã¦ããã¾ããã
*6:軽ã調ã¹ãã¨ãããå°ãªãã¨ãruby-0.69ï¼1995å¹´é ï¼ã§ã¯TRUEããããtrueã¯æªå®ç¾©ã®ããã§ãã