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
lukd has quit [Quit: WeeChat 2.3]
_whitelogger has joined #ponylang
endformationage has quit [Ping timeout: 268 seconds]
srenatus has joined #ponylang
travis-ci has joined #ponylang
<travis-ci> ponylang/ponyc#5519 (master - 2f2a84e : Stephan Renatus): The build was fixed.
travis-ci has left #ponylang [#ponylang]
<aturley> i thought i'd share a thing i'm doing with unit tests for advent of code ...
<aturley> one of the problems i have with ponytest is that i have to define the test in one place and then tell pony to use the test in another place.
<aturley> i often create a test and then forget to call `test` with it to get it to run.
<aturley> so i'll write some tests, run my test suite, see everything is green, and continue on.
<vaninwagen> and there have been some tests getting lost in the stdlib
<aturley> so, here's my solution for now ...
<aturley> basically, i define the tests as object literals inside an array and then loop through the array, picking them off and calling `test` with them.
<aturley> this is most certainly ugly.
<aturley> BUT ... it means that now all my tests always run.
<aturley> i thought i'd share this so in case other folks had the same problem i have.
<aturley> i don't think i'd recommend this as the "right" way to do things, but it has helped me for these little toy programs.
<vaninwagen> some automatic test discovery would be the real deal
<aturley> vaninwagen agreed, but we aren't really close to having anything like that yet.
<vaninwagen> some cli script, that scans some packages and runs everything that extends TestCase
<srenatus> thanks for sharing!
<srenatus> I wonder if we'd want to imitate what Go does -- if your object has the proper name prefix, it's considered a test and included... yes what @vaninwagen said.
<vaninwagen> errr, UnitTest
<srenatus> "that extends UnitTest" is also better than the naming convention! +1
<aturley> cli tool would be nice, but at some point it could get a little complicated. you could start simple and look for class definitions that end in ` is UnitTest`, which would probably get you 90% of the way. but the other 10% would probably require writing a parser.
<aturley> you could maybe use the AST instead of the raw Pony code to look for your test classes.
<aturley> then you get into the fun of figuring out how to define groups, and exclusions, and ...
<vaninwagen> The tool would need to build a binary, that detects UnitTests and builds the TestList stuff
<vaninwagen> Yeah, and those fun things
<aturley> lots of yaks to shave.
<vaninwagen> Oh yeah, with a dull spoon
<aturley> that's why i like the technique i'm using for now. it brings the smallest number of yaks into the room.
<vaninwagen> I also like it
<vaninwagen> Less yaks equals more fun
<srenatus> just how dull is it? I mean, I'm just getting my feet wet, so I can't answer this myself: would there be a way in which ponytest could detect the UnitTests "in the binary"?
<vaninwagen> If the UnitTests arent referenced somehow, they would be excluded from the binary :(
<aturley> yup.
<srenatus> ah I see. and if we have to reference them, we might as well just list them as is done now; or using the more convenient hack presented by @aturley. got it. thank you.
<aturley> another option would be to add support for something like this to the compiler itself, and justify it by saying that ponytest is part of pony in a fundamental way.
<aturley> i'm not super happy about the idea of giving ponytest special status like that.
<vaninwagen> Or we "just" quickly invent macros to handle the boilerplate
<vaninwagen> *what a day for a daydream*
* aturley pushes the eject button, bails out
* aturley re-enters the plane through a side door
acarrico has quit [Ping timeout: 250 seconds]
* vaninwagen pulls out 2 uzis i taped underneath the seat before the flight (dressed up as airport staff)
<aturley> with my hack, i was wondering if it was useful enough to consider adding a method to the PonyTest class that takes a list of tests and applies each of them.
<vaninwagen> I would love that
<aturley> basically something that automates what i'm doing with the `while` loop at the end of my `tests` method.
<aturley> i think you'd have to pass it an iso array, and the array would be emptied out.
<aturley> can somebody see a better way?
<vaninwagen> Or a val array with iso UnitTests?
<vaninwagen> Ah no, you'd only get vals from that
<aturley> yup
<vaninwagen> Would you?
<aturley> yes
<SeanTAllen> What do you do aturley if you want to turn a test off for some period of time?
<aturley> SeanTAllen good question! since this is a toy project i really haven't run into that. if i had to do it, i'd probably comment the test out.
<aturley> which isn't great.
<vaninwagen> But you could still exclude them from the ponytest cli, no?
<aturley> vaninwagen yes, you could do that as well.
<SeanTAllen> i think that Pony could really stand to have macros but that is a lot of work and someone would need to put a lot of thought into the RFC
<aturley> SeanTAllen agreed
<SeanTAllen> the way that most languages handle this is through reflection at runtime and that is fraught with far more problems than macros or compile time expressions.
acarrico has joined #ponylang
<SeanTAllen> i'd rather see macros/compile time expressions as the approach than reflection
<aturley> SeanTAllen agreed with that as well.
<SeanTAllen> capabilities secure reflection is not exactly a well established field with lots of in industry usage
<aturley> i've accepted that macros are long way off, so i'm looking for solutions to the UX problem that seems to exist with ponytest.
<SeanTAllen> yup
endformationage has joined #ponylang
<Candle> aturley: That does "fix" one of my annoyances - with ponytest you need to have the name of the test twice; once in the class name and once in the name() function.
<SeanTAllen> interesting... i dont have the same name in the class and the name() function Candle
<SeanTAllen> with your stuff, the string returned from name() is the classname? that's how you set it up?
<Candle> Well, it's not exactly the same name, but there are often similarities.
<Candle> The name() result is organised to aid the --only parameter to ponytest.
<SeanTAllen> ok, so you take the same basic approach that i do
<SeanTAllen> thanks for clearing that up
<Candle> I do have examples of what junit describes as paramertised tests; which is where separate classes shine: https://github.com/CandleCandle/mmdb/blob/master/test/parser_test.pony
OtakuSenpai has joined #ponylang
<aturley> Candle yeah that's a thing, but the impact for me is smaller.
<aturley> that said, it is one more piece of boilerplate (that's probably an unfair word to use here) that adds to the overall work of writing a test.
<_andre> is it possible somehow to have a 'new val' constructor that takes a ref parameter?
<_andre> the parameter is not stored in a property of the class
<vaninwagen> That should work, no? _andre
<vaninwagen> Do you get an error with sth like that?
<_andre> yes, i get "this parameter must be sendable (iso, val or tag)"
<aturley> _andre what are you doing with the parameter?
<aturley> i ran into this yesterday and it took me a minute to realize i was trying to use it inside a `val` lambda.
<aturley> (more than a minute, really)
<_andre> it's an optional Random instance
<aturley> what do you do with it inside the constructor?
<_andre> if not given, i use Rand() with the result from Time.now(), otherwise i use the parameter
<aturley> ok but how do you use it?
<_andre> let me put something in the playground
<aturley> ok.
<_andre> though i get that error even if i don't use it at all
<vaninwagen> Yay! Playground, playground, playground!!!
<aturley> this is sounding familiar ...
<aturley> maybe we should have a "confusing error message" label for issues.
<aturley> hm ...
<_andre> so this is the minimum case, ie, don't even use the parameter: https://playground.ponylang.io/?gist=4a840d224a469ab0d5c117229f29d5f3
<aturley> got it.
<aturley> i thought you could pass refs in to the constructor, but i guess i was wrong.
<aturley> i'm sure there's a Very Good Reason for this that i'm not thinking of right now.
<aturley> yup
<_andre> hmm changing the parameter to 'Random iso^' made it work
<SeanTAllen> the reason you cant is because the compiler doesnt do escape analysis
<SeanTAllen> does that answer make sense? if not, i can elaborate
<_andre> does that mean it doesn't know that the ref won't be stored?
<SeanTAllen> correct
<_andre> i think i understand why an iso^ works but i'm not sure why a simple iso won't
<SeanTAllen> not sure what you mean _andre. do you have code that demonstrates what you are talking about?
<_andre> sure
<_andre> this works
<_andre> if you change it to 'Random iso' then i get "this capture violates capabilities, because the match would need to differentiate by capability at runtime instead of matching on type alone" on the 'let r = ...'
<_andre> oh...
<SeanTAllen> that is non-obvious though
<SeanTAllen> and i think opening an issue with the before consume and erorr message and then the consume
<SeanTAllen> and the fact that iso^ works would be good
<SeanTAllen> because, yeah that could be better
<_andre> you mean the error message could be better or that it should work without consume?
<SeanTAllen> i mean the error message could be better
<_andre> ok, i'll open an issue in a few minutes
<SeanTAllen> thanks
OtakuSenpai has quit [Ping timeout: 240 seconds]
Foaly has joined #ponylang
OtakuSenpai has joined #ponylang
OtakuSenpai has quit [Remote host closed the connection]
<SeanTAllen> thanks _andre
<_andre> no problem
<_andre> stupid question: why does the string() method from Stringable return a String iso^ (as opposed to, say, a val)?
<SeanTAllen> not a stupid question!
<_andre> hehe
<SeanTAllen> so, why do you think it should return a val?
<SeanTAllen> or rather
<SeanTAllen> why do you think that val might be a reasonable thing for it to do?
<_andre> i found it surprising because Strings are val by default, so i expected a val return type, and also because it seems to require an extra clone() for every implementation, which could be done by callers who need it
<_andre> i.e. `return "foo".clone()`
<SeanTAllen> i guess it depends on what one expects to happen with the result of that call
<SeanTAllen> should it be mutable?
<SeanTAllen> if its iso^ then you can do whatever you want with it
<SeanTAllen> there are no other references so you can assign to a val, an iso, a ref or anything else
<SeanTAllen> iso ^ is the most permissive option
<SeanTAllen> maybe that isnt the best option
<SeanTAllen> it would be interesting to look at the use of "string" in pony codebases and see how it is most commonly used
<_andre> yeah, i tend to always use immutable strings, though i can see how that is the most flexible return type
<aturley> some of the things around strings seem very opinionated and a little inconsistent.
<aturley> strings have a default refcap of `val`, which makes me think that the idea is that pony guides you toward using immutable strings.
<aturley> the default constructor returns a `ref`, which kind of makes sense i guess.
<aturley> but then you have a thing that trips up newbies all the time, where `let a: String = String` doesn't compile.
<aturley> then you have the about `string()` being defined in `Stringable` as returning an `iso ^`.
<aturley> which gives the most flexibility.
<aturley> each of these choices makes sense in some way, but i'm not sure they all make the most sense together, as a consistent whole.
<aturley> well, specifically they don't seem to cohere in my mind, but maybe that's just me.
<_andre> i also found it a bit surprising in the String class that slice() copies data and trim() doesn't. the opposite naming would seem more intuitive to me.
<aturley> it's all second nature to me at this point so i don't think about it much anymore.
<SeanTAllen> I'd remove val as the default from String
<aturley> let a million backward compatibility issues bloom!
<aturley> :)
<SeanTAllen> its really only helpful with constants or the results of building up a string in a recover block
<SeanTAllen> i would be in favor of doing away with class X foo
<SeanTAllen> and not allow you to set X
<_andre> for mutable strings wouldn't an Array[U8] be preferred?
<SeanTAllen> depends
<SeanTAllen> do you only care about the string as a series of bytes?
<SeanTAllen> if yes, yes
<SeanTAllen> but i think many people care more about the runes
<SeanTAllen> in which case array[u8] isnt very helpful
travis-ci has joined #ponylang
<travis-ci> ponylang/ponyc#5520 (master - 2f2a84e : Stephan Renatus): The build was broken.
travis-ci has left #ponylang [#ponylang]
<_andre> i've just pushed this, in case anyone is interested: https://gitlab.com/andrenathan/pony/uuid
<_andre> any comments and suggestions about the code are also appreciated
<_andre> i went with an uuid.Parse primitive so that i can return a union type with specific parse errors instead of a partial constructor. not sure how idiomatic that is.
<vaninwagen> Me neither, but i like this package
srenatus has quit [Quit: Connection closed for inactivity]
<vaninwagen> _andre: one timy thing, and also a shameless self-ad: instead of or additionally to stuff like https://gitlab.com/andrenathan/pony/uuid/blob/master/test/test.pony#L20 you could use ponycheck for testing your parser
<vaninwagen> If you are into property based testing and think it makes sense
<_andre> definitely does, i'll check it out. i copied the test cases from the Go library just to have something ready quickly
<vaninwagen> And what about making the UUID class Equatable?
<vaninwagen> Do UUIDs have an order amongst each other? If so, it could be Comparable as well
<_andre> no, they're unordered
<vaninwagen> And Hashable64
<vaninwagen> Sorry if i demand too much
<vaninwagen> I can also do a pr
<_andre> is there any guideline on how to implement the hash() method? this is on my todo list, actually
<vaninwagen> Good question, there should be one
<vaninwagen> This should be part of the tutorial or the patterns
<SeanTAllen> writing good hash methods is damn hard
<_andre> Equatable is done
<vaninwagen> SeanTAllen: lets make this an issue on the patterns repo and maybe discuss it during sync to get more input
<vaninwagen> My guess is sylvan or jemc or theo know some cool trick or paper
<SeanTAllen> there's no cool trick
<SeanTAllen> so
<SeanTAllen> you can write hash methods that are probably reasonable but eventually you will get hit with something awful
<SeanTAllen> what are you hashing _andre ?
<SeanTAllen> ah an Array[U8] val
<_andre> yes
<SeanTAllen> So, just for anyone following along at home.
<SeanTAllen> If something is equatable and hashable you need to make sure those two things agree
<SeanTAllen> any things are equatable need to have the same hash value
<vaninwagen> Good property for implementing using ponycheck
<SeanTAllen> but unequal things can hash to the same value
<SeanTAllen> that's ok
<SeanTAllen> that is the #1 hash algo mistake that i have seen in the wild
<vaninwagen> https://github.com/ponylang/pony-patterns/issues/34 SeanTAllen i hope that makes sense as an issue, if not feel free to modify until it does
<SeanTAllen> _andre: if you used Strng instead of Array[U8], you get equatable and hashable "for free" from the String.
<_andre> hmm, i could also call cpointer() on the array and call @ponyint_hash_block like String does, right?
<aturley> streaming some advent of code here starting now if anyone is interested: https://www.twitch.tv/aturls/
<_andre> that seems to have worked
<SeanTAllen> _andre: i think so
<_andre> alright, it's home time for me. have a great weekend everyone
Foaly has quit [Quit: Now 'mid shadows deep falls blessed sleep.]
aturley has quit [Ping timeout: 250 seconds]
aturley has joined #ponylang
endformationage has quit [Quit: WeeChat 2.3]