ChanServ changed the topic of #crystal-lang to: The Crystal programming language | https://crystal-lang.org | Fund Crystal's development: https://crystal-lang.org/sponsors | GH: https://github.com/crystal-lang/crystal | Docs: https://crystal-lang.org/docs | Gitter: https://gitter.im/crystal-lang/crystal
wwalker has joined #crystal-lang
ur5us has joined #crystal-lang
Sankalp has quit [Ping timeout: 264 seconds]
Sankalp has joined #crystal-lang
<FromGitter> <djberg96> A bit confused as to why `Bytes#to_s` isn't effectively the same as `String.new(bytes)`. The current behavior of the former doesn't strike me as very useful or intuitive. What am I missing?
<FromGitter> <Blacksmoke16> the former is giving you a string representation of the bytes themselves, not what they represent, while the latter creates a new string instance by interpreting the provided bytes as a string
<FromGitter> <Blacksmoke16> e.g. creating a string from a pointer or something from a c lib
renich has quit [Remote host closed the connection]
ur5us has quit [Ping timeout: 256 seconds]
renich has joined #crystal-lang
renich has quit [Remote host closed the connection]
renich has joined #crystal-lang
renich has quit [Remote host closed the connection]
renich has joined #crystal-lang
ur5us has joined #crystal-lang
ur5us has quit [Remote host closed the connection]
ur5us has joined #crystal-lang
renich has quit [Remote host closed the connection]
ur5us has quit [Ping timeout: 256 seconds]
ur5us has joined #crystal-lang
ur5us has quit [Ping timeout: 256 seconds]
_ht has joined #crystal-lang
walez has joined #crystal-lang
<FromGitter> <djberg96> I get what it's doing, I just don't find it useful. I thought maybe there was a deeper technical reason for why altering `Bytes#to_s` would be a bad idea.
<FromGitter> <oprypin:matrix.org> @djberg96: turning bytes to a string is not to be taken lightly. String.new has a lot of mental overhead behind it. "take these exact bytes, i promise it's utf-8 and i already validated, please just copy it into a string". `.to_s` doesn't look nearly heavy enough to capture the sentiment
<FromGitter> <oprypin:matrix.org> Python had a years-long fight so people don't equate bytes with strings. it also doesn't do this through a str(call) , instead you must call `.decode('utf-8')` - that's what i wish Crystal would force people to write as well
<FromGitter> <oprypin:matrix.org> and let me expand a bit more on reasoning: ⏎ .to_s is the only obvious representation as a string. for a number, sure, it's the base10 printout. for a sequence of bytes it's just.. a printout of the sequence of bytes, what else? ⏎ guessing that it actually happens to represent a string and guessing that the encoding happens to be utf-8 would be out of line for to_s
<FromGitter> <oprypin:matrix.org> @djberg96: so it is a design reason, not a technical limitation
<FromGitter> <djberg96> maybe let users pass an argument to `to_s` then so it's explicit?
<FromGitter> <djberg96> on an unrelated note, how do i make up-arrow work in the repl?
<FromGitter> <oprypin:matrix.org> @djberg96: i think the issue is that Bytes is just Slice(UInt8) so the methods are just from Slice and it can't add more methods. we don't want to provide a decode method on a Slice(Dog) or whatever
<FromGitter> <djberg96> actually, how do I make *any* of the arrow keys work in the repl?
<FromGitter> <djberg96> @oprypin:matrix.org ok, thanks
<FromGitter> <oprypin:matrix.org> @djberg96: this is the first thing i'd look at https://github.com/crystal-lang/crystal/issues/11340#issuecomment-947589301
<FromGitter> <oprypin:matrix.org> or build from https://github.com/crystal-lang/crystal/pull/12738
<FromGitter> <djberg96> ok, thanks!
<FromGitter> <djberg96> now to remember to type "exit" instead of "quit" ;)
hightower2 has quit [Ping timeout: 264 seconds]
walez has quit [Quit: Leaving]
renich has joined #crystal-lang
renich has quit [Max SendQ exceeded]
renich has joined #crystal-lang
renich has quit [Remote host closed the connection]
renich has joined #crystal-lang
renich has quit [Remote host closed the connection]
sagax has quit [Remote host closed the connection]
hightower2 has joined #crystal-lang
irc_user has joined #crystal-lang
taupiqueur has quit [Quit: WeeChat 3.7.1]
yxhuvud has quit [Remote host closed the connection]
yxhuvud has joined #crystal-lang
rocx has joined #crystal-lang
<rocx> what exactly is the difference between the Iterable and Iterator modules? besides what #each returns? like what sort of use cases would there be for one and not the other?
<FromGitter> <Blacksmoke16> my understanding is the former just adds some extra methods powered by `#each : Iterator`, whereas `Iterator` module itself is the thing that allows defining an iterator
<FromGitter> <Blacksmoke16> like a simple example being: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=6383959bf9491f62c9d21e86]
<rocx> so if i have a class like Die (as in rolling a die), would i want that to be using Iterator? i have a MVP using Iterator(UInt32) but i guess i'm wondering if i'm doing it right.
<FromGitter> <Blacksmoke16> afaik unless you have a reason to have the extra iterator methods, what you're doing now is prob fine
<FromGitter> <Blacksmoke16> maybe a better explanation would be like `Iterable` denotes a type *can* be iterated in that you can obtain an `Iterator` to iterate its values
<FromGitter> <Blacksmoke16> while the `Iterator` itself is thing that actually iterates
taupiqueur has joined #crystal-lang
<FromGitter> <Blacksmoke16> like take an `Array` for example. it includes `Iterable` since you can get an `Iterator` by calling its `#each` method
jmdaemon has quit [Ping timeout: 264 seconds]
taupiqueur has quit [Client Quit]
irc_user has quit [Quit: Connection closed for inactivity]
<rocx> i just have my `Die#each` return a random number since it already is an infinite source of random integers.
<FromGitter> <Blacksmoke16> which if you had a method like `def foo(iterator : Iterator(Int32))` you couldnt pass `[1, 2, 3]` but you could pass `[1, 2, 3].each`
<FromGitter> <Blacksmoke16> oh wait, i see the real benefit of `Iterable` each method that it adds returns a dedicated `Iterator` instance that does something more specialized
<FromGitter> <Blacksmoke16> so you're returning a number from `Die#each`?
<rocx> yeah.
<FromGitter> <Blacksmoke16> i would say thats not expected
<rocx> it's not expected because i'm learning the difference of the modules and i don't know what i'm doing.
<FromGitter> <Blacksmoke16> i think you might want to look into including `Random` and not `Iterator`, tho you could use the latter to allow iterating over an infinite amount of random numbers
<FromGitter> <Blacksmoke16> what language are you coming from?
<rocx> java and ruby.
<FromGitter> <Blacksmoke16> https://crystal-lang.org/api/Random.html
<rocx> huh. TIL Random is a module and not strictly a class.
<rocx> guess that's the part i should have been paying attention to.
<FromGitter> <Blacksmoke16> yea its kinda confusing since it also acts as a sort of default implementation
<rocx> the Random module looks like it's mainly for rolling your own method of generating random numbers, reading the description.
<FromGitter> <Blacksmoke16> yea you're prob right
<FromGitter> <Blacksmoke16> sec
<FromGitter> <Blacksmoke16> id make it `Iterator` then
<FromGitter> <Blacksmoke16> could also include `Iterable` to get the extra methods, implementation would be like `def each; self; end`
<FromGitter> <Blacksmoke16> or really could just not worry about it and have a method called `#roll` to get the next number
<rocx> already have a `Die#roll` but figured i'd make it like a stream to nail some of these concepts down.
<FromGitter> <Blacksmoke16> ah yea go for it then, https://crystal-lang.org/api/Iterable.html#cycle%28n%29-instance-method would prob be pretty helpful
<FromGitter> <naqvis> > *<rocx>* what exactly is the difference between the Iterable and Iterator modules? besides what #each returns? like what sort of use cases would there be for one and not the other? ⏎ ⏎ These concepts are similar to what you see in Java, but in Crystal `Iterable` is a *mixin* (think of it like Java Interface, but with default implementations) to data structures which can be *iterated over*. Every
<FromGitter> ... collection class in Crystal kind of have this `mixin` and provides an implementation for its only abstract method `each` which returns an `Iterator`.
<rocx> keeping it an Iterator lets me do, say, `d20 : Die = Die.new(20); d20.first(2).max` lets me roll 2d20 and take the highest.
<FromGitter> <Blacksmoke16> it is somewhat confusing since `Iterator` is also a mixin
<rocx> 'scuse me, `d20.first(2).to_a.max`
<FromGitter> <Blacksmoke16> try `d20.first(2).each.max`
<FromGitter> <Blacksmoke16> then you dont create an intermediary array
<rocx> i just ripped that from a spec test to compare to an array. to be honest, writing tests is ALSO a new concept for me since throughout my career, no one wrote tests.
<FromGitter> <Blacksmoke16> ah for a spec its fine
<rocx> yeah but then it makes me wonder if i'm just writing a tautological test.
<FromGitter> <Blacksmoke16> hard to test randomness yea, might not be a lot you need to test given the compiler would enforce `#roll` and `#next` are returning integers
<FromGitter> <Blacksmoke16> unless there's a way for you to supply the seed and ensure if you call it n times you get the same n values or something. but at that point you're kinda testing the stdlib
<rocx> exactly, it feels like testing the stdlib. have a couple of seeds like 12345 and 42069 (because we have a 12-year-old's sense of humor) and checking to see if those seeds return the right numbers based on the die's limit.
<rocx> come to think of it, if `Random` is a module, then how come i can declare new instances of it?
<FromGitter> <Blacksmoke16> relates to the part where i mentioned it also acts as default implementation
<rocx> yeah i just saw that and realized "wait, so it's not just classes and structs that can be initialized?".
taupiqueur has joined #crystal-lang
<FromGitter> <Blacksmoke16> well technically you're not instantiating the module. any type can have a `self.new` method that returns something, in this case an instance of another type
<rocx> ah yeah i see now. it's just more of the fact that `#new` is simply just a class method and returns a default. though i wonder why they didn't use DEFAULT in the default methods.
<FromGitter> <Blacksmoke16> prob so it returns a new instance with a diff seed
<rocx> ah yeah because DEFAULT is an instance of `PCG32`, not a class to declare a new one of.
<rocx> bah. all i need is a d6 for my current app. don't need to work on a roll-building library yet.
<rocx> but hey, new insight. thanks.
<FromGitter> <Blacksmoke16> np
<rocx> wonder if there'd be an eventual feature to be able to specify the license when running `crystal init` so i don't have to go hunting for the GPL3 text.
<FromGitter> <Blacksmoke16> related: https://github.com/crystal-lang/crystal/issues/8844
* rocx will probably see about updating the docs for `crystal init` just to answer some questions about the project skeleton.
taupiqueur has quit [Quit: WeeChat 3.7.1]
taupiqueur has joined #crystal-lang
renich has joined #crystal-lang
taupiqueur has quit [Quit: WeeChat 3.7.1]
ur5us has joined #crystal-lang
_ht has quit [Quit: _ht]
jmdaemon has joined #crystal-lang
<FromGitter> <lebogan> A matter of idiomatic crystal: ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ This actually works. I'm just wondering if I'm painting myself into a code-smell corner or if this is just bad or ill-informed coding:? [https://gitter.im/crystal-lang/crystal?at=6383e578473cf9664805ddeb]
<FromGitter> <lebogan> The above is heavily influenced by veelenga's ameba project. I just made the class instantiate itself:()
<FromGitter> <moe:busyloop.net> that's fine, not a smell at all
<FromGitter> <moe:busyloop.net> the only potential smell there might be the explicit abort() and use of colorize ⏎ (usually better to let errors bubble up as exceptions and handle output formatting elsewhere - but may not matter in your codebase)
<FromGitter> <moe:busyloop.net> i.e. `raise YamlConf::FileNotFound.new(path)` instead of abort (which probably raises a generic exception?) with a pre-formatted message 🤓
<FromGitter> <jrei:matrix.org> Why using `YAML::Any` with `YAML.parse`?
<FromGitter> <jrei:matrix.org> If you know the mapping in advance, it is better to use `YAML::Serializable`
<FromGitter> <lebogan> Thanks @moe:busyloop.net . That looks cleaner. And maybe easier to maintain.