migmit: (Default)
[personal profile] migmit

1) Игра, которую мы ваяем на работе, полностью пересобирается минут за сорок. С использованием распределённой сборки удаётся сократить это время до пяти-шести минут.

В порядке эксперимента все файлы (C++) собрали в один большой. Очень большой. Его компиляция заняла двадцать секунд.

2) На ЛОРе попросили написать аналог Лисповского do - отдельно задаём переменные и то, как они изменяются от одной итерации к другой, отдельно - условие остановки, отдельно - тело цикла. Написал:


> {-# LANGUAGE Arrows, ExistentialQuantification #-}
> module LispDo where
> import Prelude hiding (id, (.))
> import Control.Category
> import Control.Arrow
> import Control.Monad
> data LispDo arrow x y = forall state. LispDo state (arrow (x, state) (y, Maybe state))
> runLispDo :: ArrowChoice arrow => LispDo arrow x y -> arrow x y
> runLispDo (LispDo init body) = proc x -> runLispDo' -< (x, init) where
>     runLispDo' =
>         proc (x, oldState) ->
>             do (y, mbNewState) <- body -< (x, oldState)
>                case mbNewState of
>                  Nothing -> returnA -< y
>                  Just newState -> runLispDo' -< (x, newState)
> evalLispDo :: LispDo (->) () x -> x
> evalLispDo lispDo = runLispDo lispDo ()
> execLispDo :: Monad m => LispDo (Kleisli m) () x -> m x
> execLispDo lispDo = runKleisli (runLispDo lispDo) ()
> loopVar :: Arrow arrow => a -> LispDo arrow (a -> a) a
> loopVar init = LispDo init (proc (f, x) -> returnA -< (x, Just $ f x))
> lVar :: Arrow arrow => a -> LispDo arrow a a
> lVar init = loopVar init . arr const
> stopIf :: Arrow arrow => LispDo arrow Bool ()
> stopIf = LispDo () (proc (b, ()) -> returnA -< ((), if b then Nothing else Just ()))
> lift :: Arrow arrow => arrow x y -> LispDo arrow x y
> lift a = LispDo () liftLispDo where
>     liftLispDo =
>         proc (x, ()) ->
>             do y <- a -< x
>                returnA -< (y, Just ())
> instance Arrow arrow => Category (LispDo arrow) where
>     id = arr id
>     LispDo init2 body2 . LispDo init1 body1 = LispDo (init1, init2) lispDoCompose
>         where
>           lispDoCompose =
>               proc (x, (oldState1, oldState2)) ->
>                   do (y, mbNewState1) <- body1 -< (x, oldState1)
>                      (z, mbNewState2) <- body2 -< (y, oldState2)
>                      returnA -< (z, liftM2 (,) mbNewState1 mbNewState2)
> instance Arrow arrow => Arrow (LispDo arrow) where
>     arr h = LispDo () (proc (x, ()) -> returnA -< (h x, Just ()))
>     first (LispDo init body) = LispDo init lispDoFirst
>         where
>           lispDoFirst =
>               proc ((x, z), oldState) ->
>                   do (y, mbNewState) <- body -< (x, oldState)
>                      returnA -< ((y, z), mbNewState)
> instance ArrowChoice arrow => ArrowChoice (LispDo arrow) where
>     left (LispDo init body) = LispDo init lispDoLeft
>         where
>           lispDoLeft =
>               proc (xOrZ, oldState) ->
>                   case xOrZ of
>                     Left x ->
>                         do (y, mbNewState) <- body -< (x, oldState)
>                            returnA -< (Left y, mbNewState)
>                     Right z -> returnA -< (Right z, Just oldState)
> instance ArrowLoop arrow => ArrowLoop (LispDo arrow) where
>     loop (LispDo init body) = LispDo init lispDoLoop
>         where
>           lispDoLoop =
>               proc (x, oldState) ->
>                   do rec {((y, z), mbNewState) <- body -< ((x, z), oldState);}
>                      returnA -< (y, mbNewState)

Testing:

> evenLoop :: Integer -> LispDo (->) () Integer
> evenLoop n =
>     proc () ->
>         do k <- loopVar 0 -< (\k -> k + 2)
>            stopIf -< k > n
>            returnA -< k
> testLoop :: LispDo (->) () Integer
> testLoop =
>     proc () ->
>         do rec {k <- lVar 0 -< k+1;}
>            rec {m <- lVar 1 -< m*2;}
>            stopIf -< k > 10
>            returnA -< m
> printLoop :: LispDo (Kleisli IO) () ()
> printLoop =
>     proc () ->
>         do rec {k <- lVar 0 -< k+m;
>                 m <- lVar 1 -< m+2*k;}
>            stopIf -< k > 10
>            lift (Kleisli print) -< (m, k)

Проверка:

*LispDo> evalLispDo $ evenLoop 100
102
*LispDo> evalLispDo testLoop
2048
*LispDo> execLispDo printLoop
(1,0)
(1,1)
(3,2)
(7,5)
(17,12)

Вряд ли когда понадобится.

3) Пока записывал (1) и (2), забыл третье.

Originally posted on migmit.vox.com

Date: 2009-12-30 10:18 pm (UTC)
From: [identity profile] zhengxi.livejournal.com
Лучше сделать для лиспа аналог хаслелевского let :)

Что-нибудь вроде
(hlet x = 1
      y = 2
  (display (+ x y))

Date: 2009-12-31 12:08 am (UTC)
From: [identity profile] nponeccop.livejournal.com
планируется ли внедрение оного способа сборки для облегчения разработки?

как собирали в файл? сравнивали производительность при конкатенации cpp-файлов и при включении всех файлов в один с помощью #include?

Date: 2009-12-31 05:53 am (UTC)
From: [identity profile] migmit.vox.com (from livejournal.com)
> планируется ли внедрение оного способа сборки для облегчения разработки?

Возможно.

> как собирали в файл?

Кто-то утилитку написал. Как работает - не в курсе.

> сравнивали производительность при конкатенации cpp-файлов и при включении всех файлов в один с помощью #include?

Нет.