<SeanTAllen>
the release process is pretty painless and while i was waiting on release stuff last night for 0.22.4, i started looking at a high priority bug and figured it out, so... new release!
<jbk>
ahh
<jbk>
i should probably resync my port
<_andre>
does anyone have an example of returning a struct from the FFI?
<_andre>
i have some old code where the pony-side type was a tuple and it used to work, but not anymore
<Bombe>
How do I specify an empty method body?
<SeanTAllen>
Bombe: can you provide some context for that?
<SeanTAllen>
_andre: can you post a small example of what used to work?
<SeanTAllen>
Also, _andre , worked as of what version?
<Bombe>
SeanTAllen, I am using TDD for development and thus the first test case is “object can be created” so I would need a constructor that doesn’t do anything.
<Bombe>
SeanTAllen, so, pony doesn’t do empty methods at all?
<SeanTAllen>
Ok that's a long time ago _andre. I'm on the Subway now. Can't look for a while. Maybe someone else will be along in the meantime who can help. Otherwise I can look later.
<SeanTAllen>
Bombe: the empty constructor is implicit
<SeanTAllen>
Bombe: what is "an empty method"
<_andre>
SeanTAllen: no problem. I could return the struct via a pointer on the C side, like shown in the FFI tutorial... I was just wondering if directly returning it would still work
<Bombe>
A method with a body containing no statements/expression.
endformationage has joined #ponylang
<SeanTAllen>
You can't define a concrete method that has no implementation
<SeanTAllen>
Do you mean a method that "does nothing"?
<Bombe>
Well, that’s what it would do without any statements, no?
<SeanTAllen>
No
<SeanTAllen>
That's a syntax error
<Bombe>
Hence my initial question.
<SeanTAllen>
Only interfaces and traits can have abstract methods
<SeanTAllen>
You have to define a body
<SeanTAllen>
Classes are concrete. You have to define all methods.
<Bombe>
I’m totally fine with a body that doesn’t do anything.
<SeanTAllen>
So what your "empty method" should do depends on your return type
<Bombe>
Let’s assume it doesn’t have a return type.
<SeanTAllen>
Everything has a return type. None is the implicit if you don't give one in the signature. So you'd return None.
<Bombe>
Thanks, I can work with that, I believe. (Maybe I won’t even have to.)
<SeanTAllen>
Awesome
<SeanTAllen>
Good luck
<Bombe>
---- 1 test ran.
<Bombe>
---- Passed: 1
khan__ has quit [Quit: khan__]
<Bombe>
Looks good. )
<Bombe>
:)
khan__ has joined #ponylang
khan__ has quit [Client Quit]
bimawa has joined #ponylang
jemc has joined #ponylang
WMD_Edoardo has joined #ponylang
WMD_Edoardo has quit [Client Quit]
SenasOzys has quit [Ping timeout: 256 seconds]
SenasOzys has joined #ponylang
pzel has quit [Ping timeout: 248 seconds]
<Bombe>
So, I have a field “let _foo: (String|None)” but how do I do anything with it? Trying to call e.g. _foo.hash() results in “couldn't find 'hash' in 'None'”.
<Bombe>
Ah, I guess I need to pattern match it…
<slfritchie>
Correct
<slfritchie>
Or `(_foo as String).hash()` inside of a `try` block
<Bombe>
Pattern matching is more appropriate here. :)
jemc has quit [Ping timeout: 256 seconds]
pzel has joined #ponylang
droman has joined #ponylang
<Bombe>
Do I also need pattern matching to == two (String|None) values?
<slfritchie>
Hrm, I'm not quite understanding your question Bombe -- None is a primitive, so there's only one instance of a None, so you can use `if var == None then /*stuff*/ else /* do String stuff */` ... which might be a "no" to your question?
<Bombe>
I have two values of type (String|None) and I want to compare them using ==.
<SeanTAllen>
So you have a thing that is string or none, and another things that is string or none correct Bombe?
<aturley>
Bombe you'd probably want to use a `match` statement to figure out if you had the right types, then within that use `==` to compare the two strings.
<Bombe>
SeanTAllen, yes.
<SeanTAllen>
I will drop a playground link in a minute
<Bombe>
That doesn’t sound like == should work… :)
<SeanTAllen>
bombe why should the compiler be able to do that for you?
<Bombe>
Why shouln’t it? It can do x.eq(y) for other types T, why can’t it do the above for (T|None)?
<aturley>
Bombe that could be a bit expensive.
<aturley>
from a performance standpoint.
<aturley>
and it would require the language to make some assumptions about what you want.
<SeanTAllen>
Bombe you can do x.eq(y) for the same type
<aturley>
you'd need `None` to implement `eq`.
<aturley>
and `None` and `String` would need to implement `eq` in a way that first did a type-check.
<SeanTAllen>
One could argue that comparing a string to None for equality is a bug
<SeanTAllen>
and the compiler shoudnt let you do that, unless you explicitly ask it to.
<SeanTAllen>
I, for example, would make that argument.
<SeanTAllen>
Implicit data type conversions are the source of lots of bugs in some languages.
<Bombe>
You would need an eq() for (T|None), not for None itself (because that would be silly).
<SeanTAllen>
you lost me Bombe
<SeanTAllen>
(T|None) is not a type
<aturley>
well, that would mean that pony would need a way to attach a method to a sum type.
<SeanTAllen>
its a union of two possible types
<Bombe>
Well, if it’s not a type this is moot, then. :)
<aturley>
Bombe there are certainly mechanisms in other languages that let you express something along these lines, but there's not a good way to do it in pony.
<Bombe>
Okay, onward with pattern matching then. Thanks. :)
<pzel>
It breaks encapsulation because `v` is public, but presents a single Optional type that *is* a type.
<endformationage>
FWIW, the tutorial's language (as well as Pony's `type` alias keyword) around types, type expressions, and complex types might lead one to believe tuples, unions, and intersections are "types."
<SeanTAllen>
A union type is a type.
<SeanTAllen>
It's a union type
<SeanTAllen>
Which is a kind of type
<Ferdirand>
tuples are not types ?
<SeanTAllen>
A tuple has a type
<SeanTAllen>
Classes have a type
<SeanTAllen>
Actors have a type
<pzel>
wait wait @SeanTAllen. You did say: 13:32 <@SeanTAllen> (T|None) is not a type
<SeanTAllen>
I was being too loose with my usage of type
<SeanTAllen>
That's a type
<SeanTAllen>
It's either this or that
<SeanTAllen>
But no object will ever have that type
<pzel>
Right. The problems appears on the value level
<pzel>
*problem
<SeanTAllen>
And an object can have more than one type
<pzel>
How? That's interesting
<SeanTAllen>
In the sense that it can satisfy more than one trait or interface
<pzel>
Right, but sastisfying one of those is not a type, right? It's a property of an object or type (if it's included in the type constraints)
<pzel>
And two objects of the same class can't satisfy different sets of traits/interfaces
<SeanTAllen>
Not sure how the last point masters
<pzel>
There was somethign I was latching onto that escapes me now
<SeanTAllen>
It would matter in a prototype based language or one where you can add methods to an instance
<pzel>
I guess that looking at 'objects' at 'runtime' is not conducive to type-level understanding. So saying that an object (instance of a type) fulfills x,y,z or more interfaces is
<SeanTAllen>
but you cant do that in Pony
<pzel>
yes!
<pzel>
exactly
<SeanTAllen>
normal parlance around types is very...
<SeanTAllen>
lacking in specificity
<SeanTAllen>
for example:
<SeanTAllen>
let a: String
<SeanTAllen>
we generally say that a has the type of String
<SeanTAllen>
but that's not really true
<SeanTAllen>
a thing that satisfies String can be bound to the name `a`
<SeanTAllen>
so
<SeanTAllen>
let b: (String | None)
<SeanTAllen>
the type is String or None is common parlance
<SeanTAllen>
but really there is no String | None type
<SeanTAllen>
but generally when we do speak of (String|None) as a type
<SeanTAllen>
If I went back and read some type theory stuff i could remember the particular terms that are used to get really pedantic about it
<SeanTAllen>
what i should have said was (String|None) is not an class, interface or trait
<SeanTAllen>
its the union of 2
<pzel>
and no value at runtime can be both at once
<SeanTAllen>
so there is nothing for .eq to be called on because methods exist on classes, interfaces, traits (or actors)
<SeanTAllen>
correct
<SeanTAllen>
a union type is by definiton, one of the other
<SeanTAllen>
the bound variable will be one of the items in the set
<SeanTAllen>
btw in case anyone cares, unions in Pony are untyped
<SeanTAllen>
sorry
<SeanTAllen>
untagged
<SeanTAllen>
long day
<pzel>
I will ask about match statements another day then :)
<SeanTAllen>
fire away
<SeanTAllen>
and i will try to be precise with my language
<SeanTAllen>
which might be easier now that i am not on my phone
<pzel>
The question itself is not very precise.
<pzel>
How do they dispatch at runtime?
<SeanTAllen>
hmmm
<SeanTAllen>
well, can you clarify that?
<SeanTAllen>
btw, matching on a type at runtime (based on a capability) isnt allowed
<SeanTAllen>
so you cant match on String val vs String ref at runtme as there is no concept of val or ref at runtime
<SeanTAllen>
do you mean how do we know if its a String?
<pzel>
yes
<pzel>
(and thank you for the capablitiy explanation, that clarifies a lot)
<pzel>
Is is deduced from the runtime representation (tag?)
<SeanTAllen>
on compilation, ids are generated for different types
<SeanTAllen>
and objects have information about their type
<pzel>
That answers my question, thanks.
<SeanTAllen>
tuples have no such information because...
<SeanTAllen>
well tuples have no such information
<SeanTAllen>
this is both good and bad
<SeanTAllen>
like most things
<SeanTAllen>
it makes tuples really inexpensive
<SeanTAllen>
its just a tuple, it contains no extra info
<SeanTAllen>
so... fast
<SeanTAllen>
also...
<SeanTAllen>
it means that a tuple is not a "type"
<SeanTAllen>
its a tuple of objects that have types
<SeanTAllen>
really though you dont need to care unless you are implementing the language then you need to be really aware of it
<SeanTAllen>
but for example
<SeanTAllen>
you cant say
<SeanTAllen>
match (a,b)
<SeanTAllen>
| Any => blah
<SeanTAllen>
end
<SeanTAllen>
because (a,b) wouldnt match Any because its not a type
<SeanTAllen>
except i think for that one case, I think we added support for that
<SeanTAllen>
i'd have to check
<SeanTAllen>
but i am using it as a general example
<pzel>
yep
<SeanTAllen>
tuples not having type info does cause some bugs
<SeanTAllen>
and we constantly agonize about changing it
<SeanTAllen>
but the speed and cheapness is nice
<SeanTAllen>
no extra allocations like you would get if you had a class with fields
<pzel>
Is the speed factor need for ad-hoc things like pairing values up for mathing?
<pzel>
*needed
<SeanTAllen>
AH
<SeanTAllen>
this is what we added: "Allow tuples to match empty interfaces"
<SeanTAllen>
the speed factor is, there's no allocation like there is with an object
<pzel>
Let me be more precise: if the most common usage of the fast-tuple is to submit candidates for match expressions, and the biggest problem with not typing tuples does NOT involve match expressions
<pzel>
then perhaps that's a hint to optimize tuples so that underneath there are two representations: cheap within the scope of match, and real+expensive elsewhere
<pzel>
IDK, just musing
<pzel>
back to python land
<SeanTAllen>
that is not the most common usage
<SeanTAllen>
the most common usage would be to group a collection of values together without the allocation and gc overhead of a class
<SeanTAllen>
let person = (first, last, address)
<SeanTAllen>
is less expensive than
<SeanTAllen>
let person = Person(first, last, address)
<SeanTAllen>
and if i send the 2nd version of person from 1 actor to another
<pzel>
yeah, and for passing accumulators in folds, etc. I see your point
<SeanTAllen>
there's extra gc overhead that there isnt with the tuple
<pzel>
ack
<SeanTAllen>
you'll note there is lots of tuple passing between actors in Wallaroo
<SeanTAllen>
there's work on a new gc that would remove the GC overhead from the actor to actor send of a class
<SeanTAllen>
BUT
<SeanTAllen>
would not remove the extra allocation