ChanServ changed the topic of #crystal-lang to: The Crystal programming language | | Fund Crystal's development: | GH: | Docs: | Gitter:
<FromGitter> <> @Blacksmoke16: All the logic and docs are finally done. Only specs left, if you want to see how it came out.
<FromGitter> <Blacksmoke16> Nice!
<FromGitter> <Blacksmoke16> Congrats
<FromGitter> <eliasjpr> Is there any plan to have an Any type so that it is easier to work with generics?
<FromGitter> <eliasjpr> I am trying to define a collection of generics for instance `[] of SomeGeneric(A)` where is not yet a known.
<FromGitter> <Blacksmoke16> ```class Base; end ⏎ ⏎ class SomeType(T) < Base; end ⏎ ⏎ arr = [] of Base``` []
<FromGitter> <eliasjpr> when defining `@somevar = [] of SomeGeneric` and then fill it with an actual generic such as `@somevar << SomeGeneric(A)` and `@somevar << SomeGeneric(B)` it fails
<FromGitter> <eliasjpr> Interesting so it has to inherit from a base type. Well that doesn't feel natural
<FromGitter> <eliasjpr> @Blacksmoke16 I think this is a valid example that should be added to the Generics section of crystal docs
<FromGitter> <Blacksmoke16> is the best you're going to get atm
<FromGitter> <Blacksmoke16> mm it's probably the reason i run into so many compiler bugs tho :/ Not sure on the status of how "blessed" that pattern is tbh
<FromGitter> <eliasjpr> if it works it works, not pretty but gets the job done
<FromGitter> <eliasjpr> :)
<FromGitter> <> Hmm, I'm not sure I'm a fan of "the closest match" model wrt non-fully-qualified modules.
<FromGitter> <Blacksmoke16> i've considered an `import` macro before
<FromGitter> <> It breaks the rule of least surprise when it comes to resolving ties.
<FromGitter> <Blacksmoke16> i usually just use the FQN all the time :/
<FromGitter> <Blacksmoke16> but one option is to do like
<FromGitter> <Blacksmoke16> ```private alias Type = Some::Namespaced::Type ⏎ ⏎ # The `Type` alias is scoped to this file``` []
<FromGitter> <> I do that too, but I go back and forth on doing that or leaving off N levels of the FQ name. I never liked the "import as" thing in some languages either, because you can have the same alias mean different things in different files, and as you "go to definition" you constantly have to scan the top of the file. I know, I'm weird.
ur5us has quit [Ping timeout: 240 seconds]
<FromGitter> <> I guess it's time to go research how to write specs now. Don't remember seeing anything in the reference anyway
<FromGitter> <> Thank you
ur5us has joined #crystal-lang
<FromGitter> <> Not sure I understand the focus thing
<FromGitter> <Blacksmoke16> it only runs that one block, or children under it
<FromGitter> <Blacksmoke16> e.g. if you want to "focus" on a single failing spec w/o the noise of running them all
<FromGitter> <> should that be a flag like --tag is?
<FromGitter> <Blacksmoke16> tag is kinda similar but can be added to 1+ blocks
<FromGitter> <Blacksmoke16> focus is more of a dev thing, while tags could be used to separate unit versus integration tests or example
<FromGitter> <> I see
<FromGitter> <> Is there a way to have the spec runner output the result of all tests, not just failed ones?
<FromGitter> <Blacksmoke16> thats what the green `.` are for no?
<FromGitter> <Blacksmoke16> what else would there be to output
<FromGitter> <> The description and the expectation result, for generating reports
<FromGitter> <Blacksmoke16> there's a `--verbose` flag
<FromGitter> <Blacksmoke16> or `--tap` or `--junit_output out.xml`
<FromGitter> <Blacksmoke16> if any of that helps
<FromGitter> <> They are. Looks like Crystal testing is good to me. In CL, there are over 20 different testing frameworks, each with its issues.
<FromGitter> <Blacksmoke16> there are some testing shards out there that are more like RSpec
<FromGitter> <Blacksmoke16> stdlib is kinda simple
<FromGitter> <> I guess fixtures are fiy?
<FromGitter> <> diy rather
<FromGitter> <Blacksmoke16> yea
<FromGitter> <Blacksmoke16> there's also which essentially just wraps the Spec module but allows for a bit more reuse via OOP unit test approach
<FromGitter> <Blacksmoke16> DataProviders are 😎
<FromGitter> <> Are there any property-based testing shards?
<FromGitter> <Blacksmoke16> like what?
<FromGitter> <> Like Haskell's Quickcheck, and Python's Hypothesis...they generate tests from a set of rules, and reduce all the similar failures to the most minimal example
<FromGitter> <> Like fuzzing
<FromGitter> <Blacksmoke16> im going to go with no
<FromGitter> <> From Hyphothesis: ⏎ ⏎ > It works by generating arbitrary data matching your specification and checking ⏎ that your guarantee still holds in that case. If it finds an example where it doesn’t, ⏎ it takes that example and cuts it down to size, simplifying it until it finds a ... []
<FromGitter> <> But fair enough
<FromGitter> <Blacksmoke16> whoa, you can include a C binding struct like a module 🤔
<FromGitter> <> Not sure what I'm doing wrong, but i only get output when I pass a file to `crystal spec`. It doesn't seem to know how to find my spec even though it's in `spec/`
<FromGitter> <Blacksmoke16> you spes need to end in ``
<FromGitter> <> oh, i thought it was `spec_*` like ``
<FromGitter> <> Oh sigh. Looks like `should eq` is broken for my project
<FromGitter> <Blacksmoke16> oh?
<FromGitter> <> Because I overloaded it to make it a compile-time error in favor of `nearly_equal?`
<FromGitter> <> `==` that is
<FromGitter> <> 🤔
<FromGitter> <Blacksmoke16> what does your overload look like?
<FromGitter> <Blacksmoke16> might just be using the wrong overload
<FromGitter> <> ```code paste, see link``` []
<FromGitter> <Blacksmoke16> and what's your spec look like?
<FromGitter> <> ```code paste, see link``` []
<FromGitter> <Blacksmoke16> and this fails?
<FromGitter> <Blacksmoke16> try defining your still within the `it`
<FromGitter> <Blacksmoke16> doing stuff within outside of that is a bad practice
<FromGitter> <Blacksmoke16> stuff outside of*
<FromGitter> <> ```code paste, see link``` []
<FromGitter> <Blacksmoke16> well yea makes sense no?
<FromGitter> <Blacksmoke16> would want to do like `o.nearly_equal?(v).should be_true`, or define some helper method in your `spec_helper` to make that easier
<FromGitter> <naqvis> o.nearly_equal(v).should_be true
<FromGitter> <> Do I have to use the builtin `should` etc DSL, or is the retval of `it` what matters?
<FromGitter> <Blacksmoke16> return value of the `it` block is ignored
<FromGitter> <naqvis> on cell phone, so unable to block code comments
<FromGitter> <Blacksmoke16> the `should` DSL is what makes the assertions
<FromGitter> <> Trying to figure out how to make that helper method
<FromGitter> <> My what?
<FromGitter> <Blacksmoke16> ```def assert_nearly_equal?(a, b) ⏎ a.nearly_equal?(b).should_be true ⏎ end``` []
<FromGitter> <Blacksmoke16> oops
<FromGitter> <Blacksmoke16> stuff*
<FromGitter> <> But that "stuff" is going to be shared by several "it"s
<FromGitter> <Blacksmoke16> it might work, but might also lead to hard to debug issues
<FromGitter> <Blacksmoke16> as all that code runs before your specs
<FromGitter> <> That is going to be a pain then
<FromGitter> <Blacksmoke16> indeed
<FromGitter> <> Every method to be tested has state that should be recorded before its tests are run
<FromGitter> <> My CL library is like 10kloc even with this shared code
<FromGitter> <> I cant imagine how long it will be in Crystal
<FromGitter> <Blacksmoke16> normally you'd define a helper method to help with the boilerplate
<FromGitter> <> 10kloc of tests that is
<FromGitter> <> That means a helper method per method though. Which is even more tedious to maintain than having it be inline with the tests.
<FromGitter> <> Guess I can't win here
<FromGitter> <Blacksmoke16> got an example of a few of the test cases?
<FromGitter> <> you mean lisp?
<FromGitter> <Blacksmoke16> of the crystal version of it
<FromGitter> <> I didn't write any but the above code yet which I'm thinking about because of all this
<FromGitter> <Blacksmoke16> id prob just start down the path of keeping things within each `it` block, then see if anything could be abstracted
<FromGitter> <Blacksmoke16> is my longest spec file iirc :P
<FromGitter> <> fair enough. that spec dir is too complex for me to follow right now. just trying to use toplevel describe with nesting, not some custom object abstraction :)
<FromGitter> <Blacksmoke16> ah yea, i forgot it was using the test case stuff
<FromGitter> <Blacksmoke16> it's a super helpful feature tho
<FromGitter> <> until something goes wrong. do your tests have tests? ;)
<FromGitter> <Blacksmoke16> sec
<FromGitter> <Blacksmoke16> i think you misunderstand how it works
<FromGitter> <> That's what I said, yes
<FromGitter> <Blacksmoke16> ```code paste, see link``` ⏎ ⏎ I.e. it's all `Spec` stuff. Just a diff way to write the test to generate the underlying describe/it blocks []
<FromGitter> <Blacksmoke16> `instance` being of that struct, i.e. `instance = new`
<FromGitter> <Blacksmoke16> as its ran in a class method on that type
<FromGitter> <> I guess. I prefer no-magic procedural tests
<FromGitter> <Blacksmoke16> i dont use it for *every* spec i write, but it suer helps with sharing logic
<FromGitter> <Blacksmoke16> which leads to easy to write/read test code, e.g.
<FromGitter> <Blacksmoke16> tests that dont need that i fall back on the normal Spec stuff
<FromGitter> <> Here's 1 method, the simplest one: ⏎ ⏎ ```code paste, see link``` []
<FromGitter> <Blacksmoke16> yea looks about like what i'd expect
<FromGitter> <> should prob change name of neq? because that method deserves a not object_id test
<FromGitter> <> The guide recommends a describe per method. do they mean per method, or per overload of the same method name?
<FromGitter> <Blacksmoke16> per method, then prob another one for each overload
<FromGitter> <Blacksmoke16> like
<FromGitter> <Blacksmoke16> ```code paste, see link``` []
<FromGitter> <> Ok
notzmv has quit [Ping timeout: 256 seconds]
<FromGitter> <> hmm
<FromGitter> <> In ⏎ ⏎ ```def nearly_equal?(a, b) ⏎ a.nearly_equal?(b).should be_true ⏎ end``` []
<FromGitter> <Blacksmoke16> looks fine yea
<FromGitter> <> But this errors for floats...
<FromGitter> <Blacksmoke16> oh?
<FromGitter> <Blacksmoke16> whats the error?
<FromGitter> <> ```code paste, see link``` []
<FromGitter> <> I'm probably too tired for this tonight :)
<FromGitter> <Blacksmoke16> did you add a `require "./spec_helper"`?
<FromGitter> <Blacksmoke16> oh
<FromGitter> <> Sure. The other method suite works
<FromGitter> <Blacksmoke16> do you mean to do `, 2).y`?
<FromGitter> <Blacksmoke16> versus just `, 2)`?
<FromGitter> <> I do mean that. The former returns a float, which is what it should be testing.
<FromGitter> <Blacksmoke16> right but `nearly_equals?` is defined on your vector type
<FromGitter> <Blacksmoke16> not float64
<FromGitter> <> and float64
<FromGitter> <Blacksmoke16> oh, you monkey patched it in?
<FromGitter> <>
<FromGitter> <> it's in my own module, which is why it doesn't work...
<FromGitter> <Blacksmoke16> indeed
<FromGitter> <> Oh fun, it's supposed to be a protected method
<FromGitter> <Blacksmoke16> oof
<FromGitter> <> I guess it really shouldn't be actually
<FromGitter> <> Ok, thanks for the help. This will surely take me a week to complete, and then I can start working on high-level math using these primitive types, all in the same library.
<FromGitter> <> o/
notzmv has joined #crystal-lang
ur5us has quit [Ping timeout: 268 seconds]
[R] has quit [Ping timeout: 258 seconds]
yxhuvud has quit [Read error: Connection reset by peer]
yxhuvud has joined #crystal-lang
hightower2 has joined #crystal-lang
<raz> linux on M1, wee
ur5us has joined #crystal-lang
[R] has joined #crystal-lang
jhass[m] has quit [Quit: Bridge terminating on SIGTERM]
fifr[m] has quit [Quit: Bridge terminating on SIGTERM]
jhass[m] has joined #crystal-lang
ur5us has quit [Ping timeout: 250 seconds]
fifr[m] has joined #crystal-lang
postmodern has quit [Remote host closed the connection]
ua_ has quit [Ping timeout: 258 seconds]
ua_ has joined #crystal-lang
hightower2 has quit [Ping timeout: 265 seconds]
<FromGitter> <jwaldrip> im confused... 1.1.1 was released but its not in master?
<FromGitter> <jwaldrip> when I run --error-trace i am getting: ```Unhandled exception: Negative argument (ArgumentError) ⏎ from raise<ArgumentError>:NoReturn ⏎ from String#*<Int32>:String ⏎ from Crystal::TypeException+@Crystal::ErrorFormat#append_error_indicator<String::Builder, Int32, Int32, Int32>:(String::Builder | Nil) ⏎ from Crystal::TypeException+@Crystal::ErrorFormat#error_body<Nil, (String | Nil)>:(String |
<FromGitter> <jwaldrip> But I dont get that error when running without error trace
<FromGitter> <RespiteSage> That certainly seems problematic.
<FromGitter> <RespiteSage> Do you have a relatively minimal set of code to reproduce it?
<FromGitter> <> would anyone be interested in a libmagic binding?
<FromGitter> <> oh... guess that exists already :)
<FromGitter> <> couldn't find it on for some reason
<straight-shoota> jwaldrip, yes 1.1.1 was released from the release/1.1 branch
<straight-shoota> because it contains a selection of commits from master that were backported to 1.1.0
<straight-shoota> merges the changelog to master
<FromGitter> <jwaldrip> gotcha, I was like where is it?!
<FromGitter> <jwaldrip> I have it working now... but it was very strange
<FromGitter> <> @jwaldrip: not sure what you mean... i was just hooking up the few functions i actually need when i found :)
<FromGitter> <spencerwi> Is there like...a "specification" or formalization of Crystal's syntax/grammar? I see the lexer and parser in the Crystal compiler, but that's pretty "imperative" rather than being sorta "declarative" about syntax definitions
<FromGitter> <spencerwi> Ah, that whole docs guide is definitely a step up from the "git book" guide I referenced at a lot back in like 0.34. Thanks!
<FromGitter> <Blacksmoke16> pretty sure its the same thing :p
<FromGitter> <spencerwi> Oh. Maybe it's my memory that's faulty then >_>
<straight-shoota> It's the same content. Some things certainly have im proved since 0.34
<straight-shoota> There is no formal specification yet, btw. Just the reference implementation.
<FromGitter> <spencerwi> Full disclosure: I was hoping to see if I could put together a tree-sitter parser for Crystal, and having a sort of "grammar specification" would be really helpful in that direction. That said, I think the docs as they're written now should still be pretty helpful.
<FromGitter> <spencerwi> well
<FromGitter> <Blacksmoke16> nvm, that was you :P
<FromGitter> <spencerwi> I am very glad I came here then
<FromGitter> <spencerwi> nope, that was not me
<FromGitter> <spencerwi> just another white dude with "will" in his name :P
<FromGitter> <Blacksmoke16> xD
<FromGitter> <Blacksmoke16> well there you go ::
<FromGitter> <spencerwi> (I recognize that I am pretty much perfectly-generic in my region)
Guest70931 has joined #crystal-lang
mookie has quit [Ping timeout: 258 seconds]
mookie has joined #crystal-lang
Guest70931 has quit [Ping timeout: 258 seconds]
<FromGitter> <> Is it frowned upon to have multiple expectations in a single `it` block?
<FromGitter> <asterite> @spencerwi do you know if you can write a tree-sitter implementation in Crystal rather than in C?
<FromGitter> <asterite> many expectations in an `it` block is good
<FromGitter> <Blacksmoke16> multiple assertions related to the same test case is fine
<FromGitter> <> Ok thanks
<FromGitter> <Blacksmoke16> two separate test cases in the same `it` block less so
<FromGitter> <Blacksmoke16> i personally like seeing all the green `.` :P
<FromGitter> <> @Blacksmoke16: I got rid of your helper function and decided to just write a `==` overload in my library code that wraps `nearly_equal?`
<FromGitter> <> It was....problematic
<FromGitter> <Blacksmoke16> oh?
<FromGitter> <> When something fails it just says: false but got true, rather than: some value but got some other value
<FromGitter> <Blacksmoke16> you can customize the failure message
<FromGitter> <> I think the only way around that is to use eq, which means I can't block my library's `==`
<FromGitter> <Blacksmoke16> or do some custom logic and manually call `fail`
<FromGitter> <Blacksmoke16> if there isn't a matcher for your use case
<FromGitter> <RespiteSage> Also, you obviously know your use case, but my concern with `==` being "nearly equal" is that it can break transitivity, which I would normally expect from the `==` operator.
<FromGitter> <Blacksmoke16> prob be okay if its overloaded for `self` tho?
<FromGitter> <Blacksmoke16> versus global `==`
<FromGitter> <RespiteSage> I mean, yeah, just like any overload you can make it whatever you want as long as you know what it is.
<FromGitter> <Blacksmoke16> 👍
<FromGitter> <> Yeah this is for `self`.
<FromGitter> <RespiteSage> ```code paste, see link``` []
<FromGitter> <RespiteSage> Obviously that's tongue-and-cheek, and I'm not trying to equate your use case to that class.
<FromGitter> <RespiteSage> That was mostly something that occurred to me that I wanted to get out of my head.
<FromGitter> <RespiteSage> But my concern is just that it breaks the expected semantics of it. If you need an approximate `==`, then you need it; you'll just need to make sure everyone working with it is aware of how it works.
<FromGitter> <> Also this is a decent write-up on why `nearly_equal?`exists in my codes, and why spec's `be_close` is not usually what one wants:
<FromGitter> <RespiteSage> Ah, I see. So it has to do with floating-point precision?
<FromGitter> <> Yes. The absolute tolerance test fails (spec's `be_close` uses this) when x and y become large, and the relative tolerance test fails when they become small. It is therefore desired to combine these two tests together in a single test.
<FromGitter> <RespiteSage> I recall reading a combined method like that a bit ago. Perhaps it was actually this article, but I'll give it a read to see.
<FromGitter> <> It was probably another short article I linked, but this one is much more in depth
<FromGitter> <> Other one for reference
<FromGitter> <RespiteSage> I hope my persistence (and my dumb code above) wasn't/isn't frustrating to you. I just read a lot of confusing code, some of which was written before I was born, so I care a lot about writing code that makes sense to read.
<FromGitter> <> No it's not.
<FromGitter> <> I understand. Code is read much more than it is written after all.
<FromGitter> <> What I can do is {{ raise ... } `==` in my library, with a suggestion to explicitly use `nearly_equal?`, and then in the unit tests, monkey patch that overload with another overload.
<FromGitter> <Blacksmoke16> prob wouldn't be too hard to add your own matcher
<FromGitter> <Blacksmoke16> id go with the simplest approach
hightower2 has joined #crystal-lang
<FromGitter> <> i'm having trouble with Digest... somehow no hashes match for SHA256 or even SHA1
<FromGitter> <Blacksmoke16> got some example code/
<FromGitter> <> ```code paste, see link``` []
<FromGitter> <> not sure what i'm doing wrong there :|
<FromGitter> <Blacksmoke16> `require "digest"; pp Digest::SHA1.hexdigest("foo\n")`
<FromGitter> <Blacksmoke16> i think you're sha1 hashing the hash
<FromGitter> <> hmm
<FromGitter> <Blacksmoke16> `require "digest"; d =; d.update("foo\n"); pp`
<FromGitter> <Blacksmoke16> or at least hashing the bytes of the string
<FromGitter> <> ah, hexstring!
<FromGitter> <Blacksmoke16> but i'd just use `.hexstring` no need to new up an instance/call update or anything
<FromGitter> <Blacksmoke16> `Digest::SHA1.hexdigest("foo\n")`
<FromGitter> <> yeah, i have to use the `#file` method though, which isn't on the class unfortunately
<FromGitter> <> anw, your suggestion works for that as well now, thanks :)
<FromGitter> <Blacksmoke16> `Digest::SHA1.hexdigest &.file("/path/to/file")`
<FromGitter> <> that sounds more like black magic, but guess it works too...
<FromGitter> <Blacksmoke16>
<FromGitter> <> yeah
<FromGitter> <> but `Yields a context object with an #update(data : String | Bytes) method available.` doesn't really sound very obvious for using with files :)
<FromGitter> <> i may just be dumb though
<FromGitter> <Blacksmoke16> it yields an instance of `self`, which when calling it on `Digest::SHA1` that is an instance of `Digest::SHA1`
<FromGitter> <Blacksmoke16> which has a `file` method from
<FromGitter> <Blacksmoke16> same type that provides `#update`
<FromGitter> <> how come none of those methods are documented at ?
<FromGitter> <Blacksmoke16> "those methods" being `#file` and `#update` or `.hexdigest`?
<FromGitter> <> hexdigest
<FromGitter> <Blacksmoke16> the type extends `ClassMethods`, so they're all on there
<FromGitter> <> shouldn't there be some kind of "Class methods inherited from Digest::ClassMethods" on that page then?
<FromGitter> <Blacksmoke16> :shrug: possibly?
ur5us has joined #crystal-lang
hightower3 has joined #crystal-lang
hightower2 has quit [Ping timeout: 240 seconds]
<FromGitter> <> oprypin ( Do you think you could share the code you use to setup the ECR GLSL integration stuff sometime? Primarily wondering at how you load shaders at runtime, and how you compose programs together from re-usable methods instead of the #include nonsense.
<FromGitter> <> That is one thing I had a very nice solution for in Lisp