jemc changed the topic of #ponylang to: Welcome! Please check out our Code of Conduct => https://github.com/ponylang/ponyc/blob/master/CODE_OF_CONDUCT.md | Public IRC logs are available => http://irclog.whitequark.org/ponylang | Please consider participating in our mailing lists => https://pony.groups.io/g/pony
atk has quit [Quit: Well this is unexpected.]
atk has joined #ponylang
<ada[m]> I've been trying to think about how I'd model different kinds of data using pony, and I haven't yet figured this one out yet. How would you implement an append-only log that needs to be readable from multiple actors? For example, a data-structure holding the history for a chat application.
<ada[m]> The best way I've come up with is just a ref holder object filled with val objects representing each individual method, but then you have to have an actor that gets queried for any data other actors are looking for. It seems like there might be a more elegant method.
_whitelogger has joined #ponylang
<doublec> ada[m]: an actor representing the log, the readers have a reference to that actor?
<doublec> ada[m]: the readers can then call behaviours on the actor to get information
<ada[m]> for clarity, above where i said "individual method" I meant "individual message"
jemc has joined #ponylang
endformationage has quit [Quit: WeeChat 1.7]
jemc has quit [Ping timeout: 268 seconds]
papey_lap has joined #ponylang
papey_lap has quit [Client Quit]
papey_lap has joined #ponylang
papey_lap has quit [Client Quit]
papey_lap has joined #ponylang
vaninwagen_ has joined #ponylang
vaninwagen_ is now known as vaninwagen
nyarum has joined #ponylang
vaninwagen has quit [Ping timeout: 268 seconds]
TheNet has joined #ponylang
vaninwagen has joined #ponylang
nyarum has quit [Remote host closed the connection]
vaninwagen has quit [Ping timeout: 246 seconds]
nyarum has joined #ponylang
nyarum has quit [Ping timeout: 268 seconds]
vaninwagen has joined #ponylang
_andre has joined #ponylang
aav has quit []
jemc has joined #ponylang
vaninwagen has quit [Ping timeout: 255 seconds]
nyarum has joined #ponylang
vaninwagen has joined #ponylang
nyarum has quit [Remote host closed the connection]
TheNet has quit [Read error: Connection reset by peer]
aav has joined #ponylang
nyarum has joined #ponylang
nyarum has quit [Remote host closed the connection]
vaninwagen has quit [Ping timeout: 260 seconds]
vaninwagen has joined #ponylang
Praetonus has joined #ponylang
vaninwagen has quit [Ping timeout: 240 seconds]
vaninwagen has joined #ponylang
endformationage has joined #ponylang
nyarum has joined #ponylang
Praetonus has quit [Ping timeout: 240 seconds]
Praetonus has joined #ponylang
vaninwagen has quit [Ping timeout: 260 seconds]
amclain has joined #ponylang
nyarum has quit [Remote host closed the connection]
nyarum has joined #ponylang
Matthias247 has joined #ponylang
nyarum has quit [Ping timeout: 260 seconds]
nyarum has joined #ponylang
nyarum has quit [Remote host closed the connection]
aav has quit []
papey_lap has quit [Quit: WeeChat 1.8]
BlackYoup has quit [Quit: ZNC - http://znc.in]
bimawa has quit [Read error: Connection reset by peer]
adam_ has joined #ponylang
Praetonus has quit [Quit: Leaving]
<adam_> Hello, this is all new and confusing. Need enlightenment.
<adam_> Attempted to modify examples/httpget to print the headers of request before being sent
<adam_> So, line 111, put "for (k, v) in req.headers().pairs() do _env.out.print(k + ": " + v) end"
<adam_> Which is what the code that deals with the response does. This fails to compile, and I don't really get how to fix.
<adam_> Error: /home/adam/ponyc/examples/httpget/httpget.pony:111:42: receiver type is not a subtype of target type for (k, v) in req.headers().pairs() do ^ Info: /home/adam/ponyc/examples/httpget/httpget.pony:111:34: receiver type: HashMap[String val, String val, HashEq[String val] val] tag for (k, v) in req.headers().pairs() do ^ /u
<adam_> That paste didn't work too well. Errors are
<adam_> Error: /home/adam/ponyc/examples/httpget/httpget.pony:111:42: receiver type is not a subtype of target type for (k, v) in req.headers().pairs() do
<adam_> Error: /home/adam/ponyc/examples/httpget/httpget.pony:111:9: cannot infer type of for loop iterator for (k, v) in req.headers().pairs() do
<adam_> Error: /home/adam/ponyc/examples/httpget/httpget.pony:112:37: cannot infer type of v _env.out.print(k + ": " + v)
<adam_> Error: /home/adam/ponyc/examples/httpget/httpget.pony:112:26: cannot infer type of k _env.out.print(k + ": " + v)
<adam_> Given that this is the same loop as used lower down, I presume that the latter errors are just artifacts of the initial error. However I don't understand the initial error at all. Could someone please help me start out here?
Matthias247 has quit [Read error: Connection reset by peer]
<jemc> adam_: welcome!
<jemc> the issue you're hitting has to do with reference uniqueness - just to set a baseline, are you already familiar with the uniqueness requirements of the `iso` and `trn` rcaps in Pony?
<adam_> I've read the tutorial, so I get what the ideas behind it are, but not sure how this works at all in practice
<jemc> great, thanks
<adam_> I think I need "recover" here, but my attempts to do so don't compile
<jemc> so, in this case, the details of what the rcaps are at any point in the snippet you're working with are hidden by type inference - which is good for succinctness and reducing clutter, but sometimes bad for understanding the rcap transitions involved
<jemc> so, let's start with `let req = Payload.request("GET", url)`
<jemc> without type inference, this would be expressed as: `let req: Payload iso = Payload.request("GET", url)`, because the `Payload.request` constructor is defined as `new iso request(method': String = "GET", url': URL = URL)`
<jemc> an `iso` reference is read-and-write-unique
<jemc> after the payload is built, it gets sent to the `HTTPClient`, with the line that reads `let sentreq = client(consume req, dumpMaker)`
<jemc> if we look at the definition of the `HTTPClient.apply` method, we can see that it accepts a `Payload trn`
<adam_> following so far...
<jemc> this means that when we `consume req`, we're saying - destroy this `Payload iso` reference, and return it as a `Payload trn` ephemeral reference (`trn^`), so it can be sent as the first argument to the `HTTPClient.apply` method
<jemc> later in the code, you'll notice that the `for (k, v) in response.headers().pairs() do` line is operating on a `Payload val`
<jemc> the way that loop works, it needs to create further references to data in the `Payload` that it can read from, in order to print out the data while the `response` reference continues to exist
<jemc> this would violate the read-uniqueness requirement imposed by `iso`, so you get a compiler telling you so (in admittedly indirect terms)
<jemc> `val` has no uniqueness requirements, and you can freely create `box` aliases of it to read from as much as you like
<jemc> `trn` has only write-uniqueness (not read-uniqueness) requirements, so you can also create `box` aliases of a `trn`
<jemc> Any aliases of an `iso` reference must be `tag` (neither readable nor writable) - `box` aliases are not allowed
<adam_> What is an alias here?
<jemc> another reference to the same object
<adam_> Very roughly, you mean I can use an 'iso' where a 'tag' is expected, but not where 'box' is?
<jemc> yes, exactly - with the additional detail that you can use `iso` as any other rcap *if you destroy your reference in the process* (using `consume`)
<adam_> got it
<adam_> From what I read, I thpught that I would want to lift the 'iso' reference to 'val' say, which I could then use in the loop
<jemc> so in this case, you can pretty easily make your snippet work by converting the `iso` to a `trn`, just before you need to read from it
<jemc> two quick comments on what you just said:
<jemc> 1) `iso` to `val` isn't a "lift" - it's actually dropping capabilities - the opposite direction from a lift
<jemc> 2) you wouldn't be able to use `val` in this context, since the call to `HTTPClient.apply` is expecting a `trn`, which you cannot get to from a `val`
<jemc> that is, if you dropped all the way down to `val`, you wouldn't be able to get back up to `trn`
<jemc> so instead, you just want to drop to `trn`, because that provides all you need in this case - being able to create readable (`box`) aliases
<jemc> you could do it like this: `let req' = consume trn req`
<jemc> (then use `req'` instead of `req` in all subsequent code)
<jemc> you could also say `let req': Payload trn = consume req`
<jemc> which would evaluate to the same thing
<jemc> just with inference happening in the other direction of the assignment
<adam_> Ok, that all makes sense, thanks
<jemc> no problem!
nyarum has joined #ponylang
<endformationage> You might also note that the client returns the request as val. Of course you wouldn't get any rcap practice in. :P
<jemc> endformationage: ah, you're right - I didn't notice that detail of the API :D
<jemc> adam_: so you could simply move your printing snippet to after the call to `HTTPClient.apply`, and use `sentreq` instead of `req` or req'` :D
<endformationage> I was going to say earlier on but new you'd have a much more informative explaination! Always great as usual.
<jemc> heh, thanks
<endformationage> Maybe some day it'll cement enough in my head to provide one as well :/
nyarum has quit [Ping timeout: 240 seconds]