ããã«ã¡ã¯ããã«ã¿ã¤ã Rubyã³ããã¿ã¨ãã¦åãã¦ãé è¤ï¼@mametterï¼ã§ããæ¨æ¥ãRuby 3.0.0-preview2ããªãªã¼ã¹ããã¾ããï¼
ãã®ãªãªã¼ã¹ã«ã¯ãé è¤ãéçºãã¦ãã Ruby ã®éçå解æãã¼ã« TypeProf ãåãã¦å梱ããã¦ãã¾ããããã®ä½¿ãæ¹ãããããã«ãç´¹ä»ãããã¨æãã¾ãã
ãã¢
TypeProf ã¯ãå注éã®ãªã Ruby ã³ã¼ããç¡çããå解æãããã¼ã«ã§ããã¨ãããããã¢ã
# user.rb class User def initialize(name:, age:) @name = name @age = age end attr_reader :name, :age end User.new(name: "John", age: 20)
typeprof ã³ãã³ãã¯ãRuby 2.7 㧠gem install typeprof
ã§ã¤ã³ã¹ãã¼ã«ã§ãã¾ã *1 ãTypeProf ã«ãã® Ruby ã³ã¼ããä¸ããtypeprof user.rb -o user.rbs
ã¨å®è¡ãã¦ãã ããã次ã®ãããªå
容㮠user.rbs ãçæããã¦ããã¯ãã§ãã
# Classes class User attr_reader name: String attr_reader age: Integer def initialize: (name: String, age: Integer) -> Integer end
TypeProf ã¯ãä¸ãããã Ruby ã³ã¼ãã®åæ
å ±ãæ¨å®ãã¦åºåãã¾ããuser.rbs ã¯ãRuby ã§ã¯ãªããRBS ã¨ãã Ruby 3 æ¨æºã®åæ
å ±è¨è¿°ã®è¨èªã§æ¸ããã¦ãã¾ããé°å²æ°ã§ãªãã¨ãªãèªãããã¨æãã¾ããããã¨ãã° def initialize: (name: String, age: Integer) -> Integer
㯠name
ã¨ãããã¼ã¯ã¼ãå¼æ°ã String
ã¤ã³ã¹ã¿ã³ã¹ãåãåããage
ã¨ãããã¼ã¯ã¼ãå¼æ°ã Integer
ã¤ã³ã¹ã¿ã³ã¹ãåãåããã¨ãããã¨ã表ç¾ãã¦ãã¾ããè¿ãå¤ã¯ Integer
ã§ãããinitialize
ã®è¿ãå¤ã¯ãã¾ãæå³ããªãã§ããã
TypeProf ã®ç¹å¾´ã¯ãã¡ã½ããå¼ã³åºãã®æ
å ±ããã«æ´»ç¨ããã¨ããã§ããããã¯å¾æ¥ã®ãµã¤ãã®å解æã¨æ¬è³ªçã«ç°ãªãã¨ããã§ããããã«ãããdef initialize(name:, age:) ... end
ã¨ããå注éãä¸åãªãå®ç¾©ã«å¯¾ãã¦ããUser.new(name: "John", age: 20)
ã¨ããå¼ã³åºãã§æ¸¡ãããåãè¦ã¦ããã£ã½ãåæ
å ±ãæ¨å®ãã¾ãã
ããã²ã¨ã¤ãã¢
TypeProf ã¯ãRuby ã³ã¼ãã ãã§ãªã RBS ãåããã¦è§£æã§ãã¾ãããã¢ã
# test.rb def hello_message(user) "The name is " + user.name end def type_error_demo(user) "The age is " + user.age end user = User.new(name: "John", age: 20) hello_message(user) type_error_demo(user)
# user.rbs class User def initialize: (name: String, age: Integer) -> void attr_reader name: String attr_reader age: Integer end
user.rbs ã¯ãåã®ä¾ã®åºåãå°ãã ãæä¿®æ£ãããã®ã§ãããã㨠test.rb ããããã¦è§£æãã¾ãã
typeprof -v test.rb user.rbs
ã¨å®è¡ãã¦ãã ããã
# Errors test.rb:7: [error] failed to resolve overload: String#+ # Classes class Object private def hello_message: (User) -> String def type_error_demo: (User) -> untyped end
ã³ãã³ãã©ã¤ã³å¼æ°ã® -v
ã¯ã¨ã©ã¼ã®å¯è½æ§ã表示ããããªãã·ã§ã³ã§ãã
ãã®ãããä»åº¦ã¯ # Errors
ã¨ããåºåãããã¾ãã
test.rb ã® 7 è¡ç®ãè¦ã¦ã¿ãã¨ã"The age is " + user.age
ã¨ããè¨ç®ããã¦ãã¾ããããã㯠String
㨠Integer
ãçµåãããã¨ãã¦ãã¾ãã
TypeProf ã¯ããããã°ã¨ãã¦è¦åãã¦ãã¾ãã
class Object
ãã end
ã¯ãå
ç¨ã¨åæ§ã« test.rb ã®åæ
å ±ãæ¨å®ãããã®ã§ãã
ãªãã7 è¡ç®ã«åã¨ã©ã¼ã®å¯è½æ§ããã£ã¦åã®è¿½è·¡ãã§ããªããªã£ããããtype_error_demo
ã¡ã½ããã®è¿ãå¤ã¯ untyped
ã¨ãªã£ã¦ã¾ãã
Ruby TypeProf Playground
TypeProf 㯠Ruby TypeProf Playground ã§ãã©ã¦ã¶ä¸ã§è©¦ãã¾ã *2 ã
- user.rb ã解æããã㢠ï¼ä¸è¨ã® 1 ã¤ãã®ä¾ï¼
- test.rb + user.rbs ã解æãããã¢ï¼ä¸è¨ã® 2 ã¤ãã®ä¾ï¼
å·¦ä¸ã Ruby ã³ã¼ããå·¦ä¸ã RBSï¼æ¸ããªãã¦ãè¯ãï¼ã§ãAnalyze ãã¿ã³ãæ¼ãã¨å³å´ã«è§£æçµæã表示ããã¾ãã Ruby ã³ã¼ããããã£ã¦è§£æãããã¨ãã§ããã®ã§ãæå¾ ã«åããæåãè¦ã¤ããã Report bug ãã¿ã³ã§ãã²å ±åãã¦ãã ãã *3 ã
TypeProf ã®èª²é¡ã¨ç¾ç¶
TypeProf ã¯ãå注éãæ¸ããªãé¸æè¢ã Ruby ã«æ®ããã¨ãããã¨ãè³ä¸å½é¡ã¨ãã極端ãªè¨è¨ã«ãªã£ã¦ããã®ã§ãæ§ã ãªåé¡ç¹ãããã¾ãã
- ã¨ã«ãã解æãé ã *4
- ã¾ã¨ããªè§£æã®ããã«ã¯ãã¹ãã³ã¼ããå¿ è¦ *5
- ç¾æç¹ã§ã¯è§£æ精度ãä½ãã誤æ¤ç¥ãè¦éããã¨ã¦ãå¤ã
- ææ¬ã«ãªãåä¾ããªããTypeProf èªä½ã®è¨è¨ã«è©¦è¡é¯èª¤ãå¿ è¦
ãã®ãã Ruby 3.0 ã® TypeProf ã§ã¯ãå注éã®ãªã Ruby ã³ã¼ãã«å¯¾ã㦠RBS ã¹ã¿ããçæãããã¨ããæ©è½ã«ãã©ã¼ã«ã¹ãã¦è¨è¨ã»å®è£ ãé²ãã¾ãã *6 ã RBS ã¹ã¿ãçææ©è½ã¨ãã¦çµé¨ãç©ã¿ãªãããé«éåã解æ精度åä¸ãé²ããå°æ¥çã«ã¯ãããããªåæ¤æ»å¨ã¨ãã¦ä½¿ãããã®ã«ã§ããããããªã¨æã£ã¦ãã¾ãã
ã¾ã¨ã
Ruby 3 ã«å梱ãããå解æãã¼ã« TypeProf ããç´¹ä»ãã¾ããããããããªä½¿ãæ¹ã«ãã©ã¼ã«ã¹ãã¦æ¸ããã®ã§ãããå°ã詳ãããã¨ã¯ããã¥ã¡ã³ããéå»ã®çºè¡¨ããåç §ãã ããã
TypeProf ã®ç¾ç¶ã®å®æ度ã¨ãã¦ã¯ãRuby ããã±ã¼ã¸ã«å«ã¾ãããã¹ã¦ã® .rb ãã¡ã¤ã«ã§è§£æãéã *7 ãã¨ã確èªã§ããç¨åº¦ã§ããåºåã®ç²¾åº¦è©ä¾¡ãé度åä¸ã¯ã¾ã ã¾ã ããããé å¼µã£ã¦ããã¾ãããã²éãã§ã¿ã¦ãæ°ã¥ãããã¨ããã£ãããã°å ±åã§ãææ³ã§ãããã ããã¨æ³£ãã¦åã³ã¾ãã
RBS 㨠TypeProf ã®é¢ä¿ã¯ï¼ Steep ã Sorbet ã¨ããã®ãèãããï¼
Ruby 3 ã®éç解æã¯åºæåè©ãå¤ãã¦ãããããã®ã§ãé¢ä¿ãå¥è¨äºã«ã¾ã¨ãã¾ããã
*1:ruby 3.0.0-preview2 ãªã gem install ãªã㧠typeprof ã³ãã³ããå©ç¨å¯è½ã§ãã
*2:社å ã§ãããããã®ãä½ããããã¨èªã£ãããid:koba789 ããã 1 æéã§ä½ã£ã¦ããã¾ããã
*3:ã¨ã¦ãé©å½ã«éç¨ãã¦ããã®ã§ããµã¼ããè½ã¡ããããããªããã
*4:ãµã¤ãã®å解æã¯åºæ¬çã«ã¡ã½ããåä½ã§è§£æãè¡ãã¾ãããTypeProf ã¯å¼ã³åºãå ããã©ãå¿ è¦ãããããã大å¤ã«ãªããã¡ã§ãããªããRBS è¨èªãé¨åçã«ææ¸ãããã°ããã»ã©ï¼çè«ä¸ã¯ï¼æ©ããªãã¾ãã
*5:解æã®ã«ãã¬ãã¸ãä¸ãããããã¹ã¿ãå®è¡ã¨ãããã¥ã¼ãªã¹ãã£ã¯ã¹ãå®è£ ãã¦ãã¾ããããã¯ãã©ããããå¼ã°ããªãã£ãã¡ã½ããã« untyped ãªå¼æ°ãä¸ãã¦ç¡çããå¼ã³åºããã®ã§ããããã«ããããã¹ãããªãã¦ãä¸éãã®è§£æã¯è¡ããããã«ãªã£ã¦ãã¾ãã
*6:ãªããrbs ã³ãã³ãã«ã Ruby ã³ã¼ããã RBS ã¹ã¿ããçæããæ©è½ãããã¾ããããã¡ãã¯åºæ¬çã«ãã¹ã¦ã®å¼æ°ã untyped ã¨ãã¦åºåãããã®ã§ãããããã¨ãåç´ãªåãéãã¦å®å®ãã¦ããã¨ããã¡ãªãããããã¾ãã
*7:TypeProf ãçä¸å°½ã«ä¾å¤çµäºããªããã¨ã確ãããç¨åº¦ã§ãããããã¡ããªã³ã¼ãã ããã® test/ruby ã ruby/spec ã¯ããã ãã§ãå°çã®è¦ãã¿ã§ããã