ChanServ changed the topic of #crystal-lang to: The Crystal programming language | http://crystal-lang.org | Crystal 0.33.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
alexherbo2 has quit [Ping timeout: 260 seconds]
<FromGitter> <Blacksmoke16> actually i might need that `next 2`...
<FromGitter> <Blacksmoke16> er nvm maybe not
<FromGitter> <watzon> Hmm
<FromGitter> <watzon> Any idea @Blacksmoke16? https://carc.in/#/r/8lud
<FromGitter> <watzon> I haven't run nested macros like this before
<FromGitter> <Blacksmoke16> idt you can
<FromGitter> <watzon> No? Shit.
<FromGitter> <Blacksmoke16> well at least not within another macro like that
<FromGitter> <Blacksmoke16> the inner macro would have be be placed by the outer macro
<FromGitter> <Blacksmoke16> if that makes sense
<FromGitter> <watzon> Well they don't really need to be macros anyway. Just figured I might get a little runtime speed boost.
<FromGitter> <watzon> You can define a macro inside of a macro though, right?
<FromGitter> <watzon> Guess not haha
<FromGitter> <Blacksmoke16> should be able to have the one macro place down the other
<FromGitter> <watzon> How?
<FromGitter> <Blacksmoke16> like
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5e5091ddc2c73b70a44ece67]
<FromGitter> <watzon> I'll just go with defs and worry about optimizing later haha
<FromGitter> <watzon> https://carc.in/#/r/8lv0
<FromGitter> <Blacksmoke16> okey dokey
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/8luy hmm is this expected?
<FromGitter> <Blacksmoke16> i suppose it makes sense, but wouldnt it work since the actual class that get passed in would be comparable?
<FromGitter> <watzon> Hmm idk
<FromGitter> <Blacksmoke16> oh wait, it works if i do it the other way
<FromGitter> <Blacksmoke16> `v.type <= HTTP::Request`
<FromGitter> <Blacksmoke16> that way it cant be a union so πŸ‘
postmodern has joined #crystal-lang
<postmodern> if you can't add methods to a C struct, is the preferred way to wrap the struct in a class?
<FromGitter> <watzon> Yeah generally you'll have the C library wrapper and then you'll wrap it again using Crystal structs and classes
<postmodern> how would you pass the struct as a pointer to the wrapper class, that way you prevent passing by value constantly
<FromGitter> <Blacksmoke16> `pointerof(struct)`?
<postmodern> guess that wouldn't forward any method calls to the struct? i'd have to somehow cast the pointer back to my struct type?
<FromGitter> <Blacksmoke16> :shrug:
<postmodern> why doesn't crystal have an alias_method macro?
<FromGitter> <watzon> Because the maintainers are against any form of unnecessary duplication
<postmodern> ah ha, thought it was a philosophical thing
<FromGitter> <watzon> It's pretty easy to make your own though
<FromGitter> <watzon> I've got an example
<FromGitter> <tenebrousedge> aren't there some subtle bugs to watch out for, though?
<FromGitter> <tenebrousedge> I feel like that was also part of the github issue discussion
<FromGitter> <watzon> There's probably a better way to do this. I've learned a bit since I wrote it.
<FromGitter> <watzon> @tenebrousedge not that I know of, but maybe
<FromGitter> <watzon> Mainly it's philisophical
<FromGitter> <tenebrousedge> when `alias_method` was part of Crystal, it couldn't handle methods with blocks
<FromGitter> <watzon> Hmm maybe a macro limitation from those dats
<FromGitter> <watzon> You should be able to now, no problem
<postmodern> does crystal have a better way of doing ruby select->maps? some kind of dynamic array builder method?
<FromGitter> <tenebrousedge> there is an array.build
<FromGitter> <tenebrousedge> is there some specific code you're trying to optimize?
<postmodern> tenebrousedge, iterating a four element array, selecting C struct elements based on a type enum, then wrapping the C struct element. Feels like doing a select { }.map { } would be a bit wasteful.
<FromGitter> <tenebrousedge> maybe `compact_map` and return `nil` for the ones you don't want to munge
<FromGitter> <watzon> There's also reduce
<FromGitter> <tenebrousedge> `reduce` can be used to write all other higher-order iterators, but I'd pick a more specialized iterator given the option
<FromGitter> <watzon> Any idea of the best way to handle a loop like this C loop? ⏎ ⏎ ```uint32_t Nk = 8, Nb = 4, i = 0 ⏎ for (i = Nk; i < Nb * (Nr + 1); ++i) { ⏎ // ... ⏎ }``` [https://gitter.im/crystal-lang/crystal?at=5e50a75514b4d670a33dfe1a]
<FromGitter> <watzon> It's a little more complicated than a `nk.upto(nb)`
<FromGitter> <tenebrousedge> is it?
<FromGitter> <tenebrousedge> what's `Nr` ?
<FromGitter> <tenebrousedge> you could write a `while` loop
<FromGitter> <tenebrousedge> I'm always tempted to wrap those in `Iterator`
<postmodern> does crystal not have a for loop primitive?
<FromGitter> <tenebrousedge> for loops are icky
<FromGitter> <watzon> Not outside of macros
<FromGitter> <watzon> While loops to handle stuff like this are ickier imo
<FromGitter> <watzon> They end up looking terrible
<postmodern> idk maybe would be nice to have some kind of legacy module full of macros to help with porting nasty C code
<FromGitter> <tenebrousedge> @watzon well what's `Nr` there? does it actually vary?
<FromGitter> <watzon> `Nr` doesn't, but `i` does
<FromGitter> <watzon> Here's the actual C
<FromGitter> <tenebrousedge> `(8..(4*15)).each do |i|`
<FromGitter> <watzon> Will that be the same thing?
<FromGitter> <tenebrousedge> it's doing `++i` so you may want to add one to each side, assuming that I know how `++` works in C
<FromGitter> <watzon> `++i` is really just an optimization thing
<FromGitter> <tenebrousedge> but the middle term is a constant value there
<FromGitter> <tenebrousedge> it looks like the c code reuses `i` as an index name for both loops
<FromGitter> <tenebrousedge> I suppose I can see why one would do that
<FromGitter> <watzon> It's weird to me that this works in C
<FromGitter> <tenebrousedge> why?
<FromGitter> <watzon> ```tmp = sub_word(tmp << 8 | tmp >> 24) ^ RCON[(i - 1) / Nk];```
<FromGitter> <watzon> This
<FromGitter> <watzon> Because `(i - 1) / Nk` should be a float
<FromGitter> <watzon> And you're using that to access an index
<FromGitter> <watzon> Doesn't compile in Crystal
<FromGitter> <tenebrousedge> I'm not a big C expert, but are you sure that's a float?
<FromGitter> <watzon> Maybe not. Tbh idk, just seems like it should be.
<FromGitter> <watzon> But since Nk is a `uint8_t` maybe not
<FromGitter> <watzon> Also in Crystal `key[4 * i].to_u32 << 24` overflows
<FromGitter> <tenebrousedge> where is that?
<FromGitter> <tenebrousedge> oh I see
<FromGitter> <watzon> Maybe it's supposed to overflow :shrug:
<FromGitter> <watzon> But that wouldn't make much sense
<FromGitter> <watzon> C is weird
<postmodern> hmm doesn't look like you can define spectator "it" specs within an .each block? suppose I need to use a macro
<FromGitter> <watzon> Yeah. I think `it` specs create a `def`, so a macro would be the way to go.
<FromGitter> <watzon> `{% for i in SOME_CONST %} ... {% end %}
<postmodern> hmm .map(&->Operand.new) doesn't do what i expected it to do. isn't there a quick way to convert a an other classes class-method to a proc?
<FromGitter> <tenebrousedge> usually you need to supply some type after `new`
<FromGitter> <tenebrousedge> `[1,2,3].map(&->Operand.new(Int32))`
<FromGitter> <watzon> Yeah I'd think that would work
<FromGitter> <watzon> It's a little different than the Ruby way
<postmodern> odd way of doing that
<FromGitter> <tenebrousedge> no, because overloading is a thing
<postmodern> ah ha
<FromGitter> <watzon> Exactly
<FromGitter> <watzon> Now if I could just figure out why this shit is overflowing
<FromGitter> <watzon> It shouldn't be as far as I can see
<postmodern> note that ++i and i++ are different in C
<FromGitter> <tenebrousedge> someone said that <___<
<FromGitter> <watzon> From what I understand the difference in this case is mainly under the hood and shouldn't affect the actual values
<FromGitter> <watzon> It's more of an optimization thing afaik
<postmodern> you could objdump -d the library and see what the assembly looks like for that for loop
<postmodern> probably some weird implicit type conversion going on
<FromGitter> <watzon> Ahh you know what, the overflow isn't an integer overflow
<FromGitter> <watzon> It's overflowing outside the array bounds
<postmodern> oops. did academics write this C code?
<FromGitter> <watzon> Lol I don't think so. I think there's just a problem in my code conversion though.
<postmodern> can macros run commands or include the contents of files? think i can do something clever and in-line the output of yasm into my specs
<FromGitter> <tenebrousedge> yes
<postmodern> do people general prefer make or cake for project tasks?
<FromGitter> <watzon> Macros, much like C macros, are for code generation. You can actually take a String and convert it into code.
<FromGitter> <watzon> I try not to use either, but I suppose cake is nice. I think it installs a binary when you add it as a project dependency.
<FromGitter> <watzon> If not, it should. Ameba does.
<FromGitter> <tenebrousedge> I prefer a poke in the eye with a sharp stick to either
<FromGitter> <watzon> Ok so this is so weird. This works: ⏎ ⏎ ```0_u32.upto(nk - 1).each do |i| ⏎ puts key[4 * i + 3] << 24 ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5e50b353b662483a8759009f]
<FromGitter> <watzon> I don't get why, because the left shift shouldn't be changing the index
<FromGitter> <watzon> Nvm, I thought the first one worked. It doesn't.
<FromGitter> <watzon> I guess the problem is with my loop. It's going too high.
<FromGitter> <watzon> Just love finding a solution and feeling so damn stupid πŸ˜‚
<FromGitter> <tenebrousedge> o.o
<postmodern> weird that Array#shift can raise an IndexError but #shift? will return nil
<postmodern> hmm no block_given?. Do you define one method which yields, then overload it with another that ignores the block?
<FromGitter> <tenebrousedge> but generally yes, it's solved with overloads
<FromGitter> <watzon> Yeah overloads are the way to go ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5e50bfd3c2c73b70a44f2ab9]
Nilium has joined #crystal-lang
<postmodern> so ptr[0] dereferences the a single pointer value?
<postmodern> is it possible to access C struct fields via a pointer, a la `ptr->i` from C
<FromGitter> <watzon> You mean for when a C function returns a struct pointer?
<FromGitter> <watzon> You can do `Pointer#value` to get the value that the pointer is pointing to
<postmodern> i kind of want to avoid excessive copying to value
<FromGitter> <watzon> This is what I typically do
<FromGitter> <watzon> Idk if there's a better way or not, but it works
<FromGitter> <bew> Iirc you can do `LibFreetype.FT_Init_FreeType(out library); library` here
<FromGitter> <bew> @watzon ☝️
<postmodern> watzon, Pointer#malloc gets GCed I assume?
<FromGitter> <watzon> Ahh yeah, I forgot about the `out` thing. Didn't know about it at all when I wrote this.
<FromGitter> <bew> And yes Pointer#malloc is tracked by the gc
<postmodern> is `asm` a function/keyword? seems to cause issues with spectator
<FromGitter> <watzon> I believe it's a keyword
<FromGitter> <watzon> For inline assembly
alexherbo2 has joined #crystal-lang
<FromGitter> <watzon> Should these two functions not be exactly the same? ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5e50d574dafa3029f6473af1]
<FromGitter> <watzon> Fuck. The Crystal one is returning a `UInt8`
<postmodern> is there a way to tell crystal to unroll loops at compile time? like say i want to convert an enum into a lookup table of enum element => Symbol, at compile time?
<FromGitter> <watzon> Yep you can do that. `YourEnum.constants` inside of you macro will give you a list of the enum's values. Idk off the top of my head how you'd make the hash, but I know you can.
<postmodern> siiiick
<FromGitter> <watzon> Actually did something similar here
<FromGitter> <watzon> But that's just making an array. The `"Tourmaline::UpdateAction::" + c.stringify` is necessary because `.constants` only returns the constant name, not the full path.
<postmodern> hmm how do you read ASCII binary data with File.read?
<postmodern> US-ASCII is still giving me `Caused by: Invalid multibyte sequence`
<FromGitter> <watzon> That one I don't know. @bew might if he's still around, but iirc US-ASCII is a Ruby specific thing. I remember needing it before while porting a library and looking it up.
<postmodern> where can i see the list of encodings?
ua has joined #crystal-lang
<FromGitter> <bew> Hmm no idea, string encoding is managed by the iconv lib, you can find the list of encoding on there website i guess
<FromGitter> <watzon> That should cover it
<FromGitter> <watzon> Weird, it does mention US-ASCII
<FromGitter> <watzon> So maybe what you're trying to decode isn't valid US-ASCII encoding @postmodern. Given the error that would actually make sense.
<postmodern> watzon, it's assembly output
<FromGitter> <watzon> Hmm
<postmodern> so probably more accurately "bytes"
<postmodern> hmm also having issues with doing a for loop macro inside { }. Complaining about me adding , on the end of the for loop output line
<FromGitter> <bew> Share some code with us (:
<FromGitter> <watzon> I feel like that should work...
<FromGitter> <watzon> Ahh wait
<FromGitter> <watzon> https://carc.in/#/r/8lvy
<FromGitter> <watzon> There you go
<postmodern> > 5 | Type::R_AL => :"al",
_ht has joined #crystal-lang
<postmodern> hmm that should work. doing {{ element.id }} => :{{ element.stringify.gsub(...) }}
<postmodern> ahh {% begin %}
<postmodern> RE my ASCII issue, it's failing in <crystal>/share/crystal/src/iconv.cr:68:9 in 'handle_invalid'
<postmodern> and the string i'm trying to read is \x90\x90\xC3
<postmodern> File.read(File.join(ROOT,name),"US-ASCII")
<postmodern> dang, looks like i can't invoke spectator expects() from within a yielded closure
<postmodern> wait nm
_ht has quit [Remote host closed the connection]
<FromGitter> <watzon> Anyone want to help me convert this to Crystal? ⏎ https://github.com/pyrogram/tgcrypto/blob/master/tgcrypto/aes256.h#L32
<FromGitter> <watzon> I'm at my wit's end lol
<FromGitter> <watzon> As far as I can tell it's basically just accessing the value at the given pointer. I'm not using pointers, so I just pass in an array and a index, access the value at the given index, and call swap on it. But I'm getting some *very* slightly different values than the C code gives
<FromGitter> <watzon> So far I've got this ⏎ ⏎ ```def get(p, i = 0) ⏎ swap((p.to_unsafe + i).as(UInt32*)[0]) ⏎ end``` ⏎ ⏎ and it's so so so close, but still not quite there [https://gitter.im/crystal-lang/crystal?at=5e50f71ca0aa6629f5e54efd]
ur5us_ has joined #crystal-lang
ur5us_ has quit [Ping timeout: 240 seconds]
<postmodern> how do you define a multi-dimension array?
<postmodern> in a C struct, that is
return0e has joined #crystal-lang
return0e_ has quit [Ping timeout: 260 seconds]
HumanGeek has joined #crystal-lang
Human_G33k has quit [Ping timeout: 258 seconds]
<postmodern> also odd that you can't define enum elements starting with a _
alexherbo26 has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 268 seconds]
alexherbo26 is now known as alexherbo2
<postmodern> if you pull in a shard, will it's dependencies also get pulled in as well?
alexherbo23 has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 240 seconds]
alexherbo23 is now known as alexherbo2
return0e has quit [Remote host closed the connection]
<FromGitter> <Blacksmoke16> Yes
return0e has joined #crystal-lang
return0e has quit [Ping timeout: 258 seconds]
return0e has joined #crystal-lang
return0e has quit [Read error: Connection reset by peer]
return0e has joined #crystal-lang
return0e has quit [Ping timeout: 258 seconds]
return0e has joined #crystal-lang
return0e has quit [Read error: Connection reset by peer]
return0e_ has joined #crystal-lang
<FromGitter> <dscottboggs_gitlab> @watzon what is the type of `p` in this case? Is it a `Pointer(UInt32)` or `Slice(UInt32)`? Or some other type which returns a `UInt32*` in response to `#to_unsafe`? ⏎ ⏎ Additionally, is there any chance `#as` is having a side effect here? What happens if you change it to `#unsafe_as`? ⏎ ⏎ Side note, I found it slightly confusing that you indexed the pointer instead of using `#value` but I
<FromGitter> ... guess that's just a style thing. [https://gitter.im/crystal-lang/crystal?at=5e514c968e726c7dc5bef5f3]
<FromGitter> <dscottboggs_gitlab> postmodern, I think a two-demensional C-array would be a `Pointer(Pointer(ValueType))`. Or is it statically defined how many of each dimension there is?
<FromGitter> <dscottboggs_gitlab> doesn't look like we can do StaticArray in libs? https://carc.in/#/r/8lxj
wakatara has joined #crystal-lang
<postmodern> dscottboggs_gitlab, it's statically defined as uint8 foo[2][24]
<FromGitter> <dscottboggs_gitlab> fack
<FromGitter> <Blacksmoke16> @watzon you'll appreciate this
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5e51502ab662483a875a5eeb]
<FromGitter> <Blacksmoke16> resolves services of a given type at compile time
<FromGitter> <Blacksmoke16> where the type is provided at runtime
<FromGitter> <Blacksmoke16> via free vars
<FromGitter> <Blacksmoke16> handles parent types, and module types
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5e51508adafa3029f64850b3]
<FromGitter> <Blacksmoke16> example debut output
<FromGitter> <Blacksmoke16> of `T` and `services`
<FromGitter> <Blacksmoke16> guess i finally found a use for `TypeNode#instance` ha
<FromGitter> <dscottboggs_gitlab> @postmodern is that 24 pairs or 2 sets of 24?
<wakatara> I am scratching my head over what should be a simple recursive function. I think it is perhaps something I do not get about ES6. Sure it's a "oh, it's this" type anser, can someone take a quick boo?
<wakatara> I have a gist. I do not get why it is not returning the correct answer. :-/
<FromGitter> <tenebrousedge> why are you using `sort`?
<wakatara> tenebrousedge: lexographic double checking. Eventually this gets used in a frequency array to make a single base over a very large DNA sequence. It is just defensive programming.
<postmodern> dscottboggs_gitlab, 2 rows of 24 elements. I suppose I could either define two fields of 24, or one field of 2 * 24
<wakatara> (in case someone re-declared the base pairs out of order at some point in the future.
<FromGitter> <tenebrousedge> wakatara you're returning 0 for the base case, which is going to make that entire term zero
<FromGitter> <dscottboggs_gitlab> @postmodern yeah I think that's the only type-safe way to go about it here. For example https://carc.in/#/r/8lxm
<wakatara> tenebrousage: that should be the final call for the function and what I was hoping returned a zero to the recursed function. But yeah, I know this approach works in python or similar, I am reimplmenting in js to make sure I understand all the algos. But I am hardly an expert in js.
<FromGitter> <tenebrousedge> so what is the output supposed to be, and what are you getting instead?
<wakatara> tenebrousage: Sorry, I meant the terminal function should return 0 to the "last" recursive call I would have thought. So, yeah, I do realize it is overriding all returns, rather than the third one made by the function (which obviously mens I don't understand return that well in js.)
<wakatara> Tenebrousage: the function should recurse to give a 003 which I'd then convert to the integer 3. The output is in comment at the bottom.
<wakatara> tenebrousage: It peels the last base, converts that and then recurses down the stack returning the value to the first retiurn (I would have thought) not returning 0 in total.
<FromGitter> <tenebrousedge> wakatara why should this be recursive?
<wakatara> tenebrousage: So, if I look at an example of a recursive factorial expression in js, it is similarly formed, the terminal condition does not override the value of the rursive return. :-/
<wakatara> tenebrousage: It is vastly more efficient recursively when used with a frequency array.
<wakatara> example a pattern of 9 bases has 4^9 combos to check. If you sort lexographically you can create an index and then just count the occurrences with one pass through the genome rather than sliding a 9 base window each base position.
<wakatara> tenebrousage: The answer of 3 is if the bases were AAT. 3. 3 + (4 * 0) + (4 * 0) for the three passes.
<wakatara> I guess my real question is why is js/node returning a 0 for the last recursive call that overrides the previous values?
<FromGitter> <tenebrousedge> because `indexOf("A") == 0`
wakatara has left #crystal-lang ["ERC (IRC client for Emacs 26.3)"]
<FromGitter> <tenebrousedge> maybe you want to add these numbers as strings instead, but I tend to doubt it
gangstacat has quit [Quit: Ĝis!]
gangstacat has joined #crystal-lang
<FromGitter> <tenebrousedge> honestly I think you can do ⏎ ⏎ ```parseInt([...input].reduce((memo, e) => memo + bases.indexOf(e).toString(), ""), 4)``` [https://gitter.im/crystal-lang/crystal?at=5e5158566053e67dc4dbde6e]
<postmodern> does crystal support mass assignment of nested struct fields? x.foo = {1,2,'A',"Foo"}?
<FromGitter> <636f7374> #8435
<DeBot> https://github.com/crystal-lang/crystal/issues/8435 (HTTP::WebSocket.run automatically Ping reply / Close as an option)
<FromGitter> <636f7374> How to implement WebSocket automatic ping? Use fiber? I don't think it's time to wait for the official Crystal, this problem has been for some time.
<FromGitter> <636f7374> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5e515b4ad97c107ed26c2fad]
<FromGitter> <636f7374> Currently Crystal HTTP :: WebSocket (Client) does not support automatic ping.
<FromGitter> <636f7374> I need to study how to implement this feature, I don't like the long wait.
<FromGitter> <636f7374> Especially in such an important feature.
<postmodern> is there a guide on preferred shard naming conventions?
<postmodern> like if i make a shard which adds stuff to LibC should it be called foo.cr, crystal-foo, or libc-foo?
<FromGitter> <tenebrousedge> none of the above?
<FromGitter> <tenebrousedge> I'd be tempted to call it `crib`
<FromGitter> <tenebrousedge> or maybe `ceeceearr`
return0e_ has quit [Remote host closed the connection]
return0e has joined #crystal-lang
return0e has quit [Remote host closed the connection]
<FromGitter> <andrewc910> Can child classes be passed into methods where the type is a parent class? IE: method defines type string, you pass in a class that inherits from string.
<FromGitter> <Blacksmoke16> yes
<FromGitter> <Blacksmoke16> i wouldnt actually inherit from stdlib primitive types tho
<FromGitter> <tenebrousedge> @Blacksmoke16 why?
<FromGitter> <Blacksmoke16> because you cant inherit from String anyway iirc
<FromGitter> <tenebrousedge> weird
<FromGitter> <Blacksmoke16> plus most of the time there's a better implementation
<FromGitter> <andrewc910> Just used as an example. Thanks!
<FromGitter> <Blacksmoke16> hmm https://play.crystal-lang.org/#/r/8lyw
<FromGitter> <Blacksmoke16> @dscottboggs_gitlab @watzon https://github.com/crystal-lang/crystal/issues/8835 if you have any opinions/thoughts
return0e has joined #crystal-lang
sz0 has quit [Quit: Connection closed for inactivity]
dadada has joined #crystal-lang
dadada has left #crystal-lang [#crystal-lang]
wakatara has joined #crystal-lang
<FromGitter> <christopherzimmerman> Finally here! ⏎ ⏎ ```#<ClTensor(Float64):0x7ff90369be70> ⏎ Tensor([[0 , 2.5], ⏎ [5 , 7.5]])``` [https://gitter.im/crystal-lang/crystal?at=5e518414dafa3029f648e92d]
<FromGitter> <wakatara> Does anyone have any particularly strong examples of solid, small cli apps in Crystal they can point me at? I'm thinking of redeveloping 3 diff small apps to get my toes more than wet and could use some "best examples" to help me out before starting.
<FromGitter> <tenebrousedge> @christopherzimmerman :plus1: super impressive
<FromGitter> <636f7374> After solving the problem of automatic pong for WebSocket, I will temporarily suspend Crystal, switch to Rust, and research smoltcp & TUNTAP & IPsec.
<FromGitter> <watzon> @Blacksmoke16 nice RFC πŸ‘
<FromGitter> <watzon> Added a comment
<FromGitter> <watzon> @christopherzimmerman got opencl working?
<FromGitter> <Blacksmoke16> seems @asterite already made a PR xD https://github.com/crystal-lang/crystal/pull/8836
<FromGitter> <Blacksmoke16> <3
<FromGitter> <watzon> @postmodern I'd say it depends. If it's just a direct wrapper over a library and not adding much functionality on top of it I'd make sure to use the name of the library in the title so people know what it is. Like for my libfreetype wrapper I called it freetype.cr. If you're extending the C library I'd say call it whatever you want πŸ€·πŸ»β€β™‚οΈ
<FromGitter> <watzon> Damn @asterite is on fire haha
<FromGitter> <watzon> Oh boy
<FromGitter> <christopherzimmerman> Yea, opencl is pretty much done, just need to go through and write the bindings for the clblas and stuff for linear algebra, but custom kernels work great.
<FromGitter> <christopherzimmerman> My graphics card doesn't have enough VRAM to really benchmark stuff well, but it's still neat to use
<FromGitter> <watzon> That's awesome man. Very good work on all of this. I'm going to have to look through my projects and see where I'm using Apetite and swap it out for Bottle. I think my Cadmium/GloVe library will benefit heavily from OpenCL integration.
<FromGitter> <watzon> It's kind of annoying that I can do this: ⏎ ⏎ ```val = ( ⏎ (x * 3) ⏎ ^ (x * 4) ⏎ ^ (x * 5) ⏎ )``` [https://gitter.im/crystal-lang/crystal?at=5e519cfc0c4514126682a8b9]
<FromGitter> <watzon> The compiler should be smart enough to figure that out
<FromGitter> <Blacksmoke16> @watzon ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ :0 [https://gitter.im/crystal-lang/crystal?at=5e519e2d89f30b126523f150]
<FromGitter> <Blacksmoke16> :S
<FromGitter> <watzon> Ooooh
<FromGitter> <Blacksmoke16> the possibilities are endless
<FromGitter> <watzon> Just noticed there's no `Hash.build` or anything
<FromGitter> <watzon> There's a version of `Hash.new` that takes a block, but that's different
<FromGitter> <tenebrousedge> what do you need that for?
<FromGitter> <watzon> Could be nice for dynamically building a Hash the same way you would an Array
<FromGitter> <tenebrousedge> I usually just use `to_h`
<FromGitter> <watzon> For instance: ⏎ ⏎ ```Hash.build(some_arr.size) do |hash, i| ⏎ hash[some_arr[i]] = some_arr[i].camelcase ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5e51a1a6a0aa6629f5e70b48]
<FromGitter> <watzon> Sure you could map over the Array, create a new Array of key value pairs, and then use `to_h`. But not only does that overcomplicate things and make for less readable code, it also performs unnecessary allocations in the middle.
<FromGitter> <tenebrousedge> looking at Array.build ⏎ ⏎ ```def self.build ⏎ yield (h = Hash(K, V).new) ⏎ h ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5e51a3478b2d4664ef1bf399]
<FromGitter> <tenebrousedge> basically the same thing as `tap`
<FromGitter> <tenebrousedge> ```Hash(String, Int32).new.tap do |h| ⏎ h.frobnicate ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5e51a41aff00c664eedd0d62]
<FromGitter> <tenebrousedge> @watzon what's the difference there? what does the class method get you?
<FromGitter> <watzon> Yeah probably pretty similar. I'm actually not a huge fan of `Array.build` the way it is now. With `Hash.build` I can't see any reason why the `Hash(K, V).new` part would be necessary though. It should be able to just point to the internal buffer. Basically I'm imagining something like this: ⏎ ⏎ ```def self.build(capacity, &block : Hash(K, V) ->) ⏎ hash = new ⏎ end```
<FromGitter> <watzon> Yeah probably pretty similar. I'm actually not a huge fan of `Array.build` the way it is now. With `Hash.build` I can't see any reason why the `Hash(K, V).new` part would be necessary though. It should be able to just point to the internal buffer. Basically I'm imagining something like this: ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ Basically it comes down to convenience and readability
<FromGitter> <watzon> You're right though, you could do the same thing with `tap`. You could for `Array.build` too afaik.
<FromGitter> <Blacksmoke16> @watzon ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5e51a910ff00c664eedd198e]
<FromGitter> <watzon> Ooooh x2
<FromGitter> <watzon> Annotations still need some work in other areas, but that's nice
<FromGitter> <Blacksmoke16> not sure how this helps yet tho
<FromGitter> <watzon> Yeah idk either haha
<FromGitter> <watzon> Would be better if you could define methods on specific annotations
<FromGitter> <Blacksmoke16> yea
<FromGitter> <Blacksmoke16> prob could do like
<FromGitter> <watzon> ```annotation Test ⏎ macro foo ⏎ self[0] ⏎ end ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5e51a997b662483a875b5505]
<FromGitter> <watzon> Or something
<FromGitter> <Blacksmoke16> cant really think of anything atm that would benefit from having a global annotation method
<FromGitter> <Blacksmoke16> unless you did something like
<FromGitter> <watzon> Me neither, but local ones could definitely come in handy
<FromGitter> <watzon> For validation of arguments and sugh
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5e51aaa4ff00c664eedd1ee4]
<FromGitter> <Blacksmoke16> :shrug:
<FromGitter> <watzon> Hmm interesting
<FromGitter> <watzon> So I think I figured out the C macros I was having a hard time with last night, I just don't know how to do this in Crystal
<FromGitter> <Blacksmoke16> recursion is going to be big, be much easier to do argument resolution for my DI shard
<FromGitter> <Blacksmoke16> i dont know C so i wont be much help :p
<FromGitter> <watzon> Basically the idea of the macros I was dealing with is thus: we're taking an array (which in C is a pointer) of 8 bit unsigned integers and inserting a 32 bit unsigned integer into it, so that one integer should take up 4 of those 8 bit slots in the array.
<FromGitter> <watzon> Theoretically I should be able to do something like this: ⏎ ⏎ ```(arr.to_unsafe + index).unsafe_as(Pointer(UInt32))[0] = new_value```` [https://gitter.im/crystal-lang/crystal?at=5e51ac47b662483a875b5f56]
<FromGitter> <watzon> I'd think anyway
<FromGitter> <watzon> And it seems to work as expected https://carc.in/#/r/8m0l
<FromGitter> <watzon> So very very close. The top is the C output, bottom is Crystal.
<FromGitter> <watzon> Got it!
<FromGitter> <watzon> Holy fuck
<FromGitter> <tenebrousedge> :plus1:
<FromGitter> <oren> I creating a tiny static site generator and I don't want to rely on external html file that exist when running it. I would like to embed this file during compilation. How do I that?
<FromGitter> <tenebrousedge> I think that someone has a shard for that, or you could use the `read_file` macro
<FromGitter> <oren> this one? https://github.com/busyloop/rucksack
<FromGitter> <tenebrousedge> yeah, that's what I was thinking of. I haven't used it
<FromGitter> <Blacksmoke16> or https://github.com/schovi/baked_file_system
<FromGitter> <oren> I'll look up that macro first. Thank you
<FromGitter> <oren> reading the macros section is similar to reading Chinese - https://crystal-lang.org/reference/syntax_and_semantics/macros.html
<FromGitter> <watzon> Yeah if you don't want to rely on an external shard, `read_file` should be fine
<FromGitter> <watzon> And yes. Macros are complicated.
<FromGitter> <watzon> If you think that's bad, check this out https://github.com/watzon/tourmaline/blob/master/src/tourmaline/handler.cr#L19
<FromGitter> <watzon> In other news, the only thing missing in my pure Crystal AES implementation is decryption which I'm adding right now!
<FromGitter> <tenebrousedge> pfft, who needs decryption
<FromGitter> <oren> i think that's read_file doc: https://crystal-lang.org/api/0.32.1/Crystal/Macros.html#read_file(filename):StringLiteral-instance-method
<FromGitter> <oren> it's just one line? sounds amazing
<FromGitter> <oren> Error: undefined method 'read_file' for top-level
<FromGitter> <oren> where do i put that line? i tried outside of my class
<FromGitter> <tenebrousedge> it's a macro method
<FromGitter> <watzon> Needs to be in a macro
<FromGitter> <watzon> So `{{ read_file(path) }}`
<FromGitter> <watzon> And ideally assign it to a constant outside of any function definitions
<FromGitter> <tenebrousedge> ^
<FromGitter> <oren> here is my code - i want to read template.html from the folder itself - https://github.com/oren/website-generator/blob/master/src/site.cr
<FromGitter> <tenebrousedge> ```TEMPLATE = {{ read_file("index.md") }}```
<FromGitter> <oren> interesting. so outside of the class?
<FromGitter> <tenebrousedge> or wherever
<FromGitter> <oren> and TEMPLATE will be available?
<FromGitter> <tenebrousedge> it will have the contents of the file as a string
<FromGitter> <oren> amazing!!
<FromGitter> <watzon> Just make sure to do it outside of a function
<FromGitter> <watzon> It's basically like copy pasting whatever you load in, so if it's inside a function it's going to be reallocating that string every time the function gets called
<FromGitter> <watzon> Afaik anyway
<FromGitter> <oren> Error: can only assign to variables, not Path
<FromGitter> <oren> it doesn't like the TEMPLATE. it's ok with html_template
<FromGitter> <tenebrousedge> you should assign it to a constant
<FromGitter> <watzon> Where are you trying to do that? Have a code snippet?
<FromGitter> <oren> when i build my app, i want to load an html file
<FromGitter> <oren> (template.html)
<FromGitter> <oren> right now it's in line 64. at run time.
<FromGitter> <watzon> So if you move it to the top and outside of any functions you should be able to do `TEMPLATE = {{ read_file("template.html") }}`
<FromGitter> <watzon> Provided the HTML file is at the root of your project
<FromGitter> <oren> i am getting this error: Error: can only assign to variables, not Path
<FromGitter> <oren> i tried outside the class and inside
<FromGitter> <watzon> Hmm
<FromGitter> <oren> oh wait...
<FromGitter> <oren> works!! let me try running it
<FromGitter> <watzon> Well I must really hate myself, but I did it
<FromGitter> <oren> @watzon what is this?
<FromGitter> <watzon> Something that kept me up until 3 last night and will be haunting my dreams for years to come
<FromGitter> <watzon> A pure crystal AES implementation
<FromGitter> <watzon> Now to move on to CBC, CTR, and IGE
<FromGitter> <oren> this? ere are various imple
<FromGitter> <watzon> Compiler question: from a compilation standpoint is having one file that imports all the other files in your project different from having a user import things explicitly?
<FromGitter> <watzon> And yes @oren, that lol
<FromGitter> <oren> who is the user of your app/library? what does it do?
<FromGitter> <oren> explain to me like i am 5 please (:
<FromGitter> <Blacksmoke16> i doubt it? prob would take a tiny more amount of time, but in the end stuff that isnt used isnt included
<FromGitter> <watzon> Well for now, me. I'm attempting to make a Telegram Client API framework, and the Telegram Client API uses an interesting form of encryption that isn't used basically anywhere else. IGE encryption, which is a derivative of AES. So I'm porting a well known C library to Crystal so that I can have it be *pure* Crystal, because stupid things like that are important to me for some reason.
<FromGitter> <watzon> @Blacksmoke16 I figured as much
<FromGitter> <watzon> CBC is an interesting algorithm
<FromGitter> <oren> @watzon i just googled for telegram. it's a cloud-based messaging app. What API are you building for it and who is the user of this API?
<FromGitter> <oren> "Telegram rolls their own β€œencryption”, which hasn’t been peer reviewed or attacked on a massive scale yet. I highly doubt that it’s actually secure. Signal uses well known and open protocols that have stood up over their lifetime." - https://www.reddit.com/r/privacy/comments/7fq16e/telegram_vs_signal/
<FromGitter> <watzon> It has two API's. Their bot API is used for making bots that users can interact with, and the client API is used for making clients that users can log in to. The client API is also good for building userbots, or bots that are using a user account. I don't expect many people to use my library to begin with tbh since Crystal isn't very well known, but Crystal's speed is perfect for stuff like this, and post v1
<FromGitter> ... hopefully it will start getting more users.
<FromGitter> <oren> (I did a quick google search since I use Signal and never heard about telegram)
<FromGitter> <watzon> Also I've seen that article about Telegram vs Signal, but Telegram does have a pretty large reward for anyone that manages to break their encryption, and none have so far
<FromGitter> <oren> ok. so if i want to build a crystal command line app that talks to my friends on telegram, am I a user for your library?