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
<SeanTAllen> we sidestepped our websockets issue by writing that one bit of our app in elixir
<polypus74> SeanTAllen: yeah, elixir is quite nice. i prefer it to Go, but then the deployment story and tiny binarys are nice on the Go side. ever consider that?
<polypus74> also as i get older i seem to be gravitating towards static typing
<polypus74> i think ws in pony would be so great though, perfect marriage
<lisael> (I should push pony-pg now I can send a raw query and fetch the result, I could discuss design and API issues)
<SeanTAllen> we wanted to stick with an actor based language
<polypus74> SeanTAllen: fair enough
<polypus74> anybody have experience with hiredis
<lisael> 'night
<jemc> polypus74: I've only used the ruby wrapper for it
<jemc> but I bet it would be super easy to implement a redis client in pony
<jemc> the redis protocol is intentionally very simple
<polypus74> jemc: i think you are correct. probably simpler that trying to wrangle hiredis. was having a look at it yesterday, along with websockets, which doesn't look so easy
<polypus74> i mean the specifications
jemc has quit [Ping timeout: 264 seconds]
jemc has joined #ponylang
toblux has joined #ponylang
<polypus74> SeanTAllen: did you go with phoenix? how did it work out for you?
<jemc> polypus74: when I did a websocket server project for my day job I used "plain cowboy" for websockets, since I found that the phoenix "channel" abstraction was way overkill for what I needed
<jemc> (can't speak for SeanTAllen of course though)
<polypus74> were you elixiring or erlanging, just out of curiosity?
<jemc> elixir, since I'm not so hyped on erlang's syntax :P
<polypus74> i don't mind erlang's funky syntax. cowboy is kind of like socket.io right, has long polling fallbacks and whatnot?
<jemc> no, I don't think it supports any of the fallbacks - it's pretty much just plain websockets, as far as I know
<jemc> if you want the fallbacks and such, phoenix channels is probably a better bet
<SeanTAllen> we used phoenix because the channel abstraction was exactly what we needed and would have had to implement something very much like it. phoenix has worked out well for that app.
<polypus74> will have to have a think about it. as i said wavering between Go and Beam. i know phoenix have had some impressive benchmark numbers. harder to find data on Go though.
toblux has left #ponylang [#ponylang]
<jemc> I don't have much meaningful advice to give on that distinction, as I personally would never want to build/maintain a Go project of any significant complexity - I have some pretty strong personal opinions against the Go culture, syntax, philosophies, etc
<jemc> I'd very much like to get Pony lifted up to the point of maturity where I could convince many of my colleages considering become Go-nads to become Pony-nads instead
<SeanTAllen> polypus74: impressive compared to?
<SeanTAllen> in the end, i think you should look at which concurrency model suits your problem better
<polypus74> SeanTAllen. 2M concurrent connections, with real-life like load. the ws layer is going to be thin, the real work gets done in pony, which is where my concurrency model comes in. i don't really care what the ws server tech is. my main aim is simple lihtweight and easy to deploy
<jemc> well, going along with what SeanTAllen said, if you use elixir with its actor-ish paradigms you may find it easier to port your code to Pony eventually :)
<polypus74> i've actually considered embedding pony in Go or the other way whichever is easier, don't know, and having a pony actor for each go socket connection. that's basically how thin i need the sockets to be. could be an interesting frankensteinian experiment.
<polypus74> could do a pony erlang port too i guess
<polypus74> or pony C-node
mcguire has quit [Ping timeout: 240 seconds]
<polypus74> this is what i was thinking of with fallbacks etc: https://github.com/ninenines/bullet
<polypus74> is built ontop of cowboy
Praetonus has quit [Quit: Leaving]
montanonic has quit [Ping timeout: 276 seconds]
<jemc> polypus74: cool, thanks for the link
montanonic has joined #ponylang
mrkishi_ has quit [Read error: Connection reset by peer]
mrkishi has joined #ponylang
mvzink has quit [Ping timeout: 240 seconds]
<polypus74> jemc: np
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 272 seconds]
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 240 seconds]
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 244 seconds]
mvzink has joined #ponylang
mvzink_ has joined #ponylang
mvzink_ has quit [Ping timeout: 264 seconds]
mvzink_ has joined #ponylang
mrkishi has quit [Ping timeout: 250 seconds]
mvzink_ has quit [Ping timeout: 248 seconds]
amclain has quit [Quit: Leaving]
mvzink_ has joined #ponylang
mvzink_ has quit [Ping timeout: 240 seconds]
mvzink has quit [Quit: A merry Christmas to all, and to all a good night!]
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 265 seconds]
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 240 seconds]
jemc has quit [Ping timeout: 244 seconds]
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 260 seconds]
<Candle> On the topic of minimal vs extensive stdlibs; I'm from a Java background mainly, and noone ever uses the built-in URL connection stuff for HTTP, yet you would be crazy to use a 3rd party ArrayList. [lots of people use the Immutable{List,Map,...} from Guava, but they remove functionality from the basic List,etc implementations.]
<Candle> There's a fine balance between things that should be core and things that can be external.
<Candle> To make things external, you *need* a package manager, even a poor one is better than none. See what NPM has done the javascript world.
<Candle> https://github.com/ponylang/ponyc/issues/247 is the issue for package management.
rosstuck has joined #ponylang
dinfuehr has quit [Ping timeout: 265 seconds]
dinfuehr has joined #ponylang
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 248 seconds]
TonyLo has joined #ponylang
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 265 seconds]
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 240 seconds]
montanonic has quit [Ping timeout: 265 seconds]
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 265 seconds]
<avsej> can I use constants from headers files when using FFI?
<avsej> I guess no
toblux has joined #ponylang
toblux has left #ponylang [#ponylang]
<avsej> or, to put it in another way. I group C interface behind group of functions at single 'primitive Pcap', the primitive cannot have fields, but most of the functions "share" some constants (they are constants in the headers). Right now I just define these constants with 'let' in each of the functions
<avsej> what would you recommend if I need some emulation of the group of immutable values accessible for all functions in that primitive (or globally)?
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 240 seconds]
mvzink has joined #ponylang
rosstuck has quit [Ping timeout: 244 seconds]
mvzink has quit [Ping timeout: 265 seconds]
rosstuck has joined #ponylang
<malthe> :fit
<malthe> that was for screen
<avsej> if foreign function needs pointer to structure, and usually this structure is allocated on the stack. How I can allocate it without declaring its layout with pony struct?
<avsej> i need to determine its size at least (if I would choose @pony_alloc() way)
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 244 seconds]
trapped has joined #ponylang
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 250 seconds]
mvzink has joined #ponylang
shepheb has joined #ponylang
mvzink has quit [Ping timeout: 240 seconds]
_andre has joined #ponylang
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 265 seconds]
<TonyLo> Hi, anyone know why there is only one scheduler per core instead of per hyperhread?
<TonyLo> I know you can change this, just curious
Praetonus has joined #ponylang
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 240 seconds]
<irx[m]> How do I end a program, e.g. the user has supplied wrong arguments and now I want to print some info, and then exit.
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 276 seconds]
<Praetonus> irx[m]: A program ends when it is quiescent, i.e. when no new message will be sent. If you're at program startup it's easy, just let Main.create end without creating new actors (you can send a message to env.out to print info). If you're in the middle of a program, you'll have to tell your actors to "logically" terminate
k0nsl has quit [Remote host closed the connection]
k0nsl has joined #ponylang
k0nsl has quit [Quit: “If we don't believe in freedom of expression for people we despise, we don't believe in it at all — Noam Chomsky”]
k0nsl has joined #ponylang
jemc has joined #ponylang
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 240 seconds]
jemc has quit [Quit: WeeChat 1.4]
jemc has joined #ponylang
<irx[m]> Praetonius: Thank you.
mvzink has joined #ponylang
mvzink has quit [Ping timeout: 244 seconds]
paperclipbadger has joined #ponylang
mvzink has joined #ponylang
k0nsl has quit [Ping timeout: 244 seconds]
mvzink has quit [Ping timeout: 248 seconds]
mvzink has joined #ponylang
paperclipbadger has quit [Ping timeout: 240 seconds]
rosstuck has quit [Ping timeout: 265 seconds]
amclain has joined #ponylang
unbalanced has joined #ponylang
polypus74 has quit [Remote host closed the connection]
mrkishi has joined #ponylang
<jemc> avsej: the common idiom for "constants" in pony is to have primitive methods that take no arguments and return a literal
<jemc> irx[m]: regarding logical termination - this usually involves calling `dispose` on any actors with "noisy" handles to asynchronous IO
<jemc> or put more simply, actors that are listenin for external input, like sockets
<jemc> for example, as long as you have a TCPConnection open, there is always the possibility of receiving packets that cause messages in your program, so it can't reach logical quiescence until that possibility is removed
mrkishi has quit [Ping timeout: 250 seconds]
paperclipbadger has joined #ponylang
rosstuck has joined #ponylang
rosstuck has quit [Remote host closed the connection]
montanonic has joined #ponylang
montanonic has quit [Ping timeout: 265 seconds]
montanonic has joined #ponylang
paperclipbadger has quit [Ping timeout: 240 seconds]
montanonic has quit [Ping timeout: 264 seconds]
TonyLo has quit [Ping timeout: 264 seconds]
<avsej> jemc, what about initializing structs for FFI? this is what I'm doing so far: http://dpaste.com/0WR0BAM#line-14, but it looks ugly. in general it doesn't seem possible to find out size of arguments in run time. Maybe ponyc can help to generate struct using headers?
montanonic has joined #ponylang
montanonic has quit [Ping timeout: 250 seconds]
<mvzink> at work right now without a working ponyc, so i can't experiment: is it possible to get data out of an instance of a class from e.g. an iso field, without re-allocating something in its place? conceptually i'm thinking "return `consume field` from dispose()". i can do this with another method that does a destructive read, but that has to re-allocate something for the field, which i'd rather not do.
Matthias247 has joined #ponylang
<irx[m]> I guess I still need some time to grok capabilities. So I am building a string, which is a ref because I am changing it. Then I want to call a function, which wants a val. How do I go from ref to val?
montanonic has joined #ponylang
<lisael> irx[m]: try this:
<lisael> val_func(recover val
<lisael> let s: String
<lisael> do_stuff_with_ref_string(s)
<lisael> s.more_stuff()
<lisael> s
<lisael> end)
<lisael> the expression is recover val ... end
<irx[m]> Ahhh, I see, I have to make the changes inside the recover. That was the missing piece for me.
<lisael> the most important part is that i create the ref alias *inside* the recover
<lisael> recover is a statement that makes sure that nothing not sendable is sent
montanonic has quit [Ping timeout: 265 seconds]
<lisael> mmmmh no, not quite ...
k0nsl has joined #ponylang
<lisael> recover is a statement that makes sure that nothing involved in the creation of the result is sent outdide of the recover
<lisael> (I tell this with my words...)
<jemc> avsej: not totally sure what part of that situaTION you're trying to avoid
<lisael> IIRC there's the same example in the tutorial, but i also recall I was quite puzzled when I first read it, irx[m]
<jemc> regarding whether ponyc can read headers to generate struct definitions for you, no such a feature does not exist at the moment - I think it would be difficult to fully translate enough meaning from headers alone when it comes to semantics relating to capabilities and also garbage collection, though there are certainly some aspects that can be generated
<avsej> jemc, this function https://linux.die.net/man/3/pcap_compile as second parameter requires pointer to allocated struct. Question in general: what approaches pony gives to initialize struct to pass through FFI
<avsej> I chose to define pony struct in my code, but it is ugly because I'm not using actually the fields. I just carefully select sizes of the fields to match the corresponding C struct
<avsej> essentially I'm doing the job, which could be done by somehow using definition from the headers
montanonic has joined #ponylang
<avsej> and it would be hard to manage it when the library will change API/ABI
<avsej> with both I don't see ways to resolve it, because for ABI I need to be able to stick to specific version of .so file, for API, I need some conditional compilation
<jemc> well part of the issue is that pony's memory safety orientation doesn't allow you to have uninitialized structs, while C has no problem with it - if C had the same requirement, you'd have to "make up values" to initialize with in the same way
<jemc> regarding keeping struct and function definitions in sync with ABI changes - this is the struggle of FFI developers in all languages that have FFI, it's part of the deal, unfortunately
<jemc> some language communities have built solutions using things like libclang to read in header files and generate corresponding code
<jemc> and these are great tools, but they can sometimes be imperfect, especially when the target language semantics may have more than one way to represent a given field or argument
<jemc> in such cases, the decision of how to represent that field or argument is best made by a human who understands the way the library works
<jemc> that is, the code content of C headers don't really convey everything you need to know about a function's semantics - for example, semantics about borrowing or transfer of ownership
<jemc> or semantics about thread use, or when a callback might be called
<jemc> these can be situations that require human thought and intervention, and cannot be necessarily delegated to a machine
<jemc> I've done a lot of FFI programming in Ruby, both by hand and through code generation, and I can say that while generating definitions from C headers can be an immensely useful tool, it is not a silver bullet for all cases
montanonic has quit [Ping timeout: 272 seconds]
<SeanTAllen> @irx[m]: with your ref string, look at trn as well. That might be what you need. It's mutable until you consume it at which point it can be assigned to a val
<jemc> overall, I had the most uniform success in situations where I had constrained the field of possibilities in C projects that I controlled by actually code-generating the *C headers* from a higher-level semantic definition that had enough information to generate both the C headers, and the FFI bindings for all necessary languages
<jemc> that was this project, for the curious: https://github.com/zeromq/zproject/
<mvzink> oh cool. just read through scalable c a few months ago; first i'd heard of zproject. interesting, but haven't found a use for it yet.
<jemc> (for anyone who wants a TLDR: it's a code generation framework for C projects in the zeromq community's "CLASS" style that also generates FFI bindings in five other languages "for free", two of which I wrote the generators for)
jemc has quit [Quit: WeeChat 1.4]
<lisael> SeanTAllen: ho yes, I didn't totaly get the semantics of trn, yet, so i tend not to use it at all. I guess one day I'll HAVE to use it and it will finally be clear to me.
<irx[m]> Thank you to all for your answers, but still ...
<irx[m]> I'm receiving data through an http get, and there is this piece of code in the examples.
<irx[m]> for chunk in response.body().values() do
<irx[m]> _env.out.write(chunk)
<irx[m]> end
<irx[m]> Buut I want to gather those chanks in a string, and parse this string into a JsonDoc.
montanonic has joined #ponylang
jemc has joined #ponylang
montanonic has quit [Ping timeout: 265 seconds]
<jemc> one of these days I need to go back and write a zproject generator for pony ffi
montanonic has joined #ponylang
<lisael> irx[m]: I have to know the type of values() and of JsonDoc to think the right way, but something like. :
<lisael> let json_string = recover val
<lisael> let s=String
<lisael> for... do
<lisael> s.append(chunk)
<lisael> end
<lisael> end
<lisael> JsonDoc(json_string)
<lisael> may work. but I guess there's a trn trick that is better for this
<lisael> JsonDoc.pars(json_string) is better.
<mvzink> JsonDoc.parse() seems like one of many things in the stdlib that should use a generic iterator instead of a bespoke iterator (_peek_char(), _get_char())
<irx[m]> If I understand the error correctly, then chunk is (String | Array[U8] val)
montanonic has quit [Ping timeout: 250 seconds]
<mvzink> irx[m]: String.append() takes a ReadSeq[U8 val] box, which i believe both String and Array[U8] val will fulfill
<lisael> I was checking, I agree with mvzink :)
<irx[m]> I'm pretty sure I tried s = String(10) and it didn't work, but now it does, thank you.
montanonic has joined #ponylang
montanonic has quit [Ping timeout: 265 seconds]
montanonic has joined #ponylang
montanonic has quit [Ping timeout: 265 seconds]
montanonic has joined #ponylang
trapped has quit [Ping timeout: 240 seconds]
montanonic has quit [Ping timeout: 265 seconds]
<avsej> FFI gives me 'struct timeval' how I should define pony struct layout to access the 'time_t tv_sec' and 'suseconds_t tv_usec'?
montanonic has joined #ponylang
montanonic has quit [Ping timeout: 248 seconds]
montanonic has joined #ponylang
<doublec> avsej: I'm not sure what you mean - do you need to pass a timeval somewhere?
<avsej> I need to pass a struct to FFI, which contains timeval
<avsej> right now ILong works for me, but I
<avsej> but I'm not sure how portable it is
<avsej> because on some platforms there might be different type behind time_t
<doublec> Yeah, hard to tell. Dealing with non-portable structs in FFI's is hard.
<doublec> Writing a C wrapper that #includes the header file for timeval and has a function that creates and returns one, or initializes one passed to it would be a way.
<doublec> Then you can deal with it as a primitive on the Pony side with no members
<avsej> and insert that .o file from wrapper into ponyc pipeline?
<doublec> Being able to embed C in Pony somehow would be a win
<avsej> or building another .so?
<doublec> It's one of the things I really like about ATS. Drop down to C whenever needed.
<doublec> avsej: yes, either a .o, .a or .so. I'd go the static library route.
<doublec> Makes packaging easier
<avsej> how I can link object file with ponyc?
<doublec> Possibly you can't - Maybe .so is the only option.
<avsej> between shipping .so with wrappers and being non-portable I would sacrifice portability :)
<lisael> ok, i've just used my first trn, now. I'm not sure it's cleaner than a big enclosing `recover val`
pyon has quit [Quit: Fix config.]
pyon has joined #ponylang
<avsej> oh, maybe you, lisael, can help me with converting 'String ref' to 'String val'? http://dpaste.com/034ZAD5
<avsej> str.array() requires str to be val
<lisael> that's exactly what I just did ^^
<SeanTAllen> var str = recover val String.from_cstring(msg) end
<SeanTAllen> but that should really be
<SeanTAllen> let str =
<SeanTAllen> not
<SeanTAllen> var str =
<SeanTAllen> as you never rebind str
<avsej> can't access a non-sendable local defined outside of a recover expression from within that recover expression
<avsej> let str = recover String.from_cstring(msg) end
<avsej> it still doesn't work
<avsej> ah, recover val
<lisael> yep recover default is iso
<avsej> no, 'recover val ... end' also doesn't work
<lisael> String.from_cstring(recover val msg end)
<lisael> rather.
<lisael> hop no
<avsej> it complains about msg
<SeanTAllen> ah yes
<lisael> yep it does
<avsej> is `Pointer[U8]` something special?
<avsej> SeanTAllen, what is 'non-sendable'?
<lisael> var msg: Pointer[U8] trn
<lisael> ....
<lisael> String.from_cstring(consume msg)
<lisael> it works?
<lisael> non sendable is not iso, val or tag
Matthias247 has quit [Read error: Connection reset by peer]
<lisael> because if you send this in another actor, you will get data-races
<avsej> no, it does not work
<lisael> arf...
<avsej> the example is minimal executable btw
<avsej> as long as you libc provides strerror
<avsej> ffi gives 'Pointer[U8] ref' and not 'Pointer[U8] trn'
<lisael> ha, yes!
<avsej> shall I recover it also?
<SeanTAllen> so your problem is that that pointer isnt copied
<jemc> avsej: with FFI you can choose your own cap, since it's up to you to ensure safety guarantees
<SeanTAllen> which makes it fundamentally unsafe for what you want to do
<jemc> so in this case, you want `let msg: Pointer[U8] val = ...`
<SeanTAllen> so be very careful, i can get this to compile but i could crash pony afterwards if i wanted
<jemc> SeanTAllen: strerror I think should be safe to use as a `val`
<avsej> SeanTAllen, is String.copy_cstring() constructor better in this case?
<SeanTAllen> yes
<avsej> jemc, strerror here as an example to make it self-contained
<jemc> SeanTAllen: avsej: nevermind, just read the man page, and it says:
<avsej> in real case it is function from libpcap
<jemc> This string must not be
<jemc> modified by the application, but may be modified by a subsequent call
<jemc> to strerror() or strerror_l().
<jemc> ah, so strerror is not your real function
<avsej> what I want to do is to bring 'char *' from FFI to pony safely
<avsej> as a Array[U8]
<avsej> through String
<jemc> here's where the not-in-the-header semantics come into play - the ones I was harping about earlier
<avsej> or directly to Array
<jemc> when doing FFI between C and Pony it's important to understand the context of how/when the value may be modified in C
<SeanTAllen> from_cstring takes a ref avsej, copy_cstring takes a box
<avsej> okay. and copy_cstring is safe in terms of memory, right?
<SeanTAllen> you can mess with the original pointer after that and it will be fine because you have a copy
<SeanTAllen> aka yes
<jemc> yes, copy_cstring is what you should use when it's possible the C string could be mutated later
<SeanTAllen> basically, pony made you do the safe thing
<SeanTAllen> anyway, i have to go read a paper for work now... back later...
<jemc> SeanTAllen: well, it was more or less by accident in this case, not enforced
<SeanTAllen> i'm not sure that is an accident
<SeanTAllen> it looks very intentional
<avsej> thank you guys
<jemc> it's still the caller's responsibility to choose-your-rcap with FFI - it just happened to be that the "default" rcap for `Pointer` is `ref`
<doublec> avsej: what is the error?
<doublec> opos, ignore me
<doublec> I was on a backscroll without realising
<jemc> in fact it's more likely that the API is returning a C string you aren't supposed to mutate, so `Pointer box` would have been the "safe thing"
<doublec> strerror_r seems the safer function for pony usage
<doublec> Otherwise two actors calling @strerror will clobber the returned string
<jemc> ouch, yeah that would be another issue
<jemc> but as it turns out, `strerror` wasn't even the function avsej really was asking about
<doublec> It's important to bikeshed all the things :)
<avsej> yes, my function is http://www.tcpdump.org/manpages/pcap_next_ex.3pcap.html: int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, const u_char **pkt_data);
<jemc> I was pretty surprised to learn (just now, in this conversation) that `strerror` doesn't return an immutable string literal
<avsej> and char * actually not return value, and out-argument
<doublec> jemc: yeah it basically returns a pointer to a static char array I believe. So it can work without allocating.
<avsej> but my code will not modify the contents of the body, only parse it
<doublec> avsej: so you need to pass in a MaybePointer[Pointer[U8]]?
<avsej> I've used addressof Pointer[U8]
<avsej> but it will be ref
<doublec> Ok
<avsej> and yet I have to convert that Pointer[U8] ref to Pointer[U8] val
<doublec> I'd do a: MaybePointer[Pointer[U8] val]
<avsej> and initialize it as .none()?
<doublec> right
<doublec> Let me do a quick paste
<avsej> no, actually I don't need to pass NULL into function
<avsej> I have to pass pointer to NULL
<avsej> so I need Pointer[U8].create()
<avsej> but this constructor will give me ref
<jemc> don't convert it to a `val` unless it will never be mutated again - with FFI you're responsible for making sure that your `val`s are truly immutable
<jemc> if the value will be mutated, you have to *copy it* to a `val`, as SeanTAllen was saying
<avsej> it is mutated during the FFI call, actually I'm asking to fill in this pointer
<avsej> and how I can copy Pointer[U8] to Pointer[U8] val?
<doublec> avsej: this is what I was thinking of http://pastebin.com/Zp18gR6g
<doublec> That creates a pointer to a Pointer[U8] which is set to null
<doublec> And the "a()" dereference that to return the Pointer[U8]
<avsej> String.from_cstring(Pointer[U8]) will not work
<doublec> Why not?
<doublec> That code compiles for me
<doublec> If you want a String val then things get tricky though
<avsej> I need String val becase I want to call .array()
<avsej> I see how sean's example is different, and it make sense, but it uses Pointer[U8] val
<avsej> I can have only Pointer[U8] so far, because I'm passing it through FFI and the C-function modifies it by assigning new pointer to it
<jemc> avsej: why do you need to go from Pointer to String to Array? Have you considered `Array[U8].from_cstring(msg)`?
<avsej> C equivalent is: const u_char *body = NULL; pcap_next_ex(..., &body); printf("the body is: %s", body);
<avsej> oh, I just didn't know that Array[U8].from_cstring() exists :)
<jemc> you'll want something like `let array = recover val /* do your FFI call in here */; Array[U8].from_cstring(msg).clone() end`
<lisael> is there a way to match on an iso reference?
<jemc> because I'm assuming that the packet data pointer is not owned by you and thus needs to be copied to be safe (I haven't read your docs to confirm this for you)
<lisael> be received(data: (Array[U8] iso | ServerMessage tag)) => //match data here...
<doublec> avsej: how about this http://pastebin.com/RZhBxbyd
<jemc> lisael: you have to consume it at the top of the match block
<doublec> avsej: or this might be better since it makes the Pointer[U8] writeable using trn http://pastebin.com/Z83DCkwb
<jemc> lisael: `match consume foo | let foo': Foo iso => /* ... */ else /* ... */ end`
<lisael> genius!
<lisael> of course it make sense.
<avsej> it is not easy to wrap ffi function with recover in my case
<avsej> but I will try as last resort
<doublec> Oops, wrong paste http://pastebin.com/NWHvKEDW
<doublec> ah ok
<jemc> avsej: doublec: this use case would be made simpler if `Array.isolate` (an iso version of Array.clone) were already implemented
<lisael> the destructuration of complex type in match expression is not advertised in the tutorial. Thank you jemc
<doublec> jemc: yes.
<doublec> jemc: I feel there is still much to learn about good API design with rcaps.
<jemc> lisael: yeah, there's a few things that haven't made it into the tutorial yet - feel free to file an issue or a PR if you notice significant gaps
<jemc> (in the pony-tutorial repo, that is)
<jemc> doublec: yeah, we're all still learning, unfortunately :/ - since the rcaps are so novel
<doublec> lisael: even an issue that just says "I wanted to learn how to do the following example but the tutorial didn't cover it"
<doublec> lisael: then someone else can write it and do the PR
<lisael> of course, I was thinking about this.
<lisael> (I realized I only needed a val, I changed the signature, though)
<avsej> okay. I've got it working http://dpaste.com/1ZQ5TCK#line-43
<avsej> unfortunately Array[U8].from_cstring() does not work in this case as requires ref
<doublec> Nice. It works but cheats via the ffi a little because the Pointer[U8] val is initially set to null and then changed by the ffi call.
<doublec> If I understand things correctly. Not that it really matters in this case.
<doublec> It's why I tried trn but that means using the FFI call inside the recover which is hard for you because of the other parameters to the FFI call.
<doublec> This is probably the most FFI usage I've seen in a pony program, well done :)
<avsej> no, that cheat does not seem to work
<avsej> let data: MaybePointer[Pointer[U8] val] = data.create(recover val Pointer[U8].create() end)
<avsej> sends NULL instead valid pointer to NULL (as I would expect)
<avsej> I suspect that MaybePointer.create just writes NULL instead of taking address of argument
<avsej> so I'm back at the problem how to convert Pointer[U8] ref to Pointer[U8] val
<doublec> huh
<doublec> MaybePointer only works for structs, interesting
<doublec> This returns a pointer value: http://pastebin.com/01JAqCQx
<doublec> But replacing Foo with Pointer[U8] prints null
<avsej> SeanTAllen,why this is not allowed? http://dpaste.com/38G9HA2#line-7
<doublec> avsej: goes back to using addressof
<doublec> avsej: because you have a ref alias still live so you can't convert to a val
<doublec> avsej: otherwise you'd have a writeable pointer (via the ref) and an alias that promises that nothing can change it (the val)
<avsej> looks like a black magic (which is FFI in most of the languages :)
<avsej> aaand, it compiles & works
<avsej> I hope eventually I will just extract all FFI into separate package and ship it as a pony library hiding all this crazy stuff behind pony API
<avsej> btw sharing code is empty in tutorial, is it going to be some package repository and manager?
<doublec> avsej: you can use iso if you want to do what you pasted to SeanTAllen http://pastebin.com/yvAkZL0r
<doublec> avsej: see this regarding package manager https://github.com/ponylang/ponyc/issues/247
<avsej> SeanTAllen, it makes sense creat val-version of Array.from_cstring()
<jemc> avsej: regarding extracting the FFI into a separate package, yeah that would be regarded as best practice - try to isolate the FFI to as small a codebase as possible, with a safe pure Pony API
<jemc> avsej: there is no official package manager yet, but I and others have been using an intermediate solution for dependency fetching and management: https://github.com/jemc/pony-stable
<avsej> but as far as my program is binary, not library I will keep it inside
<SeanTAllen> we use pony stable at Sendence and it is giving us everything we have needed thus far
<SeanTAllen> jemc needs to be careful or we will blog about it
<SeanTAllen> also when we open source our stuff next year, it will be using pony stable
<SeanTAllen> before long it will be a defacto simple standard
<jemc> every time I try to come back to working on a "real" package manager (that is integrated nicely with the compiler), I end up yak shaving on something else that stands in the way
<SeanTAllen> avsej: Array.from_cstring can't be a val. You'd need to copy the string in order to assure that the Array is a val. Otherwise, the pointer to the cstring is still out there and your "val" Array could change underneath you.
<SeanTAllen> are the yaks breeding jemc ?
<jemc> they must be!
<avsej> SeanTAllen, but right now the only way to get array is String.from_cstring(Pointer[U8]).array()
<jemc> actually, the new house we moved to this past month, it's more like elk shaving
<avsej> maybe some shortcut from Pointer[A] will be possible?
<avsej> on Array[A]
<jemc> so far I've had to scare elk away from our backyard (with our fruit trees) at least 3 times
<jemc> not to mention the black bear that lurks somewhere on the west end of the property
<jemc> so, I've got plenty of shaving to do
<SeanTAllen> life is hard jemc
<SeanTAllen> what are you trying to accomplish avsej ?
<doublec> Given a Pointer[U8], get a String val, I think is what is trying to be accomplished.
<doublec> avsej: You can use iso instead of val in your example too http://pastebin.com/z9CNbFS1
<doublec> Which resolves my complaint about setting a val to null and then changing it
<avsej> no, Pointer[U8] -> Array[U8]
<doublec> avsej: isn't that what Array[U8].from_cstring does?
<avsej> doublec, it requires ref
<doublec> avsej: can you add the rcaps into what you want to do?
<doublec> avsej: ie. is it Pointer[U8] val -> Array[U8] val
<avsej> yes, I have Pointer[U8] val from FFI, and want to call buffered.Reader.append(data: Array[U8] val)