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
jemc has joined #ponylang
jemc has quit [Client Quit]
jemc has joined #ponylang
ChatSharp has joined #ponylang
ChatSharp has left #ponylang [#ponylang]
jemc has quit [Ping timeout: 264 seconds]
dougmacdoug has quit [Ping timeout: 240 seconds]
_andre has joined #ponylang
ChatSharp has joined #ponylang
ChatSharp has left #ponylang [#ponylang]
wizeman has joined #ponylang
aav has quit [Ping timeout: 255 seconds]
doublec_ has joined #ponylang
_andre_ has joined #ponylang
_andre has quit [Write error: Broken pipe]
doublec has quit [Remote host closed the connection]
aav has joined #ponylang
zevlg has joined #ponylang
jemc has joined #ponylang
dougmacdoug has joined #ponylang
<zevlg> is there possibility to write something like python's WatchedFileHandler in pony? I see there is no information about inode/device_id is exposed to pony level via FileInfo class
<zevlg> I want to write FileStream like object which reopens file when it is rotated by external tool. So making logging to file possible via logger
<jemc> zevlg: there are a lot of things missing or in-need-of-fixing in the files API currently, so I wouldn't be surprised if what you need wasn't there yet
<jemc> one possible issue is that most of the pony standard library is supposed to be cross-platform (including windows), and there may not be corresponding info exposed on windows
<zevlg> jemc: what is the best way to add them? via RFC ?
<jemc> yes, RFC is the intended path for most API changes, though some changes that are fixing something that is obviously wrong/missing can bypass the RFC path
<zevlg> got it, thanks
<jemc> if it's something that really belongs in `FileInfo`, and that doesn't introduce anything fundamentally new to that logic, it may be a candidate for bypassing RFC
<jemc> if you think it is, feel free to go ahead and open a pull request, and if we agree about bypassing RFC, we can merge it - otherwise, the PR can wait and be merged when the RFC process is done
<zevlg> aha, great
<jemc> from my first glance at what would be required, it seems like it could be accomplished just by adding a few lines to `libponyrt/lang/stat.c`, and adding a caveat in the docs that the device and inode number will be 0 on windows, or something like that
<jemc> well, and adding the actual fields to `FileInfo`
<zevlg> device actually should be available for windows, inode - hardly
<SeanTAllen> zevlg: its also reasonable to do the work and use that as the basis for a RFC. several RFCs are for existing work folks have already done.
<jemc> if that's all the changes needed, I would personally agree that it could bypass RFC, since you would reasonably expect all useful info returned from the `stat` call on posix-based systems to be included in `FileInfo`
<SeanTAllen> i second jemc's point
graaff has joined #ponylang
amclain has joined #ponylang
jmiven has quit [Quit: co'o]
jmiven has joined #ponylang
tm-exa has joined #ponylang
<dougmacdoug> if I have a producer that periodically mutates data and sends vals to workers, but the workers only read once.. is there any way to reacquire an iso to that data .. if not .. I can create a new data object each poll, but then is there a paradigm to reuse it like a pool.. or do we just leave the dirty work up to GC?
<jemc> dougmacdoug: there's no way to reacquire an iso from a val - if you need it to be an iso at the receiving end, you'd have to send it as an iso to begin with
<jemc> > is there a paradigm to reuse it like a pool
tm-exa has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
<jemc> you could definitely add a `reclaim` behaviour to the producer that accepts as an argument the `MyData iso` that the worker is finished with - then have the worker call `producer.reclaim(consume my_data)` when done
<jemc> however, the Pony runtime does use a pool allocator already, so if all your objects are the same size to allocate, they already are being allocated and freed by the GC to a common pool
<dougmacdoug> that could work.. good to know.. so I should attempt to make my state fixed size
<jemc> making your own reclaim flow might be premature optimization - I'm not sure if it would make a significant difference, so may not be worth the complication, and I wouldn't be surprised if implementing your own was slower than that used by the runtime
<jemc> SeanTAllen or someone else at Sendence may have some thoughts on the matter, since they have done a lot of work to find patterns for squeezing out the best performance possible
<dougmacdoug> so basically i have some producer that mods a large state object.. then a bunch of workers are sent a process message.. they all process themselves based on state.. then they no longer care about that state.. but on the next cycle producer will then produce a modified state
<jemc> dougmacdoug: technically, they don't need to be the exact same size to share the same pool - each pool has an upper and lower bound in size for objects that get allocated in it, though the exact size bounds of these pools are an implementation details that is subject to change
<jemc> and even if they ended up varying a bit in size and spanning multiple pools, it may not make a performance impact, since they'd just use a few pools based on size instead of one
<jemc> one implication of sending them an iso would mean that you'd need a separate copy of the state object for each worker, right?
<jemc> that is, unless you made sure the workers only ran sequentially, and the state object was reclaimed to send to the next worker, but that kind of loses the benefits of using actors at all
<jemc> dougmacdoug: to me this sounds like what you really want is a world state made of persistent data structures
<jemc> so that you could send the world state as a `val`, and still have a paradigm for making changes to it without doing unnecessary copying
<dougmacdoug> yes, an option could be to make a few copies and start sending them out in batches.. but that seems like a lot of thread managemet.. so if a behavior receives a val, and it doesnt store it to a member and it just expires after method scope, then the reference count is removed from the originating actor correct? and if the count goes down to zero the gc collects from the originating actor correct?
<jemc> that is, there would still be copying for all changes you made, but the copying would be kept to a minimum
<jemc> yes, more or less - in general, as long as you don't hold on to a reference to the object, you should be trusting the GC algorithm to do its work
<dougmacdoug> so by persistent data structure do you mean a db .. or is there a pony data structure that can do gets across actors?
<jemc> sorry, the word "persistent" is a bit overloaded in programming - I'm not talking about persistence-to-disk, or anything like that - I'm talking about this: https://en.wikipedia.org/wiki/Persistent_data_structure
<jemc> in essence, a persistent data structure is very related to the copy-on-write concept, in that it is an immutable data structure that includes methods for modifying it that "copy" to a new structure instead of mutating the original
<jemc> Pony has some persistent collections implemented in the standard library - you can access them with `use "collections/persistent"`
<dougmacdoug> ah, yes.. thats what i am looking for .. excellent
<jemc> but you don't need to use one of those to have a persistent data structure - you can implement your own application-specific ones by implementing classes that work in an immutable/persistent way
<jemc> for example, let's say I have a `Person` class that has a `left_hand` property and a `right_hand` property, which point to the object I hold in my left and right hand, respectively
<jemc> a `Person val` is immutable, but if you want to "change" the object held in the left hand, you can create a new `Person` that holds the same object in the right hand, but holds the new object in the left hand
<jemc> the object in the right hand doesn't need to be copied - you only need to copy/allocate a new `Person` object
<jemc> however, you also would need to copy/reallocate any higher-level objects that point to the `Person`, since they would need to reallocated to point to the latest copy of the `Person`
<jemc> but the important part is that you can avoid copying "branches" of the "deep" structure that have not changed - you only need to copy the structure that changed and everything above it
<dougmacdoug> and so i can build my data structure with that in mind and attempt to block off regularly modifying data toward the top and leave less frequently changing data deeper in the tree
<aav> primitive UnexpectedEOF
<aav> fun myFunc(): InvailidProtobuf =>
<aav> InvailidProtobuf
<aav> primitive MyTest
<aav> type InvailidProtobuf is (UnexpectedEOF)
<aav> such code compiles. but my expectation is, that it should fail. how is it possible no instantiate 'InvalidProtobuf', which is basically a type alias
<aav> and when i change the second line to this - type InvailidProtobuf is (UnexpectedEOF, BadVariant)
<aav> compilation fails
<aav> so i would assime that 'type InvailidProtobuf is (UnexpectedEOF)' <=> 'type InvailidProtobuf is UnexpectedEOF'
<aav> i bit confusing i want to say
<jemc> aav: I don't think Pony supports single-element tuples
<jemc> you're right that (A) is interpreted as A
<jemc> but remember that tuples aren't the only construct that use parenthesis - we also have type unions, type intersections, etc
<jemc> type unions being (A | B), type intersections being (A & B), and tuples being (A, B)
<jemc> if we interpreted (A) as being a tuple, it would be suprising to those who where expecting to read a type union or intersection in that spot
<aav> jemc: yes, i understand. but nothing prevents having union or intersection of single type
<jemc> but like I said, we don't even have single-element tuples anyway
<aav> ok
<jemc> well, if it's a single type, it wouldn't really be a union or an intersection
<jemc> `type X is A` is just a simple aliasing of one type to another, with no unions, intersections, or tuples involved
<jemc> the parenthesis also work as a way of establishing arbitrary groupings for readability or otherwise
<aav> yes, i understand the logic. it makes sense, but is still slightly confusing
<jemc> so pretty much in every context in Pony, `(A)` is the same as `A`, and so is `(((A)))`, or any arbitrary number of parenthesis
<aav> btw, are there any plans for exhaustive match? it would be so nice not to write 'else' in every match expression.
<jemc> aav: yes, we plan to implement it, but it's not trivial for the general case.
<aav> jemc: especially with guard expressions
<jemc> not sure if you meant it would be especially useful, or especially nontrivial to have exhaustive match with guard expressions, but the latter is definitely true :P
<aav> nontrivial
<jemc> yeah
<jemc> out of curiosity, do your cases where it's bothering you include guard expressions, or not?
<aav> no guards
_andre_ has quit [Quit: leaving]
<aav> this is my typical problem
<jemc> right, gotcha
<jemc> though your U32 should be I32, or vise-versa ;)
<jemc> err... nevermind - I gues syour other method is converting to I32
<aav> jemc: yes. it's zigzag decider for signed integers
<aav> decoder
<jemc> aav: for whatever it's worth, I've been toying with a pattern for dealing with "unreachable" cases, including some that couldn't be formally proved in the type system via exhaustive match anyway
<aav> in my particular case it's all about error reporting. maybe if exception will get some 'type' - lot's of problems will go away
<aav> but if exceptions will get typed, it would be very logical to pattern match on them. any, we are back with the same issue.
<jemc> this is the approach I've been toying with ^
<jemc> it's analogous to a "hard" assert in C - it will crash the program - so it's only suitable for cases where you're convinced that it's *really* unreachable (and it's okay to crash the program if you're wrong)
<aav> yes, understand. maybe it's worth introducing additional keyword - hardmatch, which will crash the program, in nothing got matched?
<aav> but it all typical "trust me, I know what I'm doing" pattern, which doesn't fit will to Pony, as far as i understand
<jemc> yeah, I think it's somewhat anti-idiomatic
<SeanTAllen> @jemc we have a "Fail()" privimite that we call in those "this should never happen" scenario.
<SeanTAllen> remarkable how often "this should never happen" ends up happening
<aav> jemc: how about simply not complaining if declared function type and actual body type differ only by additinal '| None' element?
<SeanTAllen> that's a good way to hide bugs
<jemc> aav: best way to solve it is with exhaustive match, which could theoretically be rolled out slowly, starting with the trivial cases like yours
<jemc> and eventually working up to include more complex cases where possible
<aav> SeanTAllen: why hide?
<SeanTAllen> you are taking a compiler error and saying "its ok, in this one case because | None will never happen" and applying it to every case
<aav> SeanTAllen: actually not. it's just inderectly modifying function return type. it's not just ignoring.
<aav> but in fact it's not much better then adding '| None' option to every function type
<SeanTAllen> i dont know what that means aav and i dont see anything in what you said a out modifying. but its really a moot point.
<SeanTAllen> i don't think you will find folks on the core team amendable to hacky solutions.
<SeanTAllen> addressing in a phased approach where more trivial cases are addressed, that folks would be amendable to
<SeanTAllen> dougmacdoug: going back to your question from earlier. leave the dirty work to the GC. there are no good patterns for manually managing memory (and reusing) in Pony at this point in time.
<jemc> SeanTAllen: thanks for confirming - I'll use that as the stock response now that I know you folks at Sendence have investigated the alternatives already
<dougmacdoug> thx .. appreciate all the feedback..
graaff has quit [Quit: Leaving]
<SeanTAllen> jemc: we seem to have some to the same conclusion. we use it in cases other than "unreachable" anything where we think "this really shouldn't ever happen"
<SeanTAllen> it makes a nice release build assert replacement
<jemc> sorry, I was talking about manual memory management
<jemc> but yes, glad to know we came to the same conclusion
<jemc> on "unreachable"/"fail"
<SeanTAllen> ah
<SeanTAllen> yeah i bothered sylvanc a lot of about various memory optimizations and doing things manually and ended up deciding, this is premature and overkill
<jemc> but yes, I've also been using "unreachable" in cases where it's only unreachable if you assume the other program logic is working correctly
<jemc> but not "unreachable" in a strict sense
<SeanTAllen> my big take away that i have discussed with sylvan on more than one occasion is the need for a generational gc
<jemc> I've found that accepting an optional `Stringable` for the assert (in addition to the source location) can also make debugging easier in some cases
<jemc> especially when used in a `match` statement like that example, where when you see the abort message the first question you'll want to ask is "what the heck value ended up there?"
<jemc> if your values are `Stringable`, they can just be dumped directly into the "Unreachable" assert
aav is now known as aav_away
<jemc> just looked at your snippet - using fprintf+pony_os_stderr is a good call - stderr is more appropriate
Matthias247 has joined #ponylang
wizeman has quit [Quit: Connection closed for inactivity]
doublec_ is now known as doublec
doublec has quit [Changing host]
doublec has joined #ponylang
Matthias247 has quit [Read error: Connection reset by peer]
dougmacdoug has quit [Quit: dougmacdoug]