<aceluck>
My problem this time, is that the pointer is part of a struct, and I pass a pointer to this struct to C, which writes to it. This is preventing me from making it an iso
<aceluck>
I've been trying to do it like that , but I keep hitting the wall no matter how many recover blocks and consumes I try.
<jemc>
if you gist / pastebin your code I can try to give a recommendation
<aceluck>
Unfortunately I can't give anything that compiles this time
<jemc>
you'd have to give me something that's more in context than this - for the example you've given me, it would work to simply surround the entire contents of the `test` function in a recover block
<jemc>
but I suspect your actual context is more hairy
<aceluck>
When I wrap it in recover I get: "can't access field of non-sendable object inside of a recover expression" where I do value.data
<aceluck>
I've been trying to make value "sendable" , but it has to be writable, so if I recover it to iso, I'm not allowed to make a maybepointer to it
<aceluck>
unless I consume it, in which case I can't access the value anymore
<jemc>
to make what I said work, the `value` reference has to also be created inside the recover block
<aceluck>
It is
<aceluck>
Even so, the compiler gives that error. I agree that it's a bit weird that it does
<aceluck>
I thought you were only prohibited from accessing non sendables outside the recover block
<jemc>
that requirement doesn't seem right to me, so I'll look into it a bit
<aceluck>
Oooh... playground. That makes it easier to discuss this. Great, a compilable example. Shows my predicament exactly
<jemc>
meanwhile, you should be able to get around that by moving your example's lines 11-14 into a method of the `Return` type
<jemc>
that is, you can add a `Return.to_array` method
<aceluck>
Ah...
<aceluck>
But you made Return a class - it was a struct - remember that the C ffi call writes to it - won't a class have a different layout?
<aceluck>
Can structs have methods?
<jemc>
yeah, structs can have methods
<aceluck>
cool, let me try
<jemc>
the only thing you can't do with a struct that you can do with a class, is match on the type at runtime
<jemc>
(which is the reason MaybePointer exists - to handle the otherwise necessary case of unwrapping `(MyStruct | None)`)
<aceluck>
Interesting
<aceluck>
I was wondering where the runtime type information lay
<aceluck>
I guess in some cases it's eliminated, but it needs to be there for match and case methods
<jemc>
every Pony object has a runtime type id attached (except structs, and pointers, and things like numeric primitives)
<jemc>
however, we support matching on numeric primitives by "boxing" them when necessary
<jemc>
that is, when you have a type of `(I8 | I16)`, at runtime you end up with an object that wraps the actual value and holds the type id, so it can be matched on at runtime
<aceluck>
Ah, I see... I was wondering how that worked
<jemc>
but if you have a reference of type `I8`, it's just a one-byte raw value
<aceluck>
I just love the union types in pony
<aceluck>
Actually I love everything about pony so far
<jemc>
:)
<aceluck>
It's got pretty much all the features I want, plus a bunch more
<aceluck>
The capabilities is challenging to wrap my head around, but it's not like I shouldn't have been thinking about this in other languages, it's just that those let you hope for the best instead of warning you that you're doing unsafe things
<aceluck>
One feature I haven't found though - can you monitor actors somehow? As in kill one off if it times out / goes into infinite loops or similar?
<jemc>
I don't think there's anything in pony to help you in case of infinite loop, and in general we don't really have a way to interrupt a behaviour - if the behaviour never returns it will happily consume the entire scheduler thread, and we don't really have a way to stop it
<jemc>
however, any kind of long-running behaviour is an anti-pattern in pony
<jemc>
instead of doing a large loop, for example, we encourage the pattern of a self-calling behaviour
<aceluck>
Right
<aceluck>
Your trick worked by the way. By moving it into Return it all works smoothly
<aceluck>
If that's possible however, then the compiler error must be a bug, since it can be tricked in this way...
<jemc>
a self-calling behaviour would help with your theoretical issue, since it leaves a chance for other messages to arrive and interrupt the actor, to call `dispose` on it, or otherwise tell the actor to "cut it out"
<aceluck>
Yup, exactly
<jemc>
incidentally, it also gives a chance for the garbage collector to run, since each actor's garbage collector only runs *between* behaviours
<aceluck>
I was just thinking erlang, it has a whole framework for supervising actors
<jemc>
right, that's a common question we get, and it's a valid one
<aceluck>
Is it common to pass a closure to a behaviour, in order to get a callback when you're done?
<aceluck>
In swift the standard pattern is object.do_something(then: { do something else } )
<jemc>
other than introspection, which Pony doesn't really have a lot of help for right now, all the building blocks should be there for somebody to build some OTP-style framework on Pony to handle common supervision patterns
<jemc>
roughly speakin, anyway
<jemc>
aceluck: yeah, I personally like that pattern a lot
<jemc>
the `promises` package has a pattern that's a little bit like that, but more decoupled
<aceluck>
I'm trying to imagine how that plays with capabilities
<jemc>
but just passing a lambda in a behaviour is a really useful and lightweight pattern as well
<jemc>
(forgive me if I've already linked you to that - it comes up in conversation a lot :)
<aceluck>
Have you seen the swift syntax for passing closures?
<jemc>
no, I don't know much about swift syntax
<aceluck>
It has some sugar, that if the last parameter to a function is a closure, you can omit it, so instead of writing object.call(param1: 1, then: { something })
<aceluck>
you may write just object.call(param1: 1) { something }
<jemc>
I was thinking about something like that the other day
<aceluck>
A lot of library methods are therefore written in this way, that the last param is a closure, giving you a very nice syntax for dealing with asynch calls
<jemc>
there are a few other things I want to improve about the pony lambda syntax as well
<jemc>
specifically, I want Pony to be able to infer the parameter types if you're passing/assigning the lambda to something that knows what those parameter types are supposed to be
<jemc>
(and the return type too)
<aceluck>
The nice thing about it is that it's pure sugar, so it can easily be tacked on to the language without disrupting anything
<aceluck>
Yeah that would be very nice
<jemc>
after that, I definitely want to explore the pattern you just outlined, as I was thinking about it recently myself (with exactly the same syntax, since I do a lot of Ruby stuff in my day job :P)
<jemc>
anyway, I've gotta run for now
<aceluck>
Thanks a lot for your help!!
<jemc>
no problem
<jemc>
last time I tried to make these lambda syntax improvements I was talking about with respect to inference, I came up against some hairy roadblocks in the compiler
<jemc>
but just now I think I may have come up with some tricks to sidestep those
<jemc>
I'll brainstorm more about it over dinner :)
<aceluck>
Cool! Looking forward to what comes from it :)
jemc has quit [Ping timeout: 248 seconds]
_whitelogger has joined #ponylang
aceluck has quit [Remote host closed the connection]
aceluck has joined #ponylang
aceluck has quit [Ping timeout: 248 seconds]
jmiven has quit [Quit: co'o]
jmiven has joined #ponylang
jemc has joined #ponylang
jemc has quit [Quit: WeeChat 1.4]
jemc has joined #ponylang
_whitelogger has joined #ponylang
aceluck has joined #ponylang
aceluck has quit [Ping timeout: 276 seconds]
jemc has quit [Ping timeout: 260 seconds]
aceluck has joined #ponylang
serizawa has joined #ponylang
serizawa has quit [Client Quit]
papey_lap has joined #ponylang
amclain has quit [Quit: Leaving]
aceluck has quit [Remote host closed the connection]
aceluck has joined #ponylang
aceluck has quit [Ping timeout: 258 seconds]
Matthias247 has joined #ponylang
aceluck has joined #ponylang
papey_lap has quit [Ping timeout: 246 seconds]
k0nsl_ has quit [Ping timeout: 260 seconds]
papey_lap has joined #ponylang
papey_lap has quit [Quit: WeeChat 1.9]
Praetonus has joined #ponylang
<emilbayes>
How can Array.apply call _ptr._apply when this is a private function? Because Array is builtin and gets special treatment?
Matthias247 has quit [Read error: Connection reset by peer]
<jmiven>
emilbayes: private methods can be called from anywhere the package in which they are defined
<jmiven>
they're private to the package, not to the class, if that makes any sense
<emilbayes>
Ah, so it's because Pointer and Array are both in the builtin package?
<emilbayes>
Yes, that makes sense. Thank you!
<jmiven>
yeah
<jmiven>
I find the difference between fields and methods a bit counter-intuitive
<jmiven>
but I guess that's just because I'm a still beginner ^^
<jmiven>
(and it looks like my fingers have a data race problem)
<emilbayes>
same here ^^
plietar has joined #ponylang
<aceluck>
Is there a way to match on primitives? As in, I want to know if a variable is a primtive, as opposed to a string f.ex. But _any_ primitive
<Praetonus>
aceluck: There is no built-in way in the language. But you can exploit the fact that primitive constructors always return the same object to implement a somewhat hacky way: `x.create() is x`
<aceluck>
Ah, excellent trick
plietar has quit [Remote host closed the connection]
<aceluck>
If I comment out the method call inside the closure, it compiles fine, but not like this - despite the same function call working outside the closure. I think it has something to do with viewpoints , but that's where I'm on thin ground
<aceluck>
(adding (p0,p1,p2) as capture in the lambda seems to have no effect)
<jemc>
your error is saying that what you're expecting to be a `Person ref` is actually a `Person box`, because it's `this->Person ref` in a context where `this` is a `box`
<jemc>
when you see something like that, it usually means you want to change a `fun box` to a `fun ref`
<jemc>
in this case, it's your lambda that you need to change
<jemc>
(from the default `box` receiver cap to the `ref` receiver cap
<jemc>
do this by putting `ref` just after the opening curly brace
<aceluck>
Sorry doh. I've been putting the ref after the closing brace
<jemc>
well, that's another place you sometimes need to adjust
<jemc>
the cap inside the opening curly brace is the receiver cap of the function, and the cap after the closing curly brace is the object reference cap
<aceluck>
Ah, I see...
<aceluck>
Excellent you save the day as usual :D
<jemc>
it can be a bit confusing to work with, which is why i want to do the lambda inference stuff we were talking about yesterday
<jemc>
though that only will work when you have a type defined for the LHS, which you don't in this case
<aceluck>
The error message was a bit confusing I must admit
<autodidaddict>
Pony really feels like a mix of all my favorite things: mix-in like traits that I loved in Scala, lightweight actors, real generics w/out type erasure, race-free data sharing, Rust-level memory safety
<autodidaddict>
Go's structural typing
<aceluck>
I feel the same way
<autodidaddict>
only issue I see is adoption. We need to gain some server-side traction. Only way to do that is with Pony implementations of RESTful HTTP routers, gRPC, protobufs, DB clients, etc
<aceluck>
One thing I'm not sure it has it something like swift's protocol extensions. With it you can add a trait to an existing class, f.ex. string. Not sure if that's possible in pony
<autodidaddict>
That kind of feature could be debated. I've used it before and thought it was fantastic when I used it..but it ended up having limited value in my real production apps
<aceluck>
Oh... wait... maybe you can do something like type Newtype = (String & Mytrait) or something
<autodidaddict>
yeah, union and intersection types are awesome
<Praetonus>
In Pony you should use interfaces for that
<aceluck>
I'm talking about adding functionality though - add methods with an implementation to an existing class
<autodidaddict>
yeah if you want to "add a method" to something, just make an interface that has the old methods plus the new one, and build a class that expects this interface
<aceluck>
But I can't make String adhere to that interface
<autodidaddict>
C# static extensions are used heavily for this ... "adding" functionality
<aceluck>
In swift it's also called extension
<autodidaddict>
in fact, in C# (especially .NET Core), it's nearly impossible to avoid using extensions. You use them even without knowing you're using them.
<aceluck>
It's easy to work around though.. so it's not a big deal
<autodidaddict>
I don't miss that functionality at all, really
<aceluck>
It's just whether on can type mystring.newMethod() or have to do Primitive.newMethod(mystring)
<aceluck>
... uhm no. sorry that's not the same
<aceluck>
Forget I said that. If I want to pass my string to a function that expects it to have a .newMethod, I'd have to make String support that interface, or extend it with a trait somehow
<autodidaddict>
I don't suppose the stdlib's net/http supports HTTP/2 ?
<mikeyhew>
Hi there, I'm new to Pony and have a question
<mikeyhew>
Since behaviours execute asynchronously, what is the "right" way to do something after a behaviour finishes? Is it with callbacks?
<aceluck>
You can pass a callback closure to it, or use Promises
<Praetonus>
aceluck: Ah, I misunderstood what you meant
<aceluck>
Praetonus: I'm not familiar with the compiler yet, but I don't think something like that would be impossible to add further down the line
<jemc>
mikeyhew: there are a lot of different options depending on what your needs are - lambdas and promises as aceluck mentioned are the most flexible, but if you have two actors that you don't mind coupling to eachother, they can just share their reference with the other actor and expect a specific behaviour to be called when it's done
<mikeyhew>
Does a call to a behaviour return a Promise?
<autodidaddict>
Is there any kind of official or organized plan to "reach parity" with other ecosystems? Is there an order to which big projects are being tackled in order to give new Pony developers the libraries they'll need?
<Praetonus>
No, it wouldn't be impossible but it would require careful designing, particularly with regards to disallowing breaking the invariants of the original type and dynamic dispatch
<jemc>
there's also a "notifier" object pattern, where rather than a simple callback lambda, you pass in an object with multiple methods to be called in different circumstances, oftening acting as a sort of multi-method callback as glue code to another actor or actors
<jemc>
mikeyhew: no, a behaviour returns nothing
<jemc>
but you can create a promise, send it to the behaviour, and keep your reference to it
<jemc>
but a promise is sort of one layer removed from a callback - you still have to give a callback to the promise
<aceluck>
Praetonus: Indeed. I would put in on hold until other things have stabilized. But for porting libraries from other languages, it would of course be easier if one could support the same idioms
<jemc>
autodidaddict: no, not really - as with many volunteer-run open source projects, the active contributors of pony are mostly working to "scratch their own itch" - creating the packages and features they need to serve their own interests, in such a way that it often also serves the interests of others
<autodidaddict>
so we need to find someone with a pile of spare time who is building microservices
<autodidaddict>
there's no restful routing package?
<jemc>
theodus has a web framework package, though I've not used it and don't know much about it
<autodidaddict>
Ideally Pony should have an equivalent to crates.io so people who are looking to contribute know what's already out there
<mikeyhew>
jemc: That all seems like a lot of effort. Is that pattern discouraged in Pony for some reason?
<mikeyhew>
Kind of an abstract question, I know
<autodidaddict>
then there are repos like this: https://github.com/pdtwonotes/tokara , that require rewrites of net/http and don't really explain to newbs why
<Praetonus>
IIRC, tokara was the base of the current HTTP package in the standard lib
<autodidaddict>
this is why stale info online is so misleading :P
papey_lap has quit [Ping timeout: 240 seconds]
<mikeyhew>
Is there a tutorial for sending HTTP requests?
<mikeyhew>
How do I send a GET request to, let's say, google.com, and print out the response body?
autodidaddict has quit [Ping timeout: 260 seconds]
<autodidaddict>
wow.. that's a lot of boilerplate. I would've thought a std http client would come with some wrappers to set basic/bearer auth
<jemc>
honestly, I don't think that many folks are currently doing a lot of HTTP development in Pony - I think a lot of folks are working with other more domain-specific TCP & UDP protocols a lot of the time.
<mikeyhew>
Thanks autodidaddict. It does look like a lot of boilerplate
<mikeyhew>
Could be worse though, I guess. And about a third of it is just command-line argument parsing
<mikeyhew>
`val` fields are immutable. So why can't you read the value of a `val` field on a `tag` reference?
<Praetonus>
mikeyhew: Another actor could reassign the field at the same time, which isn't concurrency-safe
<Praetonus>
In general, `tag`s are opaque because other actors could have mutable references to the object
<mikeyhew>
Praetonus: But the other actor won't be able to reassign a field if that field is immutable
<Praetonus>
mikeyhew: I think you're confusing mutablility and reassignability
<Praetonus>
The first depends on reference capabilities, the second on var/let bindings
<mikeyhew>
OK
<Praetonus>
A `var` field containing a `val` reference can be reassigned
<Praetonus>
Even though the underlying object can't be mutated
<mikeyhew>
So if you have a `tag` reference to an object with a `let` field, can you access that field?
<jemc>
mikeyhew: no, a `tag` reference is always opaque by definition - you can't do anything but compare its identity or send it messages (if it's an actor)
aceluck has quit [Remote host closed the connection]