ChanServ changed the topic of #crystal-lang to: The Crystal programming language | | Fund Crystal's development: | GH: | Docs: | Gitter:
ur5us has quit [Ping timeout: 245 seconds]
elf_fortrez has quit [Quit: Client closed]
ur5us has joined #crystal-lang
elf_fortrez has joined #crystal-lang
ua_ has quit [Quit: Leaving]
elf_fortrez has quit [Ping timeout: 246 seconds]
<FromGitter> <> I'd like to write data to sqlite & read it back again from query results, all without writing custom serialization code. I like how `JSON::Serializable` works and would like something similar. Any suggestions?
<FromGitter> <emanzx> hi again..
<FromGitter> <emanzx> Showing last frame. Use --error-trace for full trace. ⏎ ⏎ In ⏎ ⏎ 60 | if change.includes?(monitor_path) ... []
<FromGitter> <emanzx> I always encounter this error in crystal and most of the solutions are tries and error..
<FromGitter> <emanzx> I have a hash like this. ⏎ ⏎ `````` []
<FromGitter> <emanzx> ``````
<FromGitter> <emanzx> ```code paste, see link``` []
lucf117 has quit [Remote host closed the connection]
ua_ has joined #crystal-lang
elf_fortrez has joined #crystal-lang
elf_fortrez has quit [Client Quit]
ur5us has quit [Ping timeout: 255 seconds]
elf_fortrez has joined #crystal-lang
<FromGitter> <alexherbo2> can I use `return` if I `yield` instead of ``?
<FromGitter> <emanzx> does crystal implement catch and throw like in ruby to handle nested loop?
elf_fortrez has quit [Quit: Client closed]
elf_fortrez has joined #crystal-lang
<jhass[m]> no
<jhass[m]> I never ever needed that feature in Ruby either and always found any usages of it I found strange and hard to follow
elf_fortrez has quit [Ping timeout: 246 seconds]
<mfiano> How can I define a generic struct with all of its fields being of type T (homogeneous), where T is restricted to Float32 or Float64?
<jhass[m]> We don't support restricting type variables yet. A hack is to check the type in macro land using
<mfiano> :( Thanks
<xyhuvud> shouldn't it be possible by setting type restrictions on the constructors though?
elf_fortrez has joined #crystal-lang
<FromGitter> <Blacksmoke16> you could, but then you end up with a union of the two
<FromGitter> <> is there some trick to using `@type.instance_vars` in a module to get the variables of a class that it was included into?
<FromGitter> <> i have this code, but both annoations and instance vars are empty:
<FromGitter> <> ```code paste, see link``` []
<FromGitter> <Blacksmoke16> it has to be called in the context of a method
<FromGitter> <> ah, i guess the problem is with the `macro included`...
<FromGitter> <> ```code paste, see link``` []
<FromGitter> <> this now gives me instance vars, but not annoations
<FromGitter> <Blacksmoke16> the problem is `@type.instance_vars` *has* to be used in the context of a method, which it is now
<FromGitter> <Blacksmoke16> and annotation is empty because the macro is being expanded within the module i'd guess
<FromGitter> <> ah, the annotation is on the instance var
<FromGitter> <> thanks :)
fifr has joined #crystal-lang
repo has joined #crystal-lang
Guest1975 has quit [*.net *.split]
fifr_ has quit [*.net *.split]
elf_fortrez has quit [Quit: Client closed]
<mfiano> I'm trying to affect how an instance of a struct prints with puts, but defining a custom to_s in the struct scope doesn't seem to do anything. What is the correct way?
<FromGitter> <Blacksmoke16> `def to_s(io : IO) : Nil`
<FromGitter> <Blacksmoke16> then write the content to that io
<mfiano> Perfect, thanks.
<FromGitter> <Blacksmoke16> there's also `def inspect(io : IO) : Nil` which is similar but diff
* mfiano reads
<mfiano> I see.
<mfiano> Crystal is just amazing me the more I learn it. I'm pretty excited to be getting started. It's so nice to be able to just write what I mean with minimal syntax/short symbols like "to_s".
<FromGitter> <Blacksmoke16> fun fact, `to_s` also gets invoked if you add a var into a string. I.e. `puts "Hello #{user}"` is the same as `puts "Hello #{user.to_s}"`
<mfiano> I remember reading the performance gotchas about that
<mfiano> I'm struggling with multiple struct constructors. I have a struct, `Foo`, with `@a` and `@b` variables. I'd like to invoke it as `, 3.4)`, _or_ ``, in which case, `@a` and `@b` would be set to `1.2`.
<FromGitter> <Blacksmoke16> is the 2nd value just the first one doupeld?
<FromGitter> <Blacksmoke16> doubled
<mfiano> Given one argument, both variables should be set to the same value.
<FromGitter> <Blacksmoke16> ```code paste, see link``` []
<FromGitter> <Blacksmoke16> should do it
<mfiano> Ah so you can only have 1 `initialize` method?
<mfiano> I was trying to overload that multiple times :/
<FromGitter> <Blacksmoke16> no, but
<FromGitter> <Blacksmoke16> tl;dr i always just mke `initialize` represent the actual state of the instance, but then have overloaded `.new` to transform the arguments into something the initializer constructs
<FromGitter> <Blacksmoke16> expects*
<mfiano> That post was very well explained, thanks.
<FromGitter> <Blacksmoke16>,*properties)-macro might also be helpful
<mfiano> Is there a way to alias a module at the file level?
<mfiano> I don't want to remove the full qualification, but for a long/deep module that is used all over a single file, I would like to alias it to a single character or something
<FromGitter> <Blacksmoke16> technically no, but you shouldn't need to provide the FQN if its in the same namespace
<FromGitter> <Blacksmoke16> or if its in a diff namespace you can do like ⏎ ⏎ `````` []
<FromGitter> <Blacksmoke16> ```private alias Foo = MyApp::Some::Very::Long::Namespace::Foo```
<FromGitter> <Blacksmoke16> private top level aliases are scoped to the file they're defined in
<mfiano> Oh! I wasn't aware that program-level private stuff was file-local
<mfiano> That is great
<FromGitter> <> test
mfiano has left #crystal-lang [WeeChat 3.0]
ua_ has quit [Ping timeout: 268 seconds]
<FromGitter> <alexherbo2> why I can't refer to `Scope` in `Snippet::Parser`?
<FromGitter> <alexherbo2> I have `Snippet::Scope` struct defined, it can't find it
<FromGitter> <Blacksmoke16> can you share the code/error?
<FromGitter> <alexherbo2>
ua_ has joined #crystal-lang
<FromGitter> <Blacksmoke16> seems the error is coming from YAML::Serializable, can you include more of the strack trace?
<FromGitter> <alexherbo2> it's odd because if I replace `struct Snippet::Scope {` with `struct Scope`, it finds it
<FromGitter> <Blacksmoke16> what happens if you rename the struct to like `Snippet::Scope2`
<FromGitter> <alexherbo2> Same error
<FromGitter> <alexherbo2> Can it be due to my forwarded block in Walk filter?
<FromGitter> <Blacksmoke16> im not sure
<FromGitter> <alexherbo2> I haven't found a way to use return like in other filtering methods
<FromGitter> <> Any Crystal books published yet?
<FromGitter> <Blacksmoke16> one, but it's pre 1.0
<FromGitter> <> (or WIP)
<FromGitter> <Blacksmoke16> is one that i know of that it's the works at least
<FromGitter> <> Ah is that mentioned on the homepage somewhere
<FromGitter> <Blacksmoke16> dont think so
<FromGitter> <> Ah "Programming Crystal" I take it
<FromGitter> <Blacksmoke16> yea, id prob just wait for the other to come out, as it'll be more up to date and such
<FromGitter> <> What's this other one?
<FromGitter> <Blacksmoke16> it's WIP atm, but should be out later this year
<FromGitter> <> Is the name or link still WIP?
<FromGitter> <Blacksmoke16> its still being written so both?
<FromGitter> <> Ah I see. I suppose it was just mentioned in passing here or the forums then.
<FromGitter> <Blacksmoke16> is also very good if you haven't read thru it yet
<FromGitter> <> I read the whole thing yesterday.
<FromGitter> <Blacksmoke16> 👍 nice
<FromGitter> <> Working my way through the stdlib api docs now
<FromGitter> <> (while writing code, because no book will teach you to *do* :))
<FromGitter> <RespiteSage> Advent of Code is also a very good source for exercises, especially if you want to learn the standard library. There's a lot of opportunity to use the very useful methods on `Iterable`/`Enumerable`/`Indexable`/`Array`.
<FromGitter> <> I have a problem with AoC even with the language I've been using for ~20 years...not very good at human descriptions of problems with tons red herrings
<FromGitter> <RespiteSage> That's fair.
<FromGitter> <RespiteSage> I tend to use Crystal pretty often to implement math routines that I find interesting (e.g. I've recently been interested in Lucas Sequences ( for estimating roots), so that could also be another way to practice, if you find that interesting.
ua_ has quit [Ping timeout: 265 seconds]
<FromGitter> <> Yes, I am writing a little linear algebra library to practice, actually.
ua_ has joined #crystal-lang
<FromGitter> <RespiteSage> 👍
hexreel has joined #crystal-lang
<FromGitter> <> Does Crystal have the distinction of shallow vs deep copying builtin?
<FromGitter> <> clone vs dup i take it?
<FromGitter> <Blacksmoke16> yes
<FromGitter> <> Thanks, and the last question before lunch: Is there any way to emit the disassembly, or at the very least, the IR, of a given method (preferably the former)?
<FromGitter> <Blacksmoke16> IR meaning LLVM IR yea?
<FromGitter> <> Yes, though that is foreign to me so preferably the machine code (asm)
<FromGitter> <Blacksmoke16> `--emit [asm|obj|llvm-bc|llvm-ir] Comma separated list of types of output for the compiler to emit`
<FromGitter> <> ? I want to inspect a single function.
<FromGitter> <Blacksmoke16> the compiler explorer allows going to a specific def, but you'd prob need to include prelude for your code to work
<FromGitter> <Blacksmoke16> otherwise there isn't a way to output *specific* IR, other than the whole file afaik
<FromGitter> <Blacksmoke16> so would need to output all the IR and find the method you want in it
<FromGitter> <> Ok thanks. Nothing will beat `(disassemble name)` at runtime I suppose :)
hexreel has quit [Quit: nyaa~]
elf_fortrez has joined #crystal-lang
elf_fortrez has quit [Client Quit]
lucf117 has joined #crystal-lang
<FromGitter> <> so... method overloading on works for argument and not return types?
<FromGitter> <Blacksmoke16> yes
<FromGitter> <Blacksmoke16> why?
<FromGitter> <> well, would've been a bit nicer to write the other way :)
<FromGitter> <Blacksmoke16> got some example code?
<FromGitter> <> `def convert(value : String) : Array(String).class)` instead of `def convert(value : String, kind : Array(String).class)`
<FromGitter> <Blacksmoke16> how would it know which one to use
<FromGitter> <Blacksmoke16> i guess it could look at each overload's return type and compare that to something? :shrug:
<FromGitter> <> well, i have a bunch of those that take a string and return some other type
<FromGitter> <Blacksmoke16> could you monkey patch constructors onto various other types instead?
<FromGitter> <> given that crystal already infers the return type, and it knows what type i want to assign to a given instance variable, i was hoping there was a way to elide that annoation
<FromGitter> <Blacksmoke16> ```def Array.convert(value : String) ⏎ # ... ⏎ end ⏎ ⏎ kind.convert value``` []
<FromGitter> <> yeah... not a big fan of messing with existing classes :)
<FromGitter> <Blacksmoke16> that's how all the JSON/YAML serializable stuff is implemented
<FromGitter> <> anyway, just got my code to pass a bunch of tests, here's what i got:
<FromGitter> <> maybe you can suggest some other ways to do this better :)
<FromGitter> <> so to add other conversions, you'd add another `convert` method to `Test::Configuration` instead of having them infect all other types... i guess i'm still thinking functional
<FromGitter> <> for json/yaml it makes more sense, since they're already in stdlib anyway
<FromGitter> <Blacksmoke16> `@{{}} = {{ivar.type}}.from_parameter %value`
<FromGitter> <Blacksmoke16> is what i would do
<FromGitter> <Blacksmoke16> it's not going to harm anything, as you're not messing with the state of the internal obj or anything
<FromGitter> <Blacksmoke16> can get complicated if you need to support like `Int32 | Bool | String` tho
<FromGitter> <> yeah...
<FromGitter> <Blacksmoke16> are you making a config lib or a cli maker lib?
<FromGitter> <> both ^^;
<FromGitter> <> i tried a bunch of existing ones, but none really fit my use-case...
<FromGitter> <Blacksmoke16> oh?
<FromGitter> <> well, habitat was nice, but it assumes you configure all via crystal, envy/envyable are yaml, totem was probably the closest to what i wanted i think
<FromGitter> <> but i wanted flag generation for optionparser and special handling for file paths passed as option values, since they're usually files containing secrets that i'd like to encapsulate and avoid accidental leaking of
<FromGitter> <> plus it had no idea of how to handle URIs and the types it handles are not extendable afaict
<FromGitter> <Blacksmoke16> there's als o technically it's not coupled with the rest of athena. but not sure how useful it would be in your context. I.e. if you need to support runtime alteration of the values as it doesn't support that atm
<FromGitter> <Blacksmoke16> does support alternate instantiation methods, e.g. from a file but meh
<FromGitter> <> will have a look at it :)
<FromGitter> <Blacksmoke16> eh, i wouldn't worry about it. it's not what you're wanting
<FromGitter> <> I'm curious how Crystal handles the once-only evaluation problem with macros, but that may be a question for the forums/someone experienced with macros not limited to the Crystal subset of the concept.
<FromGitter> <Blacksmoke16> whats the problem?
<FromGitter> <> Well, I know very little about Crystal macros but consider you wanted to write a `square()` macro, that takes 1 argument and multiplies it by itself. Because macros take in AST nodes and output AST nodes, and are expanded before the semantic analysis, such an invocation could be: `x = 4; square(x += 1)`, which would expand into code that basically does `(x+=1) * (x+=1)`, that is, the side effect of
<FromGitter> ... incrementing x is evaluated before the second occurence of x is evaluated, giving a wrong answer. I'm not sure if I explained that well enough...
<FromGitter> <Blacksmoke16> ah i see
<FromGitter> <Blacksmoke16> they're mainly just ways to generate crystal code
<FromGitter> <> You would expect 25, but would actually get 32
<FromGitter> <Blacksmoke16> this isn't really a good use case for a macro fwiw
<FromGitter> <> and this was a bad example, only for demonstration purposes. Clearly this should be a method, not a macro :)
<FromGitter> <> Right. Macros are strictly for 2 things only.
<FromGitter> <Blacksmoke16> main benefit of macros is they can generate code based on compile time information. I.e. accessing annotations, all types that inherit from another, or all types that include a module, etc, etc
<FromGitter> <> Syntactic abstraction and evaluation control.
<FromGitter> <> But this problem comes up a lot in unhygienic macro systems, which CL and Crystal have afaict.
<FromGitter> <> Unhygienic meaning that the the lexical state of the macro expansion can leak into the call site
<FromGitter> <> Usually generating a temporary variable that is guaranteed to be unique is the way to solve this, which I see Crystal *can* do
<FromGitter> <Blacksmoke16> mhm, those can also be keyed like a hash
<FromGitter> <Blacksmoke16> which can be quite helpful, when you also bring unique indexes into things
<FromGitter> <> Maybe your head wont explode reading this, but starts out with the same (bad) example:
<FromGitter> <> But as you can see, the once-only macro definition is rather complex to solve such a common issue
<FromGitter> <> Was just wondering if Crystal stood on the shoulder of the giants that have solved it decades ago and included such a thing in the language :)
<FromGitter> <Blacksmoke16> hmm
<FromGitter> <Blacksmoke16> you can deff run into this as you just saw, like if you did `{{x}} * {{x}}` but it's also fairly easy to fix
<FromGitter> <Blacksmoke16> ```macro square(v) ⏎ %v1 = {{v}} ⏎ %v1 * %v1 ⏎ end``` []
repo has quit [Ping timeout: 245 seconds]
<FromGitter> <Blacksmoke16> macros are deff a more advanced concept, they also aren't as type safe and have quite a few quirks :P
repo has joined #crystal-lang
<FromGitter> <> Oh sure, the solution has an easy fix, but: ⏎ ⏎ 1) It's not always obvious that there is a problem to solve. ⏎ 2) An automated solution (a macro) is fairly complicated. ⏎ 3) It saves a lot of boilerplate (over time) []
<FromGitter> <> Yeah, macros are advanced and come with a lot of footguns that take years of experience to even realize their existence, especially in Lisp, which has a much more powerful macro system. I will refrain from asking more macro questions until I have had time to see how they map over :)
<FromGitter> <Blacksmoke16> bump for
<FromGitter> <> Oh that issue surprised me...
<FromGitter> <> In Lisp a macro can evaluate at compile time arbitrary pieces of code, even methods that are shared with other macros or runtime code.
<FromGitter> <> I did not know Crystal couldn't do that
<FromGitter> <Blacksmoke16> its a pita
<FromGitter> <Blacksmoke16> because of that missing piece that you cant define reusable macro code
<riza> ^
<FromGitter> <Blacksmoke16> i.e. that you could use in two separate macros
<FromGitter> <Blacksmoke16> you can call a macro from a macro, but that just is moreso nested expansion, which doens't help in this case
<riza> @Blacksmoke16 what do you mean fresh variables can be "keyed like a hash"
<riza> hm, I'm not instantly sure how that would be useful, but it's neat to see regardless
<FromGitter> <Blacksmoke16> main use case afaik is if you want to create them in a loop
<FromGitter> <Blacksmoke16> otherwise if you just did `%key`, it would be overridden on each iteration
<FromGitter> <> I see. Also I really like Crystal and I don't mean to sound like a Lisp snob, because there are plenty of them. Lisp is nice, but it's *too* dynamic for some tasks...which is one thing that makes its macro system powerful. Every phase of the compiler can be invoked by any other phase by the user, which means macros can be expanded at runtime and all that. It's a mind!@#$, really.
<riza> Yeah I suppose that could be a useful way to replace
<riza> or several places where the finished macro is used
<FromGitter> <Blacksmoke16> use an annotation and iterate over types that have it
<FromGitter> <Blacksmoke16> then could build a hash literal at build time or whatever you need
<FromGitter> <Blacksmoke16> or what's that method doing actually?
<FromGitter> <Blacksmoke16> cant just build a hash of `Mosquito::Job.class => Mosquito::Job`?
<riza> `Mosquito::Job.class.to_s => Mosquito::Job.class`
<FromGitter> <Blacksmoke16> it's been a while since i been in the code, what's this do again?
<riza> when a job is popped out of redis, it allows the runner to do a lookup in that hash to convert the job name in redis to a reference to the job class
<FromGitter> <Blacksmoke16> can you just use the FQN of the job class as the key?
<FromGitter> <Blacksmoke16> oh wait
<FromGitter> <Blacksmoke16> this is so that you can go from a string from redis to an actual type
<FromGitter> <Blacksmoke16> should feature request `Foo::Bar.class.from_json %("Foo::Bar")` :P
<FromGitter> <> Anyway, I have to try to erase my complicated Lisp macro memory to learn the basics of Crystal, else I'm going to be violating DRY a lot in this practice project.
<FromGitter> <Blacksmoke16> most of the time you dont need them either
<FromGitter> <> (which I hope to evolve into more than a practice project as the basis for what I want to use Crystal for)
<FromGitter> <> The alternative is I just DRY without care and figure out if a macro will make it more maintainable later when I'm more accustomed.
<FromGitter> <> 🤷‍♂️
<riza> my honest advice is to avoid macros where possible (in both lisp and crystal). they're an amazing toolset when you need it but most problems can be solved elegantly without.
<riza> over-macro-ing makes code hard to maintain
<FromGitter> <> I am torn. While I do agree, what has kept Lisp a viable language since the 50's is that new language features and are just a macro away. There's only so much you can do without creating new compiler extensions (macros).
<riza> Can these fresh variable hashes be iterated, or do you have to keep the list of keys around
<riza> keep/pass
<FromGitter> <Blacksmoke16> hash was maybe the wrong work
<FromGitter> <Blacksmoke16> its more of just a means of allowing the same fresh var name to hold multiple values based on another unique identifier
<FromGitter> <Blacksmoke16> so you would need to keep the "keys" around in order to access the same value, which could just be the idx of something as that can't change
<riza> yeah makes sense
<riza> it looks like it's probably just a substitution layer where `%var{name}` when `name="test"` just gets fresh'd to `%var-test` or something
<FromGitter> <Blacksmoke16> yea prob something along those lines
<FromGitter> <> I am feeling dumb that I can't figure this out, but can someone show me an example of defining an `==` method that takes 2 Float64's at the module level? For some reason the compiler thinks I'm trying to define a setter method and yells about syntax...
<riza> @mjfiano can you post what you've got?
<FromGitter> <> ```code paste, see link``` []
<FromGitter> <Blacksmoke16> i this module included into a custom type?
<FromGitter> <Blacksmoke16> you probably want
repo has quit [Ping timeout: 246 seconds]
<FromGitter> <> No
<FromGitter> <Blacksmoke16> oh, got an example of how this is to be used then?
<riza> I don't know if the == operator can be overloaded that way
<FromGitter> <Blacksmoke16> it cant
<FromGitter> <Blacksmoke16> normally it would be 1 argument that you compare with self
hightower4 has joined #crystal-lang
<hightower4> Would anyone know offhand why a macro that works on 1.0.0 would report 'Exception: unterminated macro' on 1.1.0?
<hightower4> The macro in question is:
repo has joined #crystal-lang
<FromGitter> <> I would like to define a "safe" comparator for near floating point values, taking a relative and absolute tolerance
<riza> @mjfiano that error message is misleading for sure, but I think you'll need to go about it some other way
<riza> for example, you can subclass Float and overload `==`
<FromGitter> <Blacksmoke16> is the default `==` for Float64 not sufficient
<FromGitter> <> It is not. It does not allow supplying neither a relative nor absolute tolerance.
<FromGitter> <>
<FromGitter> <> I am trying to implement a method that accomplishes the above
<riza> I guess you can't subclass Float
<FromGitter> <Blacksmoke16> id checkout that thread
<riza> the code sample at the end is basically what I was driving at
<riza> using =~ is a good idea
<FromGitter> <> `nearly_equals?` seems to be the desired behavior. I'll have to inspect it to see if it is semantically equivalent with what I need.
<FromGitter> <> Thanks
<FromGitter> <Blacksmoke16> 👍
<FromGitter> <Blacksmoke16> hightower4: that's quite the macro you got there
<hightower4> yeah, probably {% debug %} would be the next thing
<FromGitter> <Blacksmoke16> would that help? idt it's even going to run because it doesnt even expland
<FromGitter> <Blacksmoke16> expand
<hightower4> Wouldn't it print if it was placed above the place of error?
<FromGitter> <Blacksmoke16> the error is the macro itself so no
<FromGitter> <> About the code in the above thread...they seem to overload `=~` for the language's Float type. I was hoping to not monkey patch the whole language, if that is what this is doing, and only introduce this overload when used in my specific module.
<FromGitter> <Blacksmoke16> there are no specific scope overloads
<FromGitter> <Blacksmoke16> other option would be to use a decorator
<FromGitter> <> Perhaps my concerns are nothing, but I am hesitant to do such a thing, if the library I am writing is to be used with third party code expecting different behavior for `=~` of 2 floats.
<FromGitter> <> I don't know how the language behaves in this regard
<FromGitter> <Blacksmoke16> would be better off defining a new method in such case
<FromGitter> <> Fair enough. Should I subclass the builtin float type and use that everywhere in my domain, or is there a more idiomatic approach?
<FromGitter> <Blacksmoke16> a decorator type is usually the better way to go afaik
<FromGitter> <> I'll look that up
<FromGitter> <> Thanks
<FromGitter> <> Do you mean defining an annotation?
<FromGitter> <Blacksmoke16> more like something like
<FromGitter> <Blacksmoke16> ```code paste, see link``` []
<FromGitter> <> Hmm, I don't really understand how that is delegating, but I'll study that code some. Thanks
<FromGitter> <> Yeah that was my first stop. Just trying to figure out how this is different than inheritance. The docstring/example could be better imo
hightower4 has quit [Ping timeout: 250 seconds]
<FromGitter> <alexherbo2> @Blacksmoke16 what is the `%` in the macro?
<FromGitter> <Blacksmoke16> hm?
<FromGitter> <alexherbo2> `%v1`
<FromGitter> <alexherbo2> it looks to work without the `%`
<FromGitter> <rishavs> How would one go about converting a hex string to normal string?
<FromGitter> <Blacksmoke16> what do you mean by "normal string"?
<FromGitter> <Blacksmoke16> a hex string is just a string of hex characters
<FromGitter> <alexherbo2> so I should replace my `value` with `%value` to avoid side effects?
<FromGitter> <Blacksmoke16> @alexherbo2 idt it would matter
<FromGitter> <Blacksmoke16> that's not what fresh vars are for
<FromGitter> <rishavs> I am trying to convert a hexstring to base64. I am assuming that i need to first convert the hex to slice and then to base64
<FromGitter> <Blacksmoke16> `hexstring.hexbytes`
<FromGitter> <rishavs> Thanks ❤️
<FromGitter> <rishavs> I am pretty close to being able to convert a JWK to a PEM :D
ur5us has joined #crystal-lang
ur5us has quit [Remote host closed the connection]
ur5us has joined #crystal-lang
lucf117 has quit [Remote host closed the connection]
notzmv has quit [Ping timeout: 268 seconds]
notzmv has joined #crystal-lang
ur5us has quit [Ping timeout: 255 seconds]