<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> 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
<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?
<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
<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.
* 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.