ChanServ changed the topic of #crystal-lang to: The Crystal programming language | https://crystal-lang.org | Fund Crystal's development: https://crystal-lang.org/sponsors | GH: https://github.com/crystal-lang/crystal | Docs: https://crystal-lang.org/docs | Gitter: https://gitter.im/crystal-lang/crystal
<FromGitter> <oprypin:matrix.org> πŸŽ‰ https://oprypin.github.io/crystal-db/api/ <- https://github.com/crystal-lang/crystal-db/pull/148 ⏎ hope it's received well :D
<straight-shoota> nice
<straight-shoota> how does the version selector work?
<straight-shoota> ah, mike
andremedeiros has quit [Read error: Connection reset by peer]
<FromGitter> <watzon> @Blacksmoke16 https://github.com/crystal-term
<FromGitter> <Blacksmoke16> thats the one :p
<FromGitter> <Blacksmoke16> thanks
andremedeiros has joined #crystal-lang
<oprypin> straight-shoota, eeehh you know how i keep saying about the big idea of mkdocstrings and that pages shouldn't be auto-generated at all... then the way you're suggesting "to remove the gap between structure and content" is against the philosophy. also actually nothing wrong at all with editing the nav, it's literally easier *and* more convenient than whatever other tagging method there might be
<oprypin> the CI will error when the nav doesn't match the actual pages and their existence :3
<straight-shoota> what about types that exist in code but not in SUMMARY.md?
<oprypin> yep that's a warning (erroring CI)
<straight-shoota> Yeah, maybe that approach is really better. Just spinning ideas
<straight-shoota> Also nice: Structuring methods inside a type
<straight-shoota> Like, grouping related methods,
<oprypin> that would indeed be nice, but unfortunately i haven't provided a good solution for that. though it *is* possible to just write out every method one by one manually
<straight-shoota> yeah that's a bit tricky
<straight-shoota> having some kind of automation for that would be good, so maybe section tagging is a solution
<straight-shoota> you could still write the section body in prose and also explicitly define methods there (with a specific order).
<FromGitter> <Blacksmoke16> i imagine it would be possible to have some "metadata" section in the docs that gets consumed but not rendered
<straight-shoota> Methods that are tagged but not explicitly referenced in the section would just be added at the bottom
<FromGitter> <oprypin:matrix.org> mmm good food for thought
<FromGitter> <watzon> Man crystalline eats memory for breakfast, lunch, and dinner
<FromGitter> <Blacksmoke16> Better download more RAM
<straight-shoota> oprypin ^
<straight-shoota> sry, the keys are always out of order :D
<FromGitter> <watzon> I'll get right on that lol
duane has joined #crystal-lang
<FromGitter> <Blacksmoke16> @watzon hows that parameter bag thing working out?
<FromGitter> <watzon> Worked great!
<FromGitter> <Blacksmoke16> πŸ‘ good to hear!
teardown has quit [Ping timeout: 268 seconds]
hendursaga has quit [Ping timeout: 268 seconds]
hendursaga has joined #crystal-lang
teardown has joined #crystal-lang
duane has quit [Ping timeout: 240 seconds]
aquijoule_ has quit [Remote host closed the connection]
aquijoule_ has joined #crystal-lang
<FromGitter> <Dan-Do> How we implement timeout to the HTTP::Client.get method?
_ht has joined #crystal-lang
<frojnd> watzon: but then I get no return :/ Problem is that I have a file with line that has some string and next line is date. I first match by date and line above with regex... now I don't get a hit for regex
<FromGitter> <JoeeGrigg> Hi, I wondered if anyone could help me? I am writing a CLI and want to execute a shell command. I have that working with: ⏎ ⏎ ```Process.run("command", shell: true, output)``` [https://gitter.im/crystal-lang/crystal?at=603dfe47d1aee44e2dbb817d]
<FromGitter> <JoeeGrigg> Hi, I want to capture the output of a shell command and output it as it happens. I can get the full output after the command has finished executing but I am having trouble getting it in real time as a long running command runs. Could anyone help please?
hendursa1 has joined #crystal-lang
hendursaga has quit [Ping timeout: 268 seconds]
repo has quit [Ping timeout: 258 seconds]
repo has joined #crystal-lang
bazaar has quit [Ping timeout: 246 seconds]
<FromGitter> <Dan-Do> @JoeeGrigg here is an example of mine using nodejs cli
<FromGitter> <Dan-Do> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=603e1109b5131f4f28e8a0c2]
entel has joined #crystal-lang
<FromGitter> <JoeeGrigg> That is what I have but the problem is that I can only take the full output from IO::Memory after the command has completed. I have a command that might run for 60 seconds and throughout has output and I want the output to be outputted (i.e. puts) as and when it comes in, not all at the end
<straight-shoota> You need to use Process.run with a block argument
<straight-shoota> Without a block, the method waits for the process to finish
<straight-shoota> frojnd, you got your escape sequences messed up again, this time in the other direction. line includes \\n but your regex matches against \n
<straight-shoota> also you don't need to match again in the if block, the variable match is already set there from the condition
<FromGitter> <JoeeGrigg> Okay so I think I am close with this: ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ But, after it completes, it hangs and doesn't move on. Is there something else I need to do? [https://gitter.im/crystal-lang/crystal?at=603e22b15d0bfb4e58801a2a]
<straight-shoota> you don't need to build your own pipe, Process.run handles that for you
<straight-shoota> this should work: `Process.run(command, shell: true, output: :pipe) do |process|
<straight-shoota> while line = process.output.gets?
<straight-shoota> end`
<straight-shoota> ; puts line
<straight-shoota> end
<straight-shoota> sry, that got messed up
<straight-shoota> https://carc.in/#/r/ahba
<FromGitter> <js:nil.im> Why is the option called `--cross-compile` when all it does is avoid linking and print the linking command line instead?
<straight-shoota> the most typical use case is for cross compiling
<straight-shoota> I don't know any other reason to do that
<straight-shoota> So it's descriptive about the purpose
<FromGitter> <js:nil.im> well, it's useful to create .o files to link into an existing C program, for example πŸ™‚
<FromGitter> <js:nil.im> and it is by no means enough to cross-compile
<straight-shoota> not by itself, yes. Hence it's typically combined with --target
<FromGitter> <js:nil.im> wouldn't `--no-link` be a much more descriptive and correct name?
<FromGitter> <JoeeGrigg> With the code you sent straight-shoota I get the below error? ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=603e284be8267a46f2e8894d]
<straight-shoota> ah sry, it's gets without ?
<straight-shoota> @js:nil.im maybe --no-link would also be good
<FromGitter> <Daniel-Worrall> I'd argue it could be an alias, but not replaced
<straight-shoota> so far linking to object files isn't really a practical use case
<straight-shoota> *compiling only the object files
<straight-shoota> However --cross-compile also influences the compiling process, it's not exactly the same as "just don't run the linker command and only print it"
<straight-shoota> ... at the end
<frojnd> straight-shoota: I see. Thank you: https://carc.in/#/r/ahbn
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
<FromGitter> <js:nil.im> People have been using it for that though. Or to create shared libraries. If it has other side effects, maybe there really should be a `--no-link`.
duane has joined #crystal-lang
<straight-shoota> I suppose the side effects are probably fine for generating object files
<straight-shoota> The point is, you can't really effectively use Crystal code as a library in a different program. At least not with the stdlib runtime
duane has quit [Ping timeout: 264 seconds]
duane has joined #crystal-lang
<yxhuvud> yes there is a whole lot of kernel.rb that doesn't make sense in that case. But some of it is necessary (like having an event loop, even if that also might have issues)
<FromGitter> <oprypin:matrix.org> https://github.com/search?q=user%3Aoprypin+%22--cross-compile%22&type=code is my "no link" usage. just didn't bother installing the external lib dependency
andremedeiros has quit [Read error: Connection reset by peer]
andremedeiros has joined #crystal-lang
<FromGitter> <erdnaxeli:cervoi.se> hi, is there any lib to build a cli without writing everything to stdout? I want to use it to write a text bot
<FromGitter> <erdnaxeli:cervoi.se> commander, admiral, clicr looks cool but all write to stdout
<FromGitter> <erdnaxeli:cervoi.se> I want something that returns me a string that I can send elsewhere than in stdout
<FromGitter> <Blacksmoke16> at that point it's not really a cli tho?
<FromGitter> <erdnaxeli:cervoi.se> it's not a cli but it work the same way:Β I want subcommands, arguments, options, an autogenerated help
<FromGitter> <erdnaxeli:cervoi.se> it's a "cli over IRC"Β or your favorite messaging thing
<FromGitter> <Blacksmoke16> ah gotcha
<FromGitter> <Blacksmoke16> hold on
<FromGitter> <Blacksmoke16> https://github.com/jwaldrip/admiral.cr/blob/master/src/admiral/command.cr#L44-L52 pretty sure you can define a custom `.new` in your commands to specify what `IO` will be used
<FromGitter> <Blacksmoke16> as it just defaults to `STDOUT` and stuff
<FromGitter> <Blacksmoke16> e.g. use `ARGV` and `STDIN`, but output to some other `IO`
_ht has quit [Remote host closed the connection]
<FromGitter> <erdnaxeli:cervoi.se> oh nice, thanks
robacarp has quit [Ping timeout: 256 seconds]
robacarp has joined #crystal-lang
<FromGitter> <js:nil.im> What are those other side effects, btw?
<FromGitter> <RespiteSage> Anybody else gotten email from CodeStream related to Crystal PRs you made?
<straight-shoota> @js Not sure about the exact differences. But --cross-compile takes different paths in the compiler
<FromGitter> <js:nil.im> btw if I want to port Crystal to a new OS (NetBSD, later potentially Haiku and MorphOS), what's the best place to start? I see that there is some platform (OS + CPU arch) code for interfacing with libc that contains various struct, so I guss that's where to start. But are those really handwritten, or is there a generator? I see that there is some initial things for NetBSD, but AFAIK it is currently
<FromGitter> ... unsupported, right?
<straight-shoota> No, NetBSD should be supported
<straight-shoota> Was added last year: https://github.com/crystal-lang/crystal/pull/9360
<straight-shoota> That PR should also serve to demonstrate what to do for other platforms
<FromGitter> <js:nil.im> Ah, nice, I found some platforms list where it was not listed. It is not in pkgsrc, though, so how would one use it?
<FromGitter> <js:nil.im> Ah, nia, of course πŸ˜€
<straight-shoota> ofc it differs depending on what you can reuse, netbsd could build upon existing openbsd support for example
<straight-shoota> hm, might be missing from the platform support page
<straight-shoota> anyways the only official binaries are provided for tier 1 platforms
<FromGitter> <js:nil.im> I'll talk to nia about adding it to pkgsrc. We're both NetBSD devs, so if she already did all the work and has binaries, we can probably just add those to pkgsrc. And then I'll look at NetBSD/ARM64 next, as that is what I mostly use these days
<straight-shoota> binaries for other platforms might be available through community channels
<FromGitter> <js:nil.im> Was providing cross-compiled binaries ever considered?
<straight-shoota> nice :+1:
<FromGitter> <js:nil.im> It's a nice test to see that a platform doesn't regress
<FromGitter> <js:nil.im> could even be added to CI?
<straight-shoota> since the cross-compiled binaries still need to be linked, it doesn't make much sense to provide the object files
<straight-shoota> but CI would be possible, definitely
<FromGitter> <js:nil.im> installing the linker on a DI system shouldn't be too hard - at least in the case of NetBSD, ./build.sh can just build the tools
<FromGitter> <js:nil.im> Ideally, I'd like to see Crystal's platform support one day to look like one of my projects: https://objfw.nil.im/doc/trunk/PLATFORMS.md
<straight-shoota> either just cross compile on CI or run it natively if a CI provider is available
<straight-shoota> yeah well, architectures is a bit difficult as it relies on LLVM
<FromGitter> <js:nil.im> yep, I know
<FromGitter> <js:nil.im> but at least there's m68k support for LLVM being merged πŸ™‚
<FromGitter> <js:nil.im> so maybe I can at least run Crystal on my Amiga πŸ˜›
<FromGitter> <js:nil.im> hoping the GC will not be too taxing
<straight-shoota> you could always run without...
<straight-shoota> accepting the consequences :D
<FromGitter> <js:nil.im> how well does manual memory management work with Crystal?
<FromGitter> <js:nil.im> and was it considered to do something like Python, where you have a mix of reference counting and GC?
<straight-shoota> stdlib doesn't support manual memory management, but for the language itself it's as good as any other
<straight-shoota> maybe even a bit easier than others because with blocks you can easily free memory after the block returns
<straight-shoota> AFAIK bdwgc was put in place because it's relatively easy to use and it works good enough
<straight-shoota> but there are plans to improve GC in the future
* FromGitter * Blacksmoke16 is still waiting on the next release of that
<straight-shoota> @js I updated the platform support page
<FromGitter> <js:nil.im> Hmm, I guess there could be something like stdlib-embedded which is a (more minimal, potentially) version of it that supports manual memory management
<straight-shoota> yeah, definitely
<straight-shoota> IIRC there were already some experiments with that
<FromGitter> <js:nil.im> I like how crystal just might be able to do everything C is able to πŸ˜‰
<FromGitter> <js:nil.im> is there inline assembly yet? πŸ˜€
<FromGitter> <js:nil.im> though I wish it would play better with shared libraries and hence integrate better into package managers. I'm not a huge fan of static linking / vendoring.
<straight-shoota> it is definitely able to do that. You can just write C code in Crystal syntax :D
<straight-shoota> inline assembly works, yes
<FromGitter> <js:nil.im> How tightly integrated is the compiler with LLVM? Maybe a C backend can be written so it can output C code again? πŸ˜€
<FromGitter> <js:nil.im> Crystal is basically what I looked for ~ 15 years ago, when I really liked Ruby and wanted something compiled. Instead, I turned to Objective-C, wrote my own ObjC framework and runtime for Linux and other OSes, etc - and now I feel like someone has done what I was looking for all those years ago πŸ˜€. Feels right at home - and also a little like I wasted those last 15 years ☹️
<FromGitter> <watzon> Same though lol
<FromGitter> <watzon> Except for me it was more like 10 years
<straight-shoota> codegen is pretty deep with LLVM obviously
<FromGitter> <js:nil.im> at some point you have an AST, I wonder how difficult it would be to convert that AST to C
<straight-shoota> but I suppose it wouldn't be difficult to switch the entire codegen step out and instead plug in a C transpiler
<FromGitter> <watzon> Afaik the compiler is pretty tightly coupled with LLVM, but it would be nice to eventually refactor that
<FromGitter> <watzon> Hmmm, interesting idea
<FromGitter> <HertzDevil> speaking of llvm
<FromGitter> <js:nil.im> Also I have to look into whether I can make a macro to neatly integrate with all my ObjC code that I have written in the last 15 years πŸ˜€. That would also make it immediately available to Crystal.
<FromGitter> <watzon> We don't speak of LLVM
<FromGitter> <HertzDevil> is there a reason the `LLVM` module isn't placed under `Crystal`
<FromGitter> <js:nil.im> Let me know if you see any classes in here that would be useful for Crystal, happy to port my code to Crystal and contribute πŸ˜€ https://objfw.nil.im/dir?ci=tip&name=src
<straight-shoota> @HertzDevil It was discussed in the stdlib cleanup to make LLVM module internal
<FromGitter> <js:nil.im> it's all without any dependencies on 3rd party libs
<FromGitter> <HertzDevil> i don't think any other part in the stdlib actually depends on the `LLVM` module
<straight-shoota> But IIRC the rationale was that there are quite a number of other language/compiler implementations written in Crystal that use the same LLVM bindings
<straight-shoota> no, stdlib doesn't need it
<FromGitter> <watzon> My one gripe with Crystal's compiler right now (outside of it getting exponentially slower as your codebase grows) is that there aren't any cross compilation toolchains like you'd find in Rust or Zig. It would be amazing to be able to write Crystal on my machine, run `crystal build --target x86_64-unknown-linux ./main.cr` and have a binary that will run fine on linux.
<straight-shoota> hm, can't find that discussion only https://github.com/crystal-lang/crystal/issues/5215
<straight-shoota> and there was never a final decision on LLVM, it just continues to stick around :D
<FromGitter> <watzon> My hope right now is that I might be able to facilitate the process with `zig cc` someday
<FromGitter> <js:nil.im> you'll need a liker for that, though. Unless Crystal goes the Go route and creates it's own and no longer uses libc and does syscalls itself. Please don't go there, though πŸ˜‰
<straight-shoota> exactl. and even if stdlib wouldn't rely on other libraries, it only works as long as no shard requires a linked library
<FromGitter> <watzon> I suppose if the zig route doesn't work I could also just write a deploy tool which spins up a docker container, builds your code, and spits out a binary
<straight-shoota> Simple C interop is actually a very strong point about Crystal, so I doubt we'll ditch that
<FromGitter> <js:nil.im> I think building cross-binutlis is easy enough
<FromGitter> <js:nil.im> and pkgsrc has them for most platforms. And pkgsrc also works on Linux, btw πŸ˜‰
<FromGitter> <watzon> Well I don't know the full details, but Zig uses LLVM and lldb I believe and still manages to have cross platform build support with an almost seamless C interop. The way they handle it is by maintaining their own libc headers for all of the platforms they support though.
<FromGitter> <watzon> Not saying it would be an easy accomplishment, especially with Crystal being farther along, but man would it be nice to have
<FromGitter> <watzon> Say I had libc headers for another platform though. Would it be possible with Crystal in its current state to build a program as an object file and then manually link it?
<straight-shoota> of course
<straight-shoota> that's exactly how --cross-compile works
<straight-shoota> instead of header files you need the respective LibC bindings, but it's 1:1 the same
<FromGitter> <erdnaxeli:cervoi.se> @Blacksmoke16: actually I think I can't use admiral, @input and @output must be `IO::FileDescriptor` but I would like to give it `IO::Memory`.
<FromGitter> <watzon> Ok cool. So doing what Zig is doing isn't super far fetched more than likely.
<FromGitter> <js:nil.im> is there some public list of shards or someting?
<FromGitter> <watzon> shardbox.org
<FromGitter> <js:nil.im> so I can see what is missing / where it would make sense to port my code to crystal?
<FromGitter> <js:nil.im> thx
<FromGitter> <watzon> Or https://crystalshards.org https://crystalshards.xyz as well
<FromGitter> <js:nil.im> ok seems there is nothing to handle LHA yet πŸ˜€. So I could port that
<FromGitter> <watzon> LHA?
<FromGitter> <Blacksmoke16> @erdnaxeli:cervoi.se ah rip :/
<FromGitter> <js:nil.im> @watzon: Archive format
<FromGitter> <js:nil.im> popular in Japan and on the Amiga
<FromGitter> <erdnaxeli:cervoi.se> actually I just need the string parsing, options and arguments vaidation, and help generation. Maybe there is something else I can use.
<FromGitter> <js:nil.im> there's only a non-free-but-source-available implementation and mine AFAIK πŸ˜‰
<FromGitter> <js:nil.im> ah and I think one free one that is decompression-only
<FromGitter> <watzon> Ahh interesting
<FromGitter> <js:nil.im> The format is rather simple: https://objfw.nil.im/file?name=src/OFLHAArchive.m&ci=tip https://objfw.nil.im/file?name=src/OFLHAArchiveEntry.m&ci=tip ⏎ As is the compressed stream: https://objfw.nil.im/file?name=src/OFLHADecompressingStream.m&ci=tip
<FromGitter> <js:nil.im> does Crystal already have an async DNS resolver? I could also port that I suppose
<FromGitter> <watzon> Not that I know of
<straight-shoota> I've seen that
<straight-shoota> might be a good idea :+1:
<straight-shoota> currently just uses getaddrinfo
<straight-shoota> so it has limited features and blocks the entire thread
<FromGitter> <js:nil.im> yeah, I wrote my own async resolver because of that πŸ™‚ And also to do things like looking up SRV records and other things `getaddrinfo()` can't do
<FromGitter> <watzon> Do it! That would be a great addition to the community
<FromGitter> <js:nil.im> and a great way to learn about Crystal πŸ˜‰
<FromGitter> <watzon> Truth haha
<FromGitter> <js:nil.im> I looked into the module documentation, but it is not clear to me if it means that the entire module needs to be in a single file?
<FromGitter> <watzon> Nope
<FromGitter> <watzon> Modules can be broken up among several files
<straight-shoota> Namespaces can be reopend from anywhere
<FromGitter> <js:nil.im> ok, so I just put the same module in multiple files?
<FromGitter> <watzon> Yep
<FromGitter> <watzon> You can do the same with classes and structs
<FromGitter> <js:nil.im> ok, I am missing something super obvious here. I looked at the manpage for shards, and there's shards build, but it does not seem to build my library and only tries to satisfy dependencies?
<FromGitter> <watzon> You're looking for the `targets` section of `shard.yml`
<straight-shoota> `shards build` is just `crystal build` with source paths mapped to a target name
<straight-shoota> I think it's pretty useless
<FromGitter> <watzon> For instance: ⏎ ⏎ ```targets: ⏎ server: ⏎ main: src/server/cli.cr ⏎ worker: ⏎ main: src/worker.cr``` ⏎ ⏎ `shards build` [https://gitter.im/crystal-lang/crystal?at=603ebe36e562cf54ac94c6e5]
<FromGitter> <js:nil.im> I see. So what would be the target for the library then? lib?
<FromGitter> <watzon> But yes, it's not overly useful
<FromGitter> <js:nil.im> or the name of the library? what's the convention? πŸ™‚
<straight-shoota> Libraries have no target
<straight-shoota> you don't build them
<straight-shoota> they're just provided as source
<FromGitter> <js:nil.im> so how can I run them through the compiler to see that they at least compile? πŸ˜€
<straight-shoota> spec
<straight-shoota> since there's no single entry point for arbitrary library code, it needs to be explicitly called, ideally with extensive tests
<FromGitter> <watzon> `crystal spec` will search the `spec` directory for files ending in `spec.cr` and run them
<FromGitter> <watzon> For instance, https://github.com/protoncr/proton/tree/native/spec
<FromGitter> <watzon> Granted I'm using spectator rather than the built in spec runner, but it's the same process
<FromGitter> <js:nil.im> so, basically, if I don't have any unit test for something, I cannot even be sure it compiles?
<straight-shoota> no
<FromGitter> <watzon> Well you can always make a test program
<FromGitter> <watzon> And require your library
<straight-shoota> if you have library code with no actual main program, the compiler won't compile any code because it's never used. So unless there's a syntax error, you wouldn't know if the code at least compiles
<FromGitter> <js:nil.im> I'm cheating right now by just running crystal build *.cr πŸ™‚
<FromGitter> <js:nil.im> I just realized how my ADNS implementation depends on my socket implementation πŸ˜€
<FromGitter> <js:nil.im> is there a generic type for "this is a socket address" in Crystal?
<FromGitter> <watzon> I'd limit it to a single file. Generally I do `crystal build ./src/{library_name}.cr` until I've started writing tests
<FromGitter> <js:nil.im> I'm not using sockaddr, because I might be running on a system that does not support IPv6, but I still want to be able to resolve AAAA records
<FromGitter> <watzon> Just be sure to require the code your main code depends on
<FromGitter> <watzon> In some cases I do a hybrid library/client which makes some things easy to test. Like I wrote a type language parser, so I also wrote a command line client that takes in a .tl file and spits out JSON https://github.com/protoncr/proton/blob/native/src/bin/tl-to-json.cr
<FromGitter> <watzon> Crystal is fairly flexible in that regard though
<FromGitter> <js:nil.im> so, library_name.cr should somehow pull in all the other files?
<straight-shoota> yes
<FromGitter> <js:nil.im> how would that be done? πŸ™‚
<FromGitter> <watzon> Yep, using `require` statements. A simple way to require everything would be `require "./*{library_name}"`
<FromGitter> <watzon> `require "./*{library_name}/**"`
<FromGitter> <js:nil.im> thx
<FromGitter> <Blacksmoke16> πŸ‘Ž using `*` or `**` is usually not a great idea
<straight-shoota> wildcard require can cause order issues
<FromGitter> <watzon> It's not ideal, but works fine for smaller projects
<straight-shoota> depends
<straight-shoota> if it works, it works. If not, you need to write it explicitly
<FromGitter> <js:nil.im> so, now that my asyncdns.cr requires all the other files - how do I make sure it actually compiles all code?
<straight-shoota> you write tests for it
<FromGitter> <watzon> Either write tests, or make a sample binary that relies on it
<FromGitter> <js:nil.im> is there same command to build and run tests?
<FromGitter> <watzon> Yep
<FromGitter> <watzon> Just `crystal spec`
<FromGitter> <js:nil.im> thx, I'll read through that
<FromGitter> <js:nil.im> I was kinda hoping I can skip the tests first and read on that later πŸ˜€
<FromGitter> <js:nil.im> but it seems Crystal requires TDD
<FromGitter> <watzon> Well not necesarily
<FromGitter> <watzon> You can just as easily put sample code in your main file that you're building
<FromGitter> <watzon> Tests are ideal, but not required
<FromGitter> <js:nil.im> automatic tests for async DNS are kinda hard :(
<straight-shoota> it doesn't require it, but it's very popular
<straight-shoota> you still want to make sure it works, right? =)
<straight-shoota> you'll probably need to mock a DNS server
<FromGitter> <js:nil.im> I did a lot of manual testing πŸ˜‰
<FromGitter> <js:nil.im> against various real world DNS servers
<FromGitter> <js:nil.im> mocking the server responses is kinda pointless, because it just means I'll repeat whatever wrong assumption I made in my impl in my tests πŸ˜‰
<FromGitter> <js:nil.im> spoiler alert: The DNS spec is one thing, real world another πŸ˜€
<straight-shoota> yeah, for this domain real integrations tests are easily more important than unit tests
<FromGitter> <oprypin:matrix.org> > I'm cheating right now by just running crystal build *.cr πŸ™‚ ⏎ ⏎ that.. is indeed cheating, because your methods can contain uncompilable code but crystal won't care unless they're ever used
<FromGitter> <oprypin:matrix.org> example programs that call some functions are a bare minimum
<FromGitter> <oprypin:matrix.org> js (https://matrix.to/#/@js:nil.im):
<FromGitter> <js:nil.im> btw what is the convention on when to use () for paramets and when not?
<straight-shoota> I don't think there is one
<straight-shoota> IMO parenthesis is often better
<FromGitter> <oprypin:matrix.org> js (https://matrix.to/#/@js:nil.im): my convention is too always use. my next best convention is to skip them only if makes sense as a verb+subject. e.g. `push thing, force: 5`
<straight-shoota> I use it a lot, except for DSL
<straight-shoota> that sounds like a good rule of thumb :+1:
<FromGitter> <oprypin:matrix.org> *most* people's convention seems to be avoiding parenthesis until they become to confused from avoiding them and then they add parenthesis
<FromGitter> <oprypin:matrix.org> the only official convention is to never write `foo()`, only `foo` is allowed
<FromGitter> <oprypin:matrix.org> enforced if you use `crystal tool format`
<FromGitter> <js:nil.im> I see, thx
<FromGitter> <js:nil.im> oh, so the convention to indent until the previous line when breaking a line is not used, but instead two spaces. ok.
<FromGitter> <oprypin:matrix.org> i think it depends. you can try `crystal tool format` to see what it thinks
<FromGitter> <js:nil.im> in ObjC, the delegate pattern is used a lot. I suppose in Crystal you use a bunch of blocks stored as an instance variable?
<FromGitter> <Blacksmoke16> i like to use `self.foo` to show `foo` is a method versus doing `foo()`
<FromGitter> <oprypin:matrix.org> sounds about right
<FromGitter> <oprypin:matrix.org> another common approach is to ask you to subclass and override methods
<FromGitter> <js:nil.im> hmm, right, on_foo
<FromGitter> <js:nil.im> what is usually preferred in Crystal land?
<FromGitter> <js:nil.im> In ObjC, subclassing for that is a big no-no πŸ˜‰
<FromGitter> <oprypin:matrix.org> In my opinion subclassing is more idiomatic. both are common, don't know
<FromGitter> <js:nil.im> btw, why is it that I have to write "foo : Foo" instead of "foo: Foo"?
<FromGitter> <oprypin:matrix.org> 1) strong opinions; 2. because that is very strongly associated with named method arguments
<FromGitter> <Blacksmoke16> `foo: Foo` is `NamedTuple(foo: Foo.class)`
<FromGitter> <oprypin:matrix.org> what no, not by itself
<FromGitter> <Blacksmoke16> no, but that syntax is generally used to denote that
<FromGitter> <oprypin:matrix.org> it was around 5 years ago that a commit was added explicitly forbidding no space there. there's no other technical reason
<FromGitter> <Blacksmoke16> e.g. as a named argument, or within `{}`
<FromGitter> <oprypin:matrix.org> well that's what i was saying ⏎ ⏎ > because that is very strongly associated with named method arguments
<FromGitter> <Blacksmoke16> yea πŸ‘
<FromGitter> <js:nil.im> I see, thx :)
<FromGitter> <js:nil.im> I have to say, this community is very friendly
<FromGitter> <watzon> We try
<FromGitter> <js:nil.im> you could have just said RTFM instead of answering my dumb questions πŸ˜‰
<FromGitter> <js:nil.im> btw, I see there's Int as a generic Int type, but no Int type as a generic unsigned integer type. What am I supposed to do? Just declare it e.g. UInt32?
watzon has left #crystal-lang ["User left"]
<FromGitter> <js:nil.im> I basically have a case for "It must not be negative, I don't care about the particular type, use whatever is fastest on that platform"
<FromGitter> <oprypin:matrix.org> hmm wasn't there Int::Unsigned?
<FromGitter> <Blacksmoke16> using the type to enforce non negative prob isnt the best idea
<FromGitter> <oprypin:matrix.org> js (https://matrix.to/#/@js:nil.im): for "it must not be negative" don't use Unsigned
<FromGitter> <Blacksmoke16> i've seen arguments against that in some threads and stuff
<FromGitter> <js:nil.im> oh? Why not?
<FromGitter> <js:nil.im> isn't the easiest to use a type that can't be negative?
<FromGitter> <jrei:matrix.org> unless you have only one argument
<FromGitter> <oprypin:matrix.org> the consensus is that just because your requirement happens to be ">=0" it's not a reason to use a type that happens to match that
<FromGitter> <oprypin:matrix.org> what if it was ">=1"
<FromGitter> <jrei:matrix.org> sorry was responding to a previous comment :/
<FromGitter> <js:nil.im> but that would require a lot of runtime checks rather than having it checked by the type system?
<FromGitter> <oprypin:matrix.org> > what if it was ">=1" ⏎ ⏎ .
<FromGitter> <js:nil.im> well, it's not πŸ˜‰
<FromGitter> <js:nil.im> e.g. a counter for retries
<FromGitter> <js:nil.im> or a timeout
<FromGitter> <oprypin:matrix.org> the type system will just tell you "wtf you're passing a signed integer" every time, and it's just annoying. because everything is signed
<FromGitter> <js:nil.im> both cannot be negative, but can be anything from 0..inf
<FromGitter> <js:nil.im> I see, so Crystal basically does it the same as Java?
<FromGitter> <jrei:matrix.org> the result is quite the same
<FromGitter> <js:nil.im> make everything signed, even when you don't need it, and have checks everywhere?
<FromGitter> <jrei:matrix.org> both approach results of raising at runtime
<FromGitter> <oprypin:matrix.org> js (https://matrix.to/#/@js:nil.im): yes but just by convention, not forcibly
<FromGitter> <js:nil.im> `Error: can't use Int as the type of an instance variable yet, use a more specific type`
<FromGitter> <js:nil.im> ok, that backfired anyway
<FromGitter> <js:nil.im> so, in that case then, UInt32?
<FromGitter> <oprypin:matrix.org> Int32
<FromGitter> <js:nil.im> so, if I were to just call it with 5, it would complain that I passed a signed int?
<FromGitter> <jrei:matrix.org> usually, yes. In some cast it can be autocasted
<FromGitter> <oprypin:matrix.org> js (https://matrix.to/#/@js:nil.im): a literal would be converted, but only a literal
<FromGitter> <js:nil.im> if all I do is use it internally, reading it form a file and decreasing it - is there any reason I should not use unsigned? It just feels so very wrong to use signed here πŸ˜‰
<FromGitter> <js:nil.im> also, int32 is probably too much, I guess I should go for 16
<FromGitter> <jrei:matrix.org> will it matter?
<FromGitter> <oprypin:matrix.org> because you will have a bug eventually. decreasing it past 0
<FromGitter> <watzon:matrix.org> I mean if it's not supposed to be less than zero and you do decrease it past zero you have a bug somewhere anyway, no?
<FromGitter> <js:nil.im> well, the loop will abort on 0 πŸ˜‰
<FromGitter> <oprypin:matrix.org> aha this is the comment to end them all!! ⏎ https://www.reddit.com/r/crystal_programming/comments/l5pi7d/comment/gkziv9w
<FromGitter> <oprypin:matrix.org> no you could have a loop `while i >= 0` and `i -= 1`
<FromGitter> <oprypin:matrix.org> luckily now it's an error to do that but yea...
<straight-shoota> There's no effective benefit of using unsigned or smaller integer types, so better just stay with Int32
<FromGitter> <Blacksmoke16> ah it was on reddit
<straight-shoota> well, there are some exceptions, obviously but for most regular code it doesn't make sense
<FromGitter> <watzon:matrix.org> I'd say the reason to use UInt32 would soley be if you need all 32 bits of positive integer space and don't want the extra overhead of an Int64
<straight-shoota> @Blacksmoke16 Maybe I should print that on a poster...?
<FromGitter> <oprypin:matrix.org> right
<straight-shoota> yeah, but that's a very limited use case where you have values > Int32::MAX but < UInt32::MAX
<FromGitter> <watzon:matrix.org> For instance, I use UInt32 plenty in my MTProto library I'm working on, but that's because efficiency is super important and I need that full 32 bits
<FromGitter> <jrei:matrix.org> the question then is: when to know if unsigned integers is the "perfect" fit?
<FromGitter> <jrei:matrix.org> for protocols it is indeed a good one
<FromGitter> <js:nil.im> ok, now comes the ugly part of async DNS
<FromGitter> <js:nil.im> platform-specific code to get the DNS settings
<FromGitter> <jrei:matrix.org> it saves data for the same result
<FromGitter> <js:nil.im> I suppose there is something similar to #ifdefs?
<straight-shoota> macros
<FromGitter> <js:nil.im> {% if %} I suppose
<FromGitter> <js:nil.im> ok, is there a list of platform defines?
<straight-shoota> for platform specific code you do `{% if flag?(:aarch64) %}{% end %}`
<FromGitter> <js:nil.im> I want to know the OS, e.g. Windows, UNIX, AmigaOS, etc. :)
<FromGitter> <oprypin:matrix.org> and cpu is taken from llvm target triple
<FromGitter> <js:nil.im> .has_flag?("unix") then
<FromGitter> <js:nil.im> can I have an else that aborts compilation?
<FromGitter> <js:nil.im> basically the equivalent to `#error Your platform is not supported`
<FromGitter> <oprypin:matrix.org> {% if !flag?(:unix) %}{% raise "oh no" {% end %}
<FromGitter> <js:nil.im> wait, the doc says it's a String, but now you use :unix
<FromGitter> <js:nil.im> is :unix == "unix"?
<FromGitter> <js:nil.im> in ruby they are distinct types
<FromGitter> <oprypin:matrix.org> which doc says
<FromGitter> <js:nil.im> it's also has_flag? there
<FromGitter> <js:nil.im> ahh
<FromGitter> <oprypin:matrix.org> this is compiler internals
<FromGitter> <js:nil.im> But this would fail at runtime, not at compile time, right?
<FromGitter> <oprypin:matrix.org> im just pointing out that it happens to define the available OS flags there
<FromGitter> <oprypin:matrix.org> everything within {% is compile time
<straight-shoota> this should give a list of what's used in stdlib: `grep -R -ho -P '(?<=flag\?\(:)[^\)]+' src | sort | uniq`
<FromGitter> <oprypin:matrix.org> there's a separate "hierarchy" of compile time methods
<FromGitter> <js:nil.im> if I have a @var with type Hash(String, Array(String)) and I want to clear it - is @var = Hash.new the right way?
<FromGitter> <oprypin:matrix.org> the compiletime raise happens to have the same name as the runtime raise
<FromGitter> <oprypin:matrix.org> js (https://matrix.to/#/@js:nil.im): that's fine. or there's a clear method on hash
<FromGitter> <js:nil.im> I am guessing there is no performance difference?
<FromGitter> <oprypin:matrix.org> https://crystal-lang.org/api/master/Crystal/Macros.html#raise(message):NoReturn-instance-method
<FromGitter> <js:nil.im> oh, I missed that it's `%{ raise %}`, wich the `{%%}`
<FromGitter> <oprypin:matrix.org> js (https://matrix.to/#/@js:nil.im): there is (assuming it's a bottleneck), with new you're garbage collecting the old one
<FromGitter> <js:nil.im> so I guess clear is faster?
<FromGitter> <js:nil.im> btw, in ruby, it is common to use {} for blocks and do for control. I see that Crystal often uses do for blocks as well. What's the idiomatic thing here?
<FromGitter> <oprypin:matrix.org> probably
<FromGitter> <oprypin:matrix.org> lemme pull up the thread
<straight-shoota> clear also saves an allocation
<FromGitter> <oprypin:matrix.org> agh can't find
<straight-shoota> Crystal has exactly the same block syntax as Ruby
<straight-shoota> Typical convention is to use {/} for one-liners and/or blocks that return something, otherwise do/end
<FromGitter> <oprypin:matrix.org> that's what me and the commenter think. others agree with what straight-shoota is saying :D
<FromGitter> <oprypin:matrix.org> i pretty much gave up because it's a lot of effort keeping up your own convention. so yes `do` for anything multiline
<FromGitter> <watzon:matrix.org> The only exception I have is if I'm calling a block inside of another function call
<FromGitter> <js:nil.im> hmm, there is no type for character sets in Crystal, is there? Like a whitespace character set
<FromGitter> <watzon:matrix.org> ```foo(bar { |x| ⏎ # something here ⏎ })``` [https://gitter.im/crystal-lang/crystal?at=603ecf25d2619a4f2e1b6e85]
<FromGitter> <watzon:matrix.org> But I try to keep that to a minimum
<FromGitter> <oprypin:matrix.org> js (https://matrix.to/#/@js:nil.im): no there isn't. use regex i guess
<FromGitter> <watzon:matrix.org> I mean there is `Unicode.whitespace?` and such
<FromGitter> <watzon:matrix.org> But no constants that I know of
<FromGitter> <js:nil.im> ah, too bad
<FromGitter> <js:nil.im> is 1..2 inclusie or exclusive on the 2?
<FromGitter> <oprypin:matrix.org> inclusive
<FromGitter> <js:nil.im> I suppose the same as in Ruby, but I forgot πŸ˜€ It's been a while…
<FromGitter> <oprypin:matrix.org> 1) ..2 is exclusive
<FromGitter> <js:nil.im> so, 1..2 would be just index 1?
<FromGitter> <oprypin:matrix.org> 😩
<FromGitter> <oprypin:matrix.org> what no, that's inclusive
<FromGitter> <js:nil.im> ok, so if I to String#index and I want to get the string up to there, it would be foo[0..foo.index('#') -1]
<FromGitter> <oprypin:matrix.org> yes or use ...
<FromGitter> <oprypin:matrix.org> foo[0, foo.index('#)] happens to mean the same thing too
<FromGitter> <Blacksmoke16> > hmm, there is no type for character sets in Crystal, is there? Like a whitespace character set ⏎ ⏎ if you have a `Char` type there are methods on it for that kinda stuff
<FromGitter> <Blacksmoke16> e.g. https://crystal-lang.org/api/Char.html#whitespace?-instance-method
<FromGitter> <oprypin:matrix.org> this is [index, count]
<FromGitter> <js:nil.im> Ah, thx. But it would still be foo[1, foo.size - 1], right, as I suppose that is a position, length pair and not two indices?
<FromGitter> <js:nil.im> ah, you answered that just below, nvm πŸ˜€
<FromGitter> <oprypin:matrix.org> yes
<FromGitter> <js:nil.im> can I assign a variable in an if? I want basically "if this is not nil, store it in this variable and execut this block"
<FromGitter> <oprypin:matrix.org> js (https://matrix.to/#/@js:nil.im): welp at this point i gotta say, reading all of https://crystal-lang.org/reference/syntax_and_semantics/ would be a good kickstart πŸ˜…
<FromGitter> <js:nil.im> oprypin (https://matrix.to/#/@oprypin:matrix.org): πŸ˜€ will read that, thx