ãã®è¨äºã¯ ä¸ä¼.com Advent Calendar 2024 ã®3æ¥ç®ã®è¨äºã§ãã
æ¨ä»ã¯æã
ä¸ä¼ã®ãããªäºç´ã·ã¹ãã éçºã«ããã¦ããé¢æ°åããã°ã©ãã³ã°ç±æ¥ã®ãã©ã¯ãã£ã¹ãåãå
¥ããæ©ä¼ãå¢ãã¦ãã¾ãã
ä¾ãã°ãå¤ã¯ã¤ãã¥ã¼ã¿ãã«ã§ããæ¹ãæ±ãããããé¢æ°ã¯å¯ä½ç¨ã®ãªãç´ç²é¢æ°ã«ããæ¹ããã¹ã¿ããªãã£ãªã©ãå«ãä½ãã¨é½åããããããããå ´é¢ã§ã¯ç©æ¥µçã«ä¸å¤ãªå¤ã使ããé¢æ°ãåªçã«ãªãããæèçã«å®è£
ãã¾ãããã¡ã¤ã³ãã¸ãã¯ãç´ç²é¢æ°ã¨ãã¦è¨è¿°ã§ããã¨ãå
ç¢ã§è²¬ååé¢ãããããããã¹ãããããã°ãããããã·ã¹ãã ã«ãªã£ã¦ããã¾ãã
ã¨ããã§ãé¢æ°åããã°ã©ãã³ã°ã¨ã¯ãªããããã¨ããã®ã«æ確ãªå®ç¾©ã¯ãªãããã§ããã§ããçªãè©°ãã¦ããã¨ãè¨ç®ããªãã¹ããæãã§ã¯ãªããå¼ãã§å®£è¨ãããã¨ãä¸ã¤ã®ç®æ¨ã ã¨ãããã¨ã«æ°ãã¤ãã¾ãã
æã¨å¼ã®éãã¯ä½ã§ãããã?
for æã代å
¥æãif æãªã©ã®æã¯ãåºæ¬çã«ã¯å¤ãè¿ãã¾ãããå¤ãè¿ããªãã¨ãããã¨ã¯ãæã¯ç´æ¥çµæãåãåããã®ã§ã¯ãªããå½ä»¤ã«ãªã£ã¦ããã¨è¨ãã¾ããæã¯è¨ç®æ©ã¸ã®å½ä»¤ã§ãã
ä¸æ¹ã®å¼ã¯ãå¿
ãè¿å¤ãä¼´ãã¾ãããããã®ä¸»ãªç®çã¯è¿å¤ãå¾ããã¤ã¾ãå¼ãè©ä¾¡ãã¦è¨ç®ã®çµæãå¾ããã¨ã ã¨èãããã¨ãã§ãã¾ãã
customer.archive()
ã¨ãæã«ãã£ã¦æé»çã« customer ãªãã¸ã§ã¯ãã®å
é¨ç¶æ
ãå¤æ´ããã®ã§ã¯ãªã
const archivedCustomer = archiveCustomer(customer)
ã¨ãå¼æ°ã§ä¸ãããã customer ãªãã¸ã§ã¯ããç´æ¥å¤æ´ãããã¨ãªãã«ãã¢ã¼ã«ã¤ãç¶æ
ã«å¤æ´ãããã³ãã¼ã¨ãã¦ã® archivedCustomer ãªãã¸ã§ã¯ããè¿å¤ã¨ãã¦è¿ãããããå¼ã§ãããã®é¢æ°ã¯ç´ç²é¢æ°ã¨ãã¦å®è£
ããcustomer ãªãã¸ã§ã¯ãã¯ä¸å¤ãã¤ã¾ãã¤ãã¥ã¼ã¿ãã«ãªãã®ã¨ãã¦æ±ãã¨è¯ãã§ãããã
å¼ã«ããã¤ãã¥ã¼ã¿ãã«ãªãªãã¸ã§ã¯ãã®æ´æ°ã¯ TypeScript ãªã
export const archiveCustomer = (customer : Customer ): Customer => ({
...customer,
archived : true
} )
ã¨ãã¹ãã¬ããæ§æã使ããã¨ã§ customer ãªãã¸ã§ã¯ãã®ã³ãã¼ãä½ãã¤ã¤ãå¤æ´ãããããããã£ãæ°ããªå¤ã«è¨å®ãããã®ãè¿ãããã«å®è£
ãã¾ãã
ãã®ããã«ãå¼æ°ã§ä¸ãããªãã¸ã§ã¯ãã¯ç´æ¥å¤æ´ãããç¶æ
ãå¤æ´ããå¥ã®ãªãã¸ã§ã¯ããè¿ããããªé¢æ°ã®é£ãªãã«ãã£ã¦è¨ç®ãå®ç¾©ãã¦ããã®ãé¢æ°åããã°ã©ãã³ã°ã§ãã
ãã®ãããã®èãæ¹ã«ã¤ãã¦ã¯ãéå»ã®çºè¡¨ã¹ã©ã¤ããããã¾ãã®ã§åèã«ãã¦ãã ããã
å®éãæã
ã®ä¸é¨ãããã¯ãã®ããã¯ã¨ã³ãã§ã¯ TypeScript ã«ããé¢æ°åã¹ã¿ã¤ã«ã§ã®éçºãå®è·µãã¦ãã¾ãã以ä¸ã¯ãããã¯ãã®ã³ã¼ãã®ä¸ä¾ã§ãCustomer ãªãã¸ã§ã¯ãã«æ°ããã¡ã¼ã«ã¢ãã¬ã¹ã®å¤ã追å ããããã® addEmail
é¢æ°ã§ããå
ã®å®è£
ã«åãããã¹ãã¬ããæ§æã使ã£ã¦å
ã®ãªãã¸ã§ã¯ããç ´å£ããã«ãã¡ã¼ã«ã¢ãã¬ã¹ã追å ããããªãã¸ã§ã¯ããè¿ãã¾ãã
const addEmail =
(address : EmailAddress ) =>
(customer : Customer ): Customer => {
const newAddress: CustomerEmail = {
id : generateCustomerEmailId(),
address ,
}
return {
...customer,
emails : [ ...customer.emails, newAddress] ,
}
}
ãã¡ã¤ã³ãªãã¸ã§ã¯ãã®ç¶æ
é·ç§»ã¯ãã¹ã¦ããã®å¼ã«ããç¶æ
é·ç§»ã®ã¢ãã«ã§å®è£
ãã¦ãã¾ãã
æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°
ãã¦ãæ¬è¨äºã®ãã¼ãã¯ãæ°¸ç¶ãã¼ã¿ãã§ããæ°¸ç¶ãã¼ã¿ã¨ã¯ä½ã§ãããã?
å¼ãæèçã«ä½¿ãããã¤å¤ãã¤ãã¥ã¼ã¿ãã«ã«æ±ããã¨ãåºæ¬ã¨ãã¦ãã£ã¦ããã¨ãä½æ°ãªãæ¸ããããã°ã©ã ã®ä¸ã«ç¹å¾´çãªæ§åãç¾ãããã¨ã«ãªãã¾ãã
以ä¸ããªã¹ãæä½ã®ããã°ã©ã ãè¦ã¦ã¿ã¾ãããããªã¹ãã®å
é ãæ«å°¾ã«å¤ã追å ããããé©å½ãªå¤ãåé¤ãã TypeScript ã®ããã°ã©ã ã§ãããªã¹ããã¤ãã¥ã¼ã¿ãã«ã«æ±ãã¹ããå¤ã®è¿½å ãåé¤ãªã©ãã¼ã¿æ§é ã®å¤æ´ã«ã¯ã¹ãã¬ããæ§æã使ããéç ´å£çã«ãããè¡ãããã«ãã¾ãã
const as1 = [ 1 , 2 , 3 , 4 , 5 ] ;
const as2 = [ 100 , ...as1] ;
const as3 = [ ...as2, 500 ] ;
const as4 = as3.filter (x => x !== 3 );
console .log ("as1:" , as1);
console .log ("as2:" , as2);
console .log ("as3:" , as3);
console .log ("as4:" , as4);
æ´æ°ããã¦ãå
ã®ãªã¹ãã¯ä¸å¤ãªã®ã§ãas1
ãåç
§ãã¦ãæ´æ°æ¸ã¿ã®çµæã¯å¾ããã¾ããããªã¹ãæä½ã®è¿ãå¤ã as2
as3
as4
ã¨ãã®é½åº¦å¤æ°ã«ãã£ããã£ãããã®ãã£ããã£ããå¤æ°ã«å¯¾ãã¦æ¬¡ã®ãªã¹ãæä½ãè¡ãã¾ãããããã¦ãã¼ã¿æ§é ã¯ä¸å¤ã§ããã¤ã¤ãä¸é£ã®ãé£ç¶ãããªã¹ãæä½ã表ç¾ãã¾ãã
ãã¼ã¿æ§é ãä¸å¤ã«ããçµæããªã¹ããæ´æ°ãããéç¨ã®ç¶æ
ãã¹ã¦ãæ®ãã¾ããããªã¹ããä½åº¦ãæ´æ°ããã«ãé¢ããããå¤æ´åã®ç¶æ
ãåç
§ãããã¨ãã§ãã¦ãã¾ããas1
ãåç
§ããã°åæç¶æ
ããas2
ã as3
ã§éä¸ã®ç¶æ
ãåç
§ãããã¨ãã§ãã¾ãããã®ããã«å¤ã®å¤æ´å¾ããã以åã®ç¶æ
ãæ®ããã¾ããæ°¸ç¶ãã¼ã¿ãã¨å¼ã³ã¾ããããã¦æ°¸ç¶ãã¼ã¿ãç¨ããããã°ã©ãã³ã°ããæ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ãã¨å¼ã³ã¾ãã
å¤ãã¤ãã¥ã¼ã¿ãã«ã«æ±ãã¨å¿
ç¶çã«ããã¯æ°¸ç¶ãã¼ã¿ã«ãªãã®ã§ãæ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ã¯ããèªä½ãä½ãç¹å¥ãªãã¯ããã¯ã¨ããããã§ã¯ããã¾ãããä¸æ¹ã§ãå¤ãæ°¸ç¶ãã¼ã¿ã§ãããã¨ãã¯ã£ããããããæèä¸ã§ã¯ãæ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ãã¨ããè¨èã§ããã°ã©ãã³ã°ã¹ã¿ã¤ã«ã表ç¾ããã¨ããã®æå³ãæ確ã«ãªããã¨ãå¤ãã§ãããã
以ä¸ã®å±±æ¬å彦ããã®è¨äºã§ã¯ãé¢æ°åããã°ã©ãã³ã°ããªãã¡ãæ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ãã§ãããæ°¸ç¶ãã¼ã¿ãé§ä½¿ãã¦åé¡ã解ããã¨ãããé¢æ°åããã°ã©ãã³ã°ã ãã¨è¿°ã¹ããã¦ãã¾ãã
çè
ã®é¢æ°ããã°ã©ãã³ã°ã®å®ç¾©ãããªãã¡ãã®ç¹éã§ã®å®ç¾©ã¯ããâ æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ãã§ããæ°¸ç¶ãã¼ã¿ã¨ã¯ãç ´å£ã§ããªããã¼ã¿ãã¤ã¾ãå代å
¥ã§ããªããã¼ã¿ã®ãã¨ã§ããããã¦ãæ°¸ç¶ãã¼ã¿ãé§ä½¿ãã¦åé¡ã解ãã®ãæ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ã§ãã
ã¾ãé¢æ°åè¨èªã¨ã¯ãæ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ã奨å±ãæ¯æ´ãã¦ããè¨èªã®ãã¨ã§ããé¢æ°åè¨èªã§ã¯ãå代å
¥ã®æ©è½ããªãããå代å
¥ã®ä½¿ç¨ã¯éå®ããã¦ãã¾ããçè
ã®å®ç¾©ã¯ããªãå³ããã»ãã ã¨è¨ãã¾ãã
第1ç« ãé¢æ°ããã°ã©ãã³ã°ã¯é£ãããªãï¼âåãã¦å¦ã¶äººã«ããæ«æãã人ã«ããã¡ãã¨ããã | gihyo.jp
å½ä»¤åããã°ã©ãã³ã°ã«ããã¦ã¯å¤æ´ã«ãããå¤ãç´æ¥ç ´å£çã«å¤æ´ãã¾ããå¤æ´åã®ãã¼ã¿æ§é ã®ç¶æ
ãåç
§ãããã¨ã¯ã§ãã¾ããããªã¹ãã®ç ´å£çå¤æ´ã¯ãåºæ¬çã« (å¼ã§ã¯ãªã) æã«ãã£ã¦è¡ãããã§ããããæã主ä½ã¨ããããã°ã©ãã³ã°Â·Â·Â· å½ä»¤åããã°ã©ãã³ã°ã§ã¯ãæ°¸ç¶ã§ã¯ãªããã¼ã¿ãã¤ã¾ãçå½ãã¼ã¿ãåºæ¬ã«ãã¦ããã¨è¨ãã¾ããä¸æ¹ãå¼ã«ãã£ã¦ããã°ã©ã ãæ§æããé¢æ°åããã°ã©ãã³ã°ã§ã¯ãé¢æ°ã®åªçæ§ã確ä¿ãã¹ãã¤ãã¥ã¼ã¿ãã«ã«å¤ãæ±ããã¨ã«ãªãã®ã§ãæ°¸ç¶ãã¼ã¿ãåºæ¬ã«ãªãã¾ãã
ã¤ãã¥ã¼ã¿ãã«ãªå¤ã«ããããã°ã©ãã³ã°ãããéãããã«ããå¤ã¯ä¸å¤ã§ããã ãã§ãªããåæã«æ°¸ç¶ãã¼ã¿ãªã®ã ã¨ãããã¨ãèªèã§ããã¨ãããã°ã©ãã³ã°ã¹ã¿ã¤ã«ã«å¯¾ããããããã¡ã³ã¿ã«ã¢ãã«ãæ§ç¯ã§ããã¨æãã¾ãã
Haskell ã¨æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°
ããåçªã§ãããã¤ãã¥ã¼ã¿ãã«ã¨ããã°ç´ç²é¢æ°åè¨èªã® Haskell ã§ããå
ã® TypeScript ã«ãããªã¹ãæä½ã®ããã°ã©ã ããHaskell ã§å®è£
ãã¦ã¿ã¾ãã
main :: IO ()
main = do
let as1 = [1 , 2 , 3 , 4 , 5 ]
as2 = 100 : as1
as3 = as2 ++ [500 ]
as4 = delete 3 as3
print as1
print as2
print as3
print as4
Haskell ã¯ãªã¹ãã¯ãã¡ãããåºæ¬çã«å¤ããããããã¤ãã¥ã¼ã¿ãã«ã§ãããªã¹ãæä½ã® API ã¯ãã¹ã¦éç ´å£çã«ãªãããå®è£
ããã¦ããã®ã§ãå¤æ´ã«ããã TypeScript ã®ããã«ã¹ãã¬ããæ§æã§ãã¼ã¿ãæ示çã«ã³ãã¼ãããããå¿
è¦ã¯ããã¾ãããè£ãè¿ãã°ãå¤æ´ã¯æ°¸ç¶ãã¼ã¿çã«è¡¨ç¾ããããå¾ããå¼ã«ãã£ã¦ããã°ã©ã ãæ§æãããã¨ãå¿
é ã¨ãªãã¾ããçµæãHaskell ã«ããå®è£
ã¯èªç¶ã¨æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ã«ãªãã¾ãã
é¢æ°åããã°ã©ãã³ã°ããªãã¡æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ã ãã¨ããã®ã¯ããã®å¿
ç¶æ§ããæ¥ã¦ãã¾ãã
æ°¸ç¶ãã¼ã¿ã®ç¹æ§ãå©ç¨ããåé¡è§£æ±º
æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ã¯ä¸å¤ãªå¤ã使ããã¨ã§ãããããããå®è·µãããã¨ã§è¨äºåé ã§æãããããªããã°ã©ã ã®å
ç¢æ§ãªã©æ§ã
ãªã¡ãªããã享åã§ããããã§ããããå¤æ´åã®éå»ã®ç¶æ
ãåç
§ã§ãããã¨ãããå¤ãä¸å¤ã§ããã¨ããããã¯ãã¾ãã«ãæ°¸ç¶ããã¼ã¿ã®ç¹æ§ãé¨åãæ´»ããã±ã¼ã¹ãããã¾ãã
ããããããé¡æã¨ãã¦ã競æããã°ã©ãã³ã°ã®åé¡ãä¾ã«æãã¾ãã
atcoder.jp
åé¡æãèªãã®ãé¢åãªæ¹ã®ããã«ããããã©ããªåé¡ãç°¡åã«è§£èª¬ãã¾ããå
¥åã®æ示ã«å¾ã£ã¦ãªã¹ããæ´æ°ãã¤ã¤ãä»»æã®ã¿ã¤ãã³ã°ã§ãã®ãªã¹ãã®ç¾å¨ã®ç¶æ
ãä¿åãããã¾ãä»»æã®ã¿ã¤ãã³ã°ã§å¾©å
ã§ããããããã¨ããããã¼ã¿æ§é ã®ä¿åã¨å¾©å
ãé¡æã«ããåé¡ã§ãã
ADD 3
SAVE 1
ADD 4
SAVE 2
LOAD 1
DELETE
DELETE
LOAD 2
SAVE 1
LOAD 3
LOAD 1
ããããã¯ã¨ãªãå
¥åã¨ãã¦ä¸ããããã
空ã®ãªã¹ããæåã«ãã
ã¯ã¨ãªãä¸ããé çªã«è§£éãã¦ãADD 3
ã®ã¨ãã¯ãªã¹ãæ«å°¾ã« ã追å ãã
DELETE
ãªãæ«å°¾ã®å¤ãåé¤
SAVE 1
ã®ã¨ãã¯ãä»ä½¿ã£ã¦ãããªã¹ãã ID çªå· ã®é åã«ä¿åãLOAD 1
ãªã ID çªå· ã®é åãããªã¹ãã復å
ãã
ã¯ã¨ãªã®ãã³ããã®æç¹ã§ã®ãªã¹ãã®æ«å°¾ã®è¦ç´ ãåºåãã
ã¨ããåé¡ã«ãªã£ã¦ãã¾ãã
ãã®åé¡ãæ°¸ç¶ãã¼ã¿ãªãã§è§£ããã¨ããã¨ããªã¹ããæ´æ°ãã¦ã以åã®ç¶æ³ã«æ»ãããããªæ¨ã®ãã¼ã¿æ§é ãèªåã§æ§ç¯ããå¿
è¦ããããªããªãé¢åã§ããä¸æ¹ãæ°¸ç¶ãã¼ã¿ãåæã«ããã¨ãä½ã®è¦å´ããªã解ãã¦ãã¾ãã¾ãã
以ä¸ã¯ Haskell ã§å®è£
ããä¾ã§ãããã£ã¦ãããã¨ã¯ãã¯ã¨ãªã®å
容ã«åããã¦ãªã¹ãã«å¤ã追å ã»åé¤ãä¿åã¨å¾©å
ã®ã¨ãã¯è¾æ¸ (IntMap) ã«ããã®æç¹ã®ãªã¹ããæ ¼ç´ãã¦ããã ãã§ããåé¡æã®éãã«ã·ãã¥ã¬ã¼ã·ã§ã³ãã¦ããã ããã¨ãè¨ãã¾ãã
main :: IO ()
main = do
q <- readLn @ Int
qs <- map words <$> replicateM q getLine
let qs' = [if null args then (command, - 1 ) else (command, stringToInt (head args)) | command : args <- qs]
let res = scanl' f ([], IM.empty) qs'
where
f (xs, s) query = case query of
("ADD" , x) -> (x : xs, s)
("DELETE" , _) -> (drop1 xs, s)
("SAVE" , y) -> (xs, IM.insert y xs s)
("LOAD" , z) -> (IM.findWithDefault [] z s, s)
_ -> error "!?"
printList [headDef (- 1 ) xs | (xs, _) <- tail res]
Haskell ã®ãªã¹ãã¯æ°¸ç¶ãã¼ã¿ã§ããããå¤ãå¤æ´ãã¦ãå¤æ´ä»¥åã®å¤ãæ®ãã¾ãããã®å¤ãæé»çã«ä»ã§æ¸ãæããããäºã¯ããã¾ããããã£ã¦ç´ ç´ã«ãªã¹ããè¾æ¸ã«ä¿åãã¦ããã°ããã®ã§ããä¸æ¹ãå½ä»¤åããã°ã©ãã³ã°ã«ããã¦ãªã¹ãããã¥ã¼ã¿ãã«ãªå ´åã¯ãããæç¹ã®åç
§ãè¾æ¸ã«ä¿åããã¨ãã¦ããã©ããã§æ¸ãæããçºçããã¨ãè¾æ¸ã«ä¿åãããåç
§ã®å
ã®ãã¼ã¿ãæ¸ãæãããããã¾ãããã¾ããã
æ°¸ç¶ãã¼ã¿æ§é
ãã¦ããããããæ¬é¡ã§ããTypeScript ã§ãªã¹ããæ°¸ç¶ãã¼ã¿ã¨ãã¦æ±ãã«ããããã¹ãã¬ããæ§æã«ããã³ãã¼ã使ãã¾ããã
const as2 = [ 100 , ...as1] ;
const as3 = [ ...as2, 500 ] ;
ãã§ã«ãæ°ã¥ãã®æ¹ãå¤ãã¨æãã¾ãããå¤ã®æ´æ°ã«ãããããªã¹ãå
¨ä½ã®ã³ãã¼ãèµ°ã£ã¦ãã¾ã£ã¦ãã¾ããä¸ã¤å¤ã追å ãåé¤ãæ´æ°ããã ãã§ããªã¹ãã®è¦ç´ 件ã«å¯¾ã 件ã®ã³ãã¼ãèµ°ããã¤ã¾ã ã®è¨ç®éãå¿
è¦ã«ãªã£ã¦ãã¾ãã¾ããæ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ã¯è¯ããã®ã§ããããã¤ã¼ãã«å®è£
ããã¨ãã¼ã¿ã³ãã¼ã«ããè¨ç®éã®å¢å¤§ãæããã¡ã§ãã
Haskell ãªã©ãã¤ãã¥ã¼ã¿ãã«ãåæã®ããã°ã©ãã³ã°è¨èªã¯ãã®åé¡ãã©ããã¦ããã®ã§ãããã?
çµè«ããã¼ã¿æ§é å
¨ä½ãã³ãã¼ããã®ã§ã¯ãªããå¤æ´ããããã¼ãã¨ãã®ãã¼ãã¸ç´æ¥çã»éæ¥çã«åç
§ãæã¤ãã¼ãã ããã³ãã¼ããããã¨ã«ãã£ã¦è¨ç®éãæããä¸å¤ã§ãããªãããå¹ççãªãã¼ã¿æ´æ°ãå¯è½ã«ãªãããã«ãªã¹ããã®ä»ã®ãã¼ã¿æ§é ãå®è£
ããã¦ãã¾ããã¤ã¾ãåãããªã¹ããã§ããå½ä»¤åããã°ã©ãã³ã°ã®ããã¨ãä¸å¤ãªãã¼ã¿æ§é ã®ããã¯å®è£
èªä½ãç°ãªãã®ã§ããæ½è±¡ã¯åãããªã¹ããã§ãå
·ä½ãéãã¨è¨ããã§ãããã
å¤æ´ãã£ãã¨ããã ããã³ãã¼ãããã以å¤ã¯å
ã®å¤ã¨å
±æãè¡ããã®ãã¼ã¿æ§é ã®å®è£
ææ³ã¯ Structural Sharing ã¨å¼ã°ãããã¨ãããã¾ããStructural Sharing ã«ããä¸å¤ã§ãããªããå¹ççã«æ´æ°ãå¯è½ãªæ°¸ç¶ãã¼ã¿ã®ãã¼ã¿æ§é ããæ°¸ç¶ãã¼ã¿æ§é ãã¨å¼ã³ã¾ãã
æ°¸ç¶ãã¼ã¿æ§é ã«ã¤ãã¦ã¯ã以ä¸ã®æ¸ç±ã«ãã®å®è£
æ¹æ³å«ã詳ããè¨è¼ããã¦ãã¾ãã
ç´ç²é¢æ°åãã¼ã¿æ§é - ã¢ã¹ãã¼ãã¯ã³ã´
ãã¨ããä¾ãã° Haskell ã®ãªã¹ãã¯å
é ã®å¤ãæä½ããå ´å㯠ã§ããå
é è¦ç´ ã ããã³ãã¼ããã¦ãã¦ããã以éã®è¦ç´ ãæ´æ°åå¾ã®äºã¤ã®ãªã¹ãã§å
±æãããããã§ãã
åãããå
ã®å®è£
ã§ãå©ç¨ãã Data.IntMap
ã¨ããè¾æ¸ããã¡ããæ°¸ç¶ãã¼ã¿æ§é ã§ãããå
é¨çã«ã¯ãããªã·ã¢æ¨ã§å®è£
ããã¦ãã¦ãå¤ã®æ¿å
¥ããã¼ã®æ¢ç´¢ã¯ãæ´æ°ã®ãããé·ç¨åº¦ã®è¨ç®é ··· ããã¼ã¿ãµã¤ãºã ããããé·ã¨ããã¨ã ã«åã¾ãã¾ãã
Haskell ã§å©ç¨ããæ¨æºçãªãã¼ã¿æ§é ··· ListãMapãSetãSequenceãHeap ã¯ããã¹ã¦ã¤ãã¥ã¼ã¿ãã«ã§ãããªãããå¤ã®æ¢ç´¢ãå¤æ´ã ã ç¨åº¦ã®è¨ç®éã§è¡ããæ°¸ç¶ãã¼ã¿æ§é ã«ãªã£ã¦ãã¾ãã(ãªãã誤解ã®ç¡ãããè£è¶³ããã¨ããã¥ã¼ã¿ãã«ãªãã¼ã¿æ§é ãããã¾ãããã¥ã¼ã¿ãã«ãªãã¼ã¿æ§é ã¯æç¶ãçããã°ã©ãã³ã°ã§å¤æ´ãããã¨ã«ãªãã¾ã)
æ°¸ç¶ãã¼ã¿æ§é ãå©ç¨ãããã¨ã«ãã£ã¦ãæ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°æã«ãããã©ã¼ãã³ã¹ãããã»ã©ç ç²ã«ããã大éã®ãã¼ã¿ãæ±ããã¨ãå¯è½ã«ãªãã¾ããè£ãè¿ãã°ãæ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ãããåºç¯å²ã«å®è·µãã¦ããã«ã¯ãæ°¸ç¶ãã¼ã¿æ§é ãå¿
è¦ä¸å¯æ¬ ã§ããã¨ãè¨ãã¾ããé¢æ°åããã°ã©ãã³ã°ã¯å¤ãä¸å¤ã§ãããã¨ãããã¨ãã¾ããããã®ããã«ã¯æ°¸ç¶ãã¼ã¿æ§é ãå¿
è¦ãã¤éè¦ãªãã¼ããªã®ã§ãã
TypeScript ãã®ä»ã®ããã°ã©ãã³ã°è¨èªã§æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ãå®è·µããã¨ããç´ç²é¢æ°åè¨èªã¨ã¯ç°ãªããç´ ã®ç¶æ
ã§ã¯æ°¸ç¶ãã¼ã¿æ§é ã®æ¯æ´ããªãã¨ãããã¨ã¯å¿µé ã«ç½®ãã¦ããã¹ãã§ãããã
TypeScript ã Python ã§æ°¸ç¶ãã¼ã¿æ§é ãå©ç¨ããã«ã¯?
TypeScript ã® ArrayãMapãSet ãªã©ã®æ¨æºçãªãã¼ã¿æ§é ã¯ãã¹ã¦å½ä»¤åãã¼ã¿æ§é ãã¤ã¾ããã¥ã¼ã¿ãã«ã§ããå½ä»¤åã®ããã°ã©ãã³ã°è¨èªã«ããã¦ã¯ãã©ã®è¨èªãåæ§ã§ããããä¸æ¹ãããã°ã©ãã³ã°è¨èªã«ãã£ã¦ã¯ ListãMapãSet ãªã©ã®æ°¸ç¶ãã¼ã¿æ§é ãã¼ã¸ã§ã³ãæä¾ãããµã¼ããã¼ãã£ã©ã¤ãã©ãªãããã¾ãã
ãããã®ã©ã¤ãã©ãªãå°å
¥ãããã¨ã§ãTypeScript ã Python ã§æ°¸ç¶ãã¼ã¿æ§é ãå©ç¨ãããã¨ãã§ãã¾ããããããå®éã®ã¨ãããããã®æ°¸ç¶ãã¼ã¿æ§é ã®å®è£
ããåºãæ®åãã¦ããããã«ã¯æãã¾ããã
æ°¸ç¶ãã¼ã¿æ§é ã¯æ¥åã·ã¹ãã éçºã«ãå¿
é ã?
çµè«ããããã¨ãå½ä»¤åã®ããã°ã©ãã³ã°è¨èªã§æ¥åã·ã¹ãã éçºãããå ´åã«ã¯ãå¿
é ã§ã¯ãªãã§ãããã
æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°èªä½ã¯è¯ãä½æ³ã§ãããæ¥åã·ã¹ãã ã«ããã¦ã¯ã大éãã¼ã¿ã®ãã¤ã¼ããªã³ãã¼ãèµ°ããããªå®è£
ãããå ´é¢ãå°ãªããããã¨ããã®ãçç±ã ã¨æãã¾ãã
Haskell ã®ãããªé¢æ°åè¨èªã使ã£ã¦ããã®ã§ããã°ãæ°¸ç¶ãã¼ã¿æ§é ã¯æ¨æºçã«æä¾ããã¦ãã¦ãããããå¿
é ãã©ããããæ°ã«ããå¿
è¦ãããã¾ãããæ°¸ç¶ãã¼ã¿æ§é ã®ã¡ã«ããºã ãå
¨ãç¥ããªãã¦ããèªç¶ã«ããã使ã£ãããã°ã©ã ãæ¸ãããã«å°ããã¾ãã
å½ä»¤åè¨èªã使ãã¤ã¤ããæ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ãå®è·µããã±ã¼ã¹ã§ã¯ã©ãã§ãããã?
é度ãå¿
è¦ãªå¤ãã®å ´é¢ã§ã¯ããã£ããæ°¸ç¶ãã¼ã¿ã諦ããåã«å½ä»¤åãã¼ã¿æ§é ãå©ç¨ããã°äºè¶³ããã®ã§ãããããæ°¸ç¶ãã¼ã¿æ§é ãæã¡åºãå¿
è¦ã¯ãªãã§ãããããã¡ã¤ã³ãªãã¸ã§ã¯ãã®å¤æ´ãã¤ãã¥ã¼ã¿ãã«ã«è¡¨ç¾ããããã³ãã¼ããå ´åãããããã 10 ã 20 ç¨åº¦ã®ããããã£ãã³ãã¼ããç¨åº¦ã§ãã³ãã¼ 1åã«ãããæ°ä¸ä»¶ã¨ãã£ããªã¼ãã¼ã®ã³ãã¼ãçºçãããããªãã¨ã¯å¸ã§ãããã
ãã£ã¦æ¥åã·ã¹ãã éçºã«ãã㦠Immutable.js ã pyrsistent ã®ãããªãµã¼ããã¼ãã£ã©ã¤ãã©ãªãç©æ¥µçã«ä½¿ãããå ´é¢ã¯ãå
ã«è§£ãã競æããã°ã©ãã³ã°åé¡ã®ããã«ãæ°¸ç¶ãã¼ã¿æ§é ã®æ°¸ç¶ã§ããç¹æ§ãã®ãã®ãæ©è½è¦ä»¶ã¨ãã¦å¿
è¦ã«ãªãã±ã¼ã¹ã«éãããã®ã§ã¯ãªãã? ã¨æãã¾ãã
Immutable.js ã®éçºãåæ»ãã¦ããã®ã¯ãããã³ãã¨ã³ãã§æ°¸ç¶ãã¼ã¿æ§é ã®éè¦ãä¹ããããã§ãããããã®ãããªãã¼ã¿æ§é èªä½ã¯é常ã«éè¦ãªæ¦å¿µã§ãå¤ãã®ããã°ã©ãã³ã°è¨èªã«åå¨ãã¾ããæã
ããã³ãã¨ã³ãã¨ã³ã¸ãã¢ãä¾åãããã©ã¦ã¶ã®å
é¨ã§ããå¹ççãªãã¼ã¿å¦çã®ããã«å¤ç¨ããã¦ããã¯ãã§ããããããããã³ãã¨ã³ãã¨ã³ã¸ãã¢ãã¤ãã¥ã¼ã¿ãã«ã«æ±ãã¦ããã®ã¯å¦çé度ã§ã¯ãªãè¨è¨ã®æ¹åã§ããã ãããããImmutable.js ã«ä»£ãã£ã¦ Immer ãéçããã®ã§ãããã
Immutable.jsã¨Immerãã¡ããã¨ä½¿ãåãã¦ãã¾ããï¼
ä¸æ¹ãç´ç²é¢æ°åè¨èªã§ç«¶æããã°ã©ãã³ã°ã®ãããªå¤§ããªãã¼ã¿ãæ±ãããã°ã©ãã³ã°ãè¡ãå ´åãæ°¸ç¶ãã¼ã¿æ§é ã¯å¿
é ã§ãããã¾ãæ°¸ç¶ãã¼ã¿æ§é ãå©ç¨ãã¦ãããã¨ãæèãããã¨ã§ããããå®è£
ãå¯è½ã«ãªãã¨æã£ã¦ãã¾ããå人çã«ã¯ãã®ãæ°¸ç¶ãã¼ã¿æ§é ã«ãã£ã¦ãããè¯ãå®è£
ãå¯è½ã«ãªããç¹ãããæ¬è³ªçã ã¨æã£ã¦ãã¾ãã
å
ã®ç«¶æããã°ã©ãã³ã°ã®å®è£
ãæ¹ãã¦ã¿ã¦ã¿ã¾ãã
main :: IO ()
main = do
q <- readLn @ Int
qs <- map words <$> replicateM q getLine
let qs' = [if null args then (command, - 1 ) else (command, stringToInt (head args)) | command : args <- qs]
let res = scanl' f ([], IM.empty) qs'
where
f (xs, s) query = case query of
("ADD" , x) -> (x : xs, s)
("DELETE" , _) -> (drop1 xs, s)
("SAVE" , y) -> (xs, IM.insert y xs s)
("LOAD" , z) -> (IM.findWithDefault [] z s, s)
_ -> error "!?"
printList [headDef (- 1 ) xs | (xs, _) <- tail res]
ãã®ããã°ã©ã ã§ã¯ãã¯ã¨ãªã®ãã³ã«ããã®æç¹ã§ã®ãªã¹ãã®å¤ãåºåããå¿
è¦ãããã¾ããããä¸è¨ã®ããã°ã©ã ã§ã¯ (ã¯ã¨ãªã®ãã³ã«é½åº¦åºåãå¾ã¦ããã®ã§ã¯ãªã) ã¯ã¨ãªãå
¨é¨å¦çãçµãã¦ãããæçµçãªåºåãã¤ã¾ããã¬ã¼ã³ãã¼ã·ã§ã³ãçµã¿ç«ã¦ã¦ãã¾ãã(â») ã®å®è£
ã§ãã
ãã¼ã¿æ§é ãå½ä»¤åãã¼ã¿æ§é ã®å ´åãããã¯ããã¾ãããããæç¹ã®ãã¼ã¿æ§é ã®ç¶æ
ã¯ãã®æç¹ã«ããåç
§ã§ããªãããããã¬ã¼ã³ãã¼ã·ã§ã³ããã®ã¿ã¤ãã³ã°ã§å¾ãå¿
è¦ãããã¾ãã
ä¸æ¹ãæ°¸ç¶ãã¼ã¿æ§é ã®å ´åãåã
æç¹ã®ãã¼ã¿æ§é ã®ç¶æ
ãå¾ããã§ãåç
§ã§ãã¾ãããã¡ã¢ãªä¸ã«ãã¼ã¿æ§é ãä¿æãã¦ããã¦ã Structural Sharing ã«ãããããè¥å¤§åãããã¨ãããã¾ããããã®ããã°ã©ã ã®ããã«ãä¸æ ¸ã«ãªãè¨ç® ··· ã¤ã¾ããã¡ã¤ã³ãã¸ãã¯ããã¹ã¦å¦çãçµãã¦ãããæ¹ãã¦ãã¬ã¼ã³ãã¼ã·ã§ã³ã«å¤æãããã¨ãå¯è½ã§ãããã¬ã¼ã³ãã¼ã·ã§ã³ã»ãã¡ã¤ã³åé¢ã®è¦³ç¹ã«ããã¦ãæ°¸ç¶ãã¼ã¿æ§é ãéè¦ãªå½¹å²ãæããã¦ãã¾ãããã®èãæ¹ã¯ãå®è£
ã¹ã¿ã¤ã«ã«å¤§ããªå½±é¿ãä¸ãã¾ãã
ãã®ç¹ã«é¢ãã詳細ã¯ã競æããã°ã©ãã³ã°æèã絡ãã¦è©±ãå¿
è¦ãããé·ããªããããªã®ã§æ¹ãã¦å¥ã®è¨äºã«ãããã¨æãã¾ãã
ãã¦ãæ¥åã·ã¹ãã éçºã«ã¯å¿
é ã¨ã¯è¨ããªãã¨ç§è¦ã¯è¿°ã¹ã¾ããããå½ä»¤åããã°ã©ãã³ã°è¨èªã§ãå¤ãä¸å¤ã«æ±ãã¨ãããã®ãã¤ã¼ããªã³ãã¼ãèµ°ãåé¡ãæèã§ãã¦ãããã©ããã¯éè¦ã§ããããå¤ãã®é¢æ°åè¨èªã«ããã¦ã¯ãã®èª²é¡ãæ°¸ç¶ãã¼ã¿æ§é ã«ãã£ã¦è§£æ¶ãã¦ããã¨ãããã¨ã¯ãç¥ã£ã¦ããã¦æã¯ããã¾ããã
æ°¸ç¶ãã¼ã¿æ§é ã®å®è£
ä¾
ãæ°¸ç¶ãã¼ã¿æ§é ãã¨ããã¨åé¢ããä½ããããããªãã®ãæãæµ®ãã¹ãããããã¾ãããããã®å®è£
æ¹æ³ãç¥ã£ã¦ããã¨ããå°ã身è¿ãªãã®ã«æããããã¨æãã¾ããæ°¸ç¶ãã¼ã¿æ§é ã®ä¸ã§ãæ¯è¼çå®è£
ãç°¡åãªãæ°¸ç¶ã¹ã¿ãã¯ã¨æ°¸ç¶é
åã®å®è£
ãç´¹ä»ãã¦çµããã«ãããã¨æãã¾ããå®è£
ã®è©³ç´°ã«ã¤ãã¦ã¯è§£èª¬ãã¾ããããé°å²æ°ã ãã¿ã¦ããã£ã¦ãä½ãç¹å¥ãªãã¨ãããªãã¦ãæ®éã«å®è£
ã§ãããã ãªãã¨ããé°å²æ°ãæ´ãã§ãããããã¨æãã¾ãã
æ°¸ç¶ã¹ã¿ãã¯
Haskell ã§å®è£
ããæ°¸ç¶ã¹ã¿ãã¯ã®ä¸ä¾ã§ããå帰ãã¼ã¿åã§ãªã¹ãã®ãããªãã¼ã¿æ§é ã宣è¨ããAPI ã¨ã㦠head
tail
(++)
ãªã©åºæ¬çãªé¢æ°ãå®è£
ãã¾ãã
代æ°çãã¼ã¿åã§ãªã³ã¯ãªã¹ãæ§é ã宣è¨ããå
é è¦ç´ ã¸ã®åç
§ãè¿ãããã«å®è£
ãã¾ããå
é è¦ç´ ãåç
§ãããã¨ã (head
) ã¯ãå
é è¦ç´ ã¸ã®åç
§ãããããåãåºãå¤ãå¾ãã ããå
é 以å¤ã®è¦ç´ ãå¾ããã¤ã¾ãå解ãããã¨ã (tail
) ã¯æ¬¡ã®è¦ç´ ã¸ã®åç
§ãè¿ããããã ãã§æ°¸ç¶ã¹ã¿ãã¯ãå®è£
ã§ãã¾ãã
äºã¤ã®ã¹ã¿ãã¯ãçµåãã ((++)
) ã¨ãã¯ã©ããã¦ã ããã£ã¦ãã¾ãã¾ããããã®éãåæ¹ã®ãªã¹ããã³ãã¼ããã®ã§ã¯ãªãå¤ããªã¹ãã®ä¸æ¹ã ããã³ãã¼ããã®ããã®ä¸ã¤ã¯æ°ãããªã¹ãã§å
±æãããããã«å®è£
ãã¦ãã¾ãã
import Prelude hiding ((++))
data Stack a = Nil | Cons a (Stack a) deriving (Show, Eq)
empty :: Stack a
empty = Nil
isEmpty :: Stack a -> Bool
isEmpty Nil = True
isEmpty _ = False
cons :: a -> Stack a -> Stack a
cons = Cons
head :: Stack a -> a
head Nil = error "EMPTY"
head (Cons x _) = x
tail :: Stack a -> Stack a
tail Nil = error "EMPTY"
tail (Cons _ xs) = xs
(++ ) :: Stack a -> Stack a -> Stack a
Nil ++ ys = ys
Cons x xs ++ ys = Cons x (xs ++ ys)
main :: IO ()
main = do
let s0 :: Stack Int
s0 = empty
s1 = cons (1 :: Int) s0
s2 = cons (2 :: Int) s1
s3 = cons (3 :: Int) s1
s4 = s1 ++ s3
print s0
print s1
print s2
print s3
print s4
åºåçµæã¯ä»¥ä¸ã§ãã
Nil
Cons_1_Nil
Cons_2_(Cons_1_Nil)
Cons_3_(Cons_1_Nil)
Cons_1_(Cons_3_(Cons_1_Nil))
æ°¸ç¶é
å
æ°¸ç¶é
åã¯ãé
åã¨ãã£ã¦ãå½ä»¤åã®é
åã®ããã«é£ç¶ããé åãç´¢å¼ã§åç
§ã§ããããã«ããã¢ãã«ã§ã¯ãªããå®å
¨äºåæ¨ã§è¡¨ç¾ãã¾ãã
å¤ã¯èã«æããã¦ãã¤ã³ããã¯ã¹ã«ããåç
§æã«ã¯æ ¹ããäºåæ¨ã辿ã£ã¦ç®çã®èãç¹å®ãã¾ãããã®ãããåç
§æã®è¨ç®é㯠ã§ã¯ãªã ã¨ãªãã¾ãã
äºåæ¨ã«ããé
åã®è¡¨ç¾
æ´æ°æã«ã¯ãå¤æ´ããããã¼ãã¨ãã®ãã¼ãã¸ç´æ¥çã»éæ¥çã«åç
§ãæã¤ãã¼ãã ããã³ãã¼ãããã¨ããèãã«å¾ããæ ¹ããæ´æ°å¯¾è±¡ã®èã¾ã§ã辿ãçµè·¯ä¸ã®ãã¼ããã³ãã¼ããçµè·¯ã³ãã¼ã¨ããææ³ã使ãã¾ããçµè·¯ãã³ãã¼ããã¨ãã£ã¦ããæ¨ã®é«ãç¨åº¦ã§ãããæ´æ°ãçµå± ã«ãªãã¾ãã
çµè·¯ã³ãã¼ã«ã¤ãã¦ã¯ Path Copying ã«ããæ°¸ç¶ãã¼ã¿æ§é - Speaker Deck ã®ã¹ã©ã¤ããããããããã¨æãã¾ãã
{-# LANGUAGE DeriveFunctor #-}
import Prelude hiding (read)
data Tree a = Leaf a | Node (Tree a) (Tree a) deriving (Show, Functor)
fromList :: [a] -> Tree a
fromList [] = error "Cannot build tree from empty list"
fromList [x] = Leaf x
fromList xs =
let mid = length xs `div` 2
in Node (fromList (take mid xs)) (fromList (drop mid xs))
read :: Int -> Tree a -> a
read _ (Leaf x) = x
read i (Node left right)
| i < size left = read i left
| otherwise = read (i - size left) right
write :: Int -> a -> Tree a -> Tree a
write _ v (Leaf _) = Leaf v
write i v (Node left right)
| i < size left = Node (write i v left) right
| otherwise = Node left (write (i - size left) v right)
size :: Tree a -> Int
size (Leaf _) = 1
size (Node left right) = size left + size right
main :: IO ()
main = do
let arr = fromList [1 .. 8 :: Int]
print arr
print $ read 3 arr
let arr' = write 3 42 arr
print $ read 3 arr'
print $ read 3 arr
æ°¸ç¶ã¹ã¿ãã¯ãæ°¸ç¶é
åã®å®è£
ãç°¡åã§ããç´¹ä»ãã¾ããã
ä½ãç¹æ®ãªææ³ã使ãã¨ãããã®ã§ã¯ãªãã¹ã¿ãã¯ãé
åãªã©ã®æ½è±¡ãè¦æ±ããæä½ãèãããã®æ½è±¡ã«é©ããå
·ä½çã§å¹ççãªãã¼ã¿æ§é ãç¨æãããã¨ããã®ãæ°¸ç¶ãã¼ã¿æ§é ã®å®è£
ã§ãã
ã¾ã¨ã
æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ã¨æ°¸ç¶ãã¼ã¿æ§é ã«ã¤ãã¦è§£èª¬ãã¾ããã
ä¸å¤ãªå¤ã使ããå¼ã§ããã°ã©ã ã宣è¨ããã¨æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ã«ãªã
æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ã§ã¯ãå¤æ´åã®å¤ãç ´å£ããªããå¤æ´å¾ãå¤æ´åã®å¤ãåç
§ã§ããã¨ããç¹å¾´ãæã¤
é¢æ°åããã°ã©ãã³ã°ããªãã¡æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ã§ãããã¨ãèãããã
æ°¸ç¶ãã¼ã¿ããã°ã©ãã³ã°ã«ããããã¼ã¿ã³ãã¼ãæå°éã«çãå¹ççãªå¤æ´ãå¯è½ã«ããä¸å¤ãã¼ã¿æ§é ããæ°¸ç¶ãã¼ã¿æ§é ã
æ¥åã·ã¹ãã éçºã«ããã¦ãæ°¸ç¶ãã¼ã¿æ§é ã¯å¿
é ã¨ã¯è¨ããªããããã©ã¼ãã³ã¹ãå¿
è¦ãªå ´é¢ã§ãæ°¸ç¶ãã¼ã¿æ§é ãæã¡åºã以å¤ã®è§£æ±ºæ¹æ³ããã
大éãã¼ã¿ãæ±ããã¨ãåºæ¬ã§ããã¤å¤ãä¸å¤ã«æ±ããããªãæ°¸ç¶ãã¼ã¿æ§é ã¯å¿
é
ä¸è¬ã®ã·ã¹ãã éçºã«ããã¦ãæ©è½è¦ä»¶ã¨ãã¦ãæ°¸ç¶ããã¼ã¿ãå¿
è¦ã«ãªããªããImmutable.js ã¨ããå©ç¨ãã¦ãè¯ããã
é¢æ°åããã°ã©ãã³ã°ããä¸å¤ã§ãããªãããå¤ã®å¤æ´ãã©ã®ããã«å®ç¾ãã¦ãããã¯æ°¸ç¶ãã¼ã¿æ§é ã«çç®ããã¨ããç解ã§ãã
ã¨ããã話ã§ããã
éä¸å°ã触ãããæ°¸ç¶ãã¼ã¿æ§é ãåæã«ããè¨ç®ã®åé¢ã«ã¤ãã¦ã¯å¥éããããã¦è¨äºã«ãããã¨æãã¾ãã
追è¨
以ä¸ã«è¨äºã«ãã¾ããã
zenn.dev