Rubyã§ã®DSLå®è£ ä¾ã¨æ¡å¼µããã«ã¹ã»ãã¦ã¢è¨æ³ï¼EBNFï¼
DSLã®ä»æ§ãè¨è¿°ããè¨æ³ã§ããæ¡å¼µããã«ã¹ã»ãã¦ã¢è¨æ³ï¼EBNFï¼ã¨ãRubyã§å®éã«ãã®ä»æ§ãå®è£ ããæ¹æ³ã«ã¤ãã¦èãã¦ã¿ã¾ããã
è¨èªä»æ§ã®æ§æè¦ç´ ã¨ãã¦ï¼çµç«¯è¨å· (Terminal symbols)ãéçµç«¯è¨å· (Non-terminal symbols)ãå°åºè¨å· (::=):ãé¸æ (|)ãç¹°ãè¿ã ({})ããªãã·ã§ã³ ()ãã°ã«ã¼ãã³ã° (())ã®ï¼ã¤ã®è¦ç´ ãçµã¿åãããã¦ããã®ã§ããã
ãããªããã¼ãµã¼ã®ã³ã¼ãä¾ãè¦ã¦ãç解ã§ããªãã£ãã¨æãã¾ãã
å®è£ ä¾ã¯ãç°¡åãªæ¹ã§ãã©ã¼ãããããææ¸ã®åºåãè¤éãªæ¹ã§Rubyã®ãã¹ããã¬ã¼ã ã¯ã¼ã¯ã®DSLã®ä¾ãæãã¦ãããã¾ããã
- DSLã®ä»æ§ãè¨è¿°ããæ¹æ³ãããã°æãã¦ãã ããã
- ãã¼ãµã¼ãã¤ã³ã¿ããªã¿ã¼ã®æ§æãå®ç¾©ããç°¡æ½ãªè¨æ³ãè¦ããã¨ãããã®ã§ããããåãã§ãããæãã¦ãã ããã
- EBNFè¨æ³ã«ã¤ãã¦ã詳ããæãã¦ããã ãã¾ãããï¼ãè¨èªã§ã®å®è£ ä¾ã¯Rubyã§DSLãå®ç¾©ããæ¹æ³(instance_evalã使ããã®)ã§ãé¡ããã¾ãã
- 以ä¸ããããã«å¯¾å¿ããå®è£ ã¯ã©ã®ããã«ãªãã¾ããï¼
- EBNFã«ããDSLã®å ·ä½ä¾ãæãã¦ãã ããã
- ãããã§ããªãã¤ã¡ã¼ã¸ã§ããããã«ãªã£ã¦æ¥ã¾ãããããå°ãè¤éãªä¾ãæãã¦ãã ããã
- ãããã¨ããããã¾ãããã¡ãã¯ããªãé£ããæãã¾ãã解説ããé¡ããã¦è¯ãã§ããï¼
- ä¸è¨DSLãä¸è¡ãã¤ãã©ãã§ã©ãå®è¡ããã¦ãããã解説ãé¡ããã¾ãã
- ããªãç解ãé²ã¿ã¾ãããããããCommandãå®è¡ããã¾ã§ãã¾ã ããåããã¾ããã
DSLã®ä»æ§ãè¨è¿°ããæ¹æ³ãããã°æãã¦ãã ããã
User
DSLã®ä»æ§ãè¨è¿°ããæ¹æ³ãããã°æãã¦ãã ããã
ChatGPT
DSLï¼Domain Specific Languageããã¡ã¤ã³ç¹åè¨èªï¼ã®ä»æ§ãè¨è¿°ããæ¹æ³ã«ã¯ã主ã«ä»¥ä¸ã®ãããªã¹ããããããã¾ããDSLã®è¨è¨ã¨å®è£
ã¯ãç¹å®ã®åé¡é åãã¿ã¹ã¯ã«ç¹åããè¨èªãä½ããã¨ã§ããã®ãã¡ã¤ã³ã«é¢ããä½æ¥ãããç°¡åãã¤ç´æçã«è¡ããããã«ãããã¨ãç®æãã¾ãã
1. ãã¡ã¤ã³ã®ç解
ãã¡ã¤ã³åæ: 対象ã¨ãªããã¡ã¤ã³ã®æ·±ãç解ãå¾ããé¢é£ããã¿ã¹ã¯ãã¸ã£ã¼ã´ã³ããã¼ã¿æ§é ãªã©ãç¹å®ããã
ã¦ã¼ã¶ã¼ã¨ã®å¯¾è©±: ãã¡ã¤ã³ã®å°é家ãå°æ¥ã®DSLã¦ã¼ã¶ã¼ã¨å¯¾è©±ããå½¼ãã®ãã¼ãºã¨ä½¿ç¨ããæ½è±¡æ¦å¿µãç解ããã
2. æ½è±¡æ¦å¿µã®ç¹å®
æ½è±¡æ¦å¿µã®é¸å®: ãã¡ã¤ã³åæããå¾ãããæ
å ±ãåºã«ãDSLãã«ãã¼ãã¹ã主è¦ãªæ¦å¿µãæä½ãé¸å®ããã
ã¢ããªã³ã°: é¸å®ããæ¦å¿µãã¢ãã«åããDSLã®æ½è±¡çãªæ§é ãå®ç¾©ããã
3. æ§æã®è¨è¨
æ§æã®é¸æ: å
é¨DSLã®å ´åã¯ãã¹ãè¨èªã®æ§æãæ´»ç¨ããå¤é¨DSLã®å ´åã¯ç¬èªã®æ§æãè¨è¨ããã
ã¦ã¼ã¶ããªãã£: æ§æãç´æçã§ã対象ã®ãã¡ã¤ã³ã®å°é家ã«ã¨ã£ã¦èªç¶ã«æããããããã«ããã
ä¾ã¨ãã¹ãã±ã¼ã¹: å ·ä½çãªä½¿ç¨ä¾ããã¹ãã±ã¼ã¹ãä½æãã¦ãæ§æã®å¦¥å½æ§ãæ¤è¨¼ããã
4. å®è£
ãã¼ãµã¼ã¨ã¤ã³ã¿ããªã¿ã¼ï¼ã¾ãã¯ã³ã³ãã¤ã©ã¼ï¼ã®éçº: DSLã®æ§æã解æããé©åãªæä½ãå®è¡ã§ããããã«ããã
ã©ã¤ãã©ãªã¨API: ãã¡ã¤ã³åºæã®æ©è½ãå®è£ ããå¿ è¦ã«å¿ãã¦æ¢åã®ã©ã¤ãã©ãªãAPIã¨ã®çµ±åãè¡ãã
5. ããã¥ã¡ã³ãã¨ãµãã¼ã
ããã¥ã¡ã³ãã®ä½æ: è¨èªã®ä»æ§ãæ§æã使ç¨æ¹æ³ã«ã¤ãã¦ã®è©³ç´°ãªããã¥ã¡ã³ããç¨æããã
ã¦ã¼ã¶ã¼ãµãã¼ã: ãã©ã¼ã©ã ããã£ãããªã©ãéãã¦ãã¦ã¼ã¶ã¼ããã®ãã£ã¼ãããã¯ãåãåãããµãã¼ããæä¾ããã
6. ãã£ã¼ãããã¯ã¨å復
ãã£ã¼ãããã¯ã®åé: ã¦ã¼ã¶ã¼ããã®ãã£ã¼ãããã¯ãç©æ¥µçã«åéããDSLã®æ¹åç¹ãç¹å®ããã
å復çãªæ¹å: ã¦ã¼ã¶ã¼ã®ãã£ã¼ãããã¯ãæ°ããªãã¡ã¤ã³ã®ç¥è¦ãåºã«ãDSLãç¶ç¶çã«æ¹åãæ¡å¼µããã
DSLã®éçºã¯ããã°ãã°å復çãªããã»ã¹ã§ãããã¡ã¤ã³ã®æ·±ãç解ã«åºã¥ããã¦ã¼ã¶ã¼ã®ãã¼ãºã«åããã¦è¨è¨ã»å®è£ ãããã¹ãã§ããã¾ããå®éã®ä½¿ç¨ã·ããªãªã§ã®æ¤è¨¼ã¨ã¦ã¼ã¶ã¼ããã®ãã£ã¼ãããã¯ãããã®æåã®éµã¨ãªãã¾ãã
ãã¼ãµã¼ãã¤ã³ã¿ããªã¿ã¼ã®æ§æãå®ç¾©ããç°¡æ½ãªè¨æ³ãè¦ããã¨ãããã®ã§ããããåãã§ãããæãã¦ãã ããã
User
ãã¼ãµã¼ãã¤ã³ã¿ããªã¿ã¼ã®æ§æãå®ç¾©ããç°¡æ½ãªè¨æ³ãè¦ããã¨ãããã®ã§ããããåãã§ãããæãã¦ãã ããã
ChatGPT
ã¯ãããã¼ãµã¼ãã¤ã³ã¿ããªã¿ã¼ã®æ§æãå®ç¾©ããéã«ä½¿ãããç°¡æ½ãªè¨æ³ã«ã¯ããããã«ã¹ã»ãã¦ã¢è¨æ³ï¼BNFï¼ãããã®æ´¾çå½¢ã§ãããæ¡å¼µããã«ã¹ã»ãã¦ã¢è¨æ³ï¼EBNFï¼ããããã¾ãããããã®è¨æ³ã¯ãããã°ã©ãã³ã°è¨èªããã¼ã¿å½¢å¼ã®æ§æãå½¢å¼çã«è¨è¿°ããããã«åºã使ããã¦ãã¾ãã
âããã«ã¹ã»ãã¦ã¢è¨æ³ï¼BNFï¼
ããã«ã¹ã»ãã¦ã¢è¨æ³ï¼BNFï¼ã¯ãã³ã³ãã¥ã¼ã¿è¨èªã®ææ³ãè¨è¿°ããããã®æ§æãæä¾ãã¾ããBNFã¯ä»¥ä¸ã®è¦ç´ ã§æ§æããã¾ãã
éçµç«¯è¨å·: ææ³ã®å¤æ°ã表ããä»ã®éçµç«¯è¨å·ãçµç«¯è¨å·ã«å±éããããé常ã<ã¨>ã§å²ã¾ãã¾ãï¼ä¾:
çµç«¯è¨å·: ææ³ã®åºæ¬è¦ç´ ã§ãããããã«å±éãããªãè¨å·ãæååãé常ãå¼ç¨ç¬¦ã§å²ã¾ãããããã®ã¾ã¾æ¸ããã¾ãã
å°åºè¨å·: é常ã¯::=ãç¨ãã¦ãããéçµç«¯è¨å·ãä»ã®è¨å·ã®åã«å±éããããã¨ã表ãã¾ãã
é¸æ: |è¨å·ã使ç¨ãã¦é¸æè¢ã表ããè¤æ°ã®ä»£æ¿å¯è½ãªå±éã示ãã¾ãã
âæ¡å¼µããã«ã¹ã»ãã¦ã¢è¨æ³ï¼EBNFï¼
æ¡å¼µããã«ã¹ã»ãã¦ã¢è¨æ³ï¼EBNFï¼ã¯ãBNFãæ¡å¼µãããã®ã§ãããèªã¿ãããæè»ãªææ³å®ç¾©ãå¯è½ã«ãã¾ããEBNFã¯ä»¥ä¸ã®è¿½å æ©è½ãæä¾ãã¾ãã
ãªãã·ã§ã³: [ ]ã使ç¨ãã¦ãããè¦ç´ ãä»»æã§ãããã¨ã示ãã¾ãï¼ä¾: [
ç¹°ãè¿ã: { }ã使ç¨ãã¦ãããè¦ç´ ã0å以ä¸ç¹°ãè¿ããããã¨ã示ãã¾ãï¼ä¾: {
ã°ã«ã¼ãã³ã°: ( )ã使ç¨ãã¦ãè¦ç´ ã®ã°ã«ã¼ããä½æããã°ã«ã¼ãå ¨ä½ã«å¯¾ãã¦æä½ï¼é¸æãç¹°ãè¿ãçï¼ãé©ç¨ãã¾ãã
BNFãEBNFã¯ãè¨èªã®æ§æãæ確ã«å®ç¾©ããå¼·åãªãã¼ã«ã§ããããããå©ç¨ãããã¨ã§ããã¼ãµã¼ãã³ã³ãã¤ã©ã®éçºè ã¯ãè¨èªã®æ£ç¢ºãªææ³ãå½¢å¼çã«è¨è¿°ãããã®ææ³ã«åºã¥ãã¦ã½ããã¦ã§ã¢ãéçºãããã¨ãã§ãã¾ãã
EBNFè¨æ³ã«ã¤ãã¦ã詳ããæãã¦ããã ãã¾ãããï¼ãè¨èªã§ã®å®è£ ä¾ã¯Rubyã§DSLãå®ç¾©ããæ¹æ³(instance_evalã使ããã®)ã§ãé¡ããã¾ãã
User
åãè¦ããã¨ãããã®ã¯EBNFã®æ¹ã§ããï¼
ãã®è¨æ³ã«ã¤ãã¦ã詳ããæãã¦ããã ãã¾ãããï¼ãè¨èªã§ã®å®è£ ä¾ã¯Rubyã§DSLãå®ç¾©ããæ¹æ³(instance_evalã使ããã®)ã§ãé¡ããã¾ãã
ChatGPT
æ¡å¼µããã«ã¹ã»ãã¦ã¢è¨æ³ï¼EBNFï¼ã«ã¤ãã¦ã®è©³ç´°ã¨ãRubyã§DSLãå®ç¾©ããä¾ã説æãã¾ãã
æ¡å¼µããã«ã¹ã»ãã¦ã¢è¨æ³ï¼EBNFï¼ã®è©³ç´°
EBNFã¯ãã³ã³ãã¥ã¼ã¿è¨èªã®ææ³ãè¨è¿°ããã®ã«ä½¿ãããå½¢å¼è¨èªã§ãããã®è¨æ³ã¯ãææ³ã®æ§é ã表ç¾ããããã«ç¹å¥ãªè¨å·ã¨è¦åã使ç¨ãã¾ããåºæ¬çãªè¦ç´ ã¯ä»¥ä¸ã®éãã§ãã
çµç«¯è¨å· (Terminal symbols): ææ³ã®åºæ¬çãªæ§æè¦ç´ ãé常ãæååãè¨å·ãã®ãã®ã§ãä»ã«å±éãããªãã
éçµç«¯è¨å· (Non-terminal symbols): ä»ã®éçµç«¯è¨å·ãçµç«¯è¨å·ã«å±éãããææ³ã®å¤æ°ã
å°åºè¨å· (::=): éçµç«¯è¨å·ãä»ã®è¨å·ã®åã«å±éããããã¨ã示ãã
é¸æ (|): è¤æ°ã®ä»£æ¿å¯è½ãªå±éã示ãã
ç¹°ãè¿ã ({}): æ¬å¼§å ã®è¦ç´ ã0å以ä¸ç¹°ãè¿ããããã¨ã示ãã
ãªãã·ã§ã³ (): æ¬å¼§å ã®è¦ç´ ã0åã1ååºç¾ãããã¨ã示ãã
ã°ã«ã¼ãã³ã° (()): è¦ç´ ã®ã°ã«ã¼ããä½æããã°ã«ã¼ãå ¨ä½ã«å¯¾ãã¦æä½ãé©ç¨ããã
Rubyã§ã®DSLã®å®è£
ä¾
Rubyã§ã¯ãinstance_evalã¡ã½ããã使ç¨ãããã¨ã§ãä¸ãããããããã¯å
ã§ã¬ã·ã¼ãã®ã³ã³ããã¹ãã§ã³ã¼ããè©ä¾¡ããDSLãç°¡åã«å®è£
ã§ãã¾ãã以ä¸ã¯ãã·ã³ãã«ãªDSLã®ä¾ã§ãã
class MyDSL def initialize(&block) instance_eval(&block) end def method_missing(name, *args, &block) puts "Called #{name} with #{args.inspect}" if block_given? instance_eval(&block) end end end # DSLã使ç¨ãã MyDSL.new do greeting "Hello", "world" question "how", "are", "you" do response "I'm", "fine", "thanks!" end end
ãã®ä¾ã§ã¯ãMyDSLã¯ã©ã¹å ã§instance_evalã使ç¨ãã¦ãã¾ããããã«ããããããã¯å ã§å®ç¾©ãããã¡ã½ããå¼ã³åºãï¼ãã®å ´åã¯greetingãquestionï¼ã¯ãMyDSLã¤ã³ã¹ã¿ã³ã¹ã®ã³ã³ããã¹ãã§è©ä¾¡ããã¾ããmethod_missingã¡ã½ããããªã¼ãã¼ã©ã¤ããããã¨ã§ãå®ç¾©ããã¦ããªãã¡ã½ãããå¼ã³åºãããéã«ã«ã¹ã¿ã ã®å¦çãå®è¡ã§ããããã«ãã¦ãã¾ãããã®ãã¯ããã¯ãå©ç¨ãããã¨ã§ãæè»ãªDSLãç°¡åã«ä½æã§ãã¾ãã
ãã®ä¾ã§ã¯DSLã®å®è£ ã®åºæ¬çãªä»çµã¿ã説æãã¦ãã¾ãããå®éã®ç¨éã«åããã¦ãDSLå ã§å©ç¨å¯è½ãªã¡ã½ãããæ§é ãã«ã¹ã¿ãã¤ãºãããã¨ãå¯è½ã§ããDSLã®è¨è¨ã«ã¯ããã®ç¨éã¨ç®çãæ確ã«ç解ãã使ç¨ãããã¡ã¤ã³ã«å¯æ¥ã«åããã¦éçºãããã¨ãéè¦ã§ãã
以ä¸ããããã«å¯¾å¿ããå®è£ ã¯ã©ã®ããã«ãªãã¾ããï¼
User
以ä¸ããããã«å¯¾å¿ããå®è£
ã¯ã©ã®ããã«ãªãã¾ããï¼
ChatGPT
Rubyã§DSLãå®ç¾©ããéã«ãEBNFã®åè¦ç´ ï¼çµç«¯è¨å·ãéçµç«¯è¨å·ãå°åºè¨å·ãé¸æãç¹°ãè¿ãããªãã·ã§ã³ãã°ã«ã¼ãã³ã°ï¼ã模å£ããå®è£
æ¹æ³ãèãã¦ã¿ã¾ãããã以ä¸ã®ä¾ã§ã¯ãDSLãç¨ãã¦ç°¡åãªææ¸ãå®ç¾©ããã·ããªãªãæ³å®ãã¦ãã¾ãã
çµç«¯è¨å· (Terminal symbols)
çµç«¯è¨å·ã¯ãDSLå
ã§ç´æ¥ä½¿ç¨ãããå¤ãè¨å·ã§ããRubyã®ã¡ã½ããå¼æ°ãã·ã³ãã«ãæååãªã©ã§è¡¨ç¾ã§ãã¾ãã
def text(value) puts value end
éçµç«¯è¨å· (Non-terminal symbols)
éçµç«¯è¨å·ã¯ãä»ã®è¨å·ã«å±éãããè¦ç´ ã§ããRubyã§ã¯ãã¡ã½ããã®å¼ã³åºãã使ã£ã¦ããã表ç¾ã§ãã¾ãã
def paragraph(&block) instance_eval(&block) end
å°åºè¨å· (::=)
å°åºè¨å·ã¯ãç¹å®ã®æ§æè¦åãå®ç¾©ããéã«ä½¿ç¨ãã¾ããRubyã®å ´åãã¡ã½ããå®ç¾©èªä½ããã®å°åºã表ãã¦ãã¾ãã
def document(title, &block) puts title instance_eval(&block) end
é¸æ (|)
é¸æã¯ãè¤æ°ã®ä»£æ¿å¯è½ãªæ§æè¦åããé¸ã¶ãã¨ãæå³ãã¾ããRubyã®æ¡ä»¶åå²ã使ã£ã¦ãããå®è£
ã§ãã¾ãã
def choice(option) if option == :option1 puts "Option 1 chosen" elsif option == :option2 puts "Option 2 chosen" end end
ç¹°ãè¿ã ({})
ç¹°ãè¿ãã¯ãããè¦ç´ ã0å以ä¸ç¹°ãè¿ããããã¨ã示ãã¾ããRubyã§ã¯ãé
åã¨ãããã¯ãçµã¿åããã¦ãããå®ç¾ã§ãã¾ãã
def repeat(items) items.each do |item| text(item) end end
ãªãã·ã§ã³ ([])
ãªãã·ã§ã³ã¯ãããè¦ç´ ã0åã1ååºç¾ãããã¨ã示ãã¾ããRubyã§ã¯ãå¼æ°ã«ããã©ã«ãå¤ãè¨å®ãããã¨ã§ããã表ç¾ã§ãã¾ãã
def optional_text(value = nil) puts value unless value.nil? end
ã°ã«ã¼ãã³ã° (())
ã°ã«ã¼ãã³ã°ã¯ãè¤æ°ã®è¦ç´ ãã¾ã¨ãã¦1ã¤ã®åä½ã¨ãã¦æ±ãã¾ããRubyã§ã¯ããããã¯ã使ã£ã¦ã°ã«ã¼ãåãã¾ãã
def group(&block) instance_eval(&block) end
以ä¸ã®ããã«ãRubyã§ã¯ã¡ã½ããå®ç¾©ããããã¯ãå¼æ°ã®ããã©ã«ãå¤ãªã©ãé§ä½¿ãã¦ãEBNFã®è¦ç´ ã模å£ããDSLãæ§ç¯ã§ãã¾ããDSLã®è¨è¨ã§ã¯ãå®éã«è¨èªã®ææ³ã«è¿ãå½¢ã§ã³ã¼ããæ¸ããããã«ããããã®æè¡ãçµã¿åããã¦ä½¿ç¨ãã¾ãã
EBNFã«ããDSLã®å ·ä½ä¾ãæãã¦ãã ããã
User
EBNFã«ããDSLã®å
·ä½ä¾ãæãã¦ãã ããã
ChatGPT
EBNFãç¨ããDSLï¼ãã¡ã¤ã³ç¹åè¨èªï¼ã®å
·ä½ä¾ã¨ãã¦ãã·ã³ãã«ãªããã°ãã¹ããçæããããã®DSLãèãã¦ã¿ã¾ãããããã®DSLã¯ãããã°ã®ã¿ã¤ãã«ãèè
ãæ¥ä»ãããã¦è¤æ°ã®æ®µè½ãæå®ã§ããããã«è¨è¨ãã¾ãã
ã¾ãããã®DSLã®EBNFè¨æ³ã«åºã¥ãææ³ãå®ç¾©ãã¾ãããã®å¾ãRubyã§ãã®DSLãå®è£ ããæ¹æ³ã示ãã¾ãã
EBNFè¨æ³ã«ããDSLææ³
blogpost ::= title author date paragraph+ title ::= 'title' ':' string author ::= 'author' ':' string date ::= 'date' ':' string paragraph ::= 'paragraph' ':' string string ::= '"' .* '"'
ãã®ææ³ã§ã¯ãããã°ãã¹ã(blogpost)ãã¿ã¤ãã«(title)ãèè (author)ãæ¥ä»(date)ãããã¦ä¸ã¤ä»¥ä¸ã®æ®µè½(paragraph+)ããæ§æããããã¨ãå®ç¾©ãã¦ãã¾ããstringã¯ä»»æã®æååã表ããããã§ã¯ããã«ã¯ã©ã¼ãã§å²ã¾ããä»»æã®æååãæ³å®ãã¦ãã¾ãã
Rubyã§ã®DSLå®è£ ä¾
class BlogPost def initialize(&block) @post = {} instance_eval(&block) end def title(value) @post[:title] = value end def author(value) @post[:author] = value end def date(value) @post[:date] = value end def paragraph(value) @post[:paragraphs] ||= [] @post[:paragraphs] << value end def render puts "Title: #{@post[:title]}" puts "Author: #{@post[:author]}" puts "Date: #{@post[:date]}" puts "\nParagraphs:" @post[:paragraphs].each { |para| puts para } end end # DSLã使ç¨ãã BlogPost.new do title "My First Blog Post" author "John Doe" date "2024-03-29" paragraph "This is the first paragraph of the blog post." paragraph "This is the second paragraph." end.render
ãã®å®è£ ä¾ã§ã¯ãBlogPostã¯ã©ã¹å ã§instance_evalã使ã£ã¦ãããã¯å ã®ã³ã¼ããè©ä¾¡ãã¦ãã¾ããããã§å®ç¾©ãããã¡ã½ããï¼title, author, date, paragraphï¼ã¯ãEBNFææ³ã§å®ç¾©ãããæ§æè¦åã«ç¸å½ãã¾ããrenderã¡ã½ããã¯ãããã°ãã¹ãã®å 容ãåºåãã¾ãã
DSLã使ããã¨ã§ãããã°ãã¹ãã®æ§é ãæ確ã«ããèªã¿ãããæ¸ããã¨ãã§ãã¾ããã¾ãããã®ä¾ã§ã¯ã·ã³ãã«ã«ä¿ã¤ããã«åºåã¯åç´ãªããã¹ãã§ãããHTMLãMarkdownãªã©ããã¾ãã¾ãªå½¢å¼ã§ã®åºåã«æ¡å¼µãããã¨ãå¯è½ã§ãã
ãããã§ããªãã¤ã¡ã¼ã¸ã§ããããã«ãªã£ã¦æ¥ã¾ãããããå°ãè¤éãªä¾ãæãã¦ãã ããã
User
ãããã¨ããããã¾ãããããã§ããªãã¤ã¡ã¼ã¸ã§ããããã«ãªã£ã¦æ¥ã¾ããã
ããå°ãè¤éãªä¾ãæãã¦ãã ããã
ChatGPT
ããå°ãè¤éãªDSLã®ä¾ã¨ãã¦ãã·ã³ãã«ãªãã¹ãã±ã¼ã¹ãè¨è¿°ããããã®DSLãèãã¦ã¿ã¾ãããããã®DSLã使ã£ã¦ããã¹ãã®ã»ããã¢ãããè¤æ°ã®ãã¹ãã±ã¼ã¹ãããããã®ãã¹ãã±ã¼ã¹ã«å¯¾ããæå¾
å¤ã®æå®ãã§ããããã«ãã¾ãã
EBNFè¨æ³ã«ããDSLææ³ã®ã¤ã¡ã¼ã¸
以ä¸ã¯ããã®ãããªãã¹ãã±ã¼ã¹DSLã®ææ³ãã¤ã¡ã¼ã¸ããEBNFã®ä¾ã§ãã
test_suite ::= setup test_case+ setup ::= 'setup' '{' command* '}' test_case ::= 'test' string '{' command* 'expect' string '}' command ::= 'execute' string | 'assign' string string
test_suiteã¯ãã»ããã¢ããã¨ä¸ã¤ä»¥ä¸ã®test_caseããæ§æããã¾ãã
setupã»ã¯ã·ã§ã³ã§ã¯ããã¹ãã®åææ¡ä»¶ãè¨å®ããããã®commandã0å以ä¸æå®ã§ãã¾ãã
åtest_caseã¯ããã¹ãã®èª¬æ(string)ã¨ãå®è¡ããcommandãæå¾ ããçµæ(expectå¾ã®string)ãå«ã¿ã¾ãã
commandã¯ãexecuteã¾ãã¯assignã®ããããã§ããã¹ãã®æä½ãè¨è¿°ãã¾ãã
Rubyã§ã®DSLå®è£ ä¾
class TestSuite def initialize(&block) @setup_commands = [] @test_cases = [] instance_eval(&block) end def setup(&block) @setup_context = Setup.new @setup_context.instance_eval(&block) @setup_commands = @setup_context.commands end def test(description, &block) test_case = TestCase.new(description) test_case.instance_eval(&block) @test_cases << test_case end def run puts "Running tests..." @test_cases.each_with_index do |test_case, index| puts "Test #{index + 1}: #{test_case.description}" @setup_commands.each(&:execute) test_case.run puts "" end end class Setup attr_reader :commands def initialize @commands = [] end def execute(cmd) @commands << Command.new(cmd) end end class TestCase attr_reader :description, :expectation, :commands def initialize(description) @description = description @commands = [] end def execute(cmd) @commands << Command.new(cmd) end def expect(result) @expectation = result end def run puts "Commands:" @commands.each(&:execute) puts "Expected: #{@expectation}" end end class Command def initialize(command) @command = command end def execute puts "Executing: #{@command}" end end end # DSLã使ç¨ãã TestSuite.new do setup do execute "Initialize database" end test "Addition works" do execute "Sum = add(1, 2)" expect "Sum == 3" end test "Subtraction works" do execute "Difference = subtract(5, 3)" expect "Difference == 2" end end.run
ãã®ä¾ã§ã¯ãTestSuiteã¯ã©ã¹å ã§DSLãå®ç¾©ãã¦ãã¾ããsetupã¡ã½ããã§ã¯ãã¹ãå®è¡åã®ã»ããã¢ãããè¡ããtestã¡ã½ããã§ã¯åã ã®ãã¹ãã±ã¼ã¹ã¨ãã®æå¾ å¤ãæå®ãã¾ããå®éã®ãã¹ãã±ã¼ã¹å®è¡ãã¸ãã¯ï¼ããã§ã¯åã«ã³ãã³ãã®åºåã模æ¬ãã¦ãã¾ãï¼ã¯ãå®éã®ãã¹ããã¬ã¼ã ã¯ã¼ã¯ã使ç¨ãããããããã¯ãã®DSLã®èå¾ã«ãããã¸ãã¯ã«ãã£ã¦è£å®ãããå¿ è¦ãããã¾ãã
ãã®ããã«DSLã使ç¨ããã¨ãç¹å®ã®ãã¡ã¤ã³ã«ç¹åãããã¹ãã±ã¼ã¹ã®è¨è¿°ãããç°¡åã«ãããã¦èªã¿ããããªãã¾ããDSLãéãã¦ããã¹ããã¸ãã¯ãããæ確ã«åé¢ãããã¹ãã±ã¼ã¹ã®æå³ãç´æçã«ä¼ãããã¨ãã§ãã¾ãã
ãããã¨ããããã¾ãããã¡ãã¯ããªãé£ããæãã¾ãã解説ããé¡ããã¦è¯ãã§ããï¼
User
ãããã¨ããããã¾ãããã¡ãã¯ããªãé£ããæãã¾ãã解説ããé¡ããã¦è¯ãã§ããï¼
ChatGPT
ãã¡ããã§ããä¸è¨ã®Rubyã§ã®DSLå®è£
ä¾ã¯ããã¹ãã¹ã¤ã¼ããè¨è¿°ããããã®ãã¡ã¤ã³ç¹åè¨èªã示ãã¦ãã¾ãããã®DSLã使ã£ã¦ããã¹ãã®ã»ããã¢ãããè¤æ°ã®ãã¹ãã±ã¼ã¹ãããã³ããããã®ãã¹ãã±ã¼ã¹ã®æå¾
å¤ãå®ç¾©ã§ãã¾ããããã§ã¯ããã®å®è£
ãã¹ããããã¤ã¹ãããã§è§£èª¬ãã¾ãã
âTestSuiteã¯ã©ã¹
ãã®ã¯ã©ã¹ã¯DSLã®ã¨ã³ããªã¼ãã¤ã³ãã§ãããã¹ãã¹ã¤ã¼ãå
¨ä½ã表ããã»ããã¢ããã¨ãã¹ãã±ã¼ã¹ã®å®ç¾©ãå¯è½ã«ãã¾ãã
initializeã¡ã½ãã: ã³ã³ã¹ãã©ã¯ã¿ã¯ãããã¯ãåãåããinstance_evalã使ã£ã¦ãã®ãããã¯ãè©ä¾¡ãã¾ããããã«ããããããã¯å ã®ã¡ã½ããå¼ã³åºããTestSuiteã¤ã³ã¹ã¿ã³ã¹ã®ã³ã³ããã¹ãå ã§è¡ãããããã«ãªãã¾ãã
setupã¡ã½ãã: ã»ããã¢ãããããã¯ãå®ç¾©ãã¾ããå é¨ã§Setupã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ãä½æãããã®ã¤ã³ã¹ã¿ã³ã¹ã§ãããã¯ãè©ä¾¡ãã¾ããã»ããã¢ããã§å®è¡ãããã³ãã³ãã¯ã@setup_commandsé åã«ä¿åããã¾ãã
testã¡ã½ãã: ãã¹ãã±ã¼ã¹ãå®ç¾©ãã¾ããåãã¹ãã±ã¼ã¹ã¯TestCaseã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ã¨ãã¦è¡¨ããããããã¯å ã®ã³ãã³ãã¯ãã®ã¤ã³ã¹ã¿ã³ã¹ã§è©ä¾¡ããã¾ãã
runã¡ã½ãã: å®ç¾©ããããã¹ãã±ã¼ã¹ãå®éã«å®è¡ãã¾ããã»ããã¢ããã³ãã³ããæåã«å®è¡ããç¶ãã¦åãã¹ãã±ã¼ã¹ãå®è¡ãã¾ãã
âSetupã¯ã©ã¹
ãã¹ãã®ã»ããã¢ãããæ
å½ãã¾ããã»ããã¢ããã§å®è¡ãããã¹ãã³ãã³ããæ ¼ç´ããããã®é
åãæã¡ã¾ãã
initializeã¡ã½ãã: ã³ãã³ããæ ¼ç´ããé åãåæåãã¾ãã
executeã¡ã½ãã: å®è¡ãããã³ãã³ããcommandsé åã«è¿½å ãã¾ãã
âTestCaseã¯ã©ã¹
åã
ã®ãã¹ãã±ã¼ã¹ã表ãã¾ãããã¹ãã®èª¬æãå®è¡ãããã¹ãã³ãã³ãã®ãªã¹ããæå¾
å¤ãæã¡ã¾ãã
initializeã¡ã½ãã: ãã¹ãã±ã¼ã¹ã®èª¬æãè¨å®ãã¾ãã
executeã¡ã½ãã: ãã¹ãã±ã¼ã¹ã§å®è¡ãããã³ãã³ãã追å ãã¾ãã
expectã¡ã½ãã: ãã¹ãã±ã¼ã¹ã®æå¾
å¤ãè¨å®ãã¾ãã
runã¡ã½ãã: ãã¹ãã±ã¼ã¹ã®ã³ãã³ããå®è¡ããæå¾
å¤ã表示ãã¾ãã
âCommandã¯ã©ã¹
å®è¡ãããã¹ãåã
ã®ã³ãã³ãã表ãã¾ãããã®ã¯ã©ã¹ã¯é常ã«ã·ã³ãã«ã§ãã³ãã³ãæååãä¿æããå®è¡æã«ããã表示ããã ãã§ãã
initializeã¡ã½ãã: ã³ãã³ãæååãè¨å®ãã¾ãã
executeã¡ã½ãã: ã³ãã³ãæååã表示ãã¾ãã
DSLã®ä½¿ç¨ä¾
TestSuite.new do setup do execute "Initialize database" end test "Addition works" do execute "Sum = add(1, 2)" expect "Sum == 3" end test "Subtraction works" do execute "Difference = subtract(5, 3)" expect "Difference == 2" end end.run
ãã®ã³ã¼ãã¯ãTestSuiteã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ãä½æãããããã¯å ã§ãã¹ãã¹ã¤ã¼ãã®ã»ããã¢ããã¨2ã¤ã®ãã¹ãã±ã¼ã¹ãå®ç¾©ãã¦ãã¾ããæå¾ã«ãrunã¡ã½ãããå¼ã³åºãã¦ãã¹ãã±ã¼ã¹ãå®è¡ãã¾ãããã®DSLãéãã¦ããã¹ãã®å®ç¾©ãç´æçãã¤å®£è¨çã«ãªãããã¹ãã³ã¼ãã®å¯èªæ§ã¨ã¡ã³ããã³ã¹æ§ãåä¸ãã¾ãã
ä¸è¨DSLãä¸è¡ãã¤ãã©ãã§ã©ãå®è¡ããã¦ãããã解説ãé¡ããã¾ãã
User
ä¸è¨DSLãä¸è¡ãã¤ãã©ãã§ã©ãå®è¡ããã¦ãããã解説ãé¡ããã¾ãã
ChatGPT
DSLã®åè¡ãã©ã®ããã«å®è¡ãããããå
·ä½çã«è¿½ã£ã¦ã¿ã¾ãããã
TestSuite.new do
ãã®è¡ã§ã¯TestSuiteã¯ã©ã¹ã®æ°ããã¤ã³ã¹ã¿ã³ã¹ãä½æãããä¸ãããããããã¯ãinstance_evalãéãã¦ãã®ã¤ã³ã¹ã¿ã³ã¹ã®ã³ã³ããã¹ãã§å®è¡ããã¾ããããã«ãããsetupãtestãªã©ã®ã¡ã½ããå¼ã³åºããTestSuiteã¤ã³ã¹ã¿ã³ã¹ã«å¯¾ãã¦ç´æ¥è¡ããã¾ãã
setup do execute "Initialize database" end
setupã¡ã½ãããå¼ã³åºããããã®å¼æ°ã¨ãã¦æ¸¡ããããããã¯ãSetupã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ã®ã³ã³ããã¹ãã§å®è¡ããã¾ããexecuteã¡ã½ããã¯Setupã¯ã©ã¹ã«å®ç¾©ããã¦ããã"Initialize database"ã¨ããæååãã³ãã³ããªã¹ãã«è¿½å ãã¾ãã
test "Addition works" do execute "Sum = add(1, 2)" expect "Sum == 3" end
testã¡ã½ãããå¼ã³åºããã"Addition works"ã¨ãã説æã¨ãå®è¡ããã³ãã³ãã¨æå¾ å¤ãå«ããããã¯ãå¼æ°ã¨ãã¦æ¸¡ããã¾ãããã®ãããã¯ã¯TestCaseã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ã®ã³ã³ããã¹ãã§å®è¡ããã¾ããexecuteã¯ã³ãã³ããªã¹ãã«"Sum = add(1, 2)"ã追å ããexpectã¯æå¾ å¤"Sum == 3"ãè¨å®ãã¾ãã
test "Subtraction works" do execute "Difference = subtract(5, 3)" expect "Difference == 2" end
åæ§ã«ãäºã¤ç®ã®ãã¹ãã±ã¼ã¹ãå®ç¾©ããã¾ãã"Subtraction works"ã¨ãã説æã«å¯¾ãã"Difference = subtract(5, 3)"ãå®è¡ããæå¾ å¤ã¨ãã¦"Difference == 2"ãè¨å®ããã¾ãã
end.run
endã§TestSuiteã¤ã³ã¹ã¿ã³ã¹ã®ãããã¯ãçµäºããrunã¡ã½ãããå¼ã³åºããã¾ããrunã¡ã½ããã§ã¯ãã¾ãã»ããã¢ãã段éã®ã³ãã³ããå®è¡ããï¼ãã®ä¾ã§ã¯"Initialize database"ï¼ããã®å¾ã§åãã¹ãã±ã¼ã¹ãé ã«å®è¡ããã¾ããåãã¹ãã±ã¼ã¹ã§ã¯ãã³ãã³ããå®è¡ãããæå¾ å¤ã表示ããã¾ãã
ãã®ä¸é£ã®ããã»ã¹ãéãã¦ãDSLã¯ãã¹ãã®å®ç¾©ã¨å®è¡ãç°¡æ½ãã¤ç´æçã«è¡ããã¨ãã§ãã¾ããinstance_evalã使ç¨ãããã¨ã§ãåãããã¯å ã®ã³ã³ããã¹ããé©åãªãªãã¸ã§ã¯ãï¼TestSuiteãSetupãTestCaseã®ã¤ã³ã¹ã¿ã³ã¹ï¼ã«åãæ¿ãããã®ãªãã¸ã§ã¯ãã®ã¡ã½ããããããã¯å ã§ç´æ¥å¼ã³åºããã¨ãã§ããããã«ãªãã¾ããããã«ãããèªç¶è¨èªã«è¿ãå½¢ã§ãã¹ãã¹ã¤ã¼ããè¨è¿°ãããã¨ãå¯è½ã«ãªãã¾ãã
ããªãç解ãé²ã¿ã¾ãããããããCommandãå®è¡ããã¾ã§ãã¾ã ããåããã¾ããã
User
ãããã¨ããããã¾ããããªãç解ãé²ã¿ã¾ãããããããCommandãå®è¡ããã¾ã§ãã¾ã ããåããã¾ããã
ChatGPT
Commandã¯ã©ã¹ã®å®è¡ã«ã¤ãã¦ãããå°ã詳ããè¦ã¦ã¿ã¾ããããCommandã¯ã©ã¹ã¯ãå®è¡ããã¹ãåå¥ã®ã³ãã³ãã表ãã¨ããããå§ã¾ãã¾ãããã®ã¯ã©ã¹ã¯é常ã«ã·ã³ãã«ã§ãã³ãã³ãæååãä¿æãããããå®è¡æã«è¡¨ç¤ºããæ©è½ã®ã¿ãæã£ã¦ãã¾ãã
DSLã®ã³ã³ããã¹ãã§ãã³ãã³ãã®å®è¡ãã¨è¨ã£ãå ´åãå®éã«ã¯Commandã¤ã³ã¹ã¿ã³ã¹ãä¿æããæååãå¦çï¼ãã®ä¾ã§ã¯åã«åºåï¼ãããã¨ãæãã¾ããDSLã®ã¦ã¼ã¶ã¼ï¼ãã¹ãã±ã¼ã¹ã®è¨è¿°è ï¼ã¯ãexecuteã¡ã½ããã使ã£ã¦ãä½ããã®æä½ã表ãæååãæå®ãã¾ãããã®æä½ã¯ããã¹ãã±ã¼ã¹ãå®éã«å®è¡ãããéã«ãCommandã¤ã³ã¹ã¿ã³ã¹ã«ãã£ã¦ã·ãã¥ã¬ã¼ãããã¾ãã
Commandã¯ã©ã¹ã®å®ç¾©ã¨å®è¡
class Command def initialize(command) @command = command end def execute puts "Executing: #{@command}" end end
Commandã¯ã©ã¹ã«ã¯ãinitializeã¡ã½ããã§ã³ãã³ãæååãåãåããexecuteã¡ã½ããã§ãã®æååãåºåããæ©è½ãããã¾ãã
Commandã®å©ç¨
Commandã®ã¤ã³ã¹ã¿ã³ã¹ã¯ãSetupãTestCaseã¯ã©ã¹å
ã®executeã¡ã½ãããéãã¦ä½æããã¾ããä¾ãã°ãTestCaseã¯ã©ã¹å
ã§executeã¡ã½ãããå¼ã°ããã¨ãæå®ãããã³ãã³ãæååãæã¤æ°ããCommandã¤ã³ã¹ã¿ã³ã¹ãä½æããããã¹ãã±ã¼ã¹ã®ã³ãã³ããªã¹ãã«è¿½å ããã¾ãã
class TestCase def execute(cmd) @commands << Command.new(cmd) end def run puts "Commands:" @commands.each(&:execute) end end
ã³ãã³ãã®å®è¡ããã»ã¹
TestCaseã¤ã³ã¹ã¿ã³ã¹ã®runã¡ã½ãããå¼ã³åºãããã¨ããã®ã¤ã³ã¹ã¿ã³ã¹ãä¿æãããã¹ã¦ã®Commandã¤ã³ã¹ã¿ã³ã¹ã®executeã¡ã½ãããé ã«å¼ã³åºããã¾ãã
Commandã¤ã³ã¹ã¿ã³ã¹ã®executeã¡ã½ããã¯ãåã«ãã®ã³ãã³ãæååãåºåãã¾ãããã®åºåã¯ããã¹ãã±ã¼ã¹ã®ä¸ç°ã¨ãã¦ç¹å®ã®æä½ããå®è¡ããããã¨ãããã¨ãã·ãã¥ã¬ã¼ããã¦ãã¾ãã
ãã®ããã»ã¹ãéãã¦ãDSLã®ã¦ã¼ã¶ã¼ã¯executeã¡ã½ããã使ã£ã¦ä»»æã®æä½ããå®è¡ãã§ããã¨è¡¨ç¾ãã¾ãããå®éã®ãå®è¡ãã¯ãCommandã¤ã³ã¹ã¿ã³ã¹ããã®æååãåºåãããã¨ã§ã·ãã¥ã¬ã¼ãããã¦ãã¾ãããã®ã·ã³ãã«ãªå®è£ ã§ã¯ãå®éã«å¤é¨ã·ã¹ãã ãæä½ããããè¨ç®ãå®è¡ããããããã¨ã¯ããã¾ãããããã®ä»çµã¿ãå©ç¨ãã¦ãå®éã®ãã¹ããã¬ã¼ã ã¯ã¼ã¯ãå¤é¨ã·ã¹ãã ã¨ã®ã¤ã³ã¿ãã§ã¼ã¹ãªã©ãããè¤éãªæ©è½ãå®è£ ããåºç¤ã¨ãããã¨ãã§ãã¾ãã
User
ãããã¨ããããã¾ãããããã§ç解ã§ãã¾ããã
ChatGPT
ããã¯è¯ãã£ãã§ãï¼ããä»ã«è³ªåãããã«ç¥ããããã¨ãããã°ããã¤ã§ããç¥ãããã ãããç解ãæ·±ããããã«ãå®éã«ã³ã¼ããæ¸ãã¦ã¿ãã®ãè¯ãæ¹æ³ã§ããã