дыбр

Apr. 4th, 2018 09:22 pm
juan_gandhi: (Default)
Хитро сегодня было. Поехал, как обычно, на поезд в 7:36; проехал две остановки, вышел. Поезд постоял несколько минут и ушел. Все так стоят на платформе. Тут подходит "скорый", и мы все на него лезем. На "скором" доезжаю я до Пало Альто, иду в офис, беру рабочий комп, иду обратно на станцию. Подходит тот поезд, на котором я уже ехал от Блосом Хила до Тамиена. Я на него сажусь и еду до города.

Ну просто надо было комп забрать, ну.

А обратно приехал в шестом часу; зашел в КМарт, купил мочалку, скребок для душа, и еще, не знаю как описать, губку для мытья ванны, ну там не губка а типа тоже мочалка. Вот.

Дома мы планировали идти погулять, но погода опять шепчет, мол, дождик скоро. Так я пошел вычистил фильтрацию пруда; там столько бактерий развелось, ужас. Кошка все мне помогала, ходила со мной туда-сюда, серьезная такая. Только что в воду не лезла. И все время что-то говорит. Жаль, я ее акцента не понимаю.

А, ну так-то главная развлекуха - это Akka Streams. Прогресс зафигачил хрен знает куда; и удобная такая вещь.

Например, вопрос - а как мне в акке файл в вебсервере послать на запрос? Ответ - стримами. Сорс - файл, синк - httpResponse. Привинтили - и готово; никаких байтов, никаких буферов, закрытий файлов, всей этой хрени. Все сделано уже до нас.

Я единственно что написал метод >>>, чтобы типа ставить точку в конце. Ну и K-комбинатор, я вообще не понимаю, как люди без него программируют.

  def K[T, U](t: => T) = (any: U) => t
  
  implicit class MyFuture[T](f: Future[T]) {
    def >>>(op: T => Unit): Unit = f.onComplete(_.foreach(op))
  }


Вот в этом кусочеке я соединяю последовательно несколько фьючерсов, потом в конце закрываю лавочку.

  def f4: Future[Done] = {
    val all = FileIO.fromPath(factorialPath)
    val numbersBS = all.via(Framing.delimiter(ByteString("\n"), Int.MaxValue))
    val numbers = numbersBS map (_.utf8String)
    numbers.runWith(Sink.foreach(s => println(s"<<$s>>")))
  }
  
  (f1 flatMap K(f2) flatMap K(f3) flatMap K(f4)) >>> K(system.terminate())



Здесь f4 читает файл, режет его на строки, и выдает на консоль каждую строку.
Ну это к примеру.

Причем, похоже, что flatMap тут у меня зря, надо соединять будет не фьючерсы, а элементы потока.
Ну я просто типа балуюсь еще пока.
juan_gandhi: (VP)
"В locally finitely presentable categories инициальные алгебры и терминальные коалгебры естественным образом снабжаются метрикой, причем последние являются пополнением первых по Коши (для одного и того же функтора, конечно), например, streams это пополнение lists. (Адамек)." (10x [livejournal.com profile] furia_krucha)

Красиво же
juan_gandhi: (VP)
Ok, my stuff is still not working. Discovered that for every imported row all kinds of hell are raised, including reading a "property" from db.

So I thought, wtf, let's use expiring cache, from spray. But spray for some reason is incompatible with the rest of the app, lift, etc. So I pulled the source code and decided to finish it with my own hands. Wtf, I wrote those expiring caches more than twice. Now what. Busy.

And then I figured, why map? All in need is an expiring value. So, "decorate" the property entries with caching. Stuff the property provider inside, give it TTL (time to live), and refresh on demand, storing it in a private var.

Wait, a var? Wtf, a variable? No way. Let's make it a stream, and use it in loops, like
for {
  val value ← cached(source:Something, ttl: Duration)
} doStuff(value)


Ok, but what's source? It was Future[T] in Spray's ExpiringLruCache, it was something like that in com.google.common.cache that I was kind of developing with Bob Lee while at Google and while naïve like a boyscout.

No, that's stupid. source is also a stream, and there's no need to pass it anywhere. This is how it should look:

  for {
    val value0 ← (source:Stream[T]) // a stream
    val value ← cache(ttl: Duration)(value0)
  } doStuff(value)


But wait, so cache provides a flatMap, that's it right? And what does it do? It's a stream, but well... does it have a var? Probably not, just checks that the time is up, and then ends, meanwhile returning the same value all the time. What does it depend on? Time.

I want to mock time, how else do I check it all? So, I have to stuff the source of time, something like

  for {
    val value0 ← (source:Stream[T]) // a stream
    val value ← cache(ttl: Duration, timeSource: TimeReader = StandardTime/*we have this class*/)(value0)
  } doStuff(value)


Don't you see, time is also a stream.

What we produce, having a stream of time and a stream of values is pairs, (value:T, time:Timestamp), then we are free to abandon time

Of course the source of time is not infinite, it just lasts ttl units of time.

In short, what do we have here? We have a Cartesian product of input source and time segments.

That's it.

Once I got it, the true nature of caching kind of became clear to me. Everything's illuminated. МПЯ, момент предельной ясности, как выражаются люди с туманом в голове.

Well, of course, additionally we can pass doStuff to the stream; it's a codata, is not it. Just not what I was going to talk about, but anyway.

Profile

juan_gandhi: (Default)
Juan-Carlos Gandhi

May 2025

S M T W T F S
    1 2 3
456 7 8 9 10
11 121314151617
18192021222324
25262728293031

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 15th, 2025 02:25 pm
Powered by Dreamwidth Studios