<FromGitter>
<meltheadorable> you are using the ternary operator wrong
<FromGitter>
<kniknoo> Yay Truthiness!!! The first thing that made me fall in love with Ruby.
<FromGitter>
<tenebrousedge> I'm on the fence about whether `0` should be truthy though
<FromGitter>
<kniknoo> If you don't get back Nil or False, it's true.
<FromGitter>
<Blacksmoke16> id vote no
<FromGitter>
<kniknoo> It's true isn't it?
laaron has quit [Ping timeout: 260 seconds]
<FromGitter>
<Blacksmoke16> debatable
<FromGitter>
<tenebrousedge> in many languages it's true, in others it's false
<FromGitter>
<kniknoo> I can see an argument either way.
<FromGitter>
<girng> okay, seems like i got it confused because i was using a ternary as a return value in a method
<FromGitter>
<meltheadorable> 😒
<FromGitter>
<girng> i actually like my way better, i think it's more readable
<FromGitter>
<kniknoo> Single return by nature so a return will always end the current function. It gets nice once you're used to it. ⏎ ⏎ Speaking of which, is the correct Crystal way for me to return a true on a conditional block or false otherwise to ⏎ ⏎ return true if {blah blah} ... [https://gitter.im/crystal-lang/crystal?at=5d3ceace8aab922429d1c4c0]
<FromGitter>
<girng> however, that's not how ternary operators work i guess
<FromGitter>
<Blacksmoke16> what were you expecting it to be?
<FromGitter>
<Blacksmoke16> you an still use `return` *within* the ternary
<FromGitter>
<Blacksmoke16> could just do `some_condition || false`
<FromGitter>
<meltheadorable> @kniknoo `return (blah == blah)` any boolean expression already returns true or false, no need for an if/else or ternary
<FromGitter>
<kniknoo> crap, I forgot no "?" in variables, I'm still learning.
<FromGitter>
<Blacksmoke16> also dont forget about `!!`
<FromGitter>
<Blacksmoke16> `!!"hello"` or `!!false`
<FromGitter>
<kniknoo> Um... I only know that in a shell for 1337 cred.
<FromGitter>
<kniknoo> I'ma look that up
<FromGitter>
<girng> @meltheadorable i apologize you are correct. i was thinking of it wrong and derped out. won't happen again
<FromGitter>
<dscottboggs_gitlab> @kniknoo I think ending a variable in `?` was removed just recently. :/
<FromGitter>
<meltheadorable> @kniknoo it’s just the negation operator twice — the first time essentially casts to a boolean, truthy values become false, falsy values become true — the second time swaps it back, so it’s a way of ensuring that something that can be truthy or falsey gets reduced to the literal boolean true or false
<FromGitter>
<dscottboggs_gitlab> yeah that
<FromGitter>
<kniknoo> Ah, noted. I like the expressiveness of it, but I can just make a method represent what I want I reckon.
<FromGitter>
<kniknoo> I must have been pretty drunk when I wrote that exercise. I don't know how I didn't just translate it from Ruby.
<FromGitter>
<dscottboggs_gitlab> @girng like in python! I'm guessing godot does that too?
<FromGitter>
<dscottboggs_gitlab> @kniknoo which exercise?
<FromGitter>
<kniknoo> leap year, which I went on to perfectly implement in a library 2 days ago. :D
<FromGitter>
<dscottboggs_gitlab> oh nice, I just did that exercise in rust a few days ago
<FromGitter>
<tenebrousedge> @kniknoo if you're doing exercism/crystal, feel free to share your solutions here; I am a mentor on there for that track, but I haven't been active lately
<FromGitter>
<kniknoo> Nice! I'm so bad with regex that Bob is a nightmare for me. I've done so much in zachtronics that I'll bust out a mathematical algorithm just fine, but strings rip me up.
<FromGitter>
<dscottboggs_gitlab> I should be a crystal mentor on there, shit. Why didn't I think of that before?
<FromGitter>
<dscottboggs_gitlab> well tbf I just heard of exercism a few weeks ago
<FromGitter>
<kniknoo> Thanks! I posted on the forum a few days ago, which is actually how I got here.
<FromGitter>
<kniknoo> IIRC straight-shoota signed up as a mentor.
<FromGitter>
<tenebrousedge> I actually wrote a set of mentor notes for the Crystal track; they've lingered in a PR for months now. I should bother someone about it
<FromGitter>
<kniknoo> Yeah, it needs a maintainer.
<FromGitter>
<kniknoo> And exercism is why I'm here at all. I'm so excited I'm doing a talk for my nerd friends in a couple weeks. If anyone is in the southeast, feel free to come up, it's in Asheville.
<FromGitter>
<kniknoo> er US I mean.
<FromGitter>
<meltheadorable> i started the crystal track before they switched up their structure and never got any feedback on my exercises
<FromGitter>
<kniknoo> I deeply grateful for the steps y'all took there. I feel like I found my calling thanks to being curious about a language I'd never heard of.
<FromGitter>
<kniknoo> My plan to help generate interest with my friends is to follow the Rosetta Code suggestion and collaboratively port the Ruby code. I do wanna help flesh out places like that to get Crystal closer to a first class citizen.
<FromGitter>
<dscottboggs_gitlab> TBH in my experience Crystal does not port super well from Ruby. I think you'd have better luck porting golang stuff or even other statically-compiled languages like Kotlin or C++17+
<FromGitter>
<meltheadorable> i think that depends what you’re porting
<FromGitter>
<kniknoo> Indeed. Sometimes ruby accidentally compiles. :D
<FromGitter>
<dscottboggs_gitlab> true, small scripts can be run on the crystal compiler or in ruby
<FromGitter>
<kniknoo> But yeah, I'm going to start with the most toy-like problems. Last time I looked, palindrome wasn't even done.
<FromGitter>
<meltheadorable> and for anything vaguely exorcism sized, it’s realistically probably at most going to be a matter of adding appropriate type annotations, i can’t imagine rosetta code examples being complex enough to be closer to Go than Ruby
<FromGitter>
<meltheadorable> in most cases
<FromGitter>
<kniknoo> Yep, I always finish my Crystal exercise right after my Ruby exercise so the differences really stick.
<FromGitter>
<kniknoo> My Ruby experience is 90% Sonic Pi so I'm trying to get competent with it. Along the way, I'll be pretty used to translation, which could come in handy for large porting efforts.
commavir has joined #crystal-lang
<FromGitter>
<meltheadorable> larger porting efforts i expect to get more and more difficult due to metaprogramming
<FromGitter>
<kniknoo> And lol. Keeping the dream alive!
<FromGitter>
<dscottboggs_gitlab> although, @girng, shouldn't you simulate a backspace on receiving the backspace character? I.E. for `n` received `0x08` chars, delete that many chars from the string before it?
<FromGitter>
<dscottboggs_gitlab> shit that would be a really good exercism-like problem
<FromGitter>
<girng> telnet gonna make a comeback after this 😆
<FromGitter>
<kniknoo> Tell that to SSH.
<FromGitter>
<tenebrousedge> probably want to strip out all control chars
<FromGitter>
<girng> @kniknoo hahhaah
<FromGitter>
<tenebrousedge> I have a soft spot for IRC still
<FromGitter>
<tenebrousedge> not enough to use it for gitter though
<FromGitter>
<kniknoo> I'm a security enthusiast so telnet means only one thing to me...
laaron- has quit [Remote host closed the connection]
<FromGitter>
<girng> when i worked at Costco, all their terminals looked like `htop`. all color coded and with tables
<FromGitter>
<girng> so damn beautiful
laaron has joined #crystal-lang
<FromGitter>
<girng> `colorize` module is my fav ever
<FromGitter>
<dscottboggs_gitlab> @girng `"some string with ctrl chars".gsub { |char| char if char.ord > 0x1F }`
<FromGitter>
<kniknoo> It was Papa John's godforsaken post-SCO Linux POS that got me loving Linux.
<FromGitter>
<kniknoo> Yah, I use colorize in every library already.
<FromGitter>
<dscottboggs_gitlab> `0x1F` (https://ascii.cl/) and less are control characters
<FromGitter>
<girng> @kniknoo my mom ordered papa john's recently, was the best pizza i ever had. just drenched in grease. my mom said she hated it but w/e lol
<FromGitter>
<kniknoo> I got frustrated with my ASCII art library. I can get a greyscale that I like, but I need a better way of averaging colors because everything winds up skewing bright on an average. I know there's a library to do k-means but I don't fully understand it and I'm not sure if it's overkill. I need to look into how caca did it.
<FromGitter>
<dscottboggs_gitlab> My roommate made us stop ordering Papa Johns when she read an article that said that Papa John was a huge racist :/
<FromGitter>
<kniknoo> I like Papa vs most other chains, even as a former employee. I cannot say the same for Applebee's.
<FromGitter>
<girng> @Blacksmoke16 how can you tell which ones are control chars
<FromGitter>
<kniknoo> Yeah, John has been removed for that.
<FromGitter>
<dscottboggs_gitlab> oh wow
<FromGitter>
<Blacksmoke16> `"hey thanks for the gold ,,br!!!!!".gsub /[[:cntrl:]]/, ""`
<FromGitter>
<girng> @dscottboggs_gitlab not blacksmoke, my bad
<FromGitter>
<kniknoo> It's mosly the beginning of the ASCII sequence.
<FromGitter>
<Blacksmoke16> would have to benchmark it to see which is better
<FromGitter>
<girng> like `\`?
<FromGitter>
<Blacksmoke16> sec
<FromGitter>
<dscottboggs_gitlab> @girng look at the ASCII table I linked to
<FromGitter>
<girng> i am lol
<FromGitter>
<kniknoo> Keep everything that's not a control sequence rather than editing them out each.
<FromGitter>
<Blacksmoke16> `puts "hey thanks for the gold ,,br!!!!!".chars.reject(&.control?).join` :S
<FromGitter>
<girng> 😢
<FromGitter>
<dscottboggs_gitlab> oof
<FromGitter>
<tenebrousedge> is the bang method necessary?
<FromGitter>
<girng> can't you just remove them without joining
<FromGitter>
<kniknoo> That's fine, I was meaning to use something like scan to keep /[a-zA-z0-9]/ and punctuation. But like I said above, I'm still derpy with strings so I don' have the best strategies without coaching.
<FromGitter>
<dscottboggs_gitlab> why doesn't `String` have `#reject`?????
<FromGitter>
<dscottboggs_gitlab> @tenebrousedge why wouldn't you just do `#delete('l')`
<FromGitter>
<dscottboggs_gitlab> oh I see what you're trying to say, but that is documented
<FromGitter>
<tenebrousedge> that it's documented does not make it sane <_<
<FromGitter>
<girng> > This allows to easily chain methods which could return empty value. Note that &. skips only one next call, so for a longer chain it is necessary to add operator on each level: ⏎ ⏎ What does "skips only one next call" mean
<FromGitter>
<dscottboggs_gitlab> yeah, what?
<FromGitter>
<tenebrousedge> it means that if your next value is nil you can still get an error
<FromGitter>
<girng> O_o
<FromGitter>
<dscottboggs_gitlab> yeah, what?
<FromGitter>
<dscottboggs_gitlab> @tenebrousedge I think a PR adding support for a `String#delete(Regex)` overload would probably not be denied
<FromGitter>
<girng> wait really
<FromGitter>
<girng> so if `what.delete &.control?` .control? somehow returned nil, an error will be thrown?
<FromGitter>
<girng> but that will surely never happen right
<FromGitter>
<dscottboggs_gitlab> no, `nil` would be falsey, so it would just delete that char
<FromGitter>
<tenebrousedge> no, if you continues and the return from `control` was also nil
<FromGitter>
<girng> it's literally true or false.. hmm
<FromGitter>
<dscottboggs_gitlab> but yeah that shouldn't happen
<FromGitter>
<tenebrousedge> `what.delete &.control.meow` <-- if `control` is `nil`, then `meow` will still throw
<FromGitter>
<girng> why do i even read the docs. makes my life even more confusing gosh damn. ijust thought &. is used for chaining / short-hand notation so i don't ahve to write another block
<FromGitter>
<tenebrousedge> but this is probably the safe navigation operator
<FromGitter>
<girng> then realized, if you are inside the struct Char, self is the CHAR LOL
<FromGitter>
<girng> @Blacksmoke16 nice
<FromGitter>
<dscottboggs_gitlab> Fuck that's a bad buck @tenebrousedge
<FromGitter>
<dscottboggs_gitlab> \
<FromGitter>
<girng> so what's the difference between these primitive structs
<FromGitter>
<girng> compared to extending them in your own code?
<FromGitter>
<girng> do they offer a performance advantage since they are compiled with crystal
<FromGitter>
<Blacksmoke16> hm?
<FromGitter>
<kniknoo> a struct vs class can offer a performance advantage, if that's what you're asking.
<FromGitter>
<girng> nah hard to explain 1 sec
lucasb has quit [Quit: Connection closed for inactivity]
<FromGitter>
<tenebrousedge> @dscottboggs_gitlab it's cute though, if you run it more than once you get different answers. But the same answer each time. Non-deterministic behavior is so much fun
<FromGitter>
<dscottboggs_gitlab> ...what??
<FromGitter>
<tenebrousedge> try it in the terminal
<FromGitter>
<girng> for example, if i were to add a `am_i_the_letter_k` method to struct Char, i'd have to re-compile crystal from source with that method in the struct. ⏎ HOWEVER, i can also just write `struct Class` and basically add that method there in my own code. ⏎ when the crystal code is compiled, does it perform faster than the code you have written?
<FromGitter>
<tenebrousedge> `crystal eval "a = 15; b = ->a.divisible_by?(Int32); pp [3,5,7].map(&b)"`
<FromGitter>
<Blacksmoke16> prob not
<FromGitter>
<dscottboggs_gitlab> @girng no
<FromGitter>
<tenebrousedge> @dscottboggs_gitlab run it a couple times :D
<FromGitter>
<kniknoo> Yeah, I'm getting random answers
<FromGitter>
<dscottboggs_gitlab> One may *reopen* a class/struct which adds a function as a method on that class/struct at compile time. This does not require recompiling Crystal
<FromGitter>
<kniknoo> Not unless you use a less efficient algorithm.
<FromGitter>
<girng> @dscottboggs_gitlab i know that!!
<FromGitter>
<dscottboggs_gitlab> Then what are you saying?
<FromGitter>
<kniknoo> No, your objects are the same as native objects.
<FromGitter>
<girng> that's what i showed in my example playground. but what's the difference between the compiled code, and your high level code you are writing. surely there is a performance difference right
<FromGitter>
<kniknoo> The high level is a directive to create the low level.
<FromGitter>
<girng> really?
<FromGitter>
<kniknoo> Crystal is written in crystal
<FromGitter>
<tenebrousedge> and compiled to llvm-ir and then to machine code
<FromGitter>
<dscottboggs_gitlab> yeah crystal is translated rather than interpreted on the fly so this all basically compiles to some really complicated assembly
<FromGitter>
<dscottboggs_gitlab> yeah what @tenebrousedge said
<FromGitter>
<girng> for example, in gdscript in godot. if you wanted performance, you'd write your own method in c++, then it'll be available in gdscript. you'd have to re-compile the engine though. doesn't this apply here because if i wanted a performant `am_i_the_letter_k` method for a struct, i'd add it to the core library then re-compile crystal. now i can use it
<FromGitter>
<girng> and it would be faster
<FromGitter>
<Blacksmoke16> its the same as just reopening the struct and adding it
<FromGitter>
<kniknoo> If you want non crystal, you get into link and fun.
<FromGitter>
<kniknoo> But for many things, compiled crystal is just as fast as c
<FromGitter>
<kniknoo> Once i_am_the_letter_k is actually run, it's not technically crystal anymore, but machine code.
<FromGitter>
<girng> damn, so i can fiddle around and basically put some of my methods in these primitives w/o having to re-compile everything
<FromGitter>
<kniknoo> That is monkey patching.
<FromGitter>
<kniknoo> yes
<FromGitter>
<dscottboggs_gitlab> @girng, no, since crystal is compiled rather than interpreted, your additons to `struct Char` get compiled into the final program alongside all your other code and the stdlib code that you've used in your code. It takes no addtional compile or run-time as compared to just adding a top-level function
<FromGitter>
<girng> in gdscript, i'd have to re-write a method in c++, re-compile the engine, etc, etc. then it could be used in gdscript, but it's a lot faster
<FromGitter>
<girng> looks like i need to differentiate between compiled and interpreted, thanks scott
<FromGitter>
<kniknoo> Welcome to an esay-to-read low level language. :)
<FromGitter>
<dscottboggs_gitlab> @tenebrousedge please report the example you've posted as a bug, holy crap
<FromGitter>
<dscottboggs_gitlab> @kniknoo yeah I love how Crystal can bridge the gap completely between simple scripts and systems-level programming :D
<FromGitter>
<girng> rofl that bug looks like some `rand` shit floating around in there
<FromGitter>
<kniknoo> Why I'm obsessed already. I never cared to learn any ugly languages, it's like pulling teeth to get me to write python. (no offense, python fans)
<FromGitter>
<girng> math that is supposed to be objective values, are random, roflmao
<FromGitter>
<kniknoo> Yeah, I was bummed we don't have and or or, ruby does, but I know I know...
<FromGitter>
<girng> i like myself, too
<FromGitter>
<kniknoo> I just learned that they can be misleading in some cases though, when not using strict booleans I think?
<FromGitter>
<dscottboggs_gitlab> I really wish crystal would adopt python-style `and` rather than ruby-style, but I get that it would be ultra confusing for people coming from ruby
<FromGitter>
<dscottboggs_gitlab> yeah `and` and `&&` in ruby mean different things, which is why Crystla doesn't have `and` at all.
<FromGitter>
<girng> wait.. and and && mean diff things in ruby?
<FromGitter>
<girng> what's the differentiator
<FromGitter>
<tenebrousedge> they have different precedence
<FromGitter>
<tenebrousedge> `and` has lower precedence
<FromGitter>
<kniknoo> your "hello" would not evaluate to true, if I understood correctly.
commavir has quit [Quit: leaving]
<FromGitter>
<kniknoo> Maybe I misunderstood, I don't fully understand precedence yet, it came up when I was looking at Ruby's |> last night.
<FromGitter>
<tenebrousedge> @girng actually I think it's related to threading somehow, which is worse :(
<FromGitter>
<girng> why they make syntax that does the same thing for a condition, have diff levels of precedence......
<FromGitter>
<girng> just to confuse the sht out of the developer, am i right
<FromGitter>
<kniknoo> Kinda thought so, I thought 7.2 was where most folks should be by now.
<FromGitter>
<Blacksmoke16> yea, we're working on 7.3 atm
<FromGitter>
<girng> @Blacksmoke16 you are a contributor for php?
<FromGitter>
<Blacksmoke16> naw, just a user :P
<FromGitter>
<girng> oh i'm not alone
<FromGitter>
<Blacksmoke16> its what we use at work
<FromGitter>
<girng> oh
<FromGitter>
<Blacksmoke16> hence where most of my shard ideas come from
<FromGitter>
<kniknoo> Yeah, we do too. I don't develop, I just keep up on what libraries need to be updated as part of it.
<FromGitter>
<kniknoo> I appreciate y'all are working heavy on the web shards. That's not the domain I'm aiming for, but I do intend to bring up a crystal version of our website so that we don't actually need an outsourced dev for their framework anymore.
<FromGitter>
<Blacksmoke16> if you making a JSON API checkout Athena :P
<FromGitter>
<Blacksmoke16> if you familiar with symfony you'll be right at home
<FromGitter>
<dscottboggs_gitlab> There's also @Papierkorb's semi-abandoned bindgen project which allows bindings to C++. Hypothetically the same process could be applied to D or Rust, like D does.
<FromGitter>
<watzon> Creating C bindings is so easy in Crystal
<FromGitter>
<watzon> It's really kinda magical
<FromGitter>
<girng> and `LibC::Char*` is
<FromGitter>
<dscottboggs_gitlab> is it harder in other languages?
<FromGitter>
<girng> ` const char *`
<FromGitter>
<girng> right?
<FromGitter>
<girng> return value
<FromGitter>
<dscottboggs_gitlab> @girng yup
<FromGitter>
<watzon> Definitely harder. Especially when it comes to the build process and creating packages
<FromGitter>
<watzon> It's a nightmare with Python and pip
<FromGitter>
<watzon> Ruby it's not terrible
<FromGitter>
<girng> bro...
<FromGitter>
<watzon> Node you have to install a separate package, but it's not the worst
<FromGitter>
<girng> this is really neat
<FromGitter>
<girng> i can create stuff if i find something cool that only exists in a c library and use crystal's syntax sugar instead
<FromGitter>
<dscottboggs_gitlab> yup
<FromGitter>
<kniknoo> I'll be doing this to work with audio synthesis very soon, it's like a dream come true for me to be able to work with this stuff i a way that makes sense to me.
<FromGitter>
<girng> wtf, isn't 1 pointer confusing enough, why does c have 2 pointers
<FromGitter>
<girng> 2 asterisks*
<FromGitter>
<watzon> Pretty sure it's still a splat
<FromGitter>
<girng> what's next? they gonna have ***
<FromGitter>
<dscottboggs_gitlab> nope
<FromGitter>
<watzon> Not 100% tho
<FromGitter>
<dscottboggs_gitlab> sec
<FromGitter>
<kniknoo> Oh man, just wait til you take a closer look at optional parameters, you're gonna be mad... :D
<FromGitter>
<watzon> Hahaha
<FromGitter>
<kniknoo> optinal named, rather
<FromGitter>
<girng> i mean to create the bindings, man7 helps a lot. but those inconsistencies is why i'm using crystal in the first place, lol
<FromGitter>
<dscottboggs_gitlab> It's perfectly reasaonable to have a `Pointer(Pointer(Pointer(SomeType)))`. in C, that would be represented as `***SomeType`
<FromGitter>
<watzon> Ahhh that makes sense
<FromGitter>
<girng> localtion of the asterisk... sometimes it's one `*`, sometimes is `**`.. like wtf. the language in C is like wild wild west
<FromGitter>
<watzon> You can definitely have a pointer to a pointer
<FromGitter>
<watzon> Dealing with pointers kinda sucks
<FromGitter>
<kniknoo> yeah, I'm still trying to grok those
<FromGitter>
<girng> @dscottboggs_gitlab is that actually what Void** does?
<FromGitter>
<dscottboggs_gitlab> in C, a pointer with a range of memory allocated above it is kinda what `StaticArray` is incrystal
<FromGitter>
<dscottboggs_gitlab> @girng yeah
<FromGitter>
<girng> equivalent to `Pointer(Pointer(Pointer(SomeType)))`?
<FromGitter>
<girng> WTF
<FromGitter>
<girng> really
<FromGitter>
<dscottboggs_gitlab> well, `Void**` would be a pointer to a pointer to some region of memory with no type-data associated with it
<FromGitter>
<girng> and that's just how libmagic was developed right
<FromGitter>
<girng> pointer to pointer is not needed if we create our own c code right
<FromGitter>
<dscottboggs_gitlab> what?
<FromGitter>
<girng> i mean, if writing c code ourselves, we are not forced to use double pointers correct?
<FromGitter>
<dscottboggs_gitlab> sure
<FromGitter>
<girng> we can code something with just one pointer..
<FromGitter>
<girng> why libmagic play with us like that then
<FromGitter>
<dscottboggs_gitlab> well, yes, but C does not have an `Array` type
<FromGitter>
<girng> wait
<FromGitter>
<girng> can we create c++ bindings as well, not just c?
<FromGitter>
<dscottboggs_gitlab> in C, `char x[7]` is a location in memory with 7 bytes available to be assigned to it.
<FromGitter>
<dscottboggs_gitlab> C++ bindings are through a no-longer-maintained library by a user who is no longer active in the community. I've tried a few times to learn the library and pick up maintaining it and it's very large and complicated
<FromGitter>
<kniknoo> That's a shame. :/
<FromGitter>
<dscottboggs_gitlab> C++ methods are C functions with mangled names... it gets complicated
<FromGitter>
<girng> > in C, `char x[7]` is a location in memory with 7 bytes available to be assigned to it. ⏎ ⏎ i think that is my biggest downfall with c, memory allocation n whatnot. just so much shit you have to do
<FromGitter>
<girng> when it can be done with crystal with ease
<FromGitter>
<girng> or.. other languages
<FromGitter>
<kniknoo> It's still being done...
<FromGitter>
<tenebrousedge> there are things that you can do in C that can't be done any other way
<FromGitter>
<kniknoo> But if you tune it yourself vs letting it automatically get sorted out, you get advantages, just like with crystal over ruby.
<FromGitter>
<dscottboggs_gitlab> @tenebrousedge like what?
<FromGitter>
<dscottboggs_gitlab> @kniknoo I don't think C has many advantages over crystal, at least not in the same way as Crystal has advantages over Ruby.
<FromGitter>
<tenebrousedge> introducing backdoors into ARM-based network security devices
<FromGitter>
<meltheadorable> maybe not many, definitely some — think you still need C when you need to manually control memory layout for performance-sensitive stuff
<FromGitter>
<dscottboggs_gitlab> Crystal has both performance and safety over Ruby, with a mild sacrifice in developer time and a moderate sacrifice in the need for developer experinece. C has speed over crystal *if* the developer is experienced, but lacks the safety of C and requires developers with *much* deeper understanding of the underlying system
<FromGitter>
<kniknoo> Yep, what I realized today when asking about trying to do audio in crystal all the way down.
<FromGitter>
<meltheadorable> well, rust can maybe take care of some of that now, and be a bit safer about it, or at least more visibly unsafe when it can't
<FromGitter>
<girng> if i find a library that's in c, and write bindings. do i need to re-compile crystal?
<FromGitter>
<tenebrousedge> no
<FromGitter>
<kniknoo> It functions like any shard you bring in.
<FromGitter>
<girng> how do i include the 3rd party library
<FromGitter>
<dscottboggs_gitlab> @meltheadorable True -- I've been studying Rust and C++ lately as alternatives to Crystal (modern C++17 and 20 offer many of the safety and conveniences offered by Crystal) but both languages are much more clumsy syntactically IMO
<FromGitter>
<kniknoo> Er wait, I'm taking that for granted. Is it statically linked or does it link to the library?
<FromGitter>
<girng> what's the file though
<FromGitter>
<dscottboggs_gitlab> It's dynamically linked by default, @kniknoo but there is a `--static` compiler option
<FromGitter>
<watzon> Rust is pretty awesome
<FromGitter>
<girng> is it a .so, .dll, etc
<FromGitter>
<kniknoo> nice
<FromGitter>
<dscottboggs_gitlab> @girng gerneally if you use pkg-config and install the development libraries for your distro, it just works without worrying about where the file is
<FromGitter>
<meltheadorable> @dscottboggs_gitlab i much much much much much prefer crystal, I’m just trying to give credit where it’s due, crystal is garbage collected, can’t manually control memory layout, and can’t be used to create shared libraries, that means it’s inappropriate for some places you still need C in practice
<FromGitter>
<kniknoo> Ok. So making sure I understand, if I want to distrubute to someone without making them grab the dev files, I'll want to do the static option?
<FromGitter>
<tenebrousedge> static is for if you want to avoid linking to system binaries
<FromGitter>
<dscottboggs_gitlab> @kniknoo there is no way to export a crystal library without providing the source code currently
<FromGitter>
<kniknoo> Cool, good to know.
<FromGitter>
<dscottboggs_gitlab> @meltheadorable that said, there is the potential for the ability to export Crystal code built into the sytem -- one can declare a `fun` and call it from `C`, so the glue could be put together in time. Additionally, Crystal's garbage collection, while built into the stdlib pretty heavily, isn't strictly necessary -- one can create stack-allocated `structs` which wrap pointers just like C++'s classes.
<FromGitter>
... In time, I hope the stdlib is further optimised to take adavantage of these featurews.
<FromGitter>
<watzon> I do as well. It would be nice for some applications if you could give Crystal a `--no-gc` flag and manage memory manually
<FromGitter>
<girng> i want to bind vulkan
<FromGitter>
<girng> ;D
<FromGitter>
<girng> start with a tiny app, to display a window. that's it
<FromGitter>
<watzon> It's possible that someone's already started
<FromGitter>
<girng> wait why would i wnat to disable the gc
<FromGitter>
<girng> memory leak imminent?
<FromGitter>
<meltheadorable> @dscottboggs_gitlab i think the main use case i want shared libraries for is one that will never be supported, which i’m a little sad about, so i’ve given up on it a bit
<FromGitter>
<watzon> There are some cases when you don't want a GC
<FromGitter>
<watzon> Like when building an OS kernel
<FromGitter>
<girng> can we disable the gc, and delete structs/classes manually
<FromGitter>
<girng> that be cool lolz
<FromGitter>
<kniknoo> essentially...
<FromGitter>
<girng> but, then again, i don't want to do that
<FromGitter>
<girng> i'd rather gc take care of it
<FromGitter>
<watzon> With great power comes great responsibility...
<FromGitter>
<meltheadorable> SFML is the furthest along so far IIRC
<FromGitter>
<kniknoo> I need to figure out why I can't get it to work.
<FromGitter>
<meltheadorable> and seems generally preferred over SDL these days
<FromGitter>
<meltheadorable> at least in circles adjacent to me
<FromGitter>
<girng> david brevik (lead dev for d2), recently created his it lurks below game with directx, then ported it to SDL
<FromGitter>
<girng> can do a lot of good stuff with SDL
<FromGitter>
<tenebrousedge> brains? hmm. Is there some wizard I can run for those?
<FromGitter>
<girng> 😆
<FromGitter>
<kniknoo> Let me check the shards
<FromGitter>
<meltheadorable> vulkan seems like a needlessly painful fit for creating something like love2d
<FromGitter>
<meltheadorable> most 3d apis require you to maintain constant awareness of an entire plane that you aren’t using and include it in all your calculations anyway
<FromGitter>
<girng> yeah that might be overkill
<FromGitter>
<girng> simple opengl bindings or something prob be just fine
<FromGitter>
<girng> but gosh, i swear crystal would be a great fit for a 2d game engine
<FromGitter>
<girng> it's like the perfect syntax, imo anyway
<FromGitter>
<kniknoo> I'm hinting at the dragonruby guys to look at crystal before they're too invested...
<FromGitter>
<watzon> Do we have any OpenGL bindings yet? That seems like an obvious thing that we should have by now
<FromGitter>
<girng> what's dragonruby?
<FromGitter>
<meltheadorable> Iirc dragonruby has a long long history related to rubymotion and macruby, i doubt they’d be inclined to completely change course even though it’s technically new
* FromGitter
* girng googling
<FromGitter>
<kniknoo> It's a live-coded gaming development environment. Still in its infancy, but has a lot of potential for quick development.
<FromGitter>
<watzon> I don't know that Crystal is capable of linking a dll. If it is I don't know how.
<FromGitter>
<watzon> Actually I take that back
<FromGitter>
<watzon> I think it's possible
<FromGitter>
<girng> there must be a way, because when someone ships their game. they need to make sure the player has the required .dll
<FromGitter>
<watzon> I just don't know how
<FromGitter>
<girng> i wonder if --static
<FromGitter>
<girng> includes the opengl
<FromGitter>
<meltheadorable> @watzon if you’re binding something from C, do you need to bind all its dependencies too? I’m a little unclear on what it would take to bind certain stuff — my guess is you would need to bind anything that defines custom types, for Crystal to be aware of and properly handle those types, but possibly not like, every API interface exposed
<FromGitter>
<watzon> Idk, all I know is that with LibGL it uses the system libraries
<FromGitter>
<watzon> @meltheadorable yeah generally you can just bind what you need, along with any custom types
<FromGitter>
<girng> holy shit this is really low_level stuff
<FromGitter>
<watzon> Or you can wrap the whole API
<FromGitter>
<girng> i don't know how to even create primitives...
<FromGitter>
<girng> draw_char, etc
<FromGitter>
<meltheadorable> i was trying to figure out what it would take to bind native Cocoa but got a headache reading about the objective c runtime
<FromGitter>
<watzon> Yeah idk about that
<FromGitter>
<watzon> Objective C is a pain in the ass
<FromGitter>
<tenebrousedge> it's nuts
<FromGitter>
<meltheadorable> also GTK but then I have to deal with GObject
<FromGitter>
<meltheadorable> i saw that, it’s….really messy
<FromGitter>
<watzon> Yeah, I think it's mostly a poc
<FromGitter>
<meltheadorable> I thought about forking it and cleaning it up, but I realized after looking at it a while that by the time i split it out into appropriate shards, and cut it down to like, just the binding generator, there was very little code left and I didn’t trust the binding generator
<FromGitter>
<girng> > asterite commented on Jun 18, 2015 ⏎ ⏎ sad :(
<FromGitter>
<watzon> Yeah... Lots of people dropping libs
<FromGitter>
<girng> Asterite also mentioned something about he would like to spent time on love2d
<FromGitter>
<girng> he prob would have liked something liek that in crystal
<FromGitter>
<meltheadorable> @tenebrousedge Qt’s license situation sucks, it’s C++ not C which adds complications, and I actually want GTK specifically because I use gnome on linux and so stuff i wrote would be functionally native there, if Qt5.cr worked or was even close to working, I’d settle for it, but if I have to bind something myself, I might as well bind the something I actually want to use
<FromGitter>
<watzon> Crystal would make a great language for a game engine though
<FromGitter>
<watzon> It would make game development so much easier
<FromGitter>
<girng> i commented there
<FromGitter>
<tenebrousedge> @meltheadorable GPLv3 isn't your bag?
<FromGitter>
<meltheadorable> not really
<FromGitter>
<tenebrousedge> por que no?
<FromGitter>
<watzon> I like GPLv3 m'self
<FromGitter>
<meltheadorable> I prefer permissive licenses, mostly
laaron- has joined #crystal-lang
<FromGitter>
<girng> seems like SDL has all those primitives already
<FromGitter>
<girng> asterite is right. sdl with opengl context is the best
<FromGitter>
<girng> crsfml is really cool i looked at their game examples
rohitpaulk has quit [Ping timeout: 245 seconds]
<FromGitter>
<bararchy> Oh wow the Gitter channel is on full drive XD 600 unread messages
<FromGitter>
<watzon> Hehe
laaron has joined #crystal-lang
<FromGitter>
<meltheadorable> @watzon do you know an example of any really well-done bindings packaged as a shard — for literally anything, just trying to get a vague idea of a good folder/file structure to use
<FromGitter>
<watzon> I've got a lot of work to do still, but I don't think I've done a bad job with https://github.com/watzon/nacl
<FromGitter>
<meltheadorable> bindings take a long time to write
<FromGitter>
<watzon> Generators are helpful haha
<FromGitter>
<meltheadorable> yeah, and there’s already some bindings out there for SDL so I’m mostly wasting my time, but it’s a good learning experience, and I managed to bind just enough of it to open a window
<FromGitter>
<meltheadorable> working with pointers like that is super unpleasant, I think the challenge will ultimately actually be in wrapping SDL in something that feels more natively crystal
<FromGitter>
<meltheadorable> but still, it does like…work
<FromGitter>
<watzon> Yeah that's definitely the challenge
<FromGitter>
<watzon> You should look into libgen. It could create all the bindings for you in less than 20 minutes. You will probably have to do some tweaking, but it'll get you pretty far pretty fast and allow you to start wrapping things
<FromGitter>
<meltheadorable> I’m looking forward to being done with the boring part and getting to the neat bit, but I’m not sure a binding generator would have helped much, these headers are full of like, really weird macros
absolutejam4 has joined #crystal-lang
<FromGitter>
<meltheadorable> and for this case I also just really wanted to see how little I could do and manage to accomplish the task
<FromGitter>
<watzon> The macros you'd have to port by hand if they're important, but it can at least export the functions, classes, structs, and constants for you
<FromGitter>
<meltheadorable> if i didn’t need to bind events it would have been very very little, but I needed to pull in some structs to resolve types in events I wasn’t using but were part of a union
<FromGitter>
<meltheadorable> i’ll consider starting over with a bindings generator in the morning, for now it’s 3:30am and im glad i did this much by hand
<FromGitter>
<meltheadorable> better that i understand what’s going on my first time out
<FromGitter>
<watzon> Definitely haha
<FromGitter>
<watzon> Binding is kinda of frustrating, but fun too
<FromGitter>
<meltheadorable> the benefit of binding by hand is that i’m familiarizing myself with the library itself — I’ve never coded SDL before, so having to do all this stuff by hand is also familiarizing me with the API
<FromGitter>
<meltheadorable> which will probably mean i’ll generate a better wrapper
<FromGitter>
<meltheadorable> when the time comes
<FromGitter>
<meltheadorable> I’m not sure how much more of this i’ll do by hand because there’s just…an absurd number of enums and constants I definitely don’t want to waste my time on
<FromGitter>
<meltheadorable> but i’m for sure glad i did some of it manually
dingenskirchen has quit [Remote host closed the connection]
ht_ has joined #crystal-lang
<FromGitter>
<meltheadorable> it almost works when i try to give it individual definitions for each header except that they all mutually include each other so it just ends up making a bunch of them empty and then dumping giant stacks of defines into a catch-all
<FromGitter>
<meltheadorable> i’m not sure how to make it do the right thing
<FromGitter>
<girng> omg u got to be kidding me i almost got this to work
<FromGitter>
<girng> my SDL_GetError prints "Failed to connect to the Mir Server"
<FromGitter>
<girng> reason: WSL FML
<FromGitter>
<girng> sooooooooo close of getting that window to pop up fml
<FromGitter>
<watzon> Maybe try running Linux in a VM instead of using WSL?
<FromGitter>
<girng> eh, coding in a vm is cancer
<FromGitter>
<girng> i want to fiddle around with binding other stuff outside of the front end
<FromGitter>
<girng> i think this is quite interesting
<FromGitter>
<girng> so many c libraries
FromGitter has quit [Remote host closed the connection]
oprypin has quit [Quit: Bye]
oprypin has joined #crystal-lang
FromGitter has joined #crystal-lang
<FromGitter>
<watzon> I'd argue that coding in WSL is cancer haha. I used a Linux VM for a long time when I was on Windows. Works great.
<FromGitter>
<girng> i'm on a 144hz. going into a vm makes it seem like someone drugged me
dingenskirchen has joined #crystal-lang
<FromGitter>
<watzon> Hmm, it usually would depend on your graphics card and how powerful your system is. Can't you turn down the refresh rate on your monitor anyway?
<FromGitter>
<watzon> I never had an issue with that
<FromGitter>
<girng> if i do that, then everything is seems laggy cause my eyes are so used the fluidity of 144hz.
dingenskirchen has quit [Ping timeout: 250 seconds]
<FromGitter>
<girng> i'm not smart or knowledgable enough to be working on this sdl stuff anyway
FromGitter has quit [Remote host closed the connection]
oprypin has quit [Quit: Bye]
oprypin has joined #crystal-lang
dingenskirchen has joined #crystal-lang
FromGitter has joined #crystal-lang
<FromGitter>
<girng> since doing some of these c bindings, i watched some tutorials on c and i kinda like it. i lovee making all these functions
<FromGitter>
<girng> only thing is, there is no dictionary
<oprypin>
@meltheadorable, excuuuse me :D what hack are you speaking of? no but i'm mostly curious because people usually don't dig deep enough to have *any* opinion on VoidCSFML
<FromGitter>
<girng> @oprypin i didn't know you were the owner of voidcsfml
<FromGitter>
<girng> that's cool, you made that so sfml would bind
<oprypin>
it's really an integral part of crsfml, not truly separable
<oprypin>
then there's CSFML which i have no affiliation with
<FromGitter>
<girng> i just learned some bindings today. i was fiddling around with SDL2 and the gitbook page has been extremely helpful
<FromGitter>
<girng> a lot of it was just seeing the types and return values.. and resolving C types to Crystal's. which gitbook literally has a cheatsheet. pretty awesome
<FromGitter>
<girng> yeah dereferencing n stuff is super confusing with pointers
<FromGitter>
<girng> syntax wise, anyway
<FromGitter>
<girng> too many f*cking asterisks
<FromGitter>
<girng> c++ is aids
<oprypin>
that's not nicec
<FromGitter>
<girng> that header file looks nice
<FromGitter>
<girng> clean
<FromGitter>
<girng> did you write all those out?
<FromGitter>
<girng> or was that generated
<oprypin>
generated
<oprypin>
the .cpp was also generated
<FromGitter>
<girng> nice
<FromGitter>
<girng> should have lied
<oprypin>
writing a lot of stuff manually is nothing to brag about :D
<FromGitter>
<girng> 👍
<oprypin>
i can instead brag that i wrote the code that generated all of that
<FromGitter>
<girng> nah you wouldn't do that
<FromGitter>
<girng> hey @oprypin
<FromGitter>
<girng> do you recommend i start coding in c?
<oprypin>
girng, i categorize it in about the same category as coding in assembly, though not nearly as extreme
<oprypin>
i.e. it's good for expanding your understanding of computing but not much beyond that
<FromGitter>
<girng> well on that note, i think i'm going to say that's a big no for me then
<FromGitter>
<girng> i was having quite a bit fun watching this tutorial though and following it. then i wanted to create a dictionary/hash map, and you need to like manually allocate memory, keep a nodelist, etc. when in crystal, we can just do Hash(Int32, String).new rofl...
<oprypin>
girng, well you *could* also use a hashtable library for C that someone has already written
<oprypin>
that one is probably more educational - how to make one yourself, specifically
<FromGitter>
<girng> i thought of that
<FromGitter>
<girng> i mean, crystal uses a wrapper for hash right
<oprypin>
no
<FromGitter>
<girng> what's the Hash.cr then
<oprypin>
well it's code to implement that node list
<FromGitter>
<girng> wtf
<oprypin>
not sure what you mean by "wrapper" then
<FromGitter>
<girng> crystal has to do that too?
<FromGitter>
<girng> they just make it easier to use it, syntaxically then
<oprypin>
well a hashtable is not an intrinsic property of the universe, so yeah
<FromGitter>
<girng> if i use a hash table library in c.. i wonder if it'll be just as easy to use like how crystal's hash functions
<FromGitter>
<girng> ` def initialize(block : (Hash(K, V), K -> V)? = nil, initial_capacity = nil)` good lord
<FromGitter>
<girng> i think the .cpp code you linked was easier to read than this
<FromGitter>
<girng> crystal sure does hide the ughlier parts of the syntax
<FromGitter>
<girng> in the core files lool
<oprypin>
this is not about syntax
<FromGitter>
<girng> but, it does make it easier for me to use these
<FromGitter>
<girng> @oprypin sure it is, that's not the crystal syntax i know
<FromGitter>
<girng> @oprypin here's another `def merge(other : Hash(L, W), &block : K, V, W -> V | W) forall L, W`
<FromGitter>
<girng> wtf is that
<oprypin>
well you should know it because it's completely normal syntax for generics
<FromGitter>
<girng> is it? because i've seen a lot of shards and i've never seen methods like that
<oprypin>
Hash(K,V) merged with Hash(L,W) produces Hash(K|L, V|W)
<oprypin>
and the function/block that merges each item accepts a key and both values. it must return a value that is valid in the resulting Hash, which we've previously established to be V|W
<oprypin>
K stands for key, L is just an arbitrary letter that stands for "key of the other one"
<oprypin>
same goes for V = value but also W
<FromGitter>
<girng> feels like hash matrix
<FromGitter>
<girng> i didn't know there was that much going under the hood just for a hash
<FromGitter>
<girng> pretty cool, actuaally
<FromGitter>
<girng> also pretty nice how it's available to be used with such an easy syntax. Hash(T, T).new. hash.delete, etc
_whitelogger has joined #crystal-lang
<FromGitter>
<vladfaust> Why is Float64 considered default in Crystal, not Float32?
<FromGitter>
<tenebrousedge> somehow that seems more normal to me, but I couldn't say why
<FromGitter>
<tenebrousedge> @vladfaust you run that crystal jobs site, right?
<FromGitter>
<vladfaust> No
<FromGitter>
<tenebrousedge> hmm, kay
<FromGitter>
<vladfaust> In C, float is 32 bytes
laaron has quit [Remote host closed the connection]
laaron has joined #crystal-lang
<FromGitter>
<tenebrousedge> in Ruby it's 64
absolutejam4 has quit [Ping timeout: 245 seconds]
<Groogy>
in C float is 32 bytes because it's old
<Groogy>
but there isn't reeally any reason to not have it be 64 bits these days
<Yxhuvud>
Also you can get along with 32 bit ints in a lot of circumstances, whereas higher precision floats are usually worth the little overhead it gives.
<FromGitter>
<kniknoo> So sfml, i tried reinstalling the dependencies last night from apt and it's still complaining. Do i need to build a newer package and where does that come from if so?
<FromGitter>
<tenebrousedge> what error are you getting?
<FromGitter>
<kniknoo> Lemme fire up compy for the day.
<oprypin>
vladfaust, in C `1.234` is 64bit, just like in Crystal
<oprypin>
kniknoo, i can help but please be more precise with whats going wrong :p
<FromGitter>
<kniknoo> /usr/bin/ld: cannot find -lvoidcsfml-graphics (this usually means you need to install the development package for libvoidcsfml-graphics) ⏎ /usr/bin/ld: cannot find -lvoidcsfml-window (this usually means you need to install the development package for libvoidcsfml-window) ⏎ /usr/bin/ld: cannot find -lvoidcsfml-system (this usually means you need to install the development package for libvoidcsfml-system)
<FromGitter>
<kniknoo> I'm not sure where to find this, libvoid* brings up nothing in apt...
<oprypin>
kniknoo, no it's part of crsfml, need to follow instructions to add the local directory into LD_LIBRARY_PATH
<FromGitter>
<kniknoo> Ok, thank you. I can be bad for missing the obvious. I'll give it a read over.
<FromGitter>
<vladfaust> @oprypin, so it's `double` by default?
<oprypin>
vladfaust, yes
<FromGitter>
<kniknoo> I know why it didn't click, I went straight for the demos like a little kid and just assumed. Thank you again, I'm so used to apt being the culprit for missing stuff.
<FromGitter>
<dscottboggs_gitlab> @watzon @meltheadorable I haven't done any work on Magic.cr in a while, I consider it done. If there are any issues or anything you feel should be better documented, let me know. And I'd be glad to help with questions you have about bindings in general. For magic.cr and for the WIP av.cr (https://github.com/dscottboggs/av.cr) I used @j8r 's autobind (https://github.com/j8r/crystal-autobind) to create
<FromGitter>
... a rough template, and then manually edited from there. I'll have to take a look at libgen though, I don't think that existed when I looked into this last
<FromGitter>
<dscottboggs_gitlab> Oh wow, that libgen looks really nice. Like what bindgen was doing but with a realistic level of configuration.
dingenskirchen has quit [Ping timeout: 264 seconds]
dingenskirchen has joined #crystal-lang
dingenskirchen has quit [Read error: Connection reset by peer]
dingenskirchen1 has joined #crystal-lang
dingenskirchen1 is now known as dingenskirchen
lucasb has joined #crystal-lang
<FromGitter>
<meltheadorable> oprypin: apologies, did not intend to disparage your work at all when I called VoidCSFML a hack — I was actually just referring to the need for it in general, it’s just one extra layer too many for me, concerned about long term maintenance of a project that requires ⏎ ⏎ 1) Custom crystal bindings ⏎ 2) A bindings generator ⏎ 3) A working, generated C binding for a C++ library ...
<FromGitter>
<meltheadorable> @dscottboggs_gitlab i have unfortunately given up on libgen, i can’t seem to make it work and i have no idea how to debug it or what i’m doing wrong 😭 how was autobind?
<FromGitter>
<dscottboggs_gitlab> > how was autobind? ⏎ ⏎ minimal... it just gets you the general layout.
<FromGitter>
<dscottboggs_gitlab> disappoting that you didn't have good experience with libgen, it looks promising at a glance
<FromGitter>
<meltheadorable> well, libgen is not getting me that, it’s just getting me either error messages or ignoring the files i tell it to make and dumping everything into a global one instead
<FromGitter>
<meltheadorable> neither of which is workable
<FromGitter>
<meltheadorable> 😭
<FromGitter>
<Blacksmoke16> feel free to ask questions/etc
<FromGitter>
<meltheadorable> @dscottboggs_gitlab it might not be libgen’s fault, it’s possible SDL is just doing something super weird that it can’t cope with for whatever reason
<FromGitter>
<meltheadorable> hmmmm, the stuff that autobind silently fails to pick up might be more of a liability than an asset compared to hand-binding, i seem to be stuck between rocks and very hard places 😂
laaron has quit [Remote host closed the connection]
<FromGitter>
<meltheadorable> @naqvis libgen wraps it, so i assume it’s probably not going to help but i could be wrong, i might take a look at it later
<FromGitter>
<naqvis> yeah, but it will be good to tweak flags yourself, instead of having libgen on your way 😆 . btw its `flags:` keyword of `@Include` annotation, which require tweaking. Especially for C++ libraries
<FromGitter>
<meltheadorable> this is a C library
<FromGitter>
<meltheadorable> entirely unrelated question now though — is it possible to hook the crystal compiler from within crystal code? to like, compile an AST & write a binary
<FromGitter>
<tenebrousedge> the Crystal compiler is a Crystal program
<FromGitter>
<meltheadorable> i realize that, i was not sure that meant i could use it as a library in this kind of a way that i would like to
<FromGitter>
<meltheadorable> or what would be involved in doing so
<FromGitter>
<tenebrousedge> I think just `require "compiler"`
<FromGitter>
<tenebrousedge> that's all the setup in the spec files anyway
<FromGitter>
<meltheadorable> suppose i would need to spend a while learning about the compiler internals to figure out how to hook into the appropriate stage of the process
<FromGitter>
<meltheadorable> but nice to know it should hopefully perhaps be easy to get access to what i need
dingenskirchen has quit [Read error: Connection reset by peer]
<FromGitter>
<naqvis> or what about looking into `play` codebase? I guess this is something which you might be interested
<FromGitter>
<meltheadorable> In this case, the goal would be a (very simple) proof of concept programming language that is too syntactically different to be done with the macro system, but would hopefully be able to interop with crystal code, at least a little bit, my thinking was that if my parser could generate crystal AST nodes, i could hook the crystal compiler from there to build the binary, but i don’t want to actually
<FromGitter>
... generate crystal syntax and re-parse if it can be avoided
<FromGitter>
<naqvis> sounds sth like bytecode generation or that is how those `vm` languages work.
<FromGitter>
<meltheadorable> i don’t want it to be interpreted, that would be easy, but would still mostly preclude any crystal interop, thats why i want to hook the compiler
<FromGitter>
<meltheadorable> id just like to hook the compiler after it’s already parsed & created an AST
<FromGitter>
<meltheadorable> ideally i could generate an identical-or-close-enough AST to what crystal would have generated, but with a parser that recognizes different syntax
<FromGitter>
<kniknoo> Interesting. I have a very real reason to want to implement Ruby in crystal, I'll keep an eye on your thoughts here as it seems connected to what I want to achieve.
<FromGitter>
<meltheadorable> i think you’d be after something different actually, ruby’s got a lot of runtime behavior you wouldn’t be able to build so that it’s still compilable
<FromGitter>
<kniknoo> The idea is to be able to use a ruby interpreter to generate crystal binaries for things that I need optimized while leaving a similar and easier to use script to work with those compiled objects. In my concept for synthesis, it's used to separate slow commands (sequencing) from fast commands (dsp). Still a lot to think out in my head before I ever take a step, but what you're saying is standing out to me as
<FromGitter>
... I'm very interested in compiling from within a crystal script as a potential avenue.
<FromGitter>
<tenebrousedge> I would just write the code in Crystal. There's at least proof-of-concept stuff for using Crystal shards in Ruby apps
<FromGitter>
<tenebrousedge> but I'd be interested in going the other way
<FromGitter>
<meltheadorable> Haha yeah, I read that over a couple days ago and was very disappointed by the to be continued 😂
<FromGitter>
<naqvis> 😆
<FromGitter>
<kniknoo> Neat! I'll look into this a bit when I get back home. 6 hour drive ahead of me today, lots of time to ponder what I've read here.
dingenskirchen has quit [Ping timeout: 272 seconds]
<FromGitter>
<meltheadorable> @tenebrousedge the other way being using ruby code in crystal apps?
<FromGitter>
<tenebrousedge> yes
<FromGitter>
<meltheadorable> yeah, i’m unsure what that would take — a ruby interpreter written in crystal could be cool, even if it only implemented like, the part that’s in `mruby`
<FromGitter>
<kniknoo> In the long run, it's worth it ti me to explore both
<FromGitter>
<meltheadorable> i have nothing so ambitious in mind, myself ^_^
<FromGitter>
<tenebrousedge> I'd settle for just being able to import functions like C
<FromGitter>
<kniknoo> I envision it for Sonic Pi, so iitially I'd just be concerned about its implementation before Ruby proper
<FromGitter>
<kniknoo> It's my DAW of choice. I can't even deal with visual sequencers anymore, too linear. I'm writing stuff that makes percussionists ask me what the hell time signature I'm usinf so I know I'm onto something unique. No matter how much effort, a perfect synthesis studio for me is high priority.
<FromGitter>
<meltheadorable> idk what sonic pi is
<FromGitter>
<kniknoo> It's a music sequencer written in Ruby using Ruby code to change the sequence in real time by re-saving the script.
<FromGitter>
<kniknoo> It lets me write music as probabilities and focus on the sound design.
<FromGitter>
<meltheadorable> poking around the compiler internals, this unfortunately seems like it’d be pretty dicey to sort out
<FromGitter>
<kniknoo> I don't suppose anyone out there is researching the concept of a Crystal MCU (arduino, ESP, Micro:Bit, etc) DSL, kinda like micropython? It's not like there's an intermediate LLVM target or anything is there?
<FromGitter>
<kniknoo> Something that the arduino bootloader can read, for example. Raw atmel would be fine, but I'd like to have the advantage of behind the scenes building and pushing to device using their bootloaders.
<FromGitter>
<girng> hello
<FromGitter>
<tenebrousedge> o/
<FromGitter>
<meltheadorable> yo
<FromGitter>
<girng> i feel smarter today! yesterday was quite a ride!
<FromGitter>
<girng> i kinda overestimated the c bindings though. not a lot of c libraries i care about that i feel that could benefit me. everything i need is already in crystal, lol
<FromGitter>
<absolutejam_gitlab> @paulcsmith just listened to the Lucky bike shed episode 👌
lucasb has quit [Quit: Connection closed for inactivity]
<FromGitter>
<kniknoo> Lucky has a podcast?
<FromGitter>
<watzon> Wow there have been a lot of messages in the past 8 hours
<FromGitter>
<tenebrousedge> last night was moar, I think
blassin has joined #crystal-lang
<FromGitter>
<kniknoo> I guess i bring the party....
<FromGitter>
<kniknoo> Looks like there is active development for llvm to target 8bit atmels. Nifty!
<FromGitter>
<paulcsmith> @absolutejam_gitlab thanks! Glad you liked it. Have you had a chance to give Lucky a try?
<FromGitter>
<Blacksmoke16> @absolutejam_gitlab thanks man, it turned out quite nice i must say
<FromGitter>
<kniknoo> Would you recommend being comfortable with rails first?
<FromGitter>
<Blacksmoke16> hm?
<FromGitter>
<meltheadorable> presumably before trying out lucky
<FromGitter>
<kniknoo> I figured. On my list. I went through some of the rails guide again recently, but i let myself get into version conflict Hell on my local system and realized i need to just go back to c9 with their stable versions while learning it.
<FromGitter>
<tenebrousedge> are you not using rbenv ?
<FromGitter>
<kniknoo> I'm a noob about some things. Nearly all my ruby experiences is in a specialized environment already. I will look into this.
<FromGitter>
<denolfe> I just tried out asdf version manager the other day for both node and crystal. I assume it'd work just as well for ruby 👍
<FromGitter>
<tenebrousedge> probably
<FromGitter>
<kniknoo> asdf looks handy! Wow, thanks, i always expected it was more of an involved process like setting up a chroot or something.
<FromGitter>
<Blacksmoke16> few people had issues with it with crystal in the past
<FromGitter>
<Blacksmoke16> due to it having an old llvm version
<FromGitter>
<kniknoo> I'm sure it will be moot at 1.0 but i do like that play gives you a choice of versions for Crystal.
<FromGitter>
<kniknoo> In fact... Play is just a brilliant tool all around.
<FromGitter>
<Blacksmoke16> there is also a local version of it
<FromGitter>
<Blacksmoke16> `crystal play`
<FromGitter>
<kniknoo> My friends get wide eyed when they see a return value every time it's relevant.
<FromGitter>
<kniknoo> Oh yeah, I'd be list without it.
<FromGitter>
<tenebrousedge> return value?
<FromGitter>
<kniknoo> It's so nice to build an object in play and see every method do it's thing and report back on types. Oncei have it locked down there i move it to my ide knowing I'm pretty confident in what it's doing.
<FromGitter>
<kniknoo> If you build a class and then call it in play, every method invoked will show you what it got along the way, value and type.
<FromGitter>
<kniknoo> (I rewrote it with Arrays, but this nicely shows it off in context)
<FromGitter>
<tenebrousedge> hmm, tuple seems like it would be preferable to an Array
<FromGitter>
<Blacksmoke16> Enum would be good here
<FromGitter>
<kniknoo> Good call, I'm not used to really valuing the power of tuples yet.
<FromGitter>
<tenebrousedge> or enum, yeah
<FromGitter>
<Blacksmoke16> Actually this might already be in stdlib
<FromGitter>
<tenebrousedge> the discordian calendar? I hope not
<FromGitter>
<Blacksmoke16> Er, with actual correct info :p
<FromGitter>
<kniknoo> Yeah. I'm using mostly time.day_of_year to calculate everything. I pretend like leap day doesn't exist though so every year is 365.
<FromGitter>
<tenebrousedge> but the discordian calendar has a leap day o_o
<FromGitter>
<kniknoo> It's a st tibs day celebration when that happens, with a claim that the day isn't real.
<FromGitter>
<kniknoo> Yes, but it's considered to be a virtual day, the month and day of week do not increment for st tibs day.
<FromGitter>
<meltheadorable> yeah but won’t your duration math be off if you ignore it?
<FromGitter>
<meltheadorable> adding days to each other/removing days from each other need to account for leap days
<FromGitter>
<kniknoo> on a regular year, it goes Chaos 59 (feb 28) to Chaos 60 (march 1) on a leap year it goes Chaos 59 -> St Tibs -> Chaos 60
Yxhuvud has quit [Remote host closed the connection]
<FromGitter>
<kniknoo> I'll push it after I doc it when I get back. I tested it out with arbitrary dates and compared it to ddate.
<FromGitter>
<kniknoo> I'd be really grateful to see the Enum pattern you're talking once I do.
<FromGitter>
<Blacksmoke16> Especially since it was in Ruby, not too many di articles are
Groogy has quit [Read error: Connection reset by peer]
absolutejam4 has joined #crystal-lang
<FromGitter>
<meltheadorable> @Blacksmoke16 the thing that frustrates me is that it keeps saying things like "It is not possible to change behaviour or reuse code by providing different dependencies, if they are hard-coded.” but you have the code! You already have to change the code to make it inject a different dependency, changing `container.resolve(:user_validator)` to `container.resolve(:new_validator)` is functionally the
<FromGitter>
... exact same thing as changing `UserValidator` to `NewValidator`, but with a buttload of unnecessary complexity living in the resolution, and more complex method signatures on initialization, if you have to change the code either way I just cannot see what is added here, besides complexity for no benefit
rocx has joined #crystal-lang
<FromGitter>
<meltheadorable> it’s an extra layer of indirection and you need to change the exact same amount of code to swap one thing out for another
<FromGitter>
<meltheadorable> what am i missing?
<FromGitter>
<Blacksmoke16> IMO, mainly the points around testing and you're making two classes tightly depend on one another
<rocx>
is there any reason why annotations have an `end` at the end of their declarations and abstract methods dont?
<FromGitter>
<Blacksmoke16> also, assuming you are using the same validator in other classes, you're doing a lot of `UserValidator.new xx`
<FromGitter>
<Blacksmoke16> rocx defining an annotation is more like an empty class/struct than an abstract def
<FromGitter>
<watzon> He's got a point though
<FromGitter>
<meltheadorable> the testing point is entirely irrelevant in ruby, you have the exact same mocking capabilities
<FromGitter>
<watzon> Why have an `end` for something that has no content
<FromGitter>
<meltheadorable> and the classes already depend on each other, otherwise you wouldn’t be using dependency injection, and if your dependencies don’t follow the same interface you were going to need to change more things anyway, DI won’t bridge objects with distinct interfaces for you
<rocx>
watzon: asking because i want to see what i can do to fix that crazy `abstract def` issue in the emacs crystal mode but also discovered a similar thing with annotations.
<FromGitter>
<Blacksmoke16> @meltheadorable exactly yes, but it makes them depend on abstractions not the concrete implementations
<FromGitter>
<watzon> What issue does crystal mode have with `abstract def`?
<FromGitter>
<meltheadorable> i don’t think i’m ever going to care about dependency injection, it seems entirely pointless
<FromGitter>
<Blacksmoke16> i guess so
<FromGitter>
<watzon> Tbh I like DI, if used correctly. Take Angular for example, they made very good use of DI with Angular 2+.
<FromGitter>
<Blacksmoke16> i see your point, but disagree that its entirely pointless just because of that
<FromGitter>
<watzon> @rocx ahh yeah, VS Code has a similar issue with some things. For instance, when writing specs in Code if you do `describe "#method_name do` it doesn't automatically indent the next line for you, but `describe ".method_name" do` will.
<FromGitter>
<watzon> Just some weird behaviors
<FromGitter>
<Blacksmoke16> main things i like it for is the eas of reuse, testability, and not tightly coupling implementations
<FromGitter>
<meltheadorable> maybe it’s just me, i’ve suffered more from overabstracted code with lots of indirection than i have from code with mild duplication, and i don’t actually think DI prevents coupling
<FromGitter>
<watzon> DI makes it easy to reuse things without having some kind of manually managed global state
<FromGitter>
<Blacksmoke16> right, any class you want to send an email in or something, just inject your email sending service
<FromGitter>
<Blacksmoke16> vs doing `sender = EmailProvider.new xxx` etc
<FromGitter>
<meltheadorable> in rails i *already have a global email service* — adding another wrapper around it and using DI containers would just make it more confusing
<FromGitter>
<Blacksmoke16> You know what I mean.
<FromGitter>
<meltheadorable> this tends to be true of basically every situation i’ve seen somebody praise DI for
<FromGitter>
<Blacksmoke16> Just using email as an example
<FromGitter>
<absolutejam_gitlab> any way to get `Process.run` to emulate a TTY, or get TTY-like behaviour?
<FromGitter>
<meltheadorable> i guess what im saying is that the global namespace & constant lookup already solves all the problems DI is useful for
<FromGitter>
<absolutejam_gitlab> I'm not getting progress bars in yarn, etc..
<FromGitter>
<watzon> @absolutejam_gitlab set `output` to `STDOUT` and `error` to `STDERR`
<FromGitter>
<absolutejam_gitlab> I have
<FromGitter>
<absolutejam_gitlab> I get colour sequences
<FromGitter>
<watzon> Hmm, no clue then
<FromGitter>
<Blacksmoke16> There is another option
<FromGitter>
<absolutejam_gitlab> Seemed to be okay in docker-compose
<FromGitter>
<absolutejam_gitlab> rewriting the progress
<FromGitter>
<Blacksmoke16> Like shell: true maybe?
<FromGitter>
<absolutejam_gitlab> also that
<FromGitter>
<absolutejam_gitlab> also passed it env var of `TERM=xterm-256color`
<FromGitter>
<absolutejam_gitlab> with `enve`
<FromGitter>
<absolutejam_gitlab> -e
<FromGitter>
<Blacksmoke16> @meltheadorable I disagree but whatever works for you :shrug:
<FromGitter>
<watzon> Hmm weird, I just ran `Process.run("neofetch", output: STDOUT)` and the colors came through just fine
<FromGitter>
<absolutejam_gitlab> colours are fine
<FromGitter>
<absolutejam_gitlab> wonder if it's a yarnism
<FromGitter>
<absolutejam_gitlab> composer was okay too
<FromGitter>
<absolutejam_gitlab> bit of a pita as yarn has the longest wait time so the progress bar is nice
<FromGitter>
<watzon> Weird
<FromGitter>
<watzon> You can always do your own progress bar and hide yarns
<FromGitter>
<watzon> But that's actually hard to do
<FromGitter>
<watzon> Because you don't know the progress...
<FromGitter>
<girng> i thought i had to format it first, then to_s. but it does it all in one go
<FromGitter>
<girng> :)
ht_ has quit [Quit: ht_]
absolutejam4 has quit [Quit: WeeChat 2.5]
<FromGitter>
<girng> @watzon fb is like twitter. full of negativity and creates addictive behavior that is unhealthy. was cool and beneficial back in 2007 when my school teacher had it and i created one to keep in touch with junior high / high school friends. but it evolved far more beyond networking for students, which will be its ultimate demise.
<FromGitter>
<watzon> Yup. There's a Black Mirror episode that shows it pretty perfectly.
<FromGitter>
<watzon> I have an account, but I rarely go on
<FromGitter>
<watzon> I mainly just use messenger to talk to some people
<FromGitter>
<girng> glad your getting stars though, lol
<FromGitter>
<watzon> Haha, I need to think of another project that plays off of people's hate for Facebook
<FromGitter>
<girng> ;D
<FromGitter>
<girng> time.in shouldn't read a file each time
<FromGitter>
<girng> however, time.shift has been added recently, gonna use that
<FromGitter>
<Blacksmoke16> hm?
alex`` has quit [Ping timeout: 258 seconds]
FromGitter has quit [Remote host closed the connection]
<FromGitter>
<Blacksmoke16> you should just store all times in the db in UTC
<FromGitter>
<Blacksmoke16> then can adjust to any tz based on that
<FromGitter>
<girng> that's what i do already
<FromGitter>
<girng> but when showing results from logs
<FromGitter>
<girng> you need to adjust the time to the client's timezone
<FromGitter>
<Blacksmoke16> why?
<FromGitter>
<Blacksmoke16> if its logs having it in UTC is totally fine
<FromGitter>
<Blacksmoke16> then there is a common time people could use
<FromGitter>
<Blacksmoke16> vs having to to tz conversions
<FromGitter>
<girng> there is nothing wrong with tz conversions
<FromGitter>
<girng> it's better fo rthe end user
<FromGitter>
<girng> it shows the correct time that log happened locally (to them)
<FromGitter>
<girng> this is useful for forum dates, etc
<FromGitter>
<Blacksmoke16> is this for your game or the chat server?
<FromGitter>
<girng> literally used all over the internet lmao
<FromGitter>
<girng> this why when you usually sign up on forums it asks you for your timezone
<FromGitter>
<girng> so all the dates make sense when you read posts from diff people lol
<FromGitter>
<girng> at diff times around the world...
<FromGitter>
<girng> same applies to logs
<FromGitter>
<Blacksmoke16> is this for your game or chat project?
<FromGitter>
<girng> chat project, but i have a logs system setup for gold transactions
<FromGitter>
<Blacksmoke16> do other people also see the logs? or are they user specific?
<FromGitter>
<girng> all i'm saying is, if you were to use Time.in when reading data to convert the UTC timezone in mysql, the developer could be accidentally reading files on each iteration = bad
<FromGitter>
<girng> Time.shift or setting the offset in the mysql query select is best
<FromGitter>
<girng> user specific
<FromGitter>
<Blacksmoke16> couldnt you just do `.to_local`?
<FromGitter>
<girng> nah because diff users can have diff timezones
<FromGitter>
<Blacksmoke16> right, that would convert it to their local tz
<FromGitter>
<girng> unless there is a parameter to to_local?
<FromGitter>
<Blacksmoke16> without that there isnt any implementation to that method
<FromGitter>
<Blacksmoke16> as it just represents something that will be, not that currently is
<FromGitter>
<girng> how is it the child's job when the parent it's inheriting from is the actual *parent*. it's their job to outline what their children do. again, it's a misnomer
<FromGitter>
<absolutejam_gitlab> It's not an implemented method
<FromGitter>
<absolutejam_gitlab> You're just saying 'slot your method here'
<FromGitter>
<Blacksmoke16> > it's their job to outline what their children do ⏎ thats exactly the point of an abstract def
<FromGitter>
<absolutejam_gitlab> I'd you define the interface, it doesn't mean you've implemented it
<FromGitter>
<girng> writing something out in code for child objects to follow is not existing in thought or idea
<FromGitter>
<Blacksmoke16> giving an "outline" for the children to implement
<FromGitter>
<girng> it's already an outline, ready to be used, lol
<FromGitter>
<Blacksmoke16> thats a general definition, so obs not going to be 100% relatable to CS
<FromGitter>
<Blacksmoke16> an outline is a good term
<FromGitter>
<girng> yeah it is
<FromGitter>
<Blacksmoke16> to at least put words to what its doing
<FromGitter>
<Blacksmoke16> > it's already an outline, ready to be used, lol ⏎ ⏎ you cant use an abstract method until its implemented
<FromGitter>
<girng> i was reading about all the definitions abstract has in diff contexts too, quite a nasty word
<FromGitter>
<Blacksmoke16> was a PR merged recently that will throw a warning if you have an abstract def with a return type, where the child implementation doesn't have one, or has a different one
<FromGitter>
<girng> @Blacksmoke16 that makes it a guideline for a child to follow, not something that isn't concrete.
<FromGitter>
<Blacksmoke16> but its not concrete until the child defines it
<FromGitter>
<Blacksmoke16> its not implemented yet
<FromGitter>
<girng> sure it's concrete, it's a def written out in a programming language.
<FromGitter>
<Blacksmoke16> but its not
<FromGitter>
<girng> oh really?
<FromGitter>
<girng> what is it then
<FromGitter>
<Blacksmoke16> its defining something that the child must implement, its not actually method you can use on its own
<FromGitter>
<girng> just because a method can't be used on its own, does make it not concrete though
<FromGitter>
<girng> it's still code a developer wrote out, with intentions for it of doing something
<FromGitter>
<Blacksmoke16> it doesnt do anything at that point
<FromGitter>
<Blacksmoke16> besides saying "this needs to be implemented at some point"
<FromGitter>
<girng> well then a dev shouldn't waste time writing it
<FromGitter>
<Blacksmoke16> its useful to ensure children implemented the expected methods
<FromGitter>
<Blacksmoke16> granted crystal makes it less important as it wouldnt compile saying "unknown method"
<FromGitter>
<girng> i understand the usefulness of it, just the word doens't match it
<FromGitter>
<girng> i also don't agree with its usefulness but you already know that
<FromGitter>
<Blacksmoke16> relying on one error to catch everything isnt really ideal imo
<FromGitter>
<Blacksmoke16> esp for those who dont know your code and are just looking at it for the first time
<FromGitter>
<Blacksmoke16> its a simple thing you can add that makes it much more clear on what the intended behavior of that class is
<FromGitter>
<girng> i don't disagree
<FromGitter>
<tenebrousedge> say you have an ORM, and you have a bunch of APIs that you can also fetch data from
<FromGitter>
<tenebrousedge> you can define an interface for those APIs, so that they can be used the same way as the normal ORM methods
<FromGitter>
<tenebrousedge> and you open-source this interface so that other people can write similar code for their APIs
<FromGitter>
<Blacksmoke16> which is similar to the DI stuff, crystal doesnt have interfaces so abstract defs are like our interfaces
<FromGitter>
<girng> you can do all that without the abstract keyword
<FromGitter>
<girng> parent -> client is sufficient already
<FromGitter>
<girng> asterite even said that
<FromGitter>
<tenebrousedge> the methods need to be implemented, but they're specific to the API being used
<FromGitter>
<tenebrousedge> so you can't provide sensible default behavior
<FromGitter>
<tenebrousedge> but in order for your code to be useful to other people, they need to implement methods x, y, z
<FromGitter>
<Blacksmoke16> hes content on just relying on it saying "undefined method fetch_data"
<FromGitter>
<Blacksmoke16> which works, but :shrug:
<FromGitter>
<girng> i'm content on in about 2 years, i worry we'll have `abstract protected private annotated def`
<FromGitter>
<tenebrousedge> it works unless you have code that expects that interface to be implemented
<FromGitter>
<Blacksmoke16> it wont be that extreme
<FromGitter>
<Blacksmoke16> most you can do atm is `abstract protected def something`
<FromGitter>
<Blacksmoke16> which is all helpful info in an OOP lang
<FromGitter>
<tenebrousedge> these are very well-worn concepts in OOP
<FromGitter>
<Blacksmoke16> just because some of those practices/patterns arent as required doesnt mean you should dismiss them
<FromGitter>
<girng> for a veteran / well versed user. not someone that is fresh out of nodejs or ruby.
<FromGitter>
<Blacksmoke16> im content as long as you know what their purposes are, whether you use them is up to you
<FromGitter>
<Blacksmoke16> but having that understanding is the important part, will come a time when you'll see their usefulness
<FromGitter>
<girng> until.. every code a new user see is littered with `abstract protected private annoted def`, and then thinks negatively of crystal's syntax.
<FromGitter>
<tenebrousedge> the other thing is, in PHP and other interpreted languages, `undefined method` is a runtime error, and the `abstract` an immediate error
<FromGitter>
<Blacksmoke16> ^ right, again @girng `abstract protected private annoted def` is never going to be a thing unless this also happens to get adopted by all of OOP
<FromGitter>
<Blacksmoke16> there concepts are not specific to crystal
<FromGitter>
<Blacksmoke16> they are just there since crystal is an OOP
<FromGitter>
<girng> one of crystal's strongest things is its beautiful syntax, nn for it to be hindered with excessive OOP principles
<FromGitter>
<Blacksmoke16> i feel like that statement is somewhat contradictory, but meh
<FromGitter>
<girng> i could see how it is
<FromGitter>
<Blacksmoke16> *i want an OOP lang without OOP principles*
<FromGitter>
<tenebrousedge> I think it's very much to e.g. Python's detriment that it lacks `abstract`
<FromGitter>
<girng> @Blacksmoke16 yeah that's just a hyperbole example, but you don't want that to happen do you?
<FromGitter>
<Blacksmoke16> i dont mind it, it makes the intent much more clear
<FromGitter>
<tenebrousedge> not being able to validate an interface when the file is included sort of defeats a lot of the point of having it. Crystal ameliorates that problem somewhat
<FromGitter>
<Blacksmoke16> its a method that must be implemented by children that can only be called in the same class or its children
<FromGitter>
<girng> @Blacksmoke16 i can't argue with that, cause personal preference. i respect your right
<FromGitter>
<Blacksmoke16> `Without the abstract def there is nothing to tell someone what the intended behavior of that relationship should be. Is get_message optional? Is it required? Should it be implemented by all children or only some? You just don’t know. What happens if you have a subclass that returns a Bool instead of a string, is that the expected behavior or an error? For how simple it is to say abstract def get_message
<FromGitter>
... : String you make it SO much more clear on what the intended behavior is. Now anyone would know, ok if i want to implement a new email provider, i need to inherit from this class and implement a get_message method that returns a string. There. Done.`
<FromGitter>
<tenebrousedge> I think it might be a long time before I use the `abstract` keyword in Crystal
<FromGitter>
<Blacksmoke16> is still my stance on the matter
<FromGitter>
<tenebrousedge> but I don't argue with it being there
<FromGitter>
<Blacksmoke16> readability is a big part of crystal
<FromGitter>
<Blacksmoke16> OOP is a big part of crystal
<FromGitter>
<girng> @Blacksmoke16 yes, i understand the functionality and why it's there. however, again, i feel like now it's a misnomer
<FromGitter>
<tenebrousedge> hmm
<FromGitter>
<tenebrousedge> maybe we blame GoF for that?
<FromGitter>
<girng> i like Outline
<FromGitter>
<Blacksmoke16> make a macro called outline that defines `abstract` under the hood 😆
<FromGitter>
<girng> ;D
<FromGitter>
<girng> @tenebrousedge what's GoF?
<FromGitter>
<Blacksmoke16> anyway, my point with the readability/OOP points, is making the indent of a class to be more readable using OOP principles is a win win
<FromGitter>
<tenebrousedge> The "Gang of Four" book (https://en.wikipedia.org/wiki/Design_Patterns) is a seminal work on design patterns in object-oriented software, which has a terrible name so people just call it "GoF", but it's generally where all our OOP terminology comes from
<FromGitter>
<dscottboggs_gitlab> > What happens if you have a subclass that returns a Bool instead of a string, is that the expected behavior or an error? For how simple it is to say `abstract def get_message : String` you make it SO much more clear on what the intended behavior is. ⏎ ⏎ yeah except that `: String` isn't enforced by the compiler 😠
<FromGitter>
<Blacksmoke16> it is now @dscottboggs_gitlab with a warning for now at least
<FromGitter>
<Blacksmoke16> future version will make it a compile error
<FromGitter>
<dscottboggs_gitlab> hm, I guess I should be using `--warnings all` haha
<FromGitter>
<tenebrousedge> probs a good idea
<FromGitter>
<girng> > anyway, my point with the readability/OOP points, is making the indent of a class to be more readable using OOP principles is a win win ⏎ ⏎ IMO, abstract keywords are not needed to understand OOP
<FromGitter>
<girng> A simple Parent -> Child relationship is all it takes
<FromGitter>
<Blacksmoke16> `--error-on-warnings` is also helpful
<FromGitter>
<Blacksmoke16> i still *really* disagree with that but ok
<FromGitter>
<tenebrousedge> I don't know that anyone *truly* understands OOP
<FromGitter>
<girng> if someone can't understand your class hierarchy, and must rely on abstract, something is terrible wrong
<FromGitter>
<Blacksmoke16> i mean just looking at the parent class there is no way to know what is expected of your children
<FromGitter>
<girng> good, children can implement their own methods and functionality
<FromGitter>
<girng> that's the part of growing up
<FromGitter>
<dscottboggs_gitlab> hahahaaha
<FromGitter>
<tenebrousedge> Tonight's dinner is chile verde (https://www.simplyrecipes.com/recipes/chile_verde/), simmering on the stove, so I'mma bounce for bit, grab a beer, let it do its thing. Ciao ciao
<FromGitter>
<Blacksmoke16> now to be clear, you wouldn *NOT* define an abstract method on the parent for *every* method in the child
<FromGitter>
<Blacksmoke16> only those you want *EVERY* child to have
<FromGitter>
<dscottboggs_gitlab> sounds yummy @tenebrousedge I've got a roast in the pressure cooker :D
<FromGitter>
<girng> @Blacksmoke16 sounds like parent favoritism to me
<FromGitter>
<Blacksmoke16> 😐
<FromGitter>
<girng> 😆
<FromGitter>
<girng> @Blacksmoke16 yes, but the developer can just add those methods. if they are not there, the compiler already complains. that's more than enough, instead of littering code with `abstract` everywhere
<FromGitter>
<Blacksmoke16> i mean its hardly littering and hardly everywhere but i see your point
<FromGitter>
<dscottboggs_gitlab> @girng lets say you do something like ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ would throw an error because `method` isn't defined. If you say `abstract def method` that makes the compiler freak out if you don't implement `method` on `C` [https://gitter.im/crystal-lang/crystal?at=5d3e2e72f0ff3e2bba8598d3]
<FromGitter>
<girng> now, since every developer is different, if a developer wants to do that.. go ahead, but i think it's confusing af, and ultimately it might lead to my hyperbole example above.
<FromGitter>
<Blacksmoke16> @dscottboggs_gitlab he's fine with just letting it error with undefined method `method`
<FromGitter>
<Blacksmoke16> which works in crystal lang, but go to another lang and might not have that luxury, now you're at a disadvantage
<FromGitter>
<dscottboggs_gitlab> yeah that only works because of crystal's insanely heavy use of generics
<FromGitter>
<girng> why is a developer calling `depends_on_method` on a class that doesn't have it in the first place
<FromGitter>
<girng> contrived example, not real-world use case
<FromGitter>
<Blacksmoke16> not true, reminder of my examples on the thread
<FromGitter>
<Blacksmoke16> allows you to share common logic but have each child implement their own logic
<FromGitter>
<dscottboggs_gitlab> although I guess he has a point that it's not strictly necessary... I just think it's easier to track down if there's some standard way to document the requirement to define a method
<FromGitter>
<Blacksmoke16> yes, its all about showing intent
<FromGitter>
<dscottboggs_gitlab> it only seems like a contrived example because it's so slimmed down. It's very common to do something like that. A really great example off the top of my head is the stdlib's IO type
<FromGitter>
<Blacksmoke16> it makes it 100% known what the expected behavior will be
<FromGitter>
<dscottboggs_gitlab> an IO only needs to define `#read` and/or `#write` and it' gets all kinds of fancy helpers attached to it which all call `#read` and `#write`
<FromGitter>
<Blacksmoke16> trying to think of an example that could be useful to your game
<FromGitter>
<dscottboggs_gitlab> I mean there are tons of examles for a game -- `abstract class Character` or `Item` or `Enemy` could all implement abscract methods that would need defined on child types.
<FromGitter>
<Blacksmoke16> something like `abstract class Vehicle`
<FromGitter>
<Blacksmoke16> with a `def move` method
<FromGitter>
<Blacksmoke16> that handles the logic of if `self `can move there etc
<FromGitter>
<girng> yeha
<FromGitter>
<Blacksmoke16> but each subclass has a `protected def move_self` or something that does the logic specific to that vehicle?
<FromGitter>
<Blacksmoke16> i see your point but i disagree
<FromGitter>
<Blacksmoke16> its making it more readable, self documenting, and defining intent
<FromGitter>
<girng> one of crystal's strongest qualities is its syntax, no?
<FromGitter>
<Blacksmoke16> right, which maps to readability
<FromGitter>
<dscottboggs_gitlab> lol also one of its weakest
<FromGitter>
<Blacksmoke16> you just happen to often not need a lot of code due to its high level nature
<FromGitter>
<girng> @Blacksmoke16 right. now look at scott's example with `Character`. look at all those `abstracts`. now, you are used to it and it seems normal
<FromGitter>
<girng> HOWEVER, a new user looking at this, is like what in the ever f is going on
<FromGitter>
<Blacksmoke16> they would have a better idea of whats going on than if they werent there
<FromGitter>
<girng> no cause abstract wouldn't be used
<FromGitter>
<girng> and it wouldn't the same
<FromGitter>
<Blacksmoke16> assuming they are familiar with basic OOP principles
<FromGitter>
<dscottboggs_gitlab> one person might write `if !flag?(:some_flag)` while another might write `unless flag? :some_flag`. Crystal's syntax is EXTREMELY flexible, which as we've seen in C/C++ (https://ioccc.org/) can be just as much of a detriment in the wrong hands as a benefit in the right hands
<FromGitter>
<Blacksmoke16> alright, so how would a new user wants to create a new character, without knowing anything else, how would they know they need to implement those two methods?
<FromGitter>
<girng> they look at the parent class
<FromGitter>
<dscottboggs_gitlab> you'd have to read every line of every method!
<FromGitter>
<Blacksmoke16> and they dont see any abstracts to say the child needs them
teardown has joined #crystal-lang
<FromGitter>
<girng> that seems unfair as an argument, because docs should be showing what methods are available
<FromGitter>
<Blacksmoke16> so they assume they dont need to do anything specific and write their class, then it doesnt compile bout some random "undefined method walking_speed"
<FromGitter>
<dscottboggs_gitlab> plus, methods might be defined at the top level by something required, possibly even in another file, so just because you don't see a method defined doesn't mean you necessarliy need to implement it
<FromGitter>
<Blacksmoke16> but they wouldnt unless you define them as abstract
<FromGitter>
<girng> not fair they get to use `abstract` to generated clearer docs
<FromGitter>
<girng> when it should be the same without it.
<FromGitter>
<Blacksmoke16> how would you propose to do that?
<FromGitter>
<Blacksmoke16> it just magically know what you want?
<FromGitter>
<girng> "methods required" or "methods available not not required", etc
<FromGitter>
<girng> if abstract was read
<FromGitter>
<girng> so the docs basically screw over someone who doesn't use abstract?
<FromGitter>
<girng> on generation
<FromGitter>
<Blacksmoke16> i mean, unless you manually do like
<FromGitter>
<girng> a developer shouldn't use base crystal syntax for doc generation. if they need special generation for docs, they should use special syntax.
<FromGitter>
<dscottboggs_gitlab> but that would also slow down the compiler a decent amount
<FromGitter>
<Blacksmoke16> so now you want to implement some documentation specific thing that `abstract` already does?
<FromGitter>
<girng> i've read comements don't slow down compiler speed
<FromGitter>
<girng> it could be done
<FromGitter>
<dscottboggs_gitlab> it's beyond docs, a child class won't compile without implementing abstract methods from parent classes
<FromGitter>
<Blacksmoke16> with a super clear reason
<FromGitter>
<Blacksmoke16> and will soon handle the case of return type mismatch
<FromGitter>
<dscottboggs_gitlab> > i've read comements don't slow down compiler speed ⏎ ⏎ I meant not having `abstract def` would slow down compilation because the compiler would have to go looking for the method in every namespace and check for its presence rather than just noting that it neesd to be defined by a child
<FromGitter>
<Blacksmoke16> could be on top level, in a module, in another module included into the current module etc
<FromGitter>
<Blacksmoke16> just to say "no doesnt exist"
<FromGitter>
<girng> eh i hope not, scott.
<FromGitter>
<girng> cause i don't use abstract
<FromGitter>
<Blacksmoke16> as i said before, its all about intent. writing those *TWO* extra lines, makes it clear in the docs, clear to the reader, and clear to the compiler of what your expected behavior is
<FromGitter>
<dscottboggs_gitlab> I mean, you don't have to, and you're the only one that suffers as long as you're the only one working on it
<FromGitter>
<Blacksmoke16> ^
<FromGitter>
<girng> no
<FromGitter>
<girng> wrong
<FromGitter>
<girng> i am not suffering
<FromGitter>
<dscottboggs_gitlab> but in a professional environment you probably would be required to use it
<FromGitter>
<Blacksmoke16> ^
<FromGitter>
<girng> you think i'm suffering
<FromGitter>
<girng> but you are wrong
<FromGitter>
<Blacksmoke16> we'll see a year from now when you want to change something in your game :P
<FromGitter>
<dscottboggs_gitlab> You are suffering a minor hit on performance, but if that's a tradeoff you deem worth it then that's your call
<FromGitter>
<girng> unless actual benchmarks proves that
<FromGitter>
<Blacksmoke16> id be willing to bet you're the only person that will ever understand it
<FromGitter>
<girng> i am not listening
<FromGitter>
<Blacksmoke16> which isnt a bad thing dont get me wrong, but if you're expecting others to open PRs to it, it's prob going to be super hard for them
<FromGitter>
<girng> well yeah it's a benefit. but it shouldn't ONLY happen if abstract is there
<FromGitter>
<dscottboggs_gitlab> as you've pointed out, it doesn't
<FromGitter>
<girng> doc generation should show the classes vailable
<FromGitter>
<Blacksmoke16> again, how would you propose to do that?
<FromGitter>
<dscottboggs_gitlab> there's the fallback of the compiler just saying "this method isn't defined" which is fine but it's a little slower and less clear
<FromGitter>
<Blacksmoke16> would you really be willing to do like `document def walking_speed : Int32`?
<FromGitter>
<girng> if no abstract, then "methods are available, but not required"
<FromGitter>
<girng> if abstract, "required methods"
<FromGitter>
<Blacksmoke16> but how would it know *what* methods?
<FromGitter>
<girng> if they used abstract
<FromGitter>
<Blacksmoke16> just pull some names out of the air?
<FromGitter>
<Blacksmoke16> i mean, not perfect but not the worst iv'e seen
<FromGitter>
<Blacksmoke16> is still missing that a child could just *not* override those properties
<FromGitter>
<dscottboggs_gitlab> you've silently set it up so that if you accidentally forget to define `walking_speed` or `running_speed` on a character they'll just mysteriously stand stilll with no explanation.
<FromGitter>
<Blacksmoke16> ^
<FromGitter>
<girng> developer needs to set their speed so they can move.
<FromGitter>
<girng> that's implied
<FromGitter>
<Blacksmoke16> just making it harder on yourself but yes i guess
<FromGitter>
<girng> i mean are you serious?
<FromGitter>
<girng> hypotheticals
<FromGitter>
<girng> no you are
<FromGitter>
<dscottboggs_gitlab> Like what if you define a character with `walking_speed` only and only test in walking mode, then a user finds out the hard way that character can't run
<FromGitter>
<girng> you think of all these extra "what ifs" that arn't real-world use cases
<FromGitter>
<Blacksmoke16> tests would have caught that :P
<FromGitter>
<dscottboggs_gitlab> > that's implied ⏎ ⏎ it's definitely not
<FromGitter>
<girng> yes it is
<FromGitter>
<girng> it's their walking speed, they can't move at 0
<FromGitter>
<Blacksmoke16> maybe to you
<FromGitter>
<girng> that's implied
<FromGitter>
<Blacksmoke16> because you made it
<FromGitter>
<girng> ofcourse if they speed is at 0, they are not going to move, LOL
<FromGitter>
<girng> well yeah..
<FromGitter>
<girng> ofcourse i made it
<FromGitter>
<girng> i just wrote it
<FromGitter>
<Blacksmoke16> someone coming into your codebase and seeing 100s of lines of code might miss that
<FromGitter>
<Blacksmoke16> would be very easy to do so
<FromGitter>
<Blacksmoke16> and they wouldnt notice until they go to actually use it
<FromGitter>
<girng> just because a developer needs their code to work with others. doesn't mean features should be implemented into the base language that pollute it
<FromGitter>
<Blacksmoke16> assuming you dont have any tests
<FromGitter>
<Blacksmoke16> (which you dont)
<FromGitter>
<Blacksmoke16> they're only there to help you tho
<FromGitter>
<girng> well, tests i agree with you on, i just havn't really gotten around to them yet
<FromGitter>
<Blacksmoke16> good to hear, we're at least making some progress :P
<FromGitter>
<Blacksmoke16> this would have caught the same error much earlier and at compile time
<FromGitter>
<Blacksmoke16> (using abstract def that is)
<FromGitter>
<girng> progress not gonna happen with `abstract`,trust me. i know down deep something is very flawed
<FromGitter>
<girng> i don't have that feeling with how i did with `tests`