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
chemist69 has quit [Ping timeout: 240 seconds]
chemist69 has joined #ponylang
smoon has joined #ponylang
smoon has quit [Quit: smoon]
smoon has joined #ponylang
chemist69 has quit [Ping timeout: 258 seconds]
chemist69 has joined #ponylang
smoon has quit [Quit: smoon]
gmcabrita has quit [Quit: Connection closed for inactivity]
endformationage has joined #ponylang
<endformationage> I made Pony core dump on the Playground: http://pony-playpen.lietar.net/?gist=697dbae5077abcddb56695e1488fef1a
<endformationage> I was attempting to see if an object's field could be reached through a trait's default impl via the 'this' keyword.
endformationage has quit [Quit: WeeChat 1.7]
chemist69 has quit [Ping timeout: 255 seconds]
chemist69 has joined #ponylang
Matthias247 has joined #ponylang
chemist69 has quit [Ping timeout: 245 seconds]
chemist69 has joined #ponylang
gmcabrita has joined #ponylang
_whitelogger has joined #ponylang
virtual_lark has quit [Remote host closed the connection]
<FunkyBob> anyone willing to help me understand how to adapt my thinking from inheritance to composition?
<FunkyBob> I'm trying to work out how I can give access to my udp handlers to shared state
aedigix has quit [Remote host closed the connection]
aedigix has joined #ponylang
<doublec> FunkyBob: sure, I canhelp
<SeanTAllen> FunkyBob: what do you mean by "access to shared state"?
<doublec> FunkyBob: if you can encapsulate your state in an actor, you can share that actor with your udp handler and whatever else needs it
<doublec> FunkyBob: and access it via sending it behaviours
<doublec> FunkyBob: or have your UDP handler own the state - it can keep it as an iso, having it passed to it when it is created.
chemist69 has quit [Ping timeout: 240 seconds]
chemist69 has joined #ponylang
<SeanTAllen> endformationage: in case you read the logs, i opened an issue for that.
jemc has joined #ponylang
papey_lap has joined #ponylang
aav has joined #ponylang
papey_lap has quit [Quit: WeeChat 1.7.1]
graaff has joined #ponylang
papey_lap has joined #ponylang
amclain has joined #ponylang
FunkyBob_ has joined #ponylang
aedigix has quit [*.net *.split]
FunkyBob has quit [*.net *.split]
Bombe has quit [*.net *.split]
aedigix has joined #ponylang
Bombe has joined #ponylang
chemist69 has quit [Ping timeout: 258 seconds]
chemist69 has joined #ponylang
papey_lap has quit [Ping timeout: 260 seconds]
papey_lap has joined #ponylang
Candle has quit [Read error: Connection reset by peer]
chemist69 has quit [Ping timeout: 245 seconds]
endformationage has joined #ponylang
chemist69 has joined #ponylang
dougmacdoug has joined #ponylang
<endformationage> SeanTAllen: Regarding the code which caused the core dump, I'm still curious as to whether one's able to use `this` as shown in the example to directly access an object's field? Perhaps it's better to have a second trait fun without a default impl that would essentially return the field? For example:
<endformationage> I guess it would make it an explicit part of the trait's contract.
graaff has quit [Quit: Leaving]
papey_lap has quit [Quit: WeeChat 1.7.1]
chemist69 has quit [Ping timeout: 276 seconds]
<jemc> endformationage: the workaround using a method as the intermediary is the only option for this right now
<jemc> as you imply, the trait doesn't/can't have the field as part of its contract, so it can't reference it in any of its method bodies
chemist69 has joined #ponylang
<endformationage> I see. Does this mean there cannot be any trait function with default impl that mutate an object's field?
<jemc> they can mutate the fields of *other* (non-`this`) objects, but I don't think that's what you're asking
<jemc> also, they can mutate fields indirectly by calling methods whose concrete implementation modifies a field
dougmacdoug has quit [Quit: dougmacdoug]
<endformationage> jemc: I think you've made it clear
<endformationage> In the example just posted, set_api requires a concrete impl on the trait using class to completely replace the API.
<endformationage> Thanks for the clarification.
<FunkyBob_> doublec: that's nice in theory... but I can't see the syntax for achieving any of that
<FunkyBob_> as an example, say I want a hashmap that all the udp handlers can access
<FunkyBob_> do I make a global actor for them to access?
<FunkyBob_> since I can't inherit, I don't see how I can extend the UDPSocket without having to reimplement everything
<FunkyBob_> or write wrappers for all its methods
<FunkyBob_> that approach is insane, so clearly ther eis some way I'm not seeing
Matthias247 has quit [Read error: Connection reset by peer]
FunkyBob_ is now known as FunkyBob
FunkyBob has quit [Changing host]
FunkyBob has joined #ponylang
<jemc> FunkyBob: not sure exactly what you're doing, but what you probably want is to move all of your "business logic" (and associated state) to an actor, and only use the handler as "glue code" for forwarding incoming udp events to the actor
<jemc> in that paradigm, you could have a system of one actor per socket, or multiple actors per socket, depending on your needs
<jemc> if you give more information about what kind of state/logic you need I may be able to give better advice, but I'm also happy to give general advice like the above
<FunkyBob> well, I was following the example in the UDPSocket docs, of how to make a udp server...
<jemc> sorry, when I said "one actor per socket, or multiple actors per socket", I means "one actor per socket, or a single shared actor for all sockets"
<FunkyBob> and wanted to add a hashmap, as a toy key/value store server...
<FunkyBob> so, every UDPHandler needs access to the same hashmap
<doublec> FunkyBob: create an actor that wraps the hashmap, with behaviours to set values and get values
<FunkyBob> ...
<doublec> FunkyBob: have your other handlers have a tag reference to that actor
<FunkyBob> how?
<FunkyBob> this is the bit that's missing
<FunkyBob> how do I give it the reference
<doublec> FunkyBob: I have some examples here https://bluishcoder.co.nz/2016/05/11/exploring-actors-in-pony.html
<FunkyBob> my original thinking was to sub-class UDPSocket to have a hashmap on it, so the Handlers can access that
<FunkyBob> but I can't sub-class... so...
<doublec> FunkyBob: you implement the UDPNotify interface rather than subclass UDPSocket
<jemc> what do you mean when you say "Handlers" - in relation to the stdlib example you linked to?
<FunkyBob> jemc: sorry, I mean UDPNotify
<FunkyBob> doublec: I've done that
<FunkyBob> again
<doublec> doublec: and you'd pass the hashmap to that
<jemc> FunkyBob: are you listening on more than one UDPSocket, or just one?
<FunkyBob> how do they get the shared state?
<FunkyBob> PASS FROM WHERE?
<FunkyBob> jemc: just one
<doublec> FunkyBob: when you create it it
<doublec> FunkyBob: let me do some quick code
<jemc> then there's only one single UDPNotify object in your program
<FunkyBob> I don't create it... it's creted by the socket
<FunkyBob> jemc: ah... I was under the impression it would be created per packet
<jemc> you create it in the line `UDPSocket(env.root as AmbientAuth, MyUDPNotify, "", "8989")`
<jemc> implicitly, that's expanded to:: `UDPSocket.create(env.root as AmbientAuth, MyUDPNotify.create(), "", "8989")
<FunkyBob> right
<FunkyBob> there's what I was missing
<FunkyBob> does the language implicitly do that
<FunkyBob> ?
<FunkyBob> well, there's one of the first things about pony I disagree about :)
<FunkyBob> I thought I was just passing the handler class I wanted UDPSocket to use
<FunkyBob> and it would instantiate it on demand
<FunkyBob> that clears that up... thanks
<jemc> to do that in Pony, the UDPSocket would need to be implemented to use a type parameter, as in: `UDPSocket[MyUDPNotify](env.root as AmbientAuth, "", "8989")`
<FunkyBob> makes sense
<jemc> since types are not valid expression values in pony, so a type can't be an argument to a parameter (it can only be passed as a type parameter, in square brackets)
<FunkyBob> got it
<FunkyBob> still adjusting my brain from many many years of Python :)
<doublec> FunkyBob: https://pastebin.com/R2rBFEHC
<doublec> FunkyBob: which basically is what jemc said
<endformationage> That sugar got me at first too, but I like it.
<jemc> however, the current implementation could be made to work how you expected it to, if the notify object you passed as a "factory" for other objects that get instantiated on demand: `UDPSocket(env.root as AmbientAuth, MyNotifyFactory[MyUDPNotify], "", "8989")`
<doublec> MyUDPNotify(state) is sugar for MyUDPNotify.create(state)
<FunkyBob> doublec: now... you moved the state into its own actor... what advantages does that give?
<doublec> FunkyBob: an actor has tag reference capability meaning it can be shared across threads/other actors
<doublec> FunkyBob: calling a behaviour on it (the 'be' functions) puts a message in a queue of that actor and it processes them one by one
<doublec> FunkyBob: so access to the shared state is serialized
<jemc> FunkyBob: in general, moving state into an actor lets you share it, with the drawback that you can only access the state asynchronously
<doublec> FunkyBob: So if you have each UDP socket connection running in an actor they can all access the shared state safely
<FunkyBob> ok
<FunkyBob> as I suspected
<doublec> FunkyBob: I describe it in the post I linked above
<jemc> for example, if your toy key/value server to listen on a TCP port, and on a UDP port, you'd need to share the hashmap between the two, so you'd need an intermediate actor of some kind
<FunkyBob> will read that in more depth later, thanks
<FunkyBob> so, with only a single UDPSocket, I can never handle more than one packet at a time?
<jemc> depends on what you mean by "handle", since a packet could have asynchronous consequences that could be parallelized
<FunkyBob> or, since it's an actor, ...
<FunkyBob> hmm
<jemc> but to be clear and direct, the UDPSocket will invoke your notify object's `received` method synchronously, and finish that method before handling the next packet
<doublec> FunkyBob: it receives data and immediately sends it to the UDPNotify
<doublec> FunkyBob: if you make that UDPNotify immediately send the information to an actor then they can be processed in parallel
<doublec> FunkyBob: which is how I structure my TCP apps in Pony
<doublec> FunkyBob: A Notify that just forwards to an actor
<FunkyBob> cheers
<FunkyBob> comments start with # in pony?
<doublec> FunkyBob: see here where I have a implementation of TCPConnectionNotify where the methods just forward to the Idler actor https://github.com/doublec/imap-idler/blob/master/idle/main.pony#L96
<FunkyBob> ah, imap... you brave soul :)
<doublec> FunkyBob: only the IDLE part :)
<jemc> FunkyBob: no, they start with `//`
<FunkyBob> jemc: thanks
<endformationage> Could you also create processing actor objects on demand, paralleling the processors? or does Pony sort of do this automatically with its scheduler?
<endformationage> .. work stealing of an actors qued messages
<jemc> endformationage: can you clarify a bit?
<FunkyBob> now, when I "consume data"... does that yield a new value, or does it change data itself?
<endformationage> so instead of the notify handler sending messages to a single actor, instead create an actor for each handling
<FunkyBob> do I need to assigne it to a new variable if I want to do further operations
<jemc> endformationage: you can definitely create and forget single-use actor instances on demand if you have a reason why that helps you
<jemc> endformationage: the `promises` package is a good example of this - each `Promise` is a new actor
<doublec> endformationage: you can even create unnamed anonymous actors on the fly
<endformationage> That's probably from where I'm thinking of this..
<doublec> FunkyBob: when you consume an object it only changes the book keeping on the types
<doublec> FunkyBob: to say that you can't access it from the old reference you consumed
<doublec> FunkyBob: it doesn't change the data in any way
<FunkyBob> ok,just reading the docs
jmiven has quit [Quit: WeeChat 1.7.1]
<FunkyBob> I get passed data: Array[U8] iso
<FunkyBob> if I wanted to work on that value, would I need to, for instance: data' = String(consume data)
<FunkyBob> or can I just "consume data" then work on data?
<FunkyBob> or do I ony need o consume it to pass it to other actors?
<doublec> FunkyBob: you need to consume it whenever you need to store it in another variable
<jemc> FunkyBob: basically, `consume` is only necessary when dealing with rcaps that have a uniqueness requirement, like `iso` and `trn` - it's a way of proving to the compiler that there is still only one reference to the object - when you want to give the object to someone else, you have to give up your own reference to it, and `consume` is one way of doing that
<doublec> FunkyBob: or pass it as a parameter
<FunkyBob> ok, so if I want to parse the data, I don't need to conume it?
jmiven has joined #ponylang
<FunkyBob> but if I then want to pass part of the data to another function/actor/whatever... I do
<doublec> FunkyBob: if you need to pass it to another function, you need to consume it
<doublec> FunkyBob: Generally I'd pass it to a function, consuming it: parse(consume data)
<doublec> FunkyBob: and that function: fun parse(data: Array[U8] iso): MyDataStructure
<doublec> FunkyBob: would parse the data, returning some data structure of that parsed content
<FunkyBob> go it
<doublec> Which is basically what your "data' = String(consume data)" does. It's converting it to a String.
<FunkyBob> referencing methods and properties on the current class requires no namespace prefix? no 'self' or 'this'?
<FunkyBob> scoping is implied?
<jemc> FunkyBob: correct, the `this.` is implied
<FunkyBob> ok, and if I'm going to define N command structs, I'd start with "type Command" for them all to be?
<endformationage> So, one uses `consume` to both give up (turn into and ephemeral type) and take hold of a reference?
<jemc> FunkyBob: your `type Command` should be `trait Command`
<FunkyBob> jemc: because...?
<jemc> the `type` keyword is used to define a type alias - for example, `type Commands is Array[Command]`
<FunkyBob> gotcha
<jemc> endformationage: you basically need it when you want to move the object from one "variable" to another
<jemc> like, from a parameter to a local variable, or from a local to a field
<jemc> the catch is that you can't consume a field, because a field can never be undefined (outside of a constructor), so you have to use "destructive writing" instead of consuming
<endformationage> ok
chemist69 has quit [Ping timeout: 276 seconds]
<FunkyBob> is there any sugar about subscripting Arrays? can I just do x[0] ?
chemist69 has joined #ponylang
<jemc> FunkyBob: x(0)
<endformationage> I think the apply update sugar Pony offers is pretty handy.
<FunkyBob> jemc: found it, thanks :)
<FunkyBob> whee... _almost_ compiled :)
<FunkyBob> src/libponyc/ast/ast.c:480: ast_id: Assertion `ast != NULL` failed.
<FunkyBob> so, I'm doing well right up until the compiler crashes :P
<FunkyBob> will try the "release" branch
<jemc> FunkyBob: if you got that compiler crash using latest master, please file an issue ticket for it
<FunkyBob> I did... I also get the same on release branch
<FunkyBob> this seems to break with the same error at the same line
<jemc> k, I'll get that one fixed later tonight
<FunkyBob> hope the added detail helps
<jemc> I recently did a major refactor of that area of the compiler, so I'm not surprised to see a few breakages
<jemc> but it should be a very simple fix
<jemc> FunkyBob: for now, leaving off the explicit `this.` should work around the issue (probably)
<FunkyBob> I don't see a this... but I'll take your word on it :)
<jemc> FunkyBob: I was using the snippet shared by sean in the ticket - if you have a different snippet that triggers the error without `this.`, please paste it in the ticket for me