ChanServ changed the topic of #crystal-lang to: The Crystal programming language | http://crystal-lang.org | Crystal 0.34.0 | Fund Crystal's development: http://is.gd/X7PRtI | GH: https://github.com/crystal-lang/crystal | Docs: http://crystal-lang.org/docs/ | API: http://crystal-lang.org/api/ | Gitter: https://gitter.im/crystal-lang/crystal
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
gangstacat has quit [Quit: Ĝis!]
gangstacat has joined #crystal-lang
darkstardevx has quit [Ping timeout: 246 seconds]
darkstardev13 has joined #crystal-lang
<FromGitter> <didactic-drunk> Is it possible to get the return type of a block in a macro?
<FromGitter> <Blacksmoke16> if there was one defined on the arg yea
<FromGitter> <didactic-drunk> Yes, that's what I want.
<FromGitter> <Blacksmoke16> id imagine you would get it like any other arg
<FromGitter> <didactic-drunk> https://crystal-lang.org/api/0.31.1/Crystal/Macros/Block.html doesn't show a return type.
<FromGitter> <Blacksmoke16> no i mean like `def.args.first.restriction`
<FromGitter> <Blacksmoke16> where you have like
<FromGitter> <Blacksmoke16> ```def some_method(& : String -> String) ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5ed70efca3a1b13679c39093]
<FromGitter> <didactic-drunk> What if it's a `map` style function?
<FromGitter> <Blacksmoke16> like `def map(&)`?
<FromGitter> <didactic-drunk> With a forwardable block
<FromGitter> <Blacksmoke16> `def map(&block)`?
<FromGitter> <didactic-drunk> https://carc.in/#/r/977b
darkstardev13 has quit [Remote host closed the connection]
darkstardev13 has joined #crystal-lang
_ht has joined #crystal-lang
_ht has quit [Remote host closed the connection]
_ht has joined #crystal-lang
skrzyp has quit [Ping timeout: 260 seconds]
skrzyp has joined #crystal-lang
alexherbo2 has joined #crystal-lang
<alexherbo2> is there an equivalent to tui-rs in Crystal?
zorp_ has joined #crystal-lang
<FromGitter> <mattrberry> Alright this might be a super specific question that y'all can't answer, but I'm gonna ask anyway. I'm so lost
<FromGitter> <mattrberry> I have a class that generates audio samples and plays them through bindings to SDL
<FromGitter> <mattrberry> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed74aeadaf4cf366edb14ab]
<FromGitter> <mattrberry> Currently, I have one channel of audio
<FromGitter> <mattrberry> The "Channel" classes are simple for math. The APU class effectively tells the Channel classes how much time has passed, and the Channel classes return a sample at that time in the form of a float32
<FromGitter> <mattrberry> Sound works. By that I mean that I am playing sounds as expected through SDL. I have separate bugs where I generate the wrong tone, but the timing and everything is fine, audio is playing fine, everything is fine
<FromGitter> <mattrberry> I then tried to add another Channel. (This fails in even the minimal case) so assume that Channel2 is defined as ⏎ ⏎ ```class Channel2 ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5ed74bb589941d051a3d734b]
<FromGitter> <mattrberry> If I then add `@channel2 = Channel2.new` to my APU class as so ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ then I can no longer play anything through SDL audio. I'm not using @channel2 for *anything*. It's just declared on the class. I'm still generating samples and passing them to SDL. However, SDL isn't playing *anything*. I have no idea how this could possible cause that to happen
<FromGitter> <mattrberry> Does anybody have *any* ideas? I'm so lost here
Human_G33k has quit [Ping timeout: 240 seconds]
<FromGitter> <mattrberry> I thought just *maybe* it was something weird with the cache, like maybe it was caching the offset to the audio buffer (which I also store as an instance variable on APU). Either way, I cleared the cache to no avail
<FromGitter> <mattrberry> I don't even know where to begin debugging this
Human_G33k has joined #crystal-lang
<jhass> mattrberry: Uh, if codegen bug I'd expect it to crash at some point for a long running program like that. Nonetheless you may be able to tip that of a bit by changing the order of instance variables, adding a dummy one in between etc
<jhass> but probably it's something in your logic or maaybe semantic
Human_G33k has quit [Ping timeout: 260 seconds]
HumanG33k has joined #crystal-lang
<raz> mattrberry: since you're using bindings, does the class perhaps do something at initialization time (the part that runs when it's merely declared)?
HumanG33k has quit [Remote host closed the connection]
HumanG33k has joined #crystal-lang
<raz> e.g. if you have `class Parent; initialize(); end` then i think A > Parent and B > Parent will both run initialize() at startup, before an instance is even created
<raz> (just a wild guess tho)
<raz> (ehm, and initialize was a terrible choice for the name there... i don't mean the ctor but just any method-call right in the call body ;))
<raz> class body*
HumanG33k has quit [Remote host closed the connection]
darkstardev13 has quit [Remote host closed the connection]
<FromGitter> <igor-alexandrov> Guys, anybody tried to generate wrapper for libvips with https://github.com/olbat/libgen?
HumanG33k has joined #crystal-lang
<jhass> ?anybody
<DeBot> Just ask your question, if anyone has, is or can, they will respond.
repo has quit [Quit: WeeChat 2.7.1]
repo has joined #crystal-lang
<raz> jhass: he asked a perfectly fine question tho :p
deavmi has quit [Quit: Eish! Load shedding.]
<jhass> how can anyone answer it though? Do you know what everybody here tried? :o
* jhass gets a sticker for his webcam
<FromGitter> <igor-alexandrov> I mean, maybe someone from this chat tried.
<raz> well true, might be more productive to describe a specific problem he's having
<jhass> that's the point :)
<jhass> maybe we can phrase the fact better
<raz> igor: are you having a specific problem or just wondering if anyone tried before?
deavmi has joined #crystal-lang
<raz> (i haven't)
<FromGitter> <igor-alexandrov> Just wondering
<jhass> why don't you just try? :)
<raz> jhass: so his question was valid. i win!
<raz> :p
<FromGitter> <naqvis> lol
<FromGitter> <igor-alexandrov> Thinking about having an image manipulation plugin for Shrine and libvips looks like a good choice
<raz> jhass: btw can recommend these little slider stickers ;) (those can be opened/closed w/o peeling them off)
<jhass> raz: not confused maybe, but not valid because it's not answerable :P
<jhass> yeah I had one but lost them
<raz> jhass: ok, i'll concede a draw. :D
<raz> igor: yes, i've heard good things about vips, can say that much (that was a long time ago tho, there might be sth even better now)
<FromGitter> <naqvis> better if apple would have come with shutter for camera, i remember Lenovo has some laptops with that functionality
<jhass> it's so weird though, so many people clobber their webcam but nobody solders a switch to their microhpone :P
<FromGitter> <naqvis> lol
<raz> and few put a sticker on their phone, ipad and all the other devices that also have cams and mics
<jhass> yeah, like with always listening chipsets
<jhass> so "Ok google" works
<raz> or hi siri
<raz> i never use any of that stuff and have it all disabled. but i'm under no delusion that law enforcement or a grumpy apple admin can turn my mics and cams on at any time
<jhass> or TSA
<jhass> you're not a person or object with any rights on the US border
<raz> i think TSA doesn't have much interest in taking selfies on your devices. they're the ones with the FileVault master key ;)
<raz> (for which admittedly there is no evidence that one actually exists, but i kinda assume the worst these days)
<FromGitter> <naqvis> better go back to old gold nokia phones :)
<jhass> I'm sure they have rootkits for those as well
<FromGitter> <naqvis> agree, privacy is always a big concern
<jhass> I mean GSM is basically broken and can be considered plaintext, so that's the problem with old phones, if they can't root them they can just use an IMSI catcher without any issues or even just passively sniff it
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
<raz> that's why it's good that crystal has 7 different chat rooms
<raz> they will never know which one to follow!
<FromGitter> <naqvis> Crystal has 7 different chat rooms? I only know gitter
<jhass> how come you know gitter but IRC? :D
<raz> jk, it's only two i think (well, and a bunch that are not in use)
<jhass> some people have some weird slack I think and then some other people have another weird slack
<raz> and matrix
<jhass> there's a matrix channel? Matrix can connect to IRC, why wouldn't they just connect here :/
<raz> i don't know, maybe it was supposed to. i don't use matrix, just saw the channel when i tried it one day
<FromGitter> <naqvis> :D
<FromGitter> <naqvis> sometime I think how hard would it be have `composite literal` construct for `Array` and `Slice`
<FromGitter> <naqvis> It will be beneficial in cases like ⏎ ⏎ 1) more compactly initialize arrays and slices if the array/slice has many zero values and just a few non-zero values ⏎ 2) skip ("jump over") contiguous parts when enumerating elements, and the skipped elements will be initialized with the zero values ⏎ 3) specify the first couple of elements, and still specify the length (max index + 1) you want the array/slice
<FromGitter> <naqvis> Golang has this feature https://golang.org/ref/spec#Composite_literals
sorcus has quit [Ping timeout: 260 seconds]
<jhass> mmh, not sure about what syntax that would use
<jhass> naqvis: amazingly this works: https://carc.in/#/r/9795
<jhass> turn it into a module and encounter a codegen bug 😂
<jhass> also only for integer values I guess :D
<FromGitter> <naqvis> wow
<FromGitter> <naqvis> awsome work
<jhass> eh, it breaks as soon as you change a thing xD
<jhass> complete feature abuse
<FromGitter> <naqvis> but it shows it can be achieved
<FromGitter> <naqvis> thanks jhass
<jhass> naqvis: maybe a bit better https://carc.in/#/r/979h
<jhass> note that all the "foo"'s in there are the same foo, which is fine for immutable's and value types, mutable references not so much
<jhass> but yeah, I don't feel like this is stdlib territory tbh
<FromGitter> <naqvis> yeah, true. but having some syntactic sugar to make it look like Array Literal would make it more like stdlib territory
<jhass> I mean scope wise
<FromGitter> <naqvis> thanks jhass, its still far better than manually setting the index values
<FromGitter> <naqvis> https://github.com/naqvis/crystal-html5/blob/master/src/html/atom/table.cr#L388 ⏎ ⏎ this was my use-case, so had to do that manual assignment
<FromGitter> <naqvis> thinking of using your solution would be cleaner i believe
<jhass> better type handling https://carc.in/#/r/979n
<jhass> still breaks on an explicit array type though
<jhass> I'm not sure, it's not even less LOC
<jhass> just less TABLE[] for more =>
hightower4 has quit [Remote host closed the connection]
<FromGitter> <naqvis> true, but atleast can remove the redundant duplication of var name
<jhass> isn't there any logic or pattern to this?
<jhass> no function that could compute 0xcb03 from 0x13a?
<FromGitter> <naqvis> aahh
<FromGitter> <naqvis> my use-case was to achieve symbol like functionality for Strings
<FromGitter> <naqvis> as that's more faster and effective than doing string manipulation and comparison
<jhass> huh, why not use symbols?
<FromGitter> <naqvis> i avoided crystal symbols as i remember seeing somewhere that they might get removed
<jhass> removed like how?
<jhass> ah you mean as a feature
<FromGitter> <naqvis> yeah
<jhass> honestly I think it's just ary hating on them
<FromGitter> <igor-alexandrov> :) Removed like they will not exist
<jhass> won't happen for 1.0 for sure
<FromGitter> <naqvis> lol
<FromGitter> <naqvis> Erlang make heavy use of symbols, but they also caution against not overusing them
<FromGitter> <naqvis> i guess that's due to overloading their symbol table
<jhass> so, what exactly is your usecase here?
<jhass> you store Atom in the AST node and then do like .name == A ?
sorcus has joined #crystal-lang
<FromGitter> <naqvis> yeah
<jhass> mmh
<jhass> it feels a bit like a usecase for https://crystal-lang.org/api/0.34.0/StringPool.html
<FromGitter> <naqvis> avoid string allocation and also integer comparisons are faster than string comparison
<jhass> you'd get a pool, push all your possible symbols (as strings) into there
<jhass> and when parsing fetch them from the pool to store into the AST node
<jhass> still have them as constants too
<jhass> just as strings, A = "a"
<jhass> then compare using a reference check
<FromGitter> <naqvis> ok that fixes string allocation issue,
<FromGitter> <naqvis> but string comparison is slower than integer comparison
<jhass> no
<FromGitter> <naqvis> i am not claiming this because i haven't done any benchmarks
<jhass> because String is a reference type
<jhass> so .name.object_id == A.object_id
<jhass> maybe just A = "a".object_id; and make a nice accessor, nameid == A
<FromGitter> <naqvis> aah, so you mean perform reference equality check?
<jhass> yeah
<jhass> which will work if you pull it from the string pool during parsing
<FromGitter> <naqvis> yeah
<raz> symbols are just consts that happen to have their own name as their value :P
<FromGitter> <naqvis> true
<jhass> their representation is an integer in fact
<jhass> but yeah, a static string is just a pointer into the data section
<jhass> so your pool would be a whole bunch of pointers into the data section
<raz> i hate them with passion mainly cause they never save me any time but always cause headache
<raz> typing { foo: "bar" } is half a split second quicker than { "foo" => "bar" }
<jhass> ah, we got https://crystal-lang.org/api/0.34.0/Reference.html#same?(other:Reference)-instance-method
<raz> debugging why one of them isn't liked in some other place of the code... hours go by fast
<jhass> I wondered where ruby's eql? went :D
<jhass> so A = "a"; pool.add(A); def is?(tag); name.same?(tag); end; node.is?(A)
<raz> it even rhymes
<raz> you can call it the namesame PR
<jhass> naqvis: and then you can macro the whole lot; TAGS = {"a", "p", ..}; {% for tag in TAGS %}; {{tag.upcase.id}} = {{tag}}; pool.add({{tag}}); {% end %}
<FromGitter> <naqvis> does StringPool uses hashes to store the entries?
<jhass> I never looked
<FromGitter> <naqvis> because in my implementation i've used FNV hash
<jhass> since it doesn't need buckets
<FromGitter> <naqvis> thanks jhass
<jhass> so just two arrays, one for hash => idx and one for idx => value
<FromGitter> <naqvis> it still traverse through whole array to find the element
<FromGitter> <naqvis> https://github.com/naqvis/crystal-html5/blob/master/src/html/atom/atom.cr#L62 ⏎ this is how i've done that Atom lookup
<jhass> no, it does not?
<jhass> index = hash & mask
<jhass> it just handles hash collisions
<jhass> which yours doesn't I think
<FromGitter> <naqvis> StringPool is generic one, mine is specific to this HTML5 specific use-case
<FromGitter> <naqvis> so hashes are fixed for HTML tags
<FromGitter> <naqvis> there won't be any collision
<jhass> idk.
<jhass> I guess you could also implement yours as a run macro that generates the table
<FromGitter> <naqvis> thanks jhass
travis-ci has joined #crystal-lang
<travis-ci> crystal-lang/crystal#ea9d9b1 (master - Minor INI improvements (#9408)): The build passed. https://travis-ci.org/crystal-lang/crystal/builds/694233012
travis-ci has left #crystal-lang [#crystal-lang]
<DeBot> https://github.com/crystal-lang/crystal/pull/9408 (Minor INI improvements)
travis-ci has joined #crystal-lang
travis-ci has left #crystal-lang [#crystal-lang]
<travis-ci> crystal-lang/crystal#70bec07 (master - Ensure `type_vars` works for generic modules. (#9161)): The build passed. https://travis-ci.org/crystal-lang/crystal/builds/694252386
<DeBot> https://github.com/crystal-lang/crystal/pull/9161 (Ensure `type_vars` works for generic modules.)
<FromGitter> <watzon> Man, having thousands of lines of generated code has made me start wishing for a more optimized compiler
<FromGitter> <didactic-drunk> Preview: https://github.com/didactic-drunk/concurrent.cr/tree/parallel_map ⏎ ⏎ ```require "concurrent/enumerable" ⏎ ⏎ (1..50).parallel.select(&.even?).map(&.to_s).to_a``` [https://gitter.im/crystal-lang/crystal?at=5ed7b989b101510b2035d1a3]
<jhass> actually I'm always amazed how fast crystal parses through with crystal-gobject spits out, which iss probably well above >100kloc
<jhass> most time really is spent in codegen, so LLVM
<FromGitter> <watzon> Even if the speed is LLVMs fault though, it can still be improved with incremental compilation and some better caching. Right now I have a couple files that contain 15000 and 5500 lines, the biggest of which is also using the `use_json_discriminator` macro, and compilation takes somewhere between 30 and 40 seconds every time. Doesn't matter if I don't change a single line of code.
<FromGitter> <j8r> @watzon you think `use_json_discriminator` is partly responsible of this?
<FromGitter> <watzon> Most likely. I don't think codegen via macros is really optimized at all, and that's what `use_json_discriminator` is doing.
<FromGitter> <giuseongit> Hi folks
<FromGitter> <watzon> The final binary when compiled in release mode is 116MB
<FromGitter> <Blacksmoke16> o/
<FromGitter> <watzon> And takes a couple minutes
<FromGitter> <asterite> I would be surprised if just use `use_json_discriminator` is what makes the code take 30 seconds to compile. Do you have some shareable code?
<FromGitter> <watzon> Sure, just a sec. I'll make a gist with the generated code.
<FromGitter> <giuseongit> can someone explain to me why I have this output? https://play.crystal-lang.org/#/r/97aj ⏎ I though that in the `inherited` macro `@type` would be the inheriting type (aka the subclass), but this not seem to be true
yxhuvud has quit [Read error: Connection reset by peer]
yxhuvud has joined #crystal-lang
<FromGitter> <asterite> > how fast crystal parses through ⏎ just note that the "Parse" time that shows up in `-s` is the time it takes to parse the initial file. All other requires are not taked into account. So the stats are broken. That said, the parser is the fastest thing in the pipeline
<FromGitter> <asterite> Error: undefined constant Proton::Client
<FromGitter> <asterite> I see a lot of duplicated code. If you refactor those into helper functions it might speed up compilation
<FromGitter> <asterite> Or maybe it's impossible, I don't know
<FromGitter> <watzon> What in specific do you see duplicated?
<FromGitter> <asterite> `res = client.send("@type" => ...)` is everywhere. But I'm not sure how I would refactor that
<FromGitter> <asterite> Anyway, I can't test how fast or slow that compiles because it's incomplete: Error: undefined constant Proton::Client
<FromGitter> <watzon> Yeah it really can't be helped as far as I'm aware
<FromGitter> <asterite> and unless you are calling all of those methods, there's no way 5k lines of code will be slow to compile. The lexer has about the same lines of code and it compiles really fast
<FromGitter> <watzon> Here's the actual repo
<FromGitter> <j8r> their are lots of macros involved in the gist
<FromGitter> <watzon> `generate_types.sh` needs to be run first
<FromGitter> <j8r> long compile time does not surprise me
<FromGitter> <asterite> where? I can't see a single macro
<FromGitter> <j8r> they are hidden with `JSON::Serializable`
<FromGitter> <watzon> Oh I forgot one file
<FromGitter> <asterite> I cloned the repo. What can I try?
<FromGitter> <watzon> That has most of the discriminators
<FromGitter> <j8r> some of this macros here https://github.com/crystal-lang/crystal/blob/48e9289f5/src/json/serialization.cr#L127 have to be expanded
<FromGitter> <watzon> @asterite unfortunately it won't build unless you have `tdlib` installed, but you can generate the types by running `generate_types.sh`
<FromGitter> <j8r> omg lots of types
<FromGitter> <asterite> I can install tdlib. What's next?
<FromGitter> <watzon> You'd have to generate the types and then attempt to run `examples/userbot.cr`. Idk if you have a telegram account, but it won't actually run without an api_id and api_hash from https://my.telegram.org
<jhass> it's not even thaat many types, crystal-gobject with Gtk easily generates several thousand
<FromGitter> <asterite> library not found for -lssl
<jhass> sounds like macos :D
<jhass> export LIBRARY_PATH=/usr/local/Cellar/openssl@1.1/1.1.1g/lib:/usr/local/lib
<FromGitter> <asterite> @watzon that file compiled in like 6.5 seconds
<FromGitter> <asterite> is that the file that takes 40 seconds? Or are you talking about --release?
<FromGitter> <watzon> No, release easily takes a couple minutes for me
<FromGitter> <watzon> You're talking about `userbot.cr`?
<FromGitter> <asterite> Yes
<FromGitter> <asterite> example/userbot.cr
<FromGitter> <asterite> how long it takes to compile *without* release?
<jhass> are you compiling in a memory constrained environment? that easily makes things slower
<FromGitter> <watzon> Nope, I have 16GB of RAM
<FromGitter> <asterite> can you show the output of `crystal build example/userbot.cr -s`
<FromGitter> <watzon> Seems to be linking that's taking a year
<FromGitter> <watzon> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7c12f3ffa6106f1f15875]
<FromGitter> <asterite> Mine is: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7c176ff7a920a722d20df]
<FromGitter> <asterite> So the initial phases seem twice as fast, maybe my machine is twice as fast, but linking takes 1.54s
<jhass> where's your cache dirs? crystal env CRYSTAL_CACHE_DIR? spinning platter or SSD?
<jhass> linking is IO intensive IME
<FromGitter> <watzon> Strange. I mean my computer isn't great, but it's not bad either. I have a Intel i5-7200U (4) @ 3.100GHz and 16GB of RAM. CRYSTAL_CACHE_DIR is in my home which is on an SSD.
<FromGitter> <asterite> Also what's the output of `echo $CC` and `cc --version`?
<jhass> Ary where's your cache?
<FromGitter> <watzon> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7c227a91f120a6cdf03e7]
<FromGitter> <asterite> /Users/asterite/.cache/crystal
<jhass> mmmh
<yxhuvud> watzon: how long do make clean && time make crystal release=1 of the crystal compiler take for you?
<FromGitter> <watzon> $CC doesn't seem to be there
<FromGitter> <watzon> Let me go fetch it and see
<FromGitter> <asterite> my cc is Apple clang version 11.0.3 (clang-1103.0.32.62)
<jhass> giuseongit: I guess the inherited macro runs before the constant is defined
<jhass> giuseongit: https://play.crystal-lang.org/#/r/97b9 this seems to workaround
<FromGitter> <watzon> yxhuvud a couple years later, it's still running lol
<yxhuvud> Yeah, takes 7.30 minutes for me
<FromGitter> <watzon> Oof
<FromGitter> <watzon> Guess I'll be here a minute
<FromGitter> <giuseongit> thanks jhass
<FromGitter> <j8r> ... do we agree that the responds_to? is useless here: https://github.com/crystal-lang/crystal/blob/master/src/json/any.cr#L140
<yxhuvud> asterite: Do you know if anyone has tried to enable mutlithreaded LLVM support?
<FromGitter> <j8r> because the value will be a Any, which always implement `dig`
<jhass> uff, it already takes so much memory, that sounds dangerous :D
<jhass> j8r: String implements dig?
<FromGitter> <j8r> Why it will return String?
<FromGitter> <j8r> it returns an `Any`, that can wrap a String yes
<jhass> >> require "json"; JSON.parse(%("foo")).class
<DeBot> jhass: # => JSON::Any - https://carc.in/#/r/97bc
<FromGitter> <j8r> Look at `dig?`, it does not use this logic
<FromGitter> <asterite> yxhuvud: I tried it and I failed
<FromGitter> <asterite> unless I don't know what you mean
<yxhuvud> There is supposed to be some LLVM_ENABLE_THREADS variable. dunno what side effects it has
<FromGitter> <asterite> Oh, I think I tried compiling different LLVM modules in different threads. I didn't know about that variable
<FromGitter> <j8r> jhass in this case, the hash value can be any type
<FromGitter> <j8r> Not in `JSON::Any`
<FromGitter> <watzon> @yxhuvud `make crystal release=1 638.12s user 6.99s system 100% cpu 10:43.96 total`
<jhass> why not?
<FromGitter> <watzon> So overall about 25-30% longer than on your machine it seems
<FromGitter> <asterite> I would try `make crystal` without release
<FromGitter> <j8r> jhass Because look at the type: `Hash(String, Any)`
<FromGitter> <j8r> and then there is `self[value]`, which returns `Any` - always
<jhass> so? the value is an Any which can be a String for example like I demonstrated
<FromGitter> <j8r> ofc
<FromGitter> <j8r> You agree, than `value`, which is `Any`, always implement `dig`
<FromGitter> <j8r> so no need to check. `dig?` for instance does not
<yxhuvud> simply setting the var seems to give invalid memory access though. Shrug.
<jhass> oh, yes I see now what you mean
<jhass> well, it does no harm
<jhass> why bother
<FromGitter> <j8r> https://carc.in/#/r/97bi
<FromGitter> <j8r> The exception even not necessary
<FromGitter> <j8r> because `self[value]` will fail before
<FromGitter> <j8r> or something inside the `if` will
<FromGitter> <j8r> not mentioning the exception is not tested (I don't know how to triger it)
<FromGitter> <asterite> At least LLVM_ENABLE_THREADS seems to be enabled for mac in llvm-config.h
<FromGitter> <watzon> @asterite without `--release` mode `make crystal 88.99s user 6.07s system 189% cpu 50.277 total`
<FromGitter> <watzon> Major difference lol
<yxhuvud> ok. Hmm. I saw some reference claiming it will still be single-threaded inside each module. Dunno what that means in terms of llvm-crystal compiler interaction.
<FromGitter> <watzon> Compiling happens so much faster when I leave out the static libraries, but with `-ldtjson` for some reason it refuses to load the shared library at runtime ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7c7c222dd444224f7c2a9]
<FromGitter> <watzon> ```code paste, see link``` ⏎ ⏎ It's definitely there [https://gitter.im/crystal-lang/crystal?at=5ed7c7e97da67d06faecff97]
<jhass> watzon: Maybe /usr/local/lib is not in your LD_LIBRARY_PATH
<FromGitter> <watzon> Looks like my LD_LIBRARY_PATH is empty... I'll add it and see if that works.
<FromGitter> <watzon> Go figure
<FromGitter> <watzon> That works
<FromGitter> <watzon> Well that should save a bit of compilation time
<jhass> check /etc/ld.so.conf or your .$SHELLrc to make it permanent :)
<jhass> common to only have /usr/lib in the default linker config these days
<FromGitter> <watzon> Yeah I just went ahead and added both to my `.zshenv` file which is being sourced in my `.zshrc` file
<FromGitter> <watzon> You can check environment variables at comptime right?
<FromGitter> <watzon> Or better, is there any way to check if the `--static` flag was passed?
alexherbo25 has joined #crystal-lang
<jhass> I think it sets flag?(:static)
alexherbo2 has quit [Ping timeout: 256 seconds]
<jhass> if not it totally should
alexherbo2 has joined #crystal-lang
<jhass> how big are those .a files btw? and are they stripped?
<jhass> if not, stripping them might help with linking speed a tad little bit, also with final binary size. It won't help with debuggability though
alexherbo25 has quit [Ping timeout: 265 seconds]
<FromGitter> <watzon> I don't know if they got stripped during the build or install process. Probably not though.
<FromGitter> <watzon> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7caf0f0b8a2053ad03db8]
<FromGitter> <watzon> Quite large, especially `libtdcore.a`
erdnaxeli has left #crystal-lang ["User left"]
<jhass> `file` can tell, `strip` can do it
<FromGitter> <watzon> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7cb83a91f120a6cdf1c5e]
<FromGitter> <watzon> So no?
<FromGitter> <watzon> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7cbaf22dd444224f7cf86]
<jhass> uh, maybe actually not for .a's :/
<FromGitter> <watzon> Oh wait, does it need sudo? Probably.
<jhass> well, it needs to write, yeah
<FromGitter> <watzon> sudo did it haha. I wasn't thinking.
<FromGitter> <watzon> Brought `libtdcore.a` down to 100463964 bytes
<FromGitter> <watzon> Huge difference ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7cc65f0b8a2053ad041b9]
<FromGitter> <Blacksmoke16> `ls -lah` :)
<FromGitter> <Blacksmoke16> *math hard*
<FromGitter> <watzon> Oh that's much better haha
<FromGitter> <watzon> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7cc8e7da67d06faed0e18]
<FromGitter> <Blacksmoke16> 👏
<FromGitter> <watzon> Love learning these shell tricks
<FromGitter> <watzon> Granted 96MB and 21MB are still massive
<FromGitter> <Blacksmoke16> `git status -sb`
<FromGitter> <Blacksmoke16> another of my favs
<FromGitter> <watzon> `## master...origin/master`?
<FromGitter> <watzon> Just showing how local branches relate to remote ones?
<FromGitter> <Blacksmoke16> condensed version of `git status`, ofc more helpful when you have changes and stuff made
<FromGitter> <watzon> Ahhhh
<FromGitter> <watzon> Yeah I'm sure haha
<FromGitter> <Blacksmoke16> just shows current branch, branch on origin, and status of each file, like added, modified etc
<FromGitter> <watzon> Yeah that is nice
<FromGitter> <watzon> Well shit, stripping seems to have fucked things up lol ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7cdfab101510b20360f96]
<FromGitter> <Blacksmoke16> 😬
<FromGitter> <j8r> libtdjson, didn't know this lib
<FromGitter> <j8r> Tower Defense JSON?
<FromGitter> <watzon> It's for telegram haha
<FromGitter> <watzon> tdlib is the c++ library they made to interact with the client api
<FromGitter> <watzon> libtdjson is the c interface which uses json for communication
<FromGitter> <watzon> Tbh I wish they would've just written the whole thing in C, or at least made a C wrapper that wraps all of the C++ functionality 1:1
<FromGitter> <watzon> Dealing with their json interface is a pain in the ass
<FromGitter> <watzon> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7cf7fa91f120a6cdf2a44]
<FromGitter> <watzon> Well that's much improved at least
<FromGitter> <watzon> Would be nice to clean up that `Semantic (main)` a bit, but this is much better than the 30+ seconds I was dealing with.
<FromGitter> <mattrberry> > *<jhass>* @mattrberry: Uh, if codegen bug I'd expect it to crash at some point for a long running program like that. Nonetheless you may be able to tip that of a bit by changing the order of instance variables, adding a dummy one in between etc ⏎ ⏎ Tried that. I also don't think it's something in my logic. I'm adding an instance variable that I'm not using, and it's causing SDL to now play audio.
<FromGitter> ... Adding `@channel2 = Channel2.new` where `Channel2` has no `initialize` method, and the `channel2` name was not previously used, should not have any effect whatsoever on anything...
<FromGitter> <mattrberry> > *<raz>* @mattrberry: since you're using bindings, does the class perhaps do something at initialization time (the part that runs when it's merely declared)? ⏎ ⏎ This is the extent of the APU `initialize` method. None of the other classes involved define `initialize` methods ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7d1c122dd444224f7df58]
<FromGitter> <mattrberry> Simply uncommenting the `@channel2 = Channel2.new` line causes SDL to not play audio, and `Channel2` is an empty class
<raz> an empty class? so it's from the binding? it must do _something_ during initialize to, or why would you have it at all? :)
<raz> (my guess would be that Channel.new overwrites something shared between the two)
<FromGitter> <naqvis> also where are you initing the SDL?
<FromGitter> <mattrberry> > *<raz>* an empty class? so it's from the binding? it must do *something* during initialize to, or why would you have it at all? :⁠) ⏎ ⏎ I've minimized the example to test if it was still breaking. It is
<FromGitter> <naqvis> isn't it require to initialize SDL?
<FromGitter> <mattrberry> SDL is initialized in the class that initializes the APU. https://github.com/mattrberry/CryBoy/blob/master/src/cryboy/motherboard.cr#L17
<FromGitter> <mattrberry> > *<raz>* (my guess would be that Channel.new overwrites something shared between the two) ⏎ ⏎ I used to have Channel1 and Channel2 inheriting from an abstract class, but I've also removed that while trying to find this bug. Channel2 is literally an empty class
<raz> hm ok, if Channel2 does not inherit from anything and doesn't execute any C binding code then... sounds like a codegen bug, hmm.
<raz> (no idea what the problem could be tho, cause Channel2.new, on a completely empty class, should merely create a small data structure for the instance in memory, not touch anything else)
<FromGitter> <mattrberry> Yeah that's exactly the source of my confusion
<FromGitter> <mattrberry> I spent a bunch of time debugging this. I've minimized the test case to what I've described, and at this point I'm entirely lost
<jhass> which platform are you on, linux?
<FromGitter> <mattrberry> Yeah, Ubuntu 18.04
<jhass> do you know if SDL spawns threads? I guess it does
<FromGitter> <mattrberry> I'd imagine that it does
<jhass> I'd be curious if https://github.com/jhass/crystal-malloc_pthread_shim/ makes things better, not worse or no difference
<jhass> note it needs unreleased crystal atm
<raz> have you tried renaming Channel2 just for giggles? (very wild guess, perhaps Channel2 is an actual class introduced by the binding?)
<raz> that seems very unlikely tho ;)
<raz> also if you want to dive very deep, could perhaps strace to see what is called in what order
<raz> (not sure if that can shed any light tho)
<FromGitter> <mattrberry> > *<raz>* have you tried renaming Channel2 just for giggles? (very wild guess, perhaps Channel2 is an actual class introduced by the binding?) ⏎ ⏎ Yep, I've tried renaming the Channel2 class and the channel2 instance variable on the APU
<FromGitter> <mattrberry> > *<jhass>* I'd be curious if https://github.com/jhass/crystal-malloc_pthread_shim/ makes things better, not worse or no difference ⏎ ⏎ Do I have to build crystal from source to use this?
<raz> hm yea, then i'm out of ideas, sorry (and these were already pretty far fetched). my knowledge of bindings approaches zero, but i agree w/ jhass on "something with threads" might be another possible breadcrumb.
<jhass> or get a nightly build, yeah
<jhass> raz: it's less something with threads and more bdwgc's hate on them :P
<raz> jhass: uh oh, never argue with the GC or he might bin you next :p
<jhass> it's still far fetched but I could imagine adding the class and instance var just changes memory layout enough for the GC to subtly wreck havoc on the memory SDL allocated
<jhass> because it triggers a GC pass at another moment or whatever
<FromGitter> <naqvis> can't we try with GC disabled?
<FromGitter> <naqvis> i believe there is a flag to disable to GC at build time
<FromGitter> <naqvis> that will rule-out the GC
<jhass> true, that might be a quicker first check
<raz> do you build with preview-MT btw, or normally?
<raz> +1 on trying w/o GC
<jhass> the options to disable are building with -Dgc_none or running with GC_NO_GC=1
<jhass> running with GC_PRINT_STATS=1 is useful to verify it indeed shuts up
<FromGitter> <naqvis> `GC_DONT_GC=1` isn't this one?
<jhass> ah, yeah maybe I don't remember
<FromGitter> <Blacksmoke16> heh, *swiper no swiping*
<jhass> mattrberry: did you follow that? :D
<FromGitter> ... the buffer I pass the pointer to with 0's. Now, with garbage collection off, this random background audio stream seems to *always* play
<FromGitter> <mattrberry> With -Dgc_none it seems to play the play sounds again. ⏎ HOWEVER: As a side note, before I ran into this bug that we're talking about, I was having another issue with SDL that I couldn't work out. Seemingly at random, *sometimes* SDL would continuously steam random audio for the entire duration of my program. I figured this was something with memory, but I couldn't figure out why, since I always initialize
<raz> is this a binding you wrote/generated yourself or using a shard?
<raz> oh n/m, i see commits from you on https://github.com/ysbaddaden/sdl.cr
<jhass> well, that seems to at least prove the theory that the GC is to blame here
<raz> so i'm guessing probably that one
<jhass> not sure why you would get the permanent noise, maybe some issue in your code that was just squashed by the GC overwriting some memory within SDL
<FromGitter> <naqvis> i would say, there might be some WeakReference somewhere, which got GCed
<FromGitter> <mattrberry> I use ysbaddaden/sdl.cr for most of my sdl bindings, but I've had to add a few https://github.com/mattrberry/CryBoy/blob/master/src/cryboy/apu.cr#L1-L5
<FromGitter> <naqvis> so it might be something code related
<jhass> naqvis: you should read the readme on my repo I linked above :P
<raz> i'm a bit surprised SDL doesnt malloc/maintain its own completely separate memory. but... this is all a bit too low level for me
<FromGitter> <naqvis> sure
johnny101 has quit [Quit: Konversation terminated!]
<FromGitter> <mattrberry> Its pointer should never change
<jhass> maybe it plays whatever's in the buffer in a loop? do you zero it after you want to stop playing?
<jhass> idk, how any of this works tbh
<FromGitter> <mattrberry> Yeah, the noise plays even when the buffer is entirely 0's
<FromGitter> <mattrberry> I believe SDL is reading the wrong memory
<raz> fwiw it might make sense to get to the bottom of the noise issue first (with GC disabled). that seems potentially easier and might solve the original issue then as well
<FromGitter> <mattrberry> > *<raz>* i'm a bit surprised SDL doesnt malloc/maintain its own completely separate memory. but... this is all a bit too low level for me ⏎ ⏎ SDL maintains it's own buffer. The call here https://github.com/mattrberry/CryBoy/blob/master/src/cryboy/apu.cr#L195 copies the pointed to buffer into SDL's own buffer
<raz> mattrberry: yea, but if you fill it with zeroes *and* GC is disabled, it sounds like (no pun intended) that's not where it actually reads from
* raz scratches head
<jhass> yeah, and I think the GC doesn't see the memory malloc'ed in a thread spawned by SDL and thus makes some good use of that same memory
<FromGitter> <mattrberry> Do you see anything incorrect with my bindings maybe?
<jhass> that's what my shard above tries to workaround, make the GC see everything
<jhass> it's a bit much and I'm too infamilar with anything SDL or even low level audio to just spot I'm afraid :(
<jhass> I only arrived at my shard above because I had something crashing and could try a ton of solutions with landing on crashes in a debugger to inspect stuff a bit
<raz> mattrberry: can you get meaningful sound to play when you write something non-zero to the buffer?
<FromGitter> <mattrberry> > *<jhass>* it's a bit much and I'm too infamilar with anything SDL or even low level audio to just spot I'm afraid :⁠( ⏎ ⏎ Yeah I'm kind of in the same boat, I'm completely lost here :/
<FromGitter> <naqvis> quick skim through code, I couldn't find any place where you are clearing the buffer?
<jhass> this is way harder, putting a breakpoint onto SDLs internals that get called several times per second is much harder to debug
<FromGitter> <naqvis> might that be the reason of gibberish sounds as buffer does contain the old data
<FromGitter> <mattrberry> > *<raz>* @mattrberry: can you get meaningful sound to play when you write something non-zero to the buffer? ⏎ ⏎ Yeah, the meaningful sound always plays, but there's sometimes background audio seemingly at random
<FromGitter> <mattrberry> > quick skim through code, I couldn't find any place where you are clearing the buffer? ⏎ ⏎ At exit?
<raz> background noise *while* the real sound plays?
<FromGitter> <mattrberry> > *<raz>* background noise *while* the real sound plays? ⏎ ⏎ Yeah.....
<FromGitter> <naqvis> you are using the same buffer to feed the audio data? right?
<raz> uff.... how would that be possible (doesn't that mean it reads from *two* buffers and overlays them?)
<jhass> mattrberry: I'm still interested in how my shard affects things for you, if you can be bothered :) Running without GC forever is not very practical anyways I guess
* raz really out on a limb here
<jhass> but yeah, it'll require crystal from source or a nightly
<raz> is it always one stereo channel = real sound, other channel = noise? (wild guess: one channel doing a proper thing, the other an uninitialized thing)
<FromGitter> <asterite> @mattrberry that looks like the SDL bindings are wrong. Then a struct size is wrong and what happens is that it overrides other local variables in the stack and leads to very strange behavior.
<FromGitter> <mattrberry> Once my buffer is full here https://github.com/mattrberry/CryBoy/blob/master/src/cryboy/apu.cr#L195, I queue it up in SDL. I believe SDL then copies it to an internal buffer. I just continue that process in a loop effectively. When my buffer is full, I just wait for SDL to play everything else in its queue, then queue up the buffer again. The call to SDL's `get_queued_audio_size` doesn't seem to acknowledge
<FromGitter> ... any background audio, but its there
<FromGitter> <mattrberry> > *<jhass>* @mattrberry: I'm still interested in how my shard affects things for you, if you can be bothered :⁠) Running without GC forever is not very practical anyways I guess ⏎ ⏎ I could give it a shot. Is there an apt package for crystal nightly? Otherwise I'll just build from source
<FromGitter> <naqvis> i would say you should clear-up the buffer before feeding new data
<jhass> we should have one for debian based somewhere...
<FromGitter> <mattrberry> > @mattrberry that looks like the SDL bindings are wrong. Then a struct size is wrong and what happens is that it overrides other local variables in the stack and leads to very strange behavior. ⏎ ⏎ I don't follow. Could you please explain?
<FromGitter> <naqvis> `@buffer.to_unsafe.clear(@buffer.size)`
sagax has quit [Ping timeout: 256 seconds]
<FromGitter> <mattrberry> > `@buffer.to_unsafe.clear(@buffer.size)` ⏎ ⏎ No luck with that
<FromGitter> <naqvis> gibberish sound still get played?
<FromGitter> <mattrberry> Yeah
<raz> well, asterite is here, it seems like the guessing game is over ;)
<FromGitter> <naqvis> then I'll vote for ary comments above :)
dostoyevsky has quit [Ping timeout: 240 seconds]
<FromGitter> <mattrberry> Thank you all for all of your help btw <3
<jhass> but I mean we should be uploading those into an APT repo somewhere
<jhass> mh, we do a docker image apparently
<FromGitter> <mattrberry> It's not in the usual crystal apt repo :/
<jhass> and a snap
<jhass> yeah, the lack of an env var here https://github.com/crystal-lang/crystal/blob/master/.circleci/config.yml#L229-L242 doesn't seem promising
<jhass> so why wouldn't we publish that into the repo, seems like low hanging fruit
<FromGitter> <naqvis> have them there
<FromGitter> <naqvis> but with `ci-XXX` tags
<jhass> there's a nightly tag
<FromGitter> <naqvis> oh yeah
<FromGitter> <didactic-drunk> @mattrberry Possibly related: I've had problems with c libraries that spawn their own threads and execute crystal callbacks. Does SDL do the same?
<FromGitter> <mattrberry> > @mattrberry Possibly related: I've had problems with c libraries that spawn their own threads and execute crystal callbacks. Does SDL do the same? ⏎ ⏎ I'm not using any of SDL's callbacks, but it spawns its own threads as far as I'm aware
<jhass> also the edge channel in https://snapcraft.io/crystal, ubuntu has snap by default, no?
<FromGitter> <mattrberry> Yeah just used that. Hate snap though lol :shrug:
<FromGitter> <mattrberry> Is there a way to make shards use that version of crystal?
<FromGitter> <mattrberry> Can I specify the crystal path?
<FromGitter> <naqvis> i guess you can
<FromGitter> <naqvis> might be try to run `crystal env` first to see
<jhass> shards should use whatever comes first in your path and is called crystal
<FromGitter> <naqvis> but cache folder should be same
<jhass> but I mean shards build is just a very thin wrapper around crystal build
<jhass> just bypass it
<FromGitter> <mattrberry> Trying to build with your shard ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7e1a9778fad0b1344edce]
<jhass> oh, ugh, I never tried linking it to a static libgc, yeah :(
<jhass> that cannot work, since it needs to dlopen libgc
<FromGitter> <mattrberry> > @mattrberry that looks like the SDL bindings are wrong. Then a struct size is wrong and what happens is that it overrides other local variables in the stack and leads to very strange behavior. ⏎ ⏎ Could you please help me understand this a little bit more?
<jhass> there's probably no sane way to bypass that with the snap, so back to building from source if you want to go down that rabbit hole
<FromGitter> <mattrberry> > *<jhass>* there's probably no sane way to bypass that with the snap, so back to building from source if you want to go down that rabbit hole ⏎ ⏎ I wouldn't know what I'm doing :/
alexherbo20 has joined #crystal-lang
<FromGitter> <mattrberry> Any other workaround you can think of? Otherwise this kind of puts a pin in my project :/
<jhass> I mean to be clear, I would expect my shard to have the same effect as disabling the GC, just not with disabled GC. It probably won't fix your background noise thingy anyways
alexherbo2 has quit [Ping timeout: 272 seconds]
alexherbo20 is now known as alexherbo2
<jhass> but no, I have no other ideas
dostoyevsky has joined #crystal-lang
<FromGitter> <mattrberry> A gameboy emulator doesn't *really* require gc, so I could almost get by without it..
<jhass> heh :D
<jhass> "hard mode emulator: finish the game before you run out of memory"
<FromGitter> <mattrberry> Just download more ram!
<jhass> amazing, https://downloadmoreram.com/ is still up
<FromGitter> <naqvis> @mattrberry `LibSDL.queue_audio 1, pointerof(@buffer), BUFFER_SIZE * sizeof(Float32)` , isn't this going to provide wrong size to SDL ?
<FromGitter> <naqvis> `LibSDL.queue_audio 1, pointerof(@buffer), BUFFER_SIZE` maybe like this?
<FromGitter> <naqvis> might worth a try to see if this solves gibberish sound issue
<FromGitter> <naqvis> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7e8d04c9b0f060d41171d]
<FromGitter> <mattrberry> `len` is number of bytes, not samples
<FromGitter> <mattrberry> So `BUFFER_SIZE * sizeof(Float32)` is needed
<FromGitter> <naqvis> but your `@buf` is of `BUFFER_SIZE`
<FromGitter> <naqvis> so how can you expect more size in that buffer?
<FromGitter> <naqvis> `@buffer = Slice(Float32).new 4096, 0_f32`
<FromGitter> <mattrberry> `@buffer` contains 4096 (BUFFER_SIZE) Float32's. Therefore, the number of bytes taken by `@buffer` is 4096 * sizeof(Float32)
<FromGitter> <naqvis> ah
<FromGitter> <Blacksmoke16> implemented a new DI feature:
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7ee98b101510b203669d4]
<FromGitter> <Blacksmoke16> can use the `auto_configure` macro to alter service arguments based on type, so in this case add the `converter` tag to all instance of the `ConverterInterface`
<FromGitter> <Blacksmoke16> versus having to do `@[ADI::Register(tags: ["converter"])]` for each one
<FromGitter> <mattrberry> Any idea if my bug described above is a known bug? Should I submit an issue? I don't even know how to properly describe that..
alexherbo24 has joined #crystal-lang
<jhass> sorry, I'm not sure what you're referring to
alexherbo2 has quit [Ping timeout: 260 seconds]
alexherbo24 is now known as alexherbo2
<FromGitter> <watzon> @Blacksmoke16 have you benchmarked your JSON serializer vs the built in one?
<FromGitter> <Blacksmoke16> not really, its prob slower tho
<FromGitter> <Blacksmoke16> sec
<FromGitter> <watzon> I'd imagine so. It would be awesome to get simdjson like speed in Crystal.
<FromGitter> <watzon> Idk how feasible it would be yet to actually use simdjson, or if it might make sense to try and port some of the code
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7ff699da05a060a4cb386]
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed7ff92778fad0b134541a4]
<FromGitter> <Blacksmoke16> not *terrible*
<FromGitter> <watzon> Yeah that's not too bad
<FromGitter> <Blacksmoke16> did the discriminator annotation work for your need?
travis-ci has joined #crystal-lang
<travis-ci> crystal-lang/crystal#1a8ea04 (master - Fix overflow checking for operations with mixed sign (#9403)): The build passed. https://travis-ci.org/crystal-lang/crystal/builds/694388775
travis-ci has left #crystal-lang [#crystal-lang]
<DeBot> https://github.com/crystal-lang/crystal/pull/9403 (Fix overflow checking for operations with mixed sign)
<FromGitter> <Blacksmoke16> internally `ASR` uses `JSON.parse` so any improvements to the default parsing logic would make it faster
<FromGitter> <watzon> I didn't end up using it. I figured out how to get `use_json_discriminator` to work.
<FromGitter> <Blacksmoke16> 👍
<FromGitter> <j8r> But bigger the object, and more depth, more important will be the difference in perf
<FromGitter> <Blacksmoke16> same for both implementations ofc
<FromGitter> <j8r> Let me think, can it make sense to have an annotation on top of the object for the descriminator
<FromGitter> <j8r> then, having `deserialize(string_or_io, to: Point | Circle)`
<FromGitter> <Blacksmoke16> is how i implemented it
<FromGitter> <j8r> That's neat, I need to look at this
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed804e47f08394226c53426]
<FromGitter> <j8r> That's exactly what I thought!
<FromGitter> <Blacksmoke16> implementation checks if `T` has the annotation, and overrides `type` argument
<FromGitter> <Blacksmoke16> to be what matched in the map
<FromGitter> <j8r> there is one constraint, IIRC
<FromGitter> <j8r> the discriminator has to be placed first
<FromGitter> <Blacksmoke16> hm?
<FromGitter> <j8r> I think that's what you have done, and stdlib of course
<FromGitter> <j8r> `%({"type": "point", "x": 1, "y": 2})` works
<FromGitter> <Blacksmoke16> oh no, it can be where ever
<FromGitter> <j8r> but not `%({"x": 1, "y": 2, "type": "point"})`?
<FromGitter> <Blacksmoke16> pretty sure either would work, in both mine and stdlib versions
<FromGitter> <Blacksmoke16> that requirement would be a non-starter for something in the stdlib imo
<FromGitter> <j8r> yep
<FromGitter> <j8r> but how can it works?
<FromGitter> <Blacksmoke16> well in my case, i already parsed the JSON, so im im just using `JSON::Any#[]`
<FromGitter> <j8r> not for building, but for deserializing
<FromGitter> <j8r> Ha
<FromGitter> <Blacksmoke16> stdlib, parses and rebuilds the obj at the same time
<FromGitter> <j8r> yeah just got it
<FromGitter> <j8r> they build it at it parses
<FromGitter> <Blacksmoke16> yup
<FromGitter> <j8r> I didn't understand at first, I thought it was the serializing logic there
<FromGitter> <Blacksmoke16> one feature i want to try and do is when you do like `Point.new` it automatically has `type` set to `point`
<FromGitter> <j8r> hum
<FromGitter> <j8r> I don't understand how having a `type` ivar is relevant in fact?
<FromGitter> <j8r> or maybe having a `class_getter` on `Point` - not sure
<FromGitter> <Blacksmoke16> prob could be a method
<FromGitter> <Blacksmoke16> setup as a virtual property
<FromGitter> <Blacksmoke16> so it gets serialized
<FromGitter> <Blacksmoke16> :shrug:
* FromGitter * Blacksmoke16 adds that to the list
<FromGitter> <j8r> I mean, it could be great to have something like `@[ASRA::Discriminator(key: "type", types: [Point,Circle])]`
<FromGitter> <Blacksmoke16> main problem is you cant access class methods at compile time to build the mapping
<FromGitter> <j8r> the macro then uses the `class_getter type : String = "point"` on `Point`
<FromGitter> <Blacksmoke16> and cant assume type is same as the key
<FromGitter> <j8r> not sure to understand, it won't be needed?
<FromGitter> <Blacksmoke16> ahh, gotcha
<FromGitter> <j8r> ```{% for t in ann[:types] %} ⏎ when T.{{ann[:key]}} then {{t}} ⏎ {% end %}``` [https://gitter.im/crystal-lang/crystal?at=5ed809577f08394226c53edc]
<FromGitter> <j8r> but it means I can't have several discriminators for a same type
<FromGitter> <j8r> not sure it is a big deal
<FromGitter> <Blacksmoke16> keeping it in the ann is prob more flexible longer term
<FromGitter> <Blacksmoke16> less keystrokes too, :shrug:
<FromGitter> <j8r> maybe, but that class_getter will be shown in the api docs
<FromGitter> <j8r> One can say `getter` and `property` too, but there won't be any valye
<FromGitter> <Blacksmoke16> default values arent shown anyway
<FromGitter> <Blacksmoke16> idt they are for class getters anyway?
<FromGitter> <j8r> true, so you will define the `type` for each subclass?
<FromGitter> <j8r> your `#new` issue is solved then
<FromGitter> <j8r> I was taking the https://crystal-lang.org/api/master/JSON/Serializable.html#use_json_discriminator(field,mapping)-macro example
<FromGitter> <j8r> in that case, no default value
<FromGitter> <j8r> In that case, I think using `class_getter` vs `getter` leads to a more simple API at the end
<FromGitter> <j8r> because list simpler than map
<FromGitter> <Blacksmoke16> hmm
gangstacat has quit [Quit: Ĝis!]
gangstacat has joined #crystal-lang
<FromGitter> <Blacksmoke16> have to think about it
_ht has quit [Remote host closed the connection]
<FromGitter> <Blacksmoke16> be nice if `try` worked in macro land
<FromGitter> <evvo> It probably is a strange question, but is there any way to overload a property type ? ⏎ I tried with the hooks, but it did not worked ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed81ad04c9b0f060d419f0e]
<FromGitter> <Blacksmoke16> maybe if you include it after the one in `User`
<FromGitter> <Blacksmoke16> otherwise `Overloader` is defining it to be nilable, then the other property overrides it again to be not
<FromGitter> <evvo> I tried that as well: ⏎ ⏎ ```class User ⏎ property age : Int32 ⏎ ⏎ include Overloader ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5ed81b42a91f120a6cdffb46]
<jhass> it works if you include it after and wrap it into macro included
<jhass> but it seems very brittle
<jhass> I'd try to find a better design
<FromGitter> <evvo> jhass, thanks - it worked with macro included
<FromGitter> <evvo> That works: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ed81c554c9b0f060d41a213]
<jhass> evvo: how about defining a wrapper macro around property in the module and let your users use that?
<jhass> and leave instance vars not defined through it alone
<FromGitter> <Blacksmoke16> whats the end goal of this?
<FromGitter> <evvo> My problem is that I want to be able to initialize objects directly, but if some of the properties that are used are not nillable that cannot happen
<FromGitter> <Blacksmoke16> that seems less than ideal
<FromGitter> <evvo> That "nillifying" is a problem on it's own
<FromGitter> <Blacksmoke16> what about all the code that relies on those not being nilable?
<FromGitter> <Blacksmoke16> what are these objects? If you have any sample code that would be 💯
<FromGitter> <evvo> Yes, sure
Human_G33k has joined #crystal-lang
HumanG33k has quit [Ping timeout: 265 seconds]
cloaked1 has joined #crystal-lang
alexherbo2 has quit [Quit: The Lounge - https://thelounge.chat]
<FromGitter> <evvo> ```return @@repositories[model.name].as(FileDatabase(model))``` ⏎ ⏎ not working - Error: expecting token 'CONST', not 'model' [https://gitter.im/crystal-lang/crystal?at=5ed8208ea91f120a6ce005ee]
<FromGitter> <Blacksmoke16> right, generics have to be known at compile time
<FromGitter> <evvo> Yes, it will create "dynamic" runtime generic
<FromGitter> <Blacksmoke16> i feel like there is a better way to do this
<FromGitter> <evvo> @Blacksmoke16 , looks interesting - I've never seen this
<FromGitter> <Blacksmoke16> do your models have some common type between them?
<FromGitter> <j8r> I doubt it will work with this class var story
<FromGitter> <Blacksmoke16> like abstract class/module?
<FromGitter> <evvo> Yes, models include certain module
<FromGitter> <Blacksmoke16> Gotcha
<FromGitter> <evvo> I'm thinking of adding a macro that will create initializer with all needed properties
<FromGitter> <evvo> However, I would prefer not to create an instance to get the type if possible
<FromGitter> <Blacksmoke16> I'm always not certain how to handle this for orms
<FromGitter> <evvo> I tried to implement it without generics, however it leads to more places that needs casting
<FromGitter> <Blacksmoke16> I.e. make all properties nilable or not
<FromGitter> <Blacksmoke16> You can do some fancy stuff with those free variables and macros
<FromGitter> <evvo> If I make them nillable, that will be wrong as well, as that will "pollute" the type that was defined. If I set all of these properties to a "default" value (for example, int types = 0), that will be wrong as well
<FromGitter> <evvo> Also setting such "default" values will create another problem - what if the value is of a specific class - this means that I will have to instantiate it and set it's values as well :D
<FromGitter> <Blacksmoke16> part of me thinks its best to define all the columns with `property!`, so they're nilable under the hood, but not when you go to use them
<FromGitter> <Blacksmoke16> other part of me thinks its better to not do that and require the model itself define an initializer to determine how it gets instantiated
<FromGitter> <Blacksmoke16> the latter is prob a bit more safe at compile time, but the former is a bit more flexible
<FromGitter> <Blacksmoke16> as you could do partial hydration of the model, like if you only selected a few fields
<FromGitter> <Blacksmoke16> idk, is tricky
<FromGitter> <evvo> `property!` might raise at runtime, unfortunately
<FromGitter> <Blacksmoke16> it also defines nilable getters
<FromGitter> <Blacksmoke16> id say majority of the time you know the value isnt going to be nil
<FromGitter> <Blacksmoke16> like the `id` for example, thats for sure not going to be `nil`, but it would be until the model is saved
<FromGitter> <Blacksmoke16> so it has to be nilable, and you wouldnt want to do `model.id.not_nil!` all the time when you actually go to use it
<FromGitter> <evvo> There might be no such keys - the ORM-ish library that I'm building is very different
<FromGitter> <Blacksmoke16> oh?
<FromGitter> <evvo> Let's say that ... ...it will be a surprise :D
<FromGitter> <Blacksmoke16> oh boy
<FromGitter> <evvo> I will publish it on GitHub, hopefully soon :D
<FromGitter> <evvo> If I add a method_missing macro, it does not complains at compile time, and, if someone forgets to add the method, it's their fault
<FromGitter> <Blacksmoke16> hm?
<FromGitter> <evvo> ```macro method_missing(call) ⏎ raise "That method is actually missing" ⏎ end``` ⏎ ⏎ This seems to allow the compiler to "allow" the method calls that might be determined for different types (which, at compile time, are "missing" the methods) [https://gitter.im/crystal-lang/crystal?at=5ed82cef89941d051a3fd536]
<FromGitter> <Blacksmoke16> wouldnt that happen anyway even w/o this macro?
<FromGitter> <evvo> No, it complains that the method is missing (and it complains for the wrong type, at the wrong place)
<FromGitter> <Blacksmoke16> mmmm ok
<FromGitter> <evvo> That probably makes sense, since at compile time both types are valid (for example, it might return User repository or Address repository), but at runtime, we actually return only one of them
<FromGitter> <Blacksmoke16> cant you use overloads to return the correct repo based on the type of the model?
<FromGitter> <Blacksmoke16> then you wont have this problem of unions
zorp_ has quit [Ping timeout: 260 seconds]
<FromGitter> <evvo> Could you show me an example ?
<FromGitter> <Blacksmoke16> Sec
<FromGitter> <evvo> Thanks
<FromGitter> <Blacksmoke16> im assuming you have some type that holds all the repos?
<FromGitter> <evvo> Yes
<FromGitter> <ErikAGriffin> Is there anywhere I can read up on the differences between #include and #extend? I don't see anything on either in the reference, other than modules 'extending self'
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/97d0
<FromGitter> <Blacksmoke16> > An include makes a type include methods defined in that module as instance methods:
<FromGitter> <Blacksmoke16> > An extend makes a type include methods defined in that module as class methods:
<FromGitter> <ErikAGriffin> Where did you pull that from?
<FromGitter> <ErikAGriffin> (Thank you btw)
<FromGitter> <evvo> Thanks @Blacksmoke16 - I will look into it
<FromGitter> <ErikAGriffin> Interesting. When I used the reference's search bar in the top left, "include" returned no results and "extend" only showed the result I referenced about extending self
<FromGitter> <Blacksmoke16> np
<FromGitter> <Blacksmoke16> at least shows the concept, i didnt think too much of how it plays into the design
<FromGitter> <Blacksmoke16> like how repos are created etc
<FromGitter> <ErikAGriffin> So I'm trying to learn about the `Log` api. In my main I have the following ⏎ ⏎ ```Log = ::Log.for "main" ⏎ p Log.context``` ⏎ ⏎ As soon as I add that second line of code, the line above produces the following compiler error: ... [https://gitter.im/crystal-lang/crystal?at=5ed8322022dd444224f8e69e]
<FromGitter> <Blacksmoke16> try doing `LOG =` not `Log = `
<FromGitter> <ErikAGriffin> That produces `Undefined constant ::Log`
<FromGitter> <ErikAGriffin> Also that example instantiation is pulled directly from the api docs
<FromGitter> <Blacksmoke16> well ofc update your second line to match
<FromGitter> <ErikAGriffin> ? No it produces that for the first line ⏎ ⏎ ```LOG = ::Log.for "main" ⏎ p LOG.context``` [https://gitter.im/crystal-lang/crystal?at=5ed832a2ff7a920a722e4dd3]
<FromGitter> <Blacksmoke16> did you `require "log"`?
<FromGitter> <ErikAGriffin> I see that may be it. Also the fact that I'm in the Program scope, I think the example from the API docs is for a module and so `::Log` is the program scope log and the `Log` is the `Module::Log`
<FromGitter> <ErikAGriffin> I completely missed that their examples had require "log" *facepalm*
<FromGitter> <Blacksmoke16> well done :p
<FromGitter> <ErikAGriffin> Not all of the standard library requires a `require` statement, is it simply habit that teaches one which ones are default or not? Or is there a list somewhere describing
<FromGitter> <Blacksmoke16> anything that isnt in https://github.com/crystal-lang/crystal/blob/master/src/prelude.cr
<FromGitter> <ErikAGriffin> awesome thank you
sagax has joined #crystal-lang
<FromGitter> <evvo> @Blacksmoke16 , very nice - neat use of macro to generate the variadics of the repositories
<FromGitter> <Blacksmoke16> mhm
<FromGitter> <evvo> Works perfectly - thanks
<FromGitter> <Blacksmoke16> np